webrtc 计算解码时间的方法

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提供一个机制.

  1. 把原始的数据给它,它提供了codec.queueInputBuffer 的方法,把数据拷贝到解码器.
  2. 解出数据之后,通过codec.dequeueOutputBuffer 把数据归还给调用者。

WebRTC的代码中是这样做的,使用一个FIFO的队列;在解码的时候,存下当前时间;解出来之后,把队列的头部时间POP出来,做差。保存成解码时间。

Q:这个解码时间是不是准确的解码时间?

不是的。它还包括了从用户态拷贝数据到解码器、解码器拷贝回来的时间。

Q: 用队列算会不会有问题?

有可能有问题。
假如有ABCD几个数据,入队解码,MediaCodec在解B的时候报错,那么外面的队列还是按照原来的方式走,那么就可能存在累积误差,而且误差会累积,越来越大。

Q: 有没有办法修正这个误差?

有的,我觉得应该在入队的时候,做一个标记,标志是什么数据给了解码器。解出来后,看看是不是做了标记的数据,如果是的话,才算解码时间。
解码前: RTP.header.timestamp
解码后:PresentationTimeUs
这两个时间的关系是:
(RTP.header.timestamp/90) = frame.captureTimeNs = PresentationTimeUs/1000
我用这个关系重新校准了解码时间。

相关推荐
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页