如何缩短openmax avc解码器的延迟?

时间:2013-07-02 02:50:02

标签: android video h.264 openmax

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

  1. 分配avc解码角色的openmax节点;
  2. 将节点状态转换为空闲;
  3. 配置端口定义;
  4. 为输入和输出端口分配缓冲区;
  5. 将节点状态转换为执行;
  6. 为空缓冲区启动一个线程,为填充缓冲区启动另一个线程;
  7. 日志输出表明存在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
    

1 个答案:

答案 0 :(得分:0)

我不关心相对延迟,而是测量时间单位的延迟,然后尝试确定生成延迟的位置。可能是(我在某些平台供应商代码中看到这样的实现)输出缓冲区队列有一些阈值,并且不立即发送FBD。它也可能是内部h264解码单元实现的一个特征。

我没有Tegra的代码(注释),但默认情况下从aosp可以使用Exynos实现。假设您能够构建/上传*。所以我将从I帧解码模式中进行一些测量开始。在Exynos中(在其他情况下也是如此)它是由缩略图模式触发的,但请注意,频繁的集成商将谷歌的解码器设置为缩略图创建的默认设置 - 在这种情况下,你必须摆脱这个或运行缩略图创建高调(谷歌的编解码器)将失败,因为它支持主要和基线事件,然后将继续供应商的一个)。

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

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