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
            }
        }
    }
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With