1

我已经看到以下使用MediaCodecAPI 进行编码/解码的示例。 https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java

其中有猜测的呈现时间和从解码信息接收的呈现时间的比较。

assertEquals("Wrong time stamp", computePresentationTime(checkIndex),
    info.presentationTimeUs);

因为解码器只是解码编码缓冲区中的数据,我认为在这个编码器的输出 H.264 流中可以解析任何时间戳信息。

我正在编写一个 Android 应用程序,它使用( ) 将编码的 H264 流 (.h264) 混合MediaCodec到 mp4 容器。我不想使用,因为它需要的 4.3 版本太高了。ffmpeglibavformatMediaMuxer

但是,ffmpeg似乎无法识别由 编码的数据包中的表示时间戳MediaCodec,因此在尝试从流中读取帧时,我总是得到 NO_PTS 值。

任何人都知道如何在这种情况下获得正确的演示时间戳?

4

1 回答 1

3

要将时间戳从MediaCodec编码器发送到ffmpeg您需要这样转换:

jint Java_com_classclass_WriteVideoFrame(JNIEnv * env, jobject this, jbyteArray data, jint datasize, jlong timestamp) {

    ....

AVPacket pkt;
av_init_packet(&pkt);

AVCodecContext *c = m_pVideoStream->codec;

pkt.pts = (long)((double)timestamp * (double)c->time_base.den / 1000.0);
pkt.stream_index    = m_pVideoStream->index;
pkt.data            = rawjBytes;
pkt.size            = datasize;

time_base取决于帧率

upd re 时间戳在管道中流动: 解码器和编码器都不知道自己的时间戳。时间戳通过这些组件设置

decoder.queueInputBuffer(inputBufIndex, 0, info.size, info.presentationTimeUs, info.flags);

或者

encoder.queueInputBuffer(inputBufIndex, 0, 0, ptsUsec, info.flags);

这些时间戳可以从提取器、相机或应用程序生成,但解码器\编码器只是通过这些时间戳而不更改它们。结果,时间戳从源到接收器(复用器)保持不变。

当然有一些排除:如果帧频率发生变化 - 例如帧速率转换。或者如果编码器使用 B 帧进行编码并发生重新排序。或编码器可以将时间戳添加到编码器帧头 - 可选,不是标准强制要求。我认为所有这些都不适用于当前的 android 版本、编解码器或您的使用场景。

于 2014-05-20T10:03:27.837 回答