问题: libav/ffmpeg解码管道需要什么才能在解码的AvFrames中产生有效的演示时间戳(PTS)?
我正在解码通过RTSP收到的H264流。我使用live555来解析H264,然后将流将流提供给我的libav解码器。解码和显示工作正常,除了我没有使用时间戳信息并遇到一些口吃。
使用avcodec_decode_video2
帧后,未设置演示时间戳(PTS)。
我需要PTS才能找出需要显示每个帧的时间,并避免任何口吃。
我的管道上的注释
- 我通过live555获取SPS/PPS信息,我将这些值复制到我的
AVCodecContext->extradata
。 - 我还将SPS和PPS发送给我的解码器,作为NAL单位,并附加{0,0,0,0,1} startCode。
- live555为每个数据包提供演示时间戳,在大多数情况下,这些时间戳并非单调增加。该流包含B框架。
- 我的
AVCodecContext->time_base
无效,值为0/2。
不清楚:
- 我应该在哪里设置来自H264水槽(Live555)的NAL PT?作为avpacket-> dts,pts,无或两者兼而有之?
- 为什么我的
time_base
值无效?此信息在哪里? - 根据RTP有效载荷规格。看来
RTP时间戳设置为内容的采样时间戳。必须使用90 kHz时钟速率。
- 这是否意味着我必须始终为解码器的1/90000时数吗?如果SPS中指定了其他一些值?
将live555 pts复制到avpacket pts中。使用AVCODEC_DECODE_VIDEO2处理数据包,然后从AvFrame-> pkt_pts检索PTS,它们将单调增加。
除了在avcodeccontex extradata中设置SPS和PPS外,无需在编解码环境中设置任何内容
您可以在VLC的GitHub中找到一个很好的例子:设置AVPacket PTS:https://github.com/videolan/vlc/blob/master/modules/codec/avcodec/videeo.c#l983
将AVPacket解码为AvFrame:https://github.com/videolan/vlc/blob/master/master/modules/codec/codec/avcodec/video.c#l1014
从Avframe PTS检索:https://github.com/videolan/vlc/blob/master/modules/codec/avcodec/video.c#l1078
avcodec_decode_video2()将帧重新定位,以使解码顺序和表示顺序相同。即使您以某种方式说服FFMPEG在解码框架上给您PTS,也应该与DTS相同。
//
// decode a video frame
//
avcodec_decode_video2
(
ctxt->video_st->codec,
frame,
&is_finished,
buffer
);
if (buffer->dts != AV_NOPTS_VALUE)
{
//
// you should end up here
//
pts = buffer->dts;
}
else
{
pts = 0;
}
//
// adjust time base
//
pts *= av_q2d(ctxt->video_st->time_base);