Android相机2 API

23

我一直在尝试使用相机2 API。我已经从https://developer.android.com/samples/Camera2Video/index.html下载了代码,以了解它的工作原理。录制时一切都正常。但是当我停止录制时,它会运行以下代码。

 private void stopRecordingVideo() {
        // UI
        mIsRecordingVideo = false;
        mBtn_Video.setText(R.string.record);
        // Stop recording
        try {
            mMediaRecorder.stop();
            mMediaRecorder.reset();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        Activity activity = getActivity();
        if (null != activity) {
            System.out.println("file " +  getVideoFile(activity));
            Toast.makeText(activity, "Video saved: " + getVideoFile(activity),
                    Toast.LENGTH_SHORT).show();
        }
        startPreview();

在mMediaRecorder.stop()的时候,它会抛出以下错误

01-12 16:24:23.115    2161-2200/com.cameratwoapi E/Surface﹕ queueBuffer: error queuing buffer to SurfaceTexture, -19
01-12 16:24:23.135    2161-2200/com.cameratwoapi E/EGL_emulation﹕ tid 2200: swapBuffers(285): error 0x3003 (EGL_BAD_ALLOC)
01-12 16:24:23.197    2161-2200/com.cameratwoapi E/CameraDeviceGLThread-0﹕ Received exception on GL render thread:
    java.lang.IllegalStateException: swapBuffers: EGL error: 0x3003
            at android.hardware.camera2.legacy.SurfaceTextureRenderer.checkEglError(SurfaceTextureRenderer.java:487)
            at android.hardware.camera2.legacy.SurfaceTextureRenderer.swapBuffers(SurfaceTextureRenderer.java:480)
            at android.hardware.camera2.legacy.SurfaceTextureRenderer.drawIntoSurfaces(SurfaceTextureRenderer.java:681)
            at android.hardware.camera2.legacy.GLThreadManager$1.handleMessage(GLThreadManager.java:103)
            at android.os.Handler.dispatchMessage(Handler.java:98)
            at android.os.Looper.loop(Looper.java:135)
            at android.os.HandlerThread.run(HandlerThread.java:61)

有没有想法我做错了什么,我花了几个小时但是找不到任何解决方案。

编辑 - 我正在使用geneymotion模拟器。 我使用的路径为

文件 /storage/emulated/0/Android/data/com.gold.cameratwoapi/files/video.mp4

谢谢


EGL错误0x3003是指“Bad alloc”。内存中发生了一些错误。 - shkschneider
你尝试在实际设备上运行应用程序了吗?过去我曾在模拟器上尝试保存文件时遇到问题,即使是允许的。 - Willis
@Willis,我没有API 21的设备。 - user1154390
如果我说错了,希望有人纠正我,但问题可能与尝试调用不存在的硬件相关。我的意思是,我认为你不能可靠地使用基于硬件的API,如Camera2或其他API,而没有实际的硬件。 - Willis
2
我使用 Nexus 7(硬件)- 我遇到了这个错误。 - Puzirki
显示剩余2条评论
5个回答

30

我的解决方案是将void stopRecordingVideo()更改为以下内容:

private void stopRecordingVideo() {
// UI
mIsRecordingVideo = false;
mButtonVideo.setText(R.string.record);
// Added by Ben Ning, to resolve exception issue when stop recording.
try {
    mPreviewSession.stopRepeating();
    mPreviewSession.abortCaptures();
} catch (CameraAccessException e) {
    e.printStackTrace();
} 

// Stop recording
mMediaRecorder.stop();
mMediaRecorder.reset();

关键是:

    try {
    mPreviewSession.stopRepeating();
    mPreviewSession.abortCaptures();
} catch (CameraAccessException e) {
    e.printStackTrace();
} 

1
它在我的项目上运行良好,但您能否更详细地解释为什么在关闭录制器之前必须停止预览两次? - fxp

6
        private void stopRecordingVideo() {
// UI
        mIsRecordingVideo = false;
        mButtonVideo.setText(R.string.record);
// Added by Ben Ning, to resolve exception issue when stop recording.
        try {
            mPreviewSession.stopRepeating();
            mPreviewSession.abortCaptures();
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }

// Stop recording
        mMediaRecorder.stop();
        mMediaRecorder.reset();

        Activity activity = getActivity();
        if (null != activity) {
            Toast.makeText(activity, "Video saved: " + getVideoFile(activity),
                    Toast.LENGTH_SHORT).show();
        }
        startPreview();
    }

这对我来说是有效的。


4
调用mMediaRecorder.stop()后,总是会抛出一个IllegalStateException。我注意到,在具有INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY的设备上,CameraDevice 的状态会变成错误,并立即调用CameraDevice.StateCallback中的onError()
在您参考的示例中,onError()关闭了摄像头并完成了活动,因此只需将onError()更改为重新打开相机,如下所示:
@Override
public void onError(CameraDevice cameraDevice, int error) {
    // mCameraOpenCloseLock.release();
    // cameraDevice.close();
    // mCameraDevice = null;
    // Activity activity = getActivity();
    // if (null != activity) {
    //  activity.finish();
    // }

    closeCamera();
    openCamera(mTextureView.getWidth(), mTextureView.getHeight());
}

最好加入一些检查机制,以确保如果真的发生错误,则调用注释掉的代码而不是重复尝试打开相机。

在Moto G第二代上测试过,使用的是Android 5.0.2。


0

这取决于您对CameraCaptureSession和MediaRecorder的使用方式,但是当您调用mMediaRecorder.stop()时,我认为它会销毁用于相机预览会话的表面,因为文档中说:

一旦停止录制,您将不得不再次配置它,就像刚刚构建一样

因此,如果您调用PreviewSession.abortCaptures()(根据我的理解,不需要mPreviewSession.stopRepeating();),它会停止相机向记录器表面发送输出,这将允许您无问题地停止MediaRecorder。

PreviewSession.abortCaptures();不会立即停止相机预览输出,因此您可能需要在CameraCaptureSession.StateCallbackonClosed()onReady()方法中调用MediaRecorder.stop()


0
在我的情况下,我使用了 TimerTask 和一个 Handler。在 mMediaRecorder.stop() 的地方出现了错误。因此,我采用了这种方法。
final Handler mTimerHandler = new Handler(Looper.getMainLooper());

        mIsRecordingVideo = false;
        // Stop recording
        try {
            mPreviewSession.stopRepeating();
            mPreviewSession.abortCaptures();
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        try{
            Timer timer = new Timer();
            TimerTask timerTask = new TimerTask() {
                @Override
                public void run() {
                    mTimerHandler.post(new Runnable() {
                        @Override
                        public void run() {

                            mMediaRecorder.stop();
                            mMediaRecorder.reset();
                        }

                    });
                }
            };
            timer.schedule(timerTask,30);
        }catch(RuntimeException e){
            Log.e("----------------","---->>>>>>>>>"+e);
            e.printStackTrace();
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接