2013-11-26 38 views
10

我正在製作一個視頻編碼應用程序,當主持人活動進入後臺或屏幕循環關閉/打開時,我想阻止該應用程序停止。具有表面輸入的MediaCodec:在後臺錄製

我的編碼器的體系結構來源於優秀的CameraToMpegTest示例,並在GLSurfaceView中添加了相機框架(請參閱下面的Github鏈接)。我目前執行的背景與雙態溶液記錄:

  • 當託管活動是在前臺,在每個呼叫中​​的一個視頻幀進行編碼的GLSurfaceView.Renderer的。這允許我以突發方式訪問GLSurfaceView的EGL狀態,以免阻塞其他排隊到渲染器線程的事件。

  • 當主機活動進入後臺時,停止編碼並在循環內的另一後臺線程上對幀進行編碼。該模式與CameraToMpegTest示例相同。

然而如果屏幕斷電的GLSurfaceView的EGLContext丟失和onSurfaceCreated新呼叫發生。在這種情況下,我們必須重新創建連接到MediaCodec輸入曲面的EGL窗口表面。不幸的是,以eglCreateWindowSurface這第二個呼叫生產:

E/libEGL(18839): EGLNativeWindowType 0x7a931098 already connected to another API 

之前要調用,我release all EGL resources connected to the Android Surface

有沒有辦法交換連接到MediaCodec輸入表面的EGLSurface?

我的測試應用程序的完整源代碼是GithubMain Activity

更新我將這裏學到的經驗應用於基於MediaCodec & MediaMuxer類的video sdk for Android。希望能幫助到你!

+1

'MediaCodec'不應該受背景影響(甚至不知道)。見例如在Android 4.4中添加了'screenrecord'命令,該命令在後臺快樂地運行。事實上,它的編碼*任何*意味着它仍然接收輸入數據,somy猜測會有什麼影響'相機'。我不明白爲什麼當預覽'byte []'有實際的數據時,預覽'Surface'是空白的。 – fadden

+0

更新了我的問題。我現在可以轉換到後臺錄製(沒有GLSurfaceView顯示),然後前景錄製(GLSurfaceView顯示)**除了**當屏幕關閉/開啓事件發生在臨時... – dbro

+0

你錯過了一個'glSurfaceView .onPause()'在你的主要活動onPause()中。不知道這是否會影響。我明天可以玩一下,看看我能否複製這種行爲。 – fadden

回答

9

背景第一... ...

當你調用eglCreateWindowSurface(),Android的EGL wrapper電話native_window_api_connect()Surface你過去了。這最終變成了BufferQueue製片連接通話,這意味着該EGL表面現在是唯一的Surface的圖形緩衝區的來源。

EGL表面保持連接到Surface,直到EGL表面被破壞。如果是,則​​調用native_window_api_disconnect()將EGL曲面從BufferQueue斷開。東瀛表面是引用計數的,與當表面傳遞到eglMakeCurrent()這樣被摧毀兩件事情必須發生遞增引用計數:

  1. eglDestroySurface()必須調用
  2. 東瀛面不能是「當前」在任何線程

第二項需要調用eglMakeCurrent()與另一EGL表面(或EGL_NO_SURFACE),或主叫eglReleaseThread(),對先前使用的表面的任何線程。確認這一點的一個快速方法是在表面變爲當前和未變化時,在調用eglMakeCurrent()之前添加日誌記錄,並通過查看logcat輸出與adb logcat -v threadtime來比較線程ID。使用諸如eglGetCurrentSurface(EGL_DRAW)之類的EGL查詢來確認您正在執行使表面最新的線程中的非當前狀態也可能很有用。

如果EGL表面沒有被破壞,它將不會與Surface斷開連接,並且嘗試連接新生產者(通過調用eglCreateWindowSurface以新的EGL表面)將被「已連接」消息拒絕。

更新:我的實施現已在Grafika test project中可用。如果你安裝了這個軟件,選擇「顯示+捕獲攝像頭」,開始錄製,切換電源,然後停止錄製,你應該有一個完整的電影在中間很長的停頓。您可以退出,選擇「播放視頻」,然後選擇「camera-test.mp4」進行查看。

+1

尤里卡! Grafika很漂亮。看到所有移動的部件正確模塊化使我的蠟筆和膠水的工藝氣味。 – dbro

+0

@fadden 在ContinuousCaptureActivity.java(https://github.com/google/grafika/blob/master/src/com/android/grafika/ContinuousCaptureActivity.java)中,當onPause時,首先釋放mDisplaySurface,然後釋放mEglCore。 mDisplaySurface.release()將終於調用EGL14.eglDestroySurface,但在那一刻,您並未確認「當前」問題。 eglDestroySurface會成功嗎? – dragonfly

+0

我不確定你的意思是「沒有確認'當前'問題」。正如答案中指出的那樣,資源是參考計數的;正在增加額外的參考。所以當'eglDestroySurface()'被調用時*表面被拋棄,*不再是當前表面。 *有一個與此代碼相關的錯誤 - https://github.com/google/grafika/issues/24 - 但這更多關於我在'onResume()'中做的失敗。 – fadden