MediaRecorder video capturing in portrait mode

Oleg Karakoz picture Oleg Karakoz · Aug 16, 2012 · Viewed 14.6k times · Source

I'm try to make custom video app. Iwork using settings in manifest 2.2 only (API 8).

All goes well but I don't understand why portrait mode video does not differ from lanscape one.

To make detection of device changed orientation I use this code within surfaceChanged()

        if (mCamera != null) {

        Camera.Parameters p = mCamera.getParameters();

        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            // TODO: handle exception
        }

        int previewWidth = 0;
        int previewHeight = 0;

        if (mPreviewSize != null) {
            Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            int rotation = display.getRotation();

            switch (rotation) {
            case Surface.ROTATION_0:
                previewWidth = mPreviewSize.height;
                previewHeight = mPreviewSize.width;
                mCamera.setDisplayOrientation(90);
                break;

            case Surface.ROTATION_90:
                previewWidth = mPreviewSize.width;
                previewHeight = mPreviewSize.height;
                mCamera.setDisplayOrientation(0);
                break;

            case Surface.ROTATION_180:
                previewWidth = mPreviewSize.height;
                previewHeight = mPreviewSize.width;
                mCamera.setDisplayOrientation(270);
                break;

            case Surface.ROTATION_270:
                previewWidth = mPreviewSize.width;
                previewHeight = mPreviewSize.height;
                mCamera.setDisplayOrientation(180);
                break;
            }

            p.setPreviewSize(previewWidth, previewHeight);
            mCamera.setParameters(p);
        }
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (Exception e) {
        Log.d(TAG, "Cannot start preview.", e);
    }
}

Works like a charm. If I rotate device surface change orientation, calling surfaceChanged, where camera is set to appropriate DisplayRotation.

The question is how to determine later if the video captured either in lanscape mode or in portrait one. As I got all the videos are captured in landscape orientation. It does not depend of setDisplayOrientation which affect only preview process.

Also exploring the problem I noticed that if to use standard Camera app it writes special tag to video file (seen in MediaInfo): Rotation : 90 for the portrait captured videos.

But MediaRecorder class does not.

Seems that is the problem. Anybody got to solve this?

Answer

Taiko picture Taiko · Dec 26, 2012

Found it ! Indeed, you can change the preview, you can tag the video, but there's no way to actually change the video... (maybe a speed issue or something)

camera.setDisplayOrientation(90);

To rotate the preview, then

recorder.setOrientationHint(90);

To tag the video as having a 90° rotation, then the phone will automatically rotate it when reading.

So all you have to do is

            camera = Camera.open();
        //Set preview with a 90° ortientation
        camera.setDisplayOrientation(90);
        camera.unlock();

        holder = getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        recorder = new MediaRecorder();
        recorder.setCamera(camera);
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
        recorder.setOutputFile(getVideoFolder()+rnd.nextString()+".mp4");
        recorder.setPreviewDisplay(holder.getSurface());
        //Tags the video with a 90° angle in order to tell the phone how to display it
        recorder.setOrientationHint(90);

        if (recorder != null) {
            try {
                recorder.prepare();
            } catch (IllegalStateException e) {
                Log.e("IllegalStateException", e.toString());
            } catch (IOException e) {
                Log.e("IOException", e.toString());
            }
        }

        recorder.start();

Hope it helps ;-)