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);
} }
/* calculate the DTS by taking the PTS/DTS difference from the ffmpeg side
* and applying it to our PTS. We don't use the ffmpeg timestamps verbatim
* because they're too inaccurate and in the framerate time_base
*/
if (pkt->dts != AV_NOPTS_VALUE) { if (pkt->dts != AV_NOPTS_VALUE) {
frame->dts = gint64 pts_dts_diff = pkt->dts - pkt->pts;
gst_ffmpeg_time_ff_to_gst (pkt->dts + ffmpegenc->pts_offset, if (pts_dts_diff < 0) {
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); 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) {
frame->pts =
gst_ffmpeg_time_ff_to_gst (pkt->pts + ffmpegenc->pts_offset,
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);