wavparse: fix seeking in READY state

wavparse claims to be able to support seeking in the READY state by
saving the pending seek event and actually seeking later after having parsed the
header.
Problem was that this seek event was reset on the READY to PAUSED
transition, making all this code useless. Fixing it by stop resetting
on READY to PAUSED transition as we already reset on PAUSED to READY
and when initiating the element.

Note that DTS marker detection isn't support in such scenario as
gst_type_find_helper_for_buffer() needs a buffer containing the
beginning of the stream.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/879>
This commit is contained in:
Guillaume Desmottes 2021-02-18 10:34:25 +01:00
parent 4aa39da2d3
commit 1796f3f5e4
2 changed files with 69 additions and 2 deletions

View file

@ -1918,7 +1918,8 @@ gst_wavparse_add_src_pad (GstWavParse * wav, GstBuffer * buf)
g_assert (wav->caps != NULL);
s = gst_caps_get_structure (wav->caps, 0);
if (s && gst_structure_has_name (s, "audio/x-raw") && buf != NULL) {
if (s && gst_structure_has_name (s, "audio/x-raw") && buf != NULL
&& (GST_BUFFER_OFFSET (buf) == 0 || !GST_BUFFER_OFFSET_IS_VALID (buf))) {
GstTypeFindProbability prob;
GstCaps *tf_caps;
@ -2926,7 +2927,6 @@ gst_wavparse_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_NULL_TO_READY:
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
gst_wavparse_reset (wav);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;

View file

@ -143,6 +143,72 @@ GST_START_TEST (test_empty_file_push)
GST_END_TEST;
static GstPadProbeReturn
fakesink_buffer_cb (GstPad * sink, GstPadProbeInfo * info, gpointer user_data)
{
GstClockTime *ts = user_data;
GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER (info);
fail_unless (buf);
if (!GST_CLOCK_TIME_IS_VALID (*ts))
*ts = GST_BUFFER_PTS (buf);
return GST_PAD_PROBE_OK;
}
GST_START_TEST (test_seek)
{
GstStateChangeReturn ret;
GstElement *pipeline;
GstMessage *msg;
GstElement *wavparse, *fakesink;
GstPad *pad;
GstClockTime seek_position = (20 * GST_MSECOND);
GstClockTime first_ts = GST_CLOCK_TIME_NONE;
pipeline = create_pipeline (GST_PAD_MODE_PULL);
wavparse = gst_bin_get_by_name (GST_BIN (pipeline), "wavparse");
fail_unless (wavparse);
fakesink = gst_bin_get_by_name (GST_BIN (pipeline), "fakesink");
fail_unless (fakesink);
pad = gst_element_get_static_pad (fakesink, "sink");
fail_unless (pad);
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, fakesink_buffer_cb,
&first_ts, NULL);
gst_object_unref (pad);
/* wavparse is able to seek in the READY state */
ret = gst_element_set_state (pipeline, GST_STATE_READY);
fail_unless_equals_int (ret, GST_STATE_CHANGE_SUCCESS);
fail_unless (gst_element_seek_simple (wavparse, GST_FORMAT_TIME,
GST_SEEK_FLAG_FLUSH, seek_position));
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
fail_unless_equals_int (ret, GST_STATE_CHANGE_ASYNC);
ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
fail_unless_equals_int (ret, GST_STATE_CHANGE_SUCCESS);
msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline),
GST_CLOCK_TIME_NONE, GST_MESSAGE_EOS | GST_MESSAGE_ERROR);
/* check that the first buffer produced by wavparse matches the seek
position we requested */
fail_unless_equals_clocktime (first_ts, seek_position);
fail_unless_equals_string (GST_MESSAGE_TYPE_NAME (msg), "eos");
gst_message_unref (msg);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (wavparse);
gst_object_unref (fakesink);
gst_object_unref (pipeline);
}
GST_END_TEST;
static Suite *
wavparse_suite (void)
{
@ -154,6 +220,7 @@ wavparse_suite (void)
tcase_add_test (tc_chain, test_empty_file_push);
tcase_add_test (tc_chain, test_simple_file_pull);
tcase_add_test (tc_chain, test_simple_file_push);
tcase_add_test (tc_chain, test_seek);
return s;
}