2

バックグラウンド:

rtmp://Android の MediaCodec を FFmpeg に接続して、コンテナー経由の出力など、MediaMuxer でサポートされていないさまざまな形式を多重化しました.flv。このようなストリーミング マルチプレクサは、パケット処理ステップでネットワーク I/O を実行する可能性があるため、MediaCodec の出力バッファの予測不可能な長い所有権を必要とします。ビデオ ストリームには、Surface 入力用に構成された MediaCodec を使用しています。エンコーディングから多重化を分離するために、MediaCodec の ByteBuffer 出力バッファーを、Handler を介してマルチプレクサーにキューに入れます。

.flvrtmpエンドポイントではなく、出力をファイルに多重化すると、すべてがうまく機能します。

問題:

エンドポイントに多重化すると、ストリーミング アプリケーションが への呼び出しを一度にrtmp://...ブロックし始めることに気付きます。MediaCodec は 4 つの出力バッファーのみにロックされているように見えるため、多重化キューにいくつかの MediaCodec 出力バッファーを保持しています。eglSwapBuffers(mEGLDisplay, mEncodingEGLSurface)dequeueOutputBuffer()

によって返されたすべてのエンコーダー出力をコピーしMediaCodec#dequeueOutputBuffersてすぐに呼び出すことを避けるためのトリックはありreleaseOutputBuffer(...)ますか?

私のプロジェクトの完全なソースはGithubで入手できます。具体的には、次を参照してください。

  • AndroidEncoder.java : オーディオ エンコーダーとビデオ エンコーダーの間で動作を共有する抽象エンコーダー クラス: 主に、drainEncoder()。インスタンスにデータを書き込みMuxerます。
  • FFmpegMuxer.java : 実装Muxer
  • CameraEncoder.java . ビデオ エンコーディング用に構成された AndroidEncoder サブクラスにカメラ フレームを送信します。

シストレース

シストレース出力

これは、720p @ 2Mbps のビデオを Zencoder にストリーミングする systrace 出力です。

解決済み

MediaCodec エンコーダーの出力 ByteBuffers が利用可能になったらすぐにコピーして解放することで、パフォーマンスに大きな影響を与えることなく問題を解決できます。ArrayDeque<ByteBuffer>各マルチプレクサ トラックでByteBuffer のコピーをリサイクルします。これにより、割り当て数が制限されます。

4

1 に答える 1

3

残念ながら、この種の使用例は、ほとんどの Android フォンではサポートされていません。MediaCodec は、コーデック ベンダーがデバイスで使用する OMX IL API を抽象化したものにすぎません。ベンダー コーデックは、特定の構成に対して一定数の入力および出力バッファを必要とします。

理論的には、エンコーダーでキューに入れられた 1 つの出力バッファーで十分ですが、多くの場合、エンコードのパフォーマンスが低下するため、ベンダーのコーデックではこれがサポートされていません。したがって、コーデックが停止します。これは、入力バッファではさらに一般的です。

MediaCodec インスタンスに割り当てられる入出力バッファの数をアプリケーションで制御することはできません。Android は、メモリを節約するために、必要な最小数のバッファを割り当てようとします。したがって、唯一のオプションは、出力バッファーをコピーすることです。これは理想的ではありませんが、エンコードされたバッファはかなり小さい傾向があります。

于 2014-02-12T18:30:23.093 に答える