baseparse: Don't truncate the duration to milliseconds in gst_base_parse_convert_default().

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>
This commit is contained in:
Zebediah Figura 2020-02-17 21:50:54 -06:00
parent 334c347de2
commit cc835c0722
2 changed files with 44 additions and 4 deletions

View 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);

View 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;
}