解码 H264/RTSP 流后未设置 PTS
PTS not set after decoding H264/RTSP stream
问题:Libav/FFmpeg 解码管道需要什么才能在解码的 AVFrame 中生成有效的表示时间戳 (PTS)?
我正在解码通过 RTSP 接收的 H264 流。我使用 Live555 解析 H264 并将流提供给我的 LibAV 解码器。解码和显示工作正常,除了我没有使用时间戳信息并且有些卡顿。
获得带有 avcodec_decode_video2
的帧后,未设置呈现时间戳 (PTS)。
我需要 PTS 来找出每帧需要显示多长时间,并避免任何卡顿。
关于我的管道的注释
- 我通过 Live555 获得了 SPS/PPS 信息,我将这些值复制到我的
AVCodecContext->extradata
.
- 我还将 SPS 和 PPS 作为 NAL 单元发送到我的解码器,并附加 {0,0,0,1} 起始码。
- Live555 为每个数据包提供显示时间戳,这些时间戳在大多数情况下不是单调递增的。该流包含 B 帧。
- 我的
AVCodecContext->time_base
无效,值为0/2。
不清楚:
- 我应该在哪里设置来自我的 H264 接收器 (Live555) 的 NAL PTS?作为 AVPacket->dts, pts, none, or both?
- 为什么我的
time_base
值无效?这些信息在哪里?
- 根据RTP payload spec。好像
The RTP timestamp is set to the sampling timestamp of the content. A 90 kHz clock rate MUST be used.
- 这是否意味着我必须始终为解码器假设 1/90000 时基?如果在 SPS 中指定了其他值怎么办?
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);
将live555 pts复制到avpacket pts中。用 avcodec_decode_video2 处理数据包,然后从 avframe->pkt_pts 中检索 pts,这些将单调递增。
除了在 AVCodecContex extradata 中设置 SPS 和 PPS 之外,无需在编解码器上下文中设置任何内容
您可以在 VLC github 中找到一个很好的示例:
设置 AVPacket 点:https://github.com/videolan/vlc/blob/master/modules/codec/avcodec/video.c#L983
将 AVPacket 解码为 AVFrame:https://github.com/videolan/vlc/blob/master/modules/codec/avcodec/video.c#L1014
从 AVFrame 中检索点:
https://github.com/videolan/vlc/blob/master/modules/codec/avcodec/video.c#L1078
问题:Libav/FFmpeg 解码管道需要什么才能在解码的 AVFrame 中生成有效的表示时间戳 (PTS)?
我正在解码通过 RTSP 接收的 H264 流。我使用 Live555 解析 H264 并将流提供给我的 LibAV 解码器。解码和显示工作正常,除了我没有使用时间戳信息并且有些卡顿。
获得带有 avcodec_decode_video2
的帧后,未设置呈现时间戳 (PTS)。
我需要 PTS 来找出每帧需要显示多长时间,并避免任何卡顿。
关于我的管道的注释
- 我通过 Live555 获得了 SPS/PPS 信息,我将这些值复制到我的
AVCodecContext->extradata
. - 我还将 SPS 和 PPS 作为 NAL 单元发送到我的解码器,并附加 {0,0,0,1} 起始码。
- Live555 为每个数据包提供显示时间戳,这些时间戳在大多数情况下不是单调递增的。该流包含 B 帧。
- 我的
AVCodecContext->time_base
无效,值为0/2。
不清楚:
- 我应该在哪里设置来自我的 H264 接收器 (Live555) 的 NAL PTS?作为 AVPacket->dts, pts, none, or both?
- 为什么我的
time_base
值无效?这些信息在哪里? - 根据RTP payload spec。好像
The RTP timestamp is set to the sampling timestamp of the content. A 90 kHz clock rate MUST be used.
- 这是否意味着我必须始终为解码器假设 1/90000 时基?如果在 SPS 中指定了其他值怎么办?
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);
将live555 pts复制到avpacket pts中。用 avcodec_decode_video2 处理数据包,然后从 avframe->pkt_pts 中检索 pts,这些将单调递增。
除了在 AVCodecContex extradata 中设置 SPS 和 PPS 之外,无需在编解码器上下文中设置任何内容
您可以在 VLC github 中找到一个很好的示例: 设置 AVPacket 点:https://github.com/videolan/vlc/blob/master/modules/codec/avcodec/video.c#L983
将 AVPacket 解码为 AVFrame:https://github.com/videolan/vlc/blob/master/modules/codec/avcodec/video.c#L1014
从 AVFrame 中检索点: https://github.com/videolan/vlc/blob/master/modules/codec/avcodec/video.c#L1078