baseparse: Don't truncate the duration to milliseconds in gst_base_parse_convert_defa...
authorZebediah Figura <zfigura@codeweavers.com>
Tue, 18 Feb 2020 03:50:54 +0000 (21:50 -0600)
committerZebediah Figura <zfigura@codeweavers.com>
Tue, 8 Feb 2022 02:13:01 +0000 (20:13 -0600)
There's no need to do this, and it can make seeking far less accurate.

For a specific use case: I am working with a long (45-minute) MPEG-1 layer 3 file, which has a constant bit rate but no seeking tables. Trying to seek the pipeline immediately after pausing it, without the ACCURATE flag, to a location 41 minutes in, yields a location that is potentially over ten seconds ahead of where it should be. This patch improves that drastically.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/374>

subprojects/gstreamer/libs/gst/base/gstbaseparse.c
subprojects/gstreamer/tests/check/libs/baseparse.c

index 9e5a652..660439b 100644 (file)
@@ -1782,7 +1782,7 @@ gst_base_parse_convert_default (GstBaseParse * parse,
   if (!parse->priv->framecount)
     goto no_framecount;
 
-  duration = parse->priv->acc_duration / GST_MSECOND;
+  duration = parse->priv->acc_duration;
   bytes = parse->priv->bytecount;
 
   if (G_UNLIKELY (!duration || !bytes))
@@ -1793,7 +1793,6 @@ gst_base_parse_convert_default (GstBaseParse * parse,
       /* BYTES -> TIME conversion */
       GST_DEBUG_OBJECT (parse, "converting bytes -> time");
       *dest_value = gst_util_uint64_scale (src_value, duration, bytes);
-      *dest_value *= GST_MSECOND;
       GST_DEBUG_OBJECT (parse,
           "converted %" G_GINT64_FORMAT " bytes to %" GST_TIME_FORMAT,
           src_value, GST_TIME_ARGS (*dest_value));
@@ -1804,8 +1803,7 @@ gst_base_parse_convert_default (GstBaseParse * parse,
   } else if (src_format == GST_FORMAT_TIME) {
     if (dest_format == GST_FORMAT_BYTES) {
       GST_DEBUG_OBJECT (parse, "converting time -> bytes");
-      *dest_value = gst_util_uint64_scale (src_value / GST_MSECOND, bytes,
-          duration);
+      *dest_value = gst_util_uint64_scale (src_value, bytes, duration);
       GST_DEBUG_OBJECT (parse,
           "converted %" GST_TIME_FORMAT " to %" G_GINT64_FORMAT " bytes",
           GST_TIME_ARGS (src_value), *dest_value);
index a53fdfe..d92b19f 100644 (file)
@@ -722,6 +722,47 @@ GST_START_TEST (parser_initial_gap_prefer_upstream_caps)
 
 GST_END_TEST;
 
+GST_START_TEST (parser_convert_duration)
+{
+  static const gint64 seconds = 45 * 60;
+  gint64 value, expect;
+  gboolean ret;
+
+  have_eos = FALSE;
+  have_data = FALSE;
+  loop = g_main_loop_new (NULL, FALSE);
+
+  setup_parsertester ();
+  gst_pad_set_getrange_function (mysrcpad, _src_getrange);
+  gst_pad_set_query_function (mysrcpad, _src_query);
+  gst_pad_set_chain_function (mysinkpad, _sink_chain);
+  gst_pad_set_event_function (mysinkpad, _sink_event);
+
+  gst_pad_set_active (mysrcpad, TRUE);
+  gst_element_set_state (parsetest, GST_STATE_PLAYING);
+  gst_pad_set_active (mysinkpad, TRUE);
+
+  g_main_loop_run (loop);
+  fail_unless (have_eos == TRUE);
+  fail_unless (have_data == TRUE);
+
+  ret = gst_base_parse_convert_default (GST_BASE_PARSE (parsetest),
+      GST_FORMAT_TIME, seconds * GST_SECOND, GST_FORMAT_BYTES, &value);
+  fail_unless (ret == TRUE);
+  expect = gst_util_uint64_scale_round (seconds * sizeof (guint64),
+      TEST_VIDEO_FPS_N, TEST_VIDEO_FPS_D);
+  fail_unless_equals_int (value, expect);
+  gst_element_set_state (parsetest, GST_STATE_NULL);
+
+  check_no_error_received ();
+  cleanup_parsertest ();
+
+  g_main_loop_unref (loop);
+  loop = NULL;
+}
+
+GST_END_TEST;
+
 
 static void
 baseparse_setup (void)
@@ -755,6 +796,7 @@ gst_baseparse_suite (void)
   tcase_add_test (tc, parser_pull_short_read);
   tcase_add_test (tc, parser_pull_frame_growth);
   tcase_add_test (tc, parser_initial_gap_prefer_upstream_caps);
+  tcase_add_test (tc, parser_convert_duration);
 
   return s;
 }