webrtc 计算解码时间的方法
程序员文章站
2022-07-01 15:39:03
...
Q:如何计算?
解码的关键代码在这里:AndroidVideoDecoder.java
private static class FrameInfo {
final long decodeStartTimeMs;
final int rotation;
FrameInfo(long decodeStartTimeMs, int rotation) {
this.decodeStartTimeMs = decodeStartTimeMs;
this.rotation = rotation;
}
}
@Override
public VideoCodecStatus decode(EncodedImage frame, DecodeInfo info) {
...
frameInfos.offer(new FrameInfo(SystemClock.elapsedRealtime(), frame.rotation));
try {
codec.queueInputBuffer(index, 0 /* offset */, size,
TimeUnit.NANOSECONDS.toMicros(frame.captureTimeNs), 0 /* flags */);
} catch (IllegalStateException e) {
}
...
}
protected void deliverDecodedFrame() {
...
int result = codec.dequeueOutputBuffer(info, DEQUEUE_OUTPUT_BUFFER_TIMEOUT_US);
if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
reformat(codec.getOutputFormat());
return;
}
if (result < 0) {
Logging.v(TAG, "dequeueOutputBuffer returned " + result);
return;
}
FrameInfo frameInfo = frameInfos.poll();
Integer decodeTimeMs = null;
int rotation = 0;
if (frameInfo != null) {
decodeTimeMs = (int) (SystemClock.elapsedRealtime() - frameInfo.decodeStartTimeMs);
rotation = frameInfo.rotation;
}
...
}
在代码中,解码时间用 decodeStartTimeMs 存储。
有一点背景知识,可能需要你先熟悉下MediaCodec
简单描述下,MediaCodec提供一个机制.
- 把原始的数据给它,它提供了
codec.queueInputBuffer
的方法,把数据拷贝到解码器. - 解出数据之后,通过
codec.dequeueOutputBuffer
把数据归还给调用者。
WebRTC的代码中是这样做的,使用一个FIFO的队列;在解码的时候,存下当前时间;解出来之后,把队列的头部时间POP出来,做差。保存成解码时间。
Q:这个解码时间是不是准确的解码时间?
不是的。它还包括了从用户态拷贝数据到解码器、解码器拷贝回来的时间。
Q: 用队列算会不会有问题?
有可能有问题。
假如有ABCD几个数据,入队解码,MediaCodec在解B的时候报错,那么外面的队列还是按照原来的方式走,那么就可能存在累积误差,而且误差会累积,越来越大。
Q: 有没有办法修正这个误差?
有的,我觉得应该在入队的时候,做一个标记,标志是什么数据给了解码器。解出来后,看看是不是做了标记的数据,如果是的话,才算解码时间。
解码前: RTP.header.timestamp
解码后:PresentationTimeUs
这两个时间的关系是:
(RTP.header.timestamp/90) = frame.captureTimeNs = PresentationTimeUs/1000
我用这个关系重新校准了解码时间。
上一篇: Lucene分词器测试
下一篇: 小娃的趣图,让父母有幸福感的图片