avvidenc: Don't take ffmpeg timestamps verbatim but only use them to calculate DTS 79/288179/3
authorjiyong.min <jiyong.min@samsung.com>
Mon, 13 Feb 2023 05:39:45 +0000 (14:39 +0900)
committerjiyong.min <jiyong.min@samsung.com>
Mon, 13 Feb 2023 05:45:11 +0000 (14:45 +0900)
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: <!3808>

Change-Id: I7bf166986e5fc9b9a43a62eb32c496d4459cd445

packaging/gstreamer.spec
subprojects/gst-libav/ext/libav/gstavvidenc.c

index a4ea0a943e445b40f7f0a4c7236e67063b07960d..a9bbaf5f78bdd987391943058f3304539d0f3843 100644 (file)
@@ -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
index 34d4165a2e305251a21d4647d36b2ba0705ac35d..46899590663fbdafad6977b056e4b971780dedce 100644 (file)
@@ -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);