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/3791>
This commit is contained in:
Sebastian Dröge 2023-01-24 15:38:20 +02:00 committed by Tim-Philipp Müller
parent ceecd4717d
commit a70935782e

View file

@ -715,19 +715,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);