Android 使用ffmpeg解析MediaCodec编码的h264流中有关表示时间的信息
我已经看到了下面使用Android 使用ffmpeg解析MediaCodec编码的h264流中有关表示时间的信息,android,ffmpeg,encode,android-mediacodec,pts,Android,Ffmpeg,Encode,Android Mediacodec,Pts,我已经看到了下面使用MediaCodecAPI进行编码/解码的示例。 其中对猜测的呈现时间和从解码信息接收到的呈现时间进行了比较 assertEquals("Wrong time stamp", computePresentationTime(checkIndex), info.presentationTimeUs); 因为解码器只是对编码缓冲区中的数据进行解码,所以我认为在此编码器的输出H.264流中可以解析任何时间戳信息 我正在编写一个Android应用程序,它使用ffmpeg(
MediaCodec
API进行编码/解码的示例。
其中对猜测的呈现时间和从解码信息接收到的呈现时间进行了比较
assertEquals("Wrong time stamp", computePresentationTime(checkIndex),
info.presentationTimeUs);
因为解码器只是对编码缓冲区中的数据进行解码,所以我认为在此编码器的输出H.264流中可以解析任何时间戳信息
我正在编写一个Android应用程序,它使用ffmpeg
(libavformat
)将MediaCodec
编码的H264流(.H264)多路复用到mp4容器中。
我不想使用MediaMuxer
,因为它需要4.3版,太高了
然而,ffmpeg
似乎无法识别由MediaCodec
编码的数据包中的表示时间戳,因此在尝试从流中读取帧时,我总是得不到PTS值
有人知道在这种情况下如何获得正确的演示时间戳吗?要将时间戳从
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\u base
取决于帧率
upd重新时间戳在管道中流动:
解码器和编码器都不知道自己的时间戳。通过为这些组件设置时间戳
decoder.queueInputBuffer(inputBufIndex, 0, info.size, info.presentationTimeUs, info.flags);
或
这些时间戳可以从提取器、摄像机或应用程序生成,但解码器\编码器只是通过这些时间戳,而不改变它们。因此,从源到接收器(muxer)的时间戳保持不变
当然也有一些例外情况:如果帧频发生变化,例如帧速率转换。或者,若编码器使用B帧进行编码,则会发生重新排序。
或者编码器可以向编码器帧头添加时间戳-可选,标准中不强制。我认为所有这些都不适用于当前的android版本、编解码器或您的使用场景。基本问题是H.264流不包括演示时间戳。它们必须带外发送,或写入包装器(例如MediaMuxer创建的.mp4文件包装器)。但为什么解码器队列中的解码信息显示正确的时间戳?在EncodeDecodeTest代码中,PTS由
computePresentationTime()
生成,通过queueInputBuffer()传递给编码器
或eglPresentationTime()
,使用BufferInfo中的输出缓冲区接收,使用queueInputBuffer()
将输入缓冲区传递给解码器,然后使用BufferInfo中的输出接收。如果查看DecodeEditEncodeTest中的VideoChunk,可以看到它为每一帧保存三个片段(编码数据、标志和PTS)。时间戳在编解码器中与缓冲区关联,但它只是简单地传递。谢谢fadden。现在我知道了MediaCodec
编码器/解码器的工作原理。谢谢你的建议。我知道如何从MediaCodec
编码器向ffmpeg
发送时间戳,但不知道为什么只有MediaCodec
解码器才能从编码数据中获取时间戳信息?
encoder.queueInputBuffer(inputBufIndex, 0, 0, ptsUsec, info.flags);