2014-02-11 103 views
2

背景:擴展客戶所有權

我已經連接Android的MediaCodec到FFmpeg的路複用爲各種格式不被支持MediaMuxer,包括通過.flv容器rtmp://輸出。這樣的流式複用器需要MediaCodec輸出緩衝器的更長,不可預知的所有權,因爲它們可以在任何數據包處理步驟上執行聯網I/O。對於我的視頻流,我使用配置爲Surface輸入的MediaCodec。爲了將多路複用與編碼分離,我通過一個Handler將MediaCodec的ByteBuffer輸出緩衝區排隊到我的muxer。

如果我將.flv輸出複合到文件而非rtmp端點,所有的工作都非常出色。

問題:

當合併到rtmp://...端點我發現我流應用始於上dequeueOutputBuffer()呼籲eglSwapBuffers(mEGLDisplay, mEncodingEGLSurface)阻止一次,我保留我的複用隊列甚至幾MediaCodec輸出緩衝器作爲MediaCodec似乎只能鎖定到4個輸出緩衝區。

任何技巧,以避免複製所有編碼器輸出MediaCodec#dequeueOutputBuffers返回並立即呼籲releaseOutputBuffer(...)

我的項目的完整源代碼可在Github。具體而言,請參閱:

  • AndroidEncoder.java:主要drainEncoder():與音頻和視頻編碼器之間共享行爲摘要編碼器類。將數據寫入Muxer實例。
  • FFmpegMuxer.java:實現Muxer
  • CameraEncoder.java。將相機幀發送到爲視頻編碼配置的AndroidEncoder子類。

Systrace

Systrace output

下面是一些systrace輸出流的720p @ 2Mbps的視頻Zencoder。

解決

複製然後釋放MediaCodec編碼器輸出的ByteBuffers只要他們有空來解決問題,而顯著影響性能。我爲每個複用器軌道回收了ArrayDeque<ByteBuffer>中的ByteBuffer副本,這限制了分配的數量。

回答

3

不幸的是,這種用例大多數Android手機都不支持。 MediaCodec只是設備上編解碼器供應商使用的OMX IL API的抽象。對於給定的配置,供應商編解碼器需要一定數量的輸入和輸出緩衝區。

雖然在理論上,有一個輸出緩衝區與編碼器排隊應該足夠了,很多次這不是供應商編解碼器支持,因爲它導致較低的編碼性能;因此編解碼器失速。這在輸入緩衝區中更爲普遍。

沒有應用程序控制爲MediaCodec實例分配的輸入/輸出緩衝區的數量 - Android嘗試分配所需的最小緩衝區數量,以節省內存。因此,您唯一的選擇是複製輸出緩衝區。雖然這並不理想,但編碼緩衝區往往相當小。

+0

感謝您的徹底解答! – dbro