2013-09-30 22 views
6

我試圖通過MediaCodec.createInputSurface()從CameraPreview數據生成短序列mp4文件。但是,重新創建MediaCodec及其關聯的Surface需要停止攝像機以允許對mCamera.setPreviewTexture(...)的另一個呼叫。這種延遲會導致不可接受的丟幀數量。帶有表面輸入的MediaCodec:生成分塊輸出

因此,我需要定期生成CODEC_CONFIGEND_OF_STREAM數據,而不重新創建輸入曲面,因此必須調用mCamera.setPreviewTexture(...)。假設MediaFormat保持不變,這可能嗎?

(我適應法登的CameraToMpegTest例如我的完整代碼是here。)

不成功的嘗試:

調用MediaCodec.signalEndOfInputStream(),引流MediaCodec,然後調用塊之間MediaCodec.flush()上產生IllegalStateException第二次致電MediaCodec.signalEndOfInputStream()

調用MediaCodec.signalEndOfInputStream(),引流MediaCodec,然後調用塊之間MediaCodec.stop(); MediaCodec.configure(...), MediaCodec.start()不會再次調用MediaCodec.createInputSurface()產生以下錯誤:

09-30 13:12:49.889 17638-17719/x.xx.xxxx E/Surface﹕ queueBuffer: error queuing buffer to SurfaceTexture, -19 
09-30 13:12:49.889 17638-17719/x.xx.xxxx E/IMGSRV﹕ :0: UnlockPostBuffer: Failed to queue buffer 0x592e1e70 
09-30 13:12:49.889 17638-17719/x.xx.xxxx E/CameraToMpegTest﹕ Encoding loop exception! 
09-30 13:12:49.889 17638-17719/x.xx.xxxx W/System.err﹕ java.lang.RuntimeException: eglSwapBuffers: EGL error: 0x300b 
09-30 13:12:49.896 17638-17719/x.xx.xxxx W/System.err﹕ at x.xx.xxxx.ChunkedHWRecorder$CodecInputSurface.checkEglError(ChunkedHWRecorder.java:731) 
09-30 13:12:49.896 17638-17719/x.xx.xxxx W/System.err﹕ at x.xx.xxxx.ChunkedHWRecorder$CodecInputSurface.swapBuffers(ChunkedHWRecorder.java:713) 
09-30 13:12:49.896 17638-17719/x.xx.xxxx W/System.err﹕ at x.xx.xxxx.ChunkedHWRecorder.startRecording(ChunkedHWRecorder.java:164) 
09-30 13:12:49.896 17638-17719/x.xx.xxxx W/System.err﹕ at x.xx.xxxx.HWRecorderActivity$CameraToMpegWrapper.run(HWRecorderActivity.java:76) 
09-30 13:12:49.896 17638-17719/x.xx.xxxx W/System.err﹕ at java.lang.Thread.run(Thread.java:841) 

法登解決感謝。完整的解決方案來源是here

回答

8

signalEndOfInputStream()調用更新MediaCodec堆棧中各個層的狀態。您可以從MediaCodecTest中的測試上面的註釋中瞭解什麼操作是有效的,但總體而言,MediaCodec的行爲根本不定義爲「非常規」用途。

所以你必須看看代碼。輸入表面的壽命與OMXNodeInstance的壽命相關;它代表GraphicBufferSource。一旦發出EOS信號,GraphicBufferSource將忽略其他幀(請參見line 426)。如果不拆除GraphicBufferSource,則無法重置EOS標誌,但是當您這樣做時,它將斷開Surface底層的緩衝隊列。

所以我不認爲你將能夠停止/重新啓動MediaCodec並繼續使用Surface。

但是......你不需要。 CameraToMpegTest將相機預覽路由到SurfaceTexture,然後使用GLES將紋理渲染到編碼器的輸入表面。 SurfaceTexture與編碼器分離,不需要改變。我認爲需要改變的是CodecInputSurface,它使用MediaCodec中的Surface調用eglCreateWindowSurface()來告訴GLES在哪裏繪製。如果你在那裏添加一個新的「更新Surface」API(銷燬舊的EGLSurface,創建新的EGLSurface,eglMakeCurrent),並且每當啓動一個新的MediaCodec時調用它,我會認爲它只會工作。

更新,以解決意見

,你只能改變EGLSurface是很重要的。 GLConsumer.cpp中的checkAndUpdateEglStateLocked()函數會檢查以確保EGLDisplayEGLContext設置後不會更改。您不能在CodecInputSurface中調用release()/eglSetup(),因爲它會更改EGLContext。你只是想摧毀並重新創建EGLSurface

+0

謝謝噸! 'CodecInputSurface.updateSurface(newSurface)'做'release(); mSurface = newSurface; eglSetup();'。然後我調用'mMediaCodec.start(); mInputSurface.makeCurrent(); STextureRender.surfaceCreated();'。在下一次調用'SurfaceTexture.updateTexImage()'時,我得到'E/GLConsumer:checkAndUpdateEglState:無效的當前EGLContext'。有任何想法嗎? [簡而言之](http://pastebin.com/znwvz6wB)。 [完整代碼](https://github.com/OnlyInAmerica/HWEncoderExperiments/blob/chunked2/HWEncoderExperiments/src/main/java/net/openwatch/hwencoderexperiments/ChunkedHWRecorder.java)。我會繼續努力的。 – dbro

+1

答覆已更新。 – fadden

+1

我需要給你買一瓶啤酒。在每次調用「CodecInputSurface.updateSurface(newSurface)'後,我還必須將我的調用移除到'STextureRender.surfaceCreated()'。 – dbro