From 2843f358d91c3843d61ba02ca46fced4da36b5fe Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Mon, 14 Oct 2013 18:45:10 -0300 Subject: [PATCH] videoencoder: Keep still meaningfull pending events on FLUSH_STOP Only EOS and segment should be deleted in that case. https://bugzilla.gnome.org/show_bug.cgi?id=709868 --- gst-libs/gst/video/gstvideoencoder.c | 38 +++++++++++-- tests/check/libs/videoencoder.c | 104 +++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 4 deletions(-) diff --git a/gst-libs/gst/video/gstvideoencoder.c b/gst-libs/gst/video/gstvideoencoder.c index 09f09eb..e0264d1 100644 --- a/gst-libs/gst/video/gstvideoencoder.c +++ b/gst-libs/gst/video/gstvideoencoder.c @@ -305,6 +305,25 @@ gst_video_encoder_class_init (GstVideoEncoderClass * klass) klass->src_query = gst_video_encoder_src_query_default; } +static GList * +_flush_events (GstPad * pad, GList * events) +{ + GList *tmp; + + for (tmp = events; tmp; tmp = tmp->next) { + if (GST_EVENT_TYPE (tmp->data) == GST_EVENT_EOS || + GST_EVENT_TYPE (tmp->data) == GST_EVENT_SEGMENT || + !GST_EVENT_IS_STICKY (tmp->data)) { + gst_event_unref (tmp->data); + } else { + gst_pad_store_sticky_event (pad, GST_EVENT_CAST (tmp->data)); + } + } + g_list_free (events); + + return NULL; +} + static gboolean gst_video_encoder_reset (GstVideoEncoder * encoder, gboolean hard) { @@ -323,10 +342,6 @@ gst_video_encoder_reset (GstVideoEncoder * encoder, gboolean hard) priv->drained = TRUE; - g_list_foreach (priv->current_frame_events, (GFunc) gst_event_unref, NULL); - g_list_free (priv->current_frame_events); - priv->current_frame_events = NULL; - g_list_foreach (priv->frames, (GFunc) gst_video_codec_frame_unref, NULL); g_list_free (priv->frames); priv->frames = NULL; @@ -362,6 +377,21 @@ gst_video_encoder_reset (GstVideoEncoder * encoder, gboolean hard) gst_object_unref (priv->allocator); priv->allocator = NULL; } + + g_list_foreach (priv->current_frame_events, (GFunc) gst_event_unref, NULL); + g_list_free (priv->current_frame_events); + priv->current_frame_events = NULL; + + } else { + GList *l; + + for (l = priv->frames; l; l = l->next) { + GstVideoCodecFrame *frame = l->data; + + frame->events = _flush_events (encoder->srcpad, frame->events); + } + priv->current_frame_events = _flush_events (encoder->srcpad, + encoder->priv->current_frame_events); } GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder); diff --git a/tests/check/libs/videoencoder.c b/tests/check/libs/videoencoder.c index 925b2bf..e310f82 100644 --- a/tests/check/libs/videoencoder.c +++ b/tests/check/libs/videoencoder.c @@ -392,6 +392,109 @@ GST_START_TEST (videoencoder_events_before_eos) GST_END_TEST; +GST_START_TEST (videoencoder_flush_events) +{ + GstSegment segment; + GstBuffer *buffer; + guint64 i; + GList *events_iter; + + setup_videoencodertester (); + + gst_pad_set_active (mysrcpad, TRUE); + gst_element_set_state (dec, GST_STATE_PLAYING); + gst_pad_set_active (mysinkpad, TRUE); + + send_startup_events (); + + /* push a new segment */ + gst_segment_init (&segment, GST_FORMAT_TIME); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + + /* push buffers, the data is actually a number so we can track them */ + for (i = 0; i < NUM_BUFFERS; i++) { + if (i % 10 == 0) { + GstTagList *tags; + + tags = gst_tag_list_new (GST_TAG_TRACK_NUMBER, i, NULL); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_tag (tags))); + } else { + buffer = create_test_buffer (i); + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + } + } + + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ())); + + events_iter = events; + /* make sure the usual events have been received */ + { + GstEvent *sstart = events_iter->data; + fail_unless (GST_EVENT_TYPE (sstart) == GST_EVENT_STREAM_START); + events_iter = g_list_next (events_iter); + } + { + GstEvent *caps_event = events_iter->data; + fail_unless (GST_EVENT_TYPE (caps_event) == GST_EVENT_CAPS); + events_iter = g_list_next (events_iter); + } + { + GstEvent *segment_event = events_iter->data; + fail_unless (GST_EVENT_TYPE (segment_event) == GST_EVENT_SEGMENT); + events_iter = g_list_next (events_iter); + } + + /* check that EOS was received */ + fail_unless (GST_PAD_IS_EOS (mysrcpad)); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_start ())); + fail_unless (GST_PAD_IS_EOS (mysrcpad)); + + /* Check that we have tags */ + { + GstEvent *tags = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_TAG, 0); + + fail_unless (tags != NULL); + gst_event_unref (tags); + } + + /* Check that we still have a segment set */ + { + GstEvent *segment = + gst_pad_get_sticky_event (mysrcpad, GST_EVENT_SEGMENT, 0); + + fail_unless (segment != NULL); + gst_event_unref (segment); + } + + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_stop (TRUE))); + fail_if (GST_PAD_IS_EOS (mysrcpad)); + + /* Check that the segment was flushed on FLUSH_STOP */ + { + GstEvent *segment = + gst_pad_get_sticky_event (mysrcpad, GST_EVENT_SEGMENT, 0); + + fail_unless (segment == NULL); + } + + /* Check the tags were not lost on FLUSH_STOP */ + { + GstEvent *tags = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_TAG, 0); + + fail_unless (tags != NULL); + gst_event_unref (tags); + + } + + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + + cleanup_videoencodertest (); +} + +GST_END_TEST; + static Suite * gst_videoencoder_suite (void) { @@ -403,6 +506,7 @@ gst_videoencoder_suite (void) tcase_add_test (tc, videoencoder_tags_before_eos); tcase_add_test (tc, videoencoder_events_before_eos); + tcase_add_test (tc, videoencoder_flush_events); return s; } -- 2.7.4