Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何减少MediaCodec视频/avc解码中的延迟_Android_H.264_Android Mediacodec_Textureview_Mediaextractor - Fatal编程技术网

Android 如何减少MediaCodec视频/avc解码中的延迟

Android 如何减少MediaCodec视频/avc解码中的延迟,android,h.264,android-mediacodec,textureview,mediaextractor,Android,H.264,Android Mediacodec,Textureview,Mediaextractor,我在Nexus5上运行的MediaCodec示例代码中执行了一些简单的定时。我在以下位置放置日志语句: 在前面的203行 decoder.queueInputBuffer 在第244行之后 decoder.dequeueOutputBuffer 我使用presentationTimeUs关联日志语句 以下是logcat的摘录: 01-29 10:56:43.295: I/Grafika(21286): queueInputBuffer index/pts, 2,0 01-29 10:56:4

我在Nexus5上运行的MediaCodec示例代码中执行了一些简单的定时。我在以下位置放置日志语句:

在前面的203行

decoder.queueInputBuffer
在第244行之后

decoder.dequeueOutputBuffer
我使用
presentationTimeUs
关联日志语句

以下是logcat的摘录:

01-29 10:56:43.295: I/Grafika(21286): queueInputBuffer index/pts, 2,0
01-29 10:56:43.305: I/Grafika(21286): queueInputBuffer index/pts, 0,33100
01-29 10:56:43.315: I/Grafika(21286): queueInputBuffer index/pts, 3,66466
01-29 10:56:43.325: I/Grafika(21286): queueInputBuffer index/pts, 1,99833
01-29 10:56:43.325: I/Grafika(21286): queueInputBuffer index/pts, 2,133200
01-29 10:56:43.335: I/Grafika(21286): queueInputBuffer index/pts, 0,166566
01-29 10:56:43.345: I/ATSParser(21286): discontinuity on stream pid 0x1011
01-29 10:56:43.345: I/ATSParser(21286): discontinuity on stream pid 0x1100
01-29 10:56:43.345: I/Grafika(21286): queueInputBuffer index/pts, 3,199933
01-29 10:56:43.345: I/Grafika(21286): dequeueOutputBuffer index/pts, 7,0
01-29 10:56:43.345: I/Grafika(21286): queueInputBuffer index/pts, 1,300033
01-29 10:56:43.355: I/Grafika(21286): dequeueOutputBuffer index/pts, 6,33100
01-29 10:56:43.385: I/Grafika(21286): queueInputBuffer index/pts, 2,333400
01-29 10:56:43.385: I/Grafika(21286): dequeueOutputBuffer index/pts, 5,66466
01-29 10:56:43.415: I/Grafika(21286): queueInputBuffer index/pts, 0,366766
01-29 10:56:43.415: I/Grafika(21286): dequeueOutputBuffer index/pts, 4,99833
01-29 10:56:43.445: I/Grafika(21286): queueInputBuffer index/pts, 3,400133
01-29 10:56:43.445: I/Grafika(21286): dequeueOutputBuffer index/pts, 3,133200
我发现从第一个输入缓冲区排队到相应的输出缓冲区退出队列的时间差是50毫秒。对于硬件加速解码来说,这似乎需要很多时间


有没有办法减少延迟?

我想你看到了第一帧特有的一些效果。我重复了您的实验,并在第244行附近添加了强制
doRender=false
,以避免用于管理输出帧速率的休眠调用。我明白了:

01-29 14:05:36.552  9115  9224 I Grafika : queueInputBuffer index/pts, 2,0
01-29 14:05:36.562  9115  9224 I Grafika : queueInputBuffer index/pts, 0,66655
01-29 14:05:36.572  9115  9224 I Grafika : queueInputBuffer index/pts, 3,133288
01-29 14:05:36.582  9115  9224 I Grafika : queueInputBuffer index/pts, 1,199955

01-29 14:05:36.602  9115  9224 I Grafika : dequeueOutputBuffer index/pts, 4,0
01-29 14:05:36.602  9115  9224 I Grafika : dequeueOutputBuffer index/pts, 3,66655
01-29 14:05:36.602  9115  9224 I Grafika : dequeueOutputBuffer index/pts, 2,133288
01-29 14:05:36.612  9115  9224 I Grafika : dequeueOutputBuffer index/pts, 4,199955
(为了清晰起见,删除了多余的线条。)这证实了您的结果。注意,当pts=0时,输入和输出之间有50毫秒的延迟,随后的输出帧几乎立即可用。我使用的视频是“camera test.mp4”(720p摄像头输出)

要了解为什么会发生这种情况,请查看日志中的其他内容,以及它出现的位置。从第一个
queueInputBuffer
日志行开始,计算出现在该行和第一个
dequeueOutputBuffer
行之间的日志数。我数了一下我的OMX-VDEC-1080P大约60行输出。现在计算在输出缓冲区开始出现后出现的OMX-VDEC行数。直到视频结束我才看到

显然,视频解码器在数据可用之前推迟了一些昂贵的初始化。所以下一个问题是。。。它需要多少数据?在提交第二帧(pts==66633)后,我添加了500毫秒的睡眠。结果:提交两帧,500毫秒暂停,提交两帧,OMX-VDEC日志大堆。因此,解码器似乎需要几个帧才能开始

这表明我们可以通过快速输入前几帧来减少启动延迟。为了测试这一点,我将
TIMEOUT\u USEC
更改为零,这样它会快速响应,但会烧坏CPU。新日志输出(您的日志,无睡眠,无渲染):

通过快速输入初始帧,我们将初始延迟从50毫秒减少到30毫秒

(请注意所有时间戳如何以“2”结尾?用于日志时间的计时器似乎四舍五入到最接近的10ms,因此实际时间增量可能略有不同。)

我们缓慢地输入初始帧的原因是,在提交每个输入缓冲区后,我们试图从解码器中耗尽输出,等待10毫秒以获得从未出现的输出。我最初的想法是,我们希望在
dequeueInputBuffer()
dequeueOutputBuffer()
上等待一个超时,但不是两个都要等待——可能首先对输入使用一个超时,然后对输出使用一个快速轮询,然后在输入不足时切换到输出超时。(就此而言,输入的初始超时可以是-1,因为我们知道在第一个输入缓冲区排队之前不会发生任何事情。)


我不知道是否有办法进一步减少延迟。

我注意到@fadden在回答中提到Surface使用了BufferQueue:。我是否配置了其他缓冲区?您认为渲染基于什么?Chromium项目将其封装在一个名为So的好类中,而不是调用dequeue,然后休眠以调整输出速度,我将首先决定是否渲染然后出列。想法?你可能应该把它放在一个新问题里。FWIW,格拉菲卡“用FBO录制GL应用程序”活动由编舞推动。
01-29 14:29:04.542 10560 10599 I Grafika : queueInputBuffer index/pts, 0,0
01-29 14:29:04.542 10560 10599 I Grafika : queueInputBuffer index/pts, 2,66633
01-29 14:29:04.542 10560 10599 I Grafika : queueInputBuffer index/pts, 3,133288
...
01-29 14:29:04.572 10560 10599 I Grafika : dequeueOutputBuffer index/pts, 4,0
01-29 14:29:04.572 10560 10599 I Grafika : dequeueOutputBuffer index/pts, 3,66633
01-29 14:29:04.572 10560 10599 I Grafika : dequeueOutputBuffer index/pts, 2,133288