1

openmax のコーデックを使用して Android ビデオ会議アプリを作成しようとしています。avc デコード用に OpenMAX IL を使用して対処したところ、空のバッファ コマンドを送信してからバッファ完了コールバックを埋めるまでに大きな遅延が発生することがわかりました。私のケースは、B スライスのない 4-cif h.264 エレメンタリ ストリームを扱っています。私のomxの呼び出しシーケンスは次のとおりです。

  1. avc デコーディング ロールの openmax ノードを割り当てます。
  2. ノードの状態をアイドル状態に遷移させます。
  3. ポート定義の構成。
  4. 入力ポートと出力ポートにバッファを割り当てます。
  5. ノードの状態を実行中に遷移させます。
  6. 空のバッファ用に 1 つのスレッドを開始し、フィル バッファ用に別のスレッドを開始します。

ログ出力は、8 フレームのレイテンシーがあることを示しています。空のバッファーから #9 コマンドが送信され、メッセージ FILL_BUFFER_DONE #1 が到着しました。samsung-note2、htc-one-x、およびその他の携帯電話でテストしましたが、すべてデコードの遅延が大きくなっています。

この遅延は、ビデオ会議アプリの受け入れには大きいです。この待ち時間を短縮するのに役立つ人はいますか?

ログ出力は次のようになります。


I/java:TestKdavc(19867): video test started
I/java:TestKdavc(19867): set video source: /sdcard/DCIM/vidrev.dat
I/testkdavc/testkdavc.cpp(19867): [start@331] frame dimesion: 704 x 576
I/OMXClient(19867): Using client-side OMX mux.
D/avc/omxctrl.cpp(19867): [InitNode@671] mComType = 1
D/avc/omxctrl.cpp(19867): [createNode@516] tid = 1074982704
D/avc/omxctrl.cpp(19867): [createNode@519] m_node = 4136a16c
D/avc/omxctrl.cpp(19867): [getVideoPortInfo@290] nPorts = 2, iport = 0, oport = 1
D/avc/omxctrl.cpp(19867): [createNode@549] mComType = 1, port = 0, info.nBufferCountActual = 5, info.nBufferSize = 50688, info.nBufferCountMin = 5
D/avc/omxctrl.cpp(19867): [createNode@582] mComType = 1, port = 1, info.nBufferCountActual = 2,  info.nBufferSize = 608256, info.nBufferCountMin = 2
D/avc/omxctrl.cpp(19867): [allocatePortBuffers@321] mComType = 1,  portIndex = 0, def.nBufferCountActual = 5, def.nBufferSize = 608256, def.nBufferCountMin = 5, buffersize = 608256
D/avc/omxctrl.cpp(19867): [allocatePortBuffers@340] before useBuffer
D/avc/omxctrl.cpp(19867): [allocatePortBuffers@340] before useBuffer
D/avc/omxctrl.cpp(19867): [allocatePortBuffers@340] before useBuffer
D/avc/omxctrl.cpp(19867): [allocatePortBuffers@340] before useBuffer
D/avc/omxctrl.cpp(19867): [allocatePortBuffers@340] before useBuffer
D/avc/omxctrl.cpp(19867): [allocatePortBuffers@321] mComType = 1,  portIndex = 1, def.nBufferCountActual = 2, def.nBufferSize = 608256, def.nBufferCountMin = 2, buffersize = 608256
D/avc/omxctrl.cpp(19867): [allocatePortBuffers@336] before allocateBufferWithBackup
D/avc/omxctrl.cpp(19867): [allocatePortBuffers@336] before allocateBufferWithBackup
D/avc/omxctrl.cpp(19867): [onMessage@96] mComType: 1, OMX_CommandStateSet, state: 2
I/avc/omxctrl.cpp(19867): [onMessage@131] message type: EVENT
D/avc/omxctrl.cpp(19867): [onMessage@96] mComType: 1, OMX_CommandStateSet, state: 3
I/avc/omxctrl.cpp(19867): [onMessage@131] message type: EVENT
D/avc/omxctrl.cpp(19867): [createNode@626] mComType = 1, m_vecOutputBuffers.size() = 2, err = 0
I/testkdavc/testkdavc.cpp(19867): [start@365] found AVC/H264 decoder: OMX.SEC.AVC.Decoder, color format: OMX_COLOR_FormatYUV420Planar
I/testkdavc/testkdavc.cpp(19867): [start@376] start feed
I/avc/omxctrl.cpp(19867): [PushData@489] empty buffer #1
I/avc/omxctrl.cpp(19867): [PushData@489] empty buffer #2
I/avc/omxctrl.cpp(19867): [PushData@489] empty buffer #3
I/avc/omxctrl.cpp(19867): [PushData@489] empty buffer #4
I/avc/omxctrl.cpp(19867): [PushData@489] empty buffer #5
I/avc/omxctrl.cpp(19867): [fillBufferThreadEntry@785] fill buffer #1
I/avc/omxctrl.cpp(19867): [fillBufferThreadEntry@785] fill buffer #2
I/avc/omxctrl.cpp(19867): [handleBufferMessage@159] message type: EMPTY_BUFFER_DONE #1
I/avc/omxctrl.cpp(19867): [PushData@489] empty buffer #6
I/avc/omxctrl.cpp(19867): [handleBufferMessage@159] message type: EMPTY_BUFFER_DONE #2
I/avc/omxctrl.cpp(19867): [PushData@489] empty buffer #7
I/avc/omxctrl.cpp(19867): [handleBufferMessage@159] message type: EMPTY_BUFFER_DONE #3
I/avc/omxctrl.cpp(19867): [PushData@489] empty buffer #8
I/avc/omxctrl.cpp(19867): [handleBufferMessage@159] message type: EMPTY_BUFFER_DONE #4
I/avc/omxctrl.cpp(19867): [PushData@489] empty buffer #9
I/avc/omxctrl.cpp(19867): [handleBufferMessage@189] message type: FILL_BUFFER_DONE #1
I/testkdavc/testkdavc.cpp(19867): [OnFrame@150] get frame #1 of 704 x 576
I/avc/omxctrl.cpp(19867): [handleBufferMessage@159] message type: EMPTY_BUFFER_DONE #5
I/avc/omxctrl.cpp(19867): [fillBufferThreadEntry@785] fill buffer #3
I/avc/omxctrl.cpp(19867): [PushData@489] empty buffer #10
I/avc/omxctrl.cpp(19867): [handleBufferMessage@189] message type: FILL_BUFFER_DONE #2
I/testkdavc/testkdavc.cpp(19867): [OnFrame@150] get frame #2 of 704 x 576
I/avc/omxctrl.cpp(19867): [handleBufferMessage@159] message type: EMPTY_BUFFER_DONE #6
I/testkdavc/testkdavc.cpp(19867): [start@426] retry put data
I/avc/omxctrl.cpp(19867): [handleBufferMessage@189] message type: FILL_BUFFER_DONE #3
I/testkdavc/testkdavc.cpp(19867): [OnFrame@150] get frame #3 of 704 x 576
4

1 に答える 1

0

相対的なレイテンシーは気にしませんが、時間単位でレイテンシーを測定し、レイテンシーが発生する場所を特定しようとします。(一部のプラットフォーム ベンダー コードでそのような実装を見たことがあります) 出力バッファー キューにしきい値があり、FBD がすぐに送信されない可能性があります。これは、内部 h264 デコード ユニットの実装の特徴でもある可能性があります。

Tegra のコードは持っていませんが (注)、aosp から Exynos の実装がデフォルトで利用可能です。*.so をビルド/アップロードできると仮定すると、I フレーム デコード モードでいくつかの測定を行うことから始めます。Exynos では (他の場合と同様に) サムネイル モードによってトリガーされますが、インテグレーターが Google のデコーダーをサムネイル作成のデフォルトとして設定することが非常に多いことに注意してください。その場合、これを取り除くか、ハイ プロファイル (Google のコーデックメインとベースラインをサポートしているため失敗し、ベンダーのものを続行します)。

また、通常の再生用に IFrameMode を設定して、参照用にマスター ブランチのデコード/omx Exynos 実装を調べることもできます。つまり、コーデック構成フェーズで V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING を送信する必要があります。

IフレームモードのIMHOレイテンシは、通常のデコードのある種の漸近線になります(高度な最適化なし)。次のステップでは、カーネルを含む下位層でいくつかのタイミング測定を行います。通常のデコードと比較したすべての結果は、可能であれば全体像、どこでどのようにレイテンシーを最適化するかを示します。

于 2013-12-19T14:42:22.753 に答える