1. 程式人生 > >官方Android Camera2 video Demo崩潰的修正

官方Android Camera2 video Demo崩潰的修正

  最近在做關於視訊(YUV<–>h264)、camera、camera2相關的專案。
  首先要贊一下camera2,設計的非常良心。1920*1080的解析度下幀率依然能保持30fps。接下來就只剩下吐槽了。
  花了整整一天的時間做了camera2的在一個介面上錄影+拍照的app。唯一的感受就是坑太多!
  接下來,步入正題。官方demo,總會在stopRecording()這裡崩潰。甚至底層的camera服務崩潰,到了“除了重啟別無他法”的境地。稍微理了一下,這個問題還是對資料流向不清楚的緣故,也許是最近被camera2+mediaCodec虐的體無完膚才能看到這一點吧。當然不排除官方大牛故意在這裡埋個flag,好讓大家都對camera2映像深刻吧!
  由於專案緊的原因,先寫這麼多。當然,我是在已經寫好了app的情況下才考慮在這裡說一下。看了不少相關的解決辦法,要麼是在onError()裡重新初始化相機,要麼就直接finish當前activity,讓人感覺不務實求真。
  Error資訊:
  

E/CameraCaptureSession: Session 1: Exception while stopping repeating: 
                                                                                      android.hardware.camera2.CameraAccessException: The camera device has encountered a serious error
                                                                                          at android.hardware
.camera2.impl.CameraDeviceImpl.checkIfCameraClosedOrInError(CameraDeviceImpl.java:1478) at android.hardware.camera2.impl.CameraDeviceImpl.stopRepeating(CameraDeviceImpl.java:677) at android.hardware
.camera2.impl.CameraCaptureSessionImpl.close(CameraCaptureSessionImpl.java:328) at com.example.android.camera2video.Camera2VideoFragment.closePreviewSession(Camera2VideoFragment.java:674) at com.example.android.camera2video.Camera2VideoFragment.startPreview(Camera2VideoFragment.java:491) at com.example.android.camera2video.Camera2VideoFragment.stopRecordingVideo(Camera2VideoFragment.java:687) at com.example.android.camera2video.Camera2VideoFragment.onClick(Camera2VideoFragment.java:313) at android.view.View.performClick(View.java:4909) at android.view.View$PerformClick.run(View.java:20390) at android.os.Handler.handleCallback(Handler.java:815) at android.os.Handler.dispatchMessage(Handler.java:104) at android.os.Looper.loop(Looper.java:194) at android.app.ActivityThread.main(ActivityThread.java:5848) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815) 05-16 13:44:29.576 8036-8036/com.example.android.camera2video W/System.err: android.hardware.camera2.CameraAccessException: The camera device has encountered a serious error 05-16 13:44:29.576 8036-8036/com.example.android.camera2video W/System.err: at android.hardware.camera2.impl.CameraDeviceImpl.checkIfCameraClosedOrInError(CameraDeviceImpl.java:1478) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at android.hardware.camera2.impl.CameraDeviceImpl.createCaptureRequest(CameraDeviceImpl.java:476) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at com.example.android.camera2video.Camera2VideoFragment.startPreview(Camera2VideoFragment.java:495) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at com.example.android.camera2video.Camera2VideoFragment.stopRecordingVideo(Camera2VideoFragment.java:687) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at com.example.android.camera2video.Camera2VideoFragment.onClick(Camera2VideoFragment.java:313) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at android.view.View.performClick(View.java:4909) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at android.view.View$PerformClick.run(View.java:20390) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at android.os.Handler.handleCallback(Handler.java:815) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at android.os.Handler.dispatchMessage(Handler.java:104) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at android.os.Looper.loop(Looper.java:194) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5848) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at java.lang.reflect.Method.invoke(Native Method) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at java.lang.reflect.Method.invoke(Method.java:372) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020) 05-16 13:44:29.577 8036-8036/com.example.android.camera2video W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815) 05-16 13:44:33.518 8036-8092/com.example.android.camera2video E/RequestThread-0: Timed out while waiting for request to complete. 05-16 13:44:33.519 8036-8092/com.example.android.camera2video W/CaptureCollector: Preview buffers dropped for request: 1 05-16 13:44:33.519 8036-8092/com.example.android.camera2video E/CameraDeviceState: Cannot receive result while in state: 0 05-16 13:44:33.519 8036-8092/com.example.android.camera2video E/CameraDeviceState: Cannot receive result while in state: 0 05-16 13:44:33.520 8036-8092/com.example.android.camera2video E/CameraDeviceState: Cannot receive result while in state: 0 05-16 13:44:33.542 8036-8098/com.example.android.camera2video W/MessageQueue: Handler (android.os.Handler) {e372429} sending message to a Handler on a dead thread java.lang.IllegalStateException: Handler (android.os.Handler) {e372429} sending message to a Handler on a dead thread at android.os.MessageQueue.enqueueMessage(MessageQueue.java:337) at android.os.Handler.enqueueMessage(Handler.java:707) at android.os.Handler.sendMessageAtTime(Handler.java:609) at android.os.Handler.sendMessageDelayed(Handler.java:579) at android.os.Handler.sendMessage(Handler.java:516) at android.hardware.camera2.legacy.GLThreadManager.queueNewFrame(GLThreadManager.java:197) at android.hardware.camera2.legacy.RequestThreadManager$4.onFrameAvailable(RequestThreadManager.java:260) at android.graphics.SurfaceTexture$1.handleMessage(SurfaceTexture.java:203) at android.os.Handler.dispatchMessage(Handler.java:111) at android.os.Looper.loop(Looper.java:194) at android.os.HandlerThread.run(HandlerThread.java:61) 05-16 13:44:33.550 8036-8115/com.example.android.camera2video E/BufferQueueProducer: [unnamed-8036-2](this:0xae51d800,id:2,api:4,p:289,c:-1) queueBuffer: BufferQueue has been abandoned 05-16 13:44:33.551 8036-8058/com.example.android.camera2video E/BufferQueueProducer: [unnamed-8036-2](this:0xae51d800,id:2,api:4,p:289,c:-1) dequeueBuffer: BufferQueue has been abandoned 05-16 13:44:33.747 8036-8057/com.example.android.camera2video E/BufferQueueProducer: [unnamed-8036-2](this:0xae51d800,id:2,api:4,p:289,c:-1) cancelBuffer: BufferQueue has been abandoned 05-16 13:44:33.748 8036-8115/com.example.android.camera2video E/BufferQueueProducer: [unnamed-8036-2](this:0xae51d800,id:2,api:4,p:289,c:-1) cancelBuffer: BufferQueue has been abandoned 05-16 13:44:33.749 8036-8058/com.example.android.camera2video E/BufferQueueProducer: [unnamed-8036-2](this:0xae51d800,id:2,api:4,p:289,c:-1) cancelBuffer: BufferQueue has been abandoned 05-16 13:44:33.749 8036-8057/com.example.android.camera2video E/BufferQueueProducer: [unnamed-8036-2](this:0xae51d800,id:2,api:4,p:289,c:-1) cancelBuffer: BufferQueue has been abandoned 05-16 13:44:33.750 8036-8115/com.example.android.camera2video E/BufferQueueProducer: [unnamed-8036-2](this:0xae51d800,id:2,api:4,p:289,c:-1) cancelBuffer: BufferQueue has been abandoned

  解決辦法:
  

private void stopRecordingVideo() {
        // UI
        mIsRecordingVideo = false;
        mButtonVideo.setText(R.string.record);
        //必須將這一句放置到MediaRecorder停止釋放的前面,
        //否則就會造成,接收資料方(Encoder)已經停止了,而傳送資料的session還在執行。才會造成以上錯誤。
        startPreview(); 
        // Stop recording
        mMediaRecorder.stop();
        mMediaRecorder.reset();

        Activity activity = getActivity();
        if (null != activity) {
            Toast.makeText(activity, "Video saved: " + mNextVideoAbsolutePath,
                    Toast.LENGTH_SHORT).show();
            Log.d(TAG, "Video saved: " + mNextVideoAbsolutePath);
        }
        mNextVideoAbsolutePath = null;
    }

這樣就能保證在stopRecordingVideo的時候不會崩潰了。
程式碼地址:Camara2-Video-Demo-fixed