From 47da9736872f5cc66e16e5a92316258687e5dc6e Mon Sep 17 00:00:00 2001 From: "jiyong.min" Date: Mon, 13 Feb 2023 14:39:45 +0900 Subject: [PATCH] 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 #1544(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1544) again. Part-of: Change-Id: I7bf166986e5fc9b9a43a62eb32c496d4459cd445 --- packaging/gstreamer.spec | 2 +- subprojects/gst-libav/ext/libav/gstavvidenc.c | 30 ++++++++++++++++----------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packaging/gstreamer.spec b/packaging/gstreamer.spec index a4ea0a9..a9bbaf5 100644 --- a/packaging/gstreamer.spec +++ b/packaging/gstreamer.spec @@ -62,7 +62,7 @@ Name: %{_name} Version: 1.22.0 -Release: 8 +Release: 9 Summary: Streaming-Media Framework Runtime License: LGPL-2.0+ Group: Multimedia/Framework diff --git a/subprojects/gst-libav/ext/libav/gstavvidenc.c b/subprojects/gst-libav/ext/libav/gstavvidenc.c index 34d4165..4689959 100644 --- a/subprojects/gst-libav/ext/libav/gstavvidenc.c +++ b/subprojects/gst-libav/ext/libav/gstavvidenc.c @@ -717,19 +717,25 @@ gst_ffmpegvidenc_receive_packet (GstFFMpegVidEnc * ffmpegenc, GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame); } - if (pkt->dts != AV_NOPTS_VALUE) { - frame->dts = - gst_ffmpeg_time_ff_to_gst (pkt->dts + ffmpegenc->pts_offset, - 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 + /* 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->pts != AV_NOPTS_VALUE) { - frame->pts = - gst_ffmpeg_time_ff_to_gst (pkt->pts + ffmpegenc->pts_offset, - ffmpegenc->context->time_base); + if (pkt->dts != AV_NOPTS_VALUE) { + gint64 pts_dts_diff = pkt->dts - pkt->pts; + 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); + } } ret = gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (ffmpegenc), frame); -- 2.7.4