1

我正在尝试使用 openmax 的编解码器编写一个 android 视频会议应用程序。当我使用 OpenMAX IL 进行 avc 解码时,发现从发送空缓冲区命令到填充缓冲区完成回调有很大的延迟。我的案例是处理没有 B 片的 4-cif h.264 基本流。我的 omx 调用顺序是:

  1. 分配一个avc解码角色的openmax节点;
  2. 将节点状态转换为空闲;
  3. 配置端口定义;
  4. 为输入和输出端口分配缓冲区;
  5. 将节点状态转换为执行;
  6. 为空缓冲区启动一个线程,为填充缓冲区启动另一个线程;

日志输出表明存在 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 的解码器设置为缩略图创建的默认值 - 在这种情况下,您必须摆脱它或为高配置运行缩略图创建(谷歌的编解码器将失败,因为它支持主要和基线公平,然后将继续使用供应商的)。

您还可以设置 IFrameMode 以进行常规播放查看主分支的 decode/omx Exynos 实现以供参考,即您需要在编解码器配置阶段发送 V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING。

恕我直言,I 帧模式的延迟将是常规解码的某种渐近线(没有一些高级优化)。在下一步中,在包括内核在内的较低层中进行一些时序测量。如果可能,与常规解码相比,所有结果都将为您提供完整的图片,以及优化延迟的位置和方式。

于 2013-12-19T14:42:22.753 回答