Video display is garbled when recording on Galaxy

2020-07-16 10:39发布

问题:

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.

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?

回答1:

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.



回答2:

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/



回答3:

This is because preview resolution and Mediarecorder resolutions are different (and they can be different depending on the device, but on some devices it seems to cause an issue).

Check the Android camera app, it does not stop the preview and then start recording (you can check this by keeping the flash on, if you stop the preview and then start recording the flash will turn off and then on again, whereas in the Android camera app that does not happen).

The "accepted" answer here only works because the camera releases the preview surface and mediarecorder can then adjust the resolution to one of the mediarecorder resolutions, but it is not technically correct.