avvidenc: Don't take ffmpeg timestamps verbatim but only use them to calculate DTS

The ffmpeg timestamps are inaccurate and only in framerate granularity.
To avoid generating inaccurate output timestamps, especially with
variable framerate streams, only use the ffmpeg timestamps for
calculating the DTS.

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1544
again.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3780>
This commit is contained in:
Sebastian Dröge 2023-01-24 15:38:20 +02:00 committed by GStreamer Marge Bot
parent 5372b77987
commit 13fc49770e

View file

@ -717,19 +717,25 @@ gst_ffmpegvidenc_receive_packet (GstFFMpegVidEnc * ffmpegenc,
GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame); GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
} }
if (pkt->dts != AV_NOPTS_VALUE) { /* calculate the DTS by taking the PTS/DTS difference from the ffmpeg side
frame->dts = * and applying it to our PTS. We don't use the ffmpeg timestamps verbatim
gst_ffmpeg_time_ff_to_gst (pkt->dts + ffmpegenc->pts_offset, * because they're too inaccurate and in the framerate time_base
ffmpegenc->context->time_base);
}
/* This will lose some precision compared to setting the PTS from the input
* buffer directly, but that way we're sure PTS and DTS are consistent, in
* particular DTS should always be <= PTS
*/ */
if (pkt->pts != AV_NOPTS_VALUE) { if (pkt->dts != AV_NOPTS_VALUE) {
frame->pts = gint64 pts_dts_diff = pkt->dts - pkt->pts;
gst_ffmpeg_time_ff_to_gst (pkt->pts + ffmpegenc->pts_offset, if (pts_dts_diff < 0) {
ffmpegenc->context->time_base); GstClockTime gst_pts_dts_diff = gst_ffmpeg_time_ff_to_gst (-pts_dts_diff,
ffmpegenc->context->time_base);
if (gst_pts_dts_diff > frame->pts)
frame->pts = 0;
else
frame->dts = frame->pts - gst_pts_dts_diff;
} else {
frame->dts = frame->pts +
gst_ffmpeg_time_ff_to_gst (pts_dts_diff,
ffmpegenc->context->time_base);
}
} }
ret = gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (ffmpegenc), frame); ret = gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (ffmpegenc), frame);