baseparse: don't clear most sticky events after a FLUSH_STOP event
Clearing sticky events - besides EOS, STREAM_GROUP_DONE, and SEGMENT - risks losing them if a flush occurs before we get another buffer. Also adds a unit test: parser_sticky_events_after_flush Fixes #4193 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9506>
This commit is contained in:
parent
fc647552fa
commit
54d28569b2
@ -485,7 +485,7 @@ static gboolean gst_base_parse_is_seekable (GstBaseParse * parse);
|
||||
static void gst_base_parse_push_pending_events (GstBaseParse * parse);
|
||||
|
||||
static void
|
||||
gst_base_parse_clear_queues (GstBaseParse * parse)
|
||||
gst_base_parse_clear_queues (GstBaseParse * parse, gboolean clear_sticky_events)
|
||||
{
|
||||
g_slist_foreach (parse->priv->buffers_queued, (GFunc) gst_buffer_unref, NULL);
|
||||
g_slist_free (parse->priv->buffers_queued);
|
||||
@ -512,9 +512,30 @@ gst_base_parse_clear_queues (GstBaseParse * parse)
|
||||
|
||||
gst_buffer_replace (&parse->priv->cache, NULL);
|
||||
|
||||
g_list_foreach (parse->priv->pending_events, (GFunc) gst_event_unref, NULL);
|
||||
g_list_free (parse->priv->pending_events);
|
||||
parse->priv->pending_events = NULL;
|
||||
if (clear_sticky_events) {
|
||||
g_list_foreach (parse->priv->pending_events, (GFunc) gst_event_unref, NULL);
|
||||
g_list_free (parse->priv->pending_events);
|
||||
parse->priv->pending_events = NULL;
|
||||
} else {
|
||||
GList *cur = g_list_first (parse->priv->pending_events);
|
||||
GList *next;
|
||||
|
||||
while (cur != NULL) {
|
||||
GstEvent *event = GST_EVENT (cur->data);
|
||||
GstEventType type = GST_EVENT_TYPE (event);
|
||||
|
||||
next = g_list_next (cur);
|
||||
|
||||
if (!GST_EVENT_IS_STICKY (event) || type == GST_EVENT_EOS
|
||||
|| type == GST_EVENT_STREAM_GROUP_DONE || type == GST_EVENT_SEGMENT) {
|
||||
gst_event_unref (event);
|
||||
parse->priv->pending_events =
|
||||
g_list_delete_link (parse->priv->pending_events, cur);
|
||||
}
|
||||
|
||||
cur = next;
|
||||
}
|
||||
}
|
||||
|
||||
parse->priv->checked_media = FALSE;
|
||||
}
|
||||
@ -532,7 +553,7 @@ gst_base_parse_finalize (GObject * object)
|
||||
}
|
||||
g_mutex_clear (&parse->priv->index_lock);
|
||||
|
||||
gst_base_parse_clear_queues (parse);
|
||||
gst_base_parse_clear_queues (parse, TRUE);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
@ -1423,7 +1444,7 @@ gst_base_parse_sink_event_default (GstBaseParse * parse, GstEvent * event)
|
||||
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
gst_adapter_clear (parse->priv->adapter);
|
||||
gst_base_parse_clear_queues (parse);
|
||||
gst_base_parse_clear_queues (parse, FALSE);
|
||||
parse->priv->flushing = FALSE;
|
||||
parse->priv->discont = TRUE;
|
||||
parse->priv->last_pts = GST_CLOCK_TIME_NONE;
|
||||
@ -4782,7 +4803,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
|
||||
gst_event_set_seqnum (fevent, seqnum);
|
||||
gst_pad_push_event (parse->srcpad, gst_event_ref (fevent));
|
||||
gst_pad_push_event (parse->sinkpad, fevent);
|
||||
gst_base_parse_clear_queues (parse);
|
||||
gst_base_parse_clear_queues (parse, FALSE);
|
||||
}
|
||||
|
||||
memcpy (&parse->segment, &seeksegment, sizeof (GstSegment));
|
||||
|
@ -763,6 +763,46 @@ GST_START_TEST (parser_convert_duration)
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (parser_sticky_events_after_flush)
|
||||
{
|
||||
GstHarness *h;
|
||||
GstEvent *e;
|
||||
GstSegment segment;
|
||||
GstStreamCollection *collection;
|
||||
|
||||
parsetest = g_object_new (GST_PARSER_TESTER_TYPE, NULL);
|
||||
|
||||
h = gst_harness_new_with_element (parsetest, "sink", "src");
|
||||
gst_harness_set_caps (h, gst_caps_new_empty_simple ("video/x-test-custom"),
|
||||
gst_caps_new_empty_simple ("video/x-test-custom"));
|
||||
|
||||
collection = gst_stream_collection_new ("test");
|
||||
fail_unless (gst_harness_push_event (h,
|
||||
gst_event_new_stream_collection (collection)));
|
||||
gst_object_unref (collection);
|
||||
|
||||
fail_unless (gst_harness_push_event (h, gst_event_new_flush_start ()));
|
||||
fail_unless (gst_harness_push_event (h, gst_event_new_flush_stop (FALSE)));
|
||||
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
fail_unless (gst_harness_push_event (h, gst_event_new_segment (&segment)));
|
||||
fail_unless (gst_harness_push (h, create_test_buffer (1)) == GST_FLOW_OK);
|
||||
|
||||
// FLUSH_STOP should not clear STREAM_COLLECTION
|
||||
while (TRUE) {
|
||||
fail_unless (e = gst_harness_pull_event (h));
|
||||
if (GST_EVENT_TYPE (e) == GST_EVENT_STREAM_COLLECTION)
|
||||
break;
|
||||
gst_event_unref (e);
|
||||
}
|
||||
gst_event_unref (e);
|
||||
|
||||
gst_harness_teardown (h);
|
||||
gst_object_unref (parsetest);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
static void
|
||||
baseparse_setup (void)
|
||||
@ -797,6 +837,7 @@ gst_baseparse_suite (void)
|
||||
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);
|
||||
tcase_add_test (tc, parser_sticky_events_after_flush);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user