バックグラウンド:
rtmp://
Android の MediaCodec を FFmpeg に接続して、コンテナー経由の出力など、MediaMuxer でサポートされていないさまざまな形式を多重化しました.flv
。このようなストリーミング マルチプレクサは、パケット処理ステップでネットワーク I/O を実行する可能性があるため、MediaCodec の出力バッファの予測不可能な長い所有権を必要とします。ビデオ ストリームには、Surface 入力用に構成された MediaCodec を使用しています。エンコーディングから多重化を分離するために、MediaCodec の ByteBuffer 出力バッファーを、Handler を介してマルチプレクサーにキューに入れます。
.flv
rtmpエンドポイントではなく、出力をファイルに多重化すると、すべてがうまく機能します。
問題:
エンドポイントに多重化すると、ストリーミング アプリケーションが への呼び出しを一度に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 のコピーをリサイクルします。これにより、割り当て数が制限されます。