Android Camera 2 Api

2020-05-17 05:39发布

问题:

I have been trying camera2 API. I have downloaded code from

https://developer.android.com/samples/Camera2Video/index.html to learn about how it works. It works fine till I stop recording. When I stop recording it runs following code.

 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();

at mMediaRecorder.stop(); it throw following error

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)

Any Idea what I am doing wrong. I spent few hours but couldn't find any solution.

Edit - I am using geneymotion emulator. The path I am using

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

Thanks

回答1:

My solution is to change void stopRecordingVideo() as following:

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();

}

Key is:

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


回答2:

        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();
    }

this is working for me.



回答3:

After calling mMediaRecorder.stop() an IllegalStateException is always thrown. I've noticed that on devices with INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY the CameraDevice changes status to error, immediately calling onError() in the CameraDevice.StateCallback.

In the sample you referenced, onError() closes the camera and finishes the activity, so just change onError() to re-open the camera, like this:

@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());
}

It'd also be a good idea to put some check in there to make sure that if an error really did happen, that the commented out code gets called instead of entering a loop of trying to open the camera over and over.

Tested on a Moto G 2nd gen, with Android 5.0.2



回答4:

It depends on what you are doing with the CameraCaptureSession and the MediaRecorder but when you call mMediaRecorder.stop() I think it is destroying the surface used for the camera preview session which causes this error because the documentation says

Once recording is stopped, you will have to configure it again as if it has just been constructed

Therefore if you call PreviewSession.abortCaptures() (mPreviewSession.stopRepeating(); isn't necessary from what I gather) it stops the camera sending output to the recorder surface which will allow you to stop the MediaRecorder without issue.

PreviewSession.abortCaptures(); doesn't instantly stop the camera preview output so you might find you need to call MediaRecorder.stop() in the onClosed() or onReady() method of the CameraCaptureSession.StateCallback



回答5:

In my case, I use TimerTask and a Handler. There is error direct to the mMediaRecorder.stop(). So I use this method

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();
        }