Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Video Orientation changes on mediarecorder.Start()

This question is similar to posts here, here, here, here and here, but I'm stuck and have spent hours trying to figure it out.

I have a video camera preview (which now always shows in the correct orientation), but when I hit record (mediaRecorder.start();), the video orientation changes. I have tried using setOrientationHint, but it doesn't seem to make a difference (as marked in a comment in the code below).

It affects both my test devices (Galaxy and Xperia on Jelly Bean). What should I do to fix this please?

Here's my code:

XML

<RelativeLayout android:id="@+id/surface_camera"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_centerInParent="true"
    android:layout_weight="1"
    >

    <RelativeLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        <FrameLayout
            android:id="@+id/videoview"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"/>
        <Button
            android:id="@+id/mybutton"
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:layout_centerHorizontal="true"
            android:layout_alignParentBottom="true"
            android:text="REC"
            android:textSize="12dp"/>
    </RelativeLayout>

</RelativeLayout>

Java

package hockeyj.androidlisttesting;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;

    public class VideoWithSurfaceVw extends Activity{

        //Starter Tutorial: http://sandyandroidtutorials.blogspot.co.uk/2013/05/android-video-capture-tutorial.html

        private Camera myCamera;
        private MyCameraSurfaceView myCameraSurfaceView;
        private MediaRecorder mediaRecorder;

        Button myButton;
        SurfaceHolder surfaceHolder;
        boolean recording;

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            recording = false;

            setContentView(R.layout.activity_video_with_surface_vw);

            //Get Camera for preview
            myCamera = getCameraInstance();

            //myCamera.setDisplayOrientation(90); //Doesn't error here, but doesn't affect video.

            if(myCamera == null){
                Toast.makeText(VideoWithSurfaceVw.this,
                        "Fail to get Camera",
                        Toast.LENGTH_LONG).show();
            }

            myCameraSurfaceView = new MyCameraSurfaceView(this, myCamera);
            FrameLayout myCameraPreview = (FrameLayout)findViewById(R.id.videoview);
            myCameraPreview.addView(myCameraSurfaceView);

            myButton = (Button)findViewById(R.id.mybutton);
            myButton.setOnClickListener(myButtonOnClickListener);
        }

        Button.OnClickListener myButtonOnClickListener
                = new Button.OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                try{
                    if(recording){
                        // stop recording and release camera
                        mediaRecorder.stop();  // stop the recording
                        releaseMediaRecorder(); // release the MediaRecorder object

                        //Exit after saved
                        //finish();
                        myButton.setText("REC");
                        recording = false;
                    }else{

                        //Release Camera before MediaRecorder start
                        releaseCamera();

                        if(!prepareMediaRecorder()){
                            Toast.makeText(VideoWithSurfaceVw.this,
                                    "Fail in prepareMediaRecorder()!\n - Ended -",
                                    Toast.LENGTH_LONG).show();
                            finish();
                        }
                        mediaRecorder.start();
                        recording = true;
                        myButton.setText("STOP");
                    }
                }catch (Exception ex){
                    ex.printStackTrace();
                }
            }};

        private Camera getCameraInstance(){
            // TODO Auto-generated method stub
            Camera c = null;
            try {
                c = Camera.open(); // attempt to get a Camera instance
            }
            catch (Exception e){
                // Camera is not available (in use or does not exist)
            }
            return c; // returns null if camera is unavailable
        }


        private boolean prepareMediaRecorder(){
            myCamera = getCameraInstance();
            mediaRecorder = new MediaRecorder();

            myCamera.unlock();

            mediaRecorder.setCamera(myCamera);

            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
            mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

            mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

            mediaRecorder.setOutputFile("/sdcard/myvideo1.mp4");
            mediaRecorder.setMaxDuration(60000); // Set max duration 60 sec.
            mediaRecorder.setMaxFileSize(50000000); // Set max file size 50Mb

//Attempt commented out - Trying to get the recorder to record portrait, but doesn't work....
            //mediaRecorder.setOrientationHint(90);

            mediaRecorder.setPreviewDisplay(myCameraSurfaceView.getHolder().getSurface());

            try {
                mediaRecorder.prepare();
            } catch (IllegalStateException e) {
                releaseMediaRecorder();
                return false;
            } catch (IOException e) {
                releaseMediaRecorder();
                return false;
            }
            return true;

        }

        @Override
        protected void onPause() {
            super.onPause();
            releaseMediaRecorder();       // if you are using MediaRecorder, release it first
            releaseCamera();              // release the camera immediately on pause event
        }

        private void releaseMediaRecorder(){
            if (mediaRecorder != null) {
                mediaRecorder.reset();   // clear recorder configuration
                mediaRecorder.release(); // release the recorder object
                mediaRecorder = new MediaRecorder();
                myCamera.lock();           // lock camera for later use
            }
        }

        private void releaseCamera(){
            if (myCamera != null){
                myCamera.release();        // release the camera for other applications
                myCamera = null;
            }
        }

        public class MyCameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback{

            private SurfaceHolder mHolder;
            private Camera mCamera;

            public MyCameraSurfaceView(Context context, Camera camera) {
                super(context);
                mCamera = camera;

                // Install a SurfaceHolder.Callback so we get notified when the
                // underlying surface is created and destroyed.
                mHolder = getHolder();
                mHolder.addCallback(this);
                // deprecated setting, but required on Android versions prior to 3.0
                mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            }

            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
            {
                try {

                    if (mHolder.getSurface() == null){
                        // preview surface does not exist
                        return;
                    }

                    try{
                        mCamera.stopPreview();
                    }catch (Exception e){
                        // ignore: tried to stop a non-existent preview
                    }


                    Camera.Parameters parameters = mCamera.getParameters();
                    Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();

                    if(display.getRotation() == Surface.ROTATION_0)
                    {
                        parameters.setPreviewSize(height, width);
                        mCamera.setDisplayOrientation(90);
                    }

                    if(display.getRotation() == Surface.ROTATION_90)
                    {
                        parameters.setPreviewSize(width, height);
                    }

                    if(display.getRotation() == Surface.ROTATION_180)
                    {
                        parameters.setPreviewSize(height, width);
                    }

                    if(display.getRotation() == Surface.ROTATION_270)
                    {
                        parameters.setPreviewSize(width, height);
                        mCamera.setDisplayOrientation(180);
                    }

                    mCamera.setParameters(parameters);
                    previewCamera();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            public void previewCamera()
            {
                try
                {
                    mCamera.setPreviewDisplay(mHolder);
                    mCamera.startPreview();
                }
                catch(Exception e)
                {
                    //Log.d(APP_CLASS, "Cannot start preview", e);
                }
            }

            /*@Override
            public void surfaceChanged(SurfaceHolder holder, int format, int weight,
                                       int height) {
                // If your preview can change or rotate, take care of those events here.
                // Make sure to stop the preview before resizing or reformatting it.

                if (mHolder.getSurface() == null){
                    // preview surface does not exist
                    return;
                }

                // stop preview before making changes
                try {
                    mCamera.stopPreview();
                } catch (Exception e){
                    // ignore: tried to stop a non-existent preview
                }

                // make any resize, rotate or reformatting changes here

                // start preview with new settings
                try {
                    mCamera.setPreviewDisplay(mHolder);
                    mCamera.startPreview();

                } catch (Exception e){
                }
            }*/

            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                // TODO Auto-generated method stub
                // The Surface has been created, now tell the camera where to draw the preview.
                try {
                    mCamera.setPreviewDisplay(holder);
                    mCamera.startPreview();
                } catch (IOException e) {
                }
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                // TODO Auto-generated method stub

            }
        }
    }
like image 537
JsAndDotNet Avatar asked Dec 11 '22 23:12

JsAndDotNet


1 Answers

I had a similar problem, i used Rotating a Camera SurfaceView to portrait to set the orientation, i modified it to also set the result to a class variable and set the orientation for the media recorder.

Try this:

public class VideoWithSurfaceVw extends Activity{

//Starter Tutorial: http://sandyandroidtutorials.blogspot.co.uk/2013/05/android-video-capture-tutorial.html

private Camera myCamera;
private MyCameraSurfaceView myCameraSurfaceView;
private MediaRecorder mediaRecorder;
public static int orientation;
Button myButton;
SurfaceHolder surfaceHolder;
boolean recording;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    recording = false;

    setContentView(R.layout.activity_video_with_surface_vw);

    //Get Camera for preview
    myCamera = getCameraInstance();

    //myCamera.setDisplayOrientation(90); //Doesn't error here, but doesn't affect video.

    if(myCamera == null){
        Toast.makeText(VideoWithSurfaceVw.this,
                "Fail to get Camera",
                Toast.LENGTH_LONG).show();
    }

    myCameraSurfaceView = new MyCameraSurfaceView(this, myCamera,this);
    FrameLayout myCameraPreview = (FrameLayout)findViewById(R.id.videoview);
    myCameraPreview.addView(myCameraSurfaceView);

    myButton = (Button)findViewById(R.id.mybutton);
    myButton.setOnClickListener(myButtonOnClickListener);
}

Button.OnClickListener myButtonOnClickListener
        = new Button.OnClickListener(){

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub

        try{
            if(recording){
                // stop recording and release camera
                mediaRecorder.stop();  // stop the recording
                releaseMediaRecorder(); // release the MediaRecorder object

                //Exit after saved
                //finish();
                myButton.setText("REC");
                recording = false;
            }else{

                //Release Camera before MediaRecorder start
                releaseCamera();

                if(!prepareMediaRecorder()){
                    Toast.makeText(VideoWithSurfaceVw.this,
                            "Fail in prepareMediaRecorder()!\n - Ended -",
                            Toast.LENGTH_LONG).show();
                    finish();
                }
                mediaRecorder.start();
                recording = true;
                myButton.setText("STOP");
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }};

private Camera getCameraInstance(){
    // TODO Auto-generated method stub
    Camera c = null;
    try {
        c = Camera.open(0); // attempt to get a Camera instance
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}


private boolean prepareMediaRecorder(){
    myCamera = getCameraInstance();

    // set the orientation here to enable portrait recording.
    setCameraDisplayOrientation(this,0,myCamera);

    mediaRecorder = new MediaRecorder();

    myCamera.unlock();

    mediaRecorder.setCamera(myCamera);

    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

    mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

    mediaRecorder.setOutputFile("/sdcard/myvideo1.mp4");
    mediaRecorder.setMaxDuration(60000); // Set max duration 60 sec.
    mediaRecorder.setMaxFileSize(50000000); // Set max file size 50Mb

mediaRecorder.setPreviewDisplay(myCameraSurfaceView.getHolder().getSurface());
    mediaRecorder.setOrientationHint(VideoWithSurfaceVw.orientation);
    try {
        mediaRecorder.prepare();
    } catch (IllegalStateException e) {
        releaseMediaRecorder();
        return false;
    } catch (IOException e) {
        releaseMediaRecorder();
        return false;
    }
    return true;

}

@Override
protected void onPause() {
    super.onPause();
    releaseMediaRecorder();       // if you are using MediaRecorder, release it first
    releaseCamera();              // release the camera immediately on pause event
}

private void releaseMediaRecorder(){
    if (mediaRecorder != null) {
        mediaRecorder.reset();   // clear recorder configuration
        mediaRecorder.release(); // release the recorder object
        mediaRecorder = new MediaRecorder();
        myCamera.lock();           // lock camera for later use
    }
}

private void releaseCamera(){
    if (myCamera != null){
        myCamera.release();        // release the camera for other applications
        myCamera = null;
    }
}

public class MyCameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback{

    private SurfaceHolder mHolder;
    private Camera mCamera;
    private Activity mActivity;

    public MyCameraSurfaceView(Context context, Camera camera,Activity activity) {
        super(context);
        mCamera = camera;
        mActivity=activity;
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
    {
        try {
            setCameraDisplayOrientation(mActivity,0,mCamera);
            previewCamera();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void previewCamera()
    {
        try
        {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
        }
        catch(Exception e)
        {
            //Log.d(APP_CLASS, "Cannot start preview", e);
        }
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub

    }


}
public static void setCameraDisplayOrientation(Activity activity,
                                               int cameraId, android.hardware.Camera camera) {

    android.hardware.Camera.CameraInfo info =
            new android.hardware.Camera.CameraInfo();

    android.hardware.Camera.getCameraInfo(cameraId, info);

    int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
    int degrees = 0;

    switch (rotation) {
        case Surface.ROTATION_0: degrees = 0; break;
        case Surface.ROTATION_90: degrees = 90; break;
        case Surface.ROTATION_180: degrees = 180; break;
        case Surface.ROTATION_270: degrees = 270; break;
    }

    int result;
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        result = (info.orientation + degrees) % 360;
        result = (360 - result) % 360;  // compensate the mirror
    } else {  // back-facing
        result = (info.orientation - degrees + 360) % 360;
    }
    VideoWithSurfaceVw.orientation=result;
    camera.setDisplayOrientation(result);
}

}

like image 193
isma3l Avatar answered Dec 28 '22 22:12

isma3l