Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Video display is garbled when recording on Galaxy S3

I'm writing a camera app and am having an issue with the S3. Whenever I start recording, the display goes to garbage (see screenshots below). Then, when I stop recording I get an exception:

10-02 13:36:31.647: E/MediaRecorder(24283): stop failed: -1007
10-02 13:36:31.647: D/AndroidRuntime(24283): Shutting down VM
10-02 13:36:31.647: W/dalvikvm(24283): threadid=1: thread exiting with uncaught exception (group=0x40c49a68)
10-02 13:36:31.647: E/AndroidRuntime(24283): FATAL EXCEPTION: main
10-02 13:36:31.647: E/AndroidRuntime(24283): java.lang.RuntimeException: stop failed.
10-02 13:36:31.647: E/AndroidRuntime(24283):    at android.media.MediaRecorder.native_stop(Native Method)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at android.media.MediaRecorder.stop(MediaRecorder.java:742)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at com.myapp.android.ui.camera.NewCameraActivity.stopRecording(NewCameraActivity.java:178)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at com.myapp.android.ui.camera.NewCameraActivity.toggleRecording(NewCameraActivity.java:189)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at com.myapp.android.ui.camera.NewCameraActivity.onClick(NewCameraActivity.java:97)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at android.view.View.performClick(View.java:3565)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at android.view.View$PerformClick.run(View.java:14165)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at android.os.Handler.handleCallback(Handler.java:605)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at android.os.Handler.dispatchMessage(Handler.java:92)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at android.os.Looper.loop(Looper.java:137)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at android.app.ActivityThread.main(ActivityThread.java:4514)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at java.lang.reflect.Method.invokeNative(Native Method)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at java.lang.reflect.Method.invoke(Method.java:511)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:980)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:747)
10-02 13:36:31.647: E/AndroidRuntime(24283):    at dalvik.system.NativeStart.main(Native Method)

I've tested my app on the Galaxy Nexus (4.1), Galaxy S2, Nexus S, and Galaxy Tab 10.1. All of them work fine. I've followed development guidelines for video recording. I don't understand why this device is so different from the others. Here's what I'm seeing on the device. First picture is before I start recording. Second picture is what happens once I start recording.

Before I've started recording

After I start recording

Here's my code for preparing and starting the MediaRecorder object:

@Override
public void onClick( View v ) {

    switch (v.getId()) {
        case R.id.camera_action_ImageView:
            int mode = getMode();
            if ( mode == MODE_PHOTO ) {
                focusThenTakePicture();
            }
            else if ( mode == MODE_VIDEO ) {
                toggleRecording();
            }
            break;
    }
}

private void startRecording() {

    if ( prepareRecorder() ) {
        getRecorder().start();
        setRecording( true );
    }
}

@TargetApi( 9 )
private boolean prepareRecorder() {

    Camera camera = getCamera();
    camera.unlock();

    MediaRecorder recorder = new MediaRecorder();
    setRecorder( recorder );
    recorder.setCamera( camera );
    recorder.setAudioSource( MediaRecorder.AudioSource.CAMCORDER );
    recorder.setVideoSource( MediaRecorder.VideoSource.CAMERA );

    CamcorderProfile profile;
    if ( Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD ) {
        profile = CamcorderProfile.get( CamcorderProfile.QUALITY_HIGH );
    }
    else {
        profile = CamcorderProfile.get( getCameraId(), CamcorderProfile.QUALITY_HIGH );
    }
    recorder.setProfile( profile );

    File outputFile = LocalMediaUtil.getOutputMediaFile( LocalMediaUtil.MEDIA_TYPE_VIDEO );
    setRecorderOutputFile( outputFile );
    recorder.setOutputFile( outputFile.toString() );
    recorder.setPreviewDisplay( getPreview().getHolder().getSurface() );

    try {
        recorder.prepare();
    }
    catch (Exception e) {
        camera.lock();
        setRecorder( null );
        return false;
    }

    return true;
}

private void stopRecording() {

    MediaRecorder recorder = getRecorder();
    recorder.stop();
    releaseRecorder();
    setRecording( false );

    LocalMediaUtil.scanMedia( this, getRecorderOutputFile().toString(), 90 );
    setRecorderOutputFile( null );
}

private void toggleRecording() {

    if ( isRecording() ) {
        stopRecording();
    }
    else {
        startRecording();
    }
}

private void releaseRecorder() {

    MediaRecorder recorder = getRecorder();
    if ( recorder != null ) {

        recorder.reset();
        recorder.release();
        setRecorder( null );

        getCamera().lock();
    }
}

Edit: So this has something to do with the CamcorderProfile being set. I change it to CamcorderProfile.QUALITY_LOW and it worked fine. So how can I have high resolution video without garbled output?

Edit2: So with CamcorderProfile.QUALITY_LOW set, I get no errors using the video recorder. However, the output video looks very similar the garbled screenshot posted above. So what gives?

like image 504
Jason Robinson Avatar asked Oct 02 '12 18:10

Jason Robinson


2 Answers

I had a similar problem, and finally figured out it was due to sharing the preview surface between the camera and the media recorder (I'm not sure this is actually the underlying cause, but from the API calls it appears that way).

I'm assuming you have already opened the camera and attached a preview display to it, if so try inserting the following lines at the top of your prepareRecorder method:

Camera camera = getCamera();
camera.stopPreview();
camera.lock();
camera.release();

camera = Camera.open();
camera.unlock();

You might also need to reassign the camera local to the field hidden behind getCamera(), unfortunately I can't tell how you've implemented it with the given code snippet.

Hope this helps.

like image 114
Stuart Ervine Avatar answered Nov 30 '22 09:11

Stuart Ervine


I had a similar problem with an Samsung Note. My problem was that the preview was set in a resolution, and the recording was set in another bigger resolution (resolution which was not supported by my phone), and this is why it looked like that. You should try:

recorder.setVideoSize(320, 240);

If it works, then it means your initial resolution was not supported/

like image 29
rosu alin Avatar answered Nov 30 '22 10:11

rosu alin