diff options
-rw-r--r-- | gst-libs/gst/video/gstvideodecoder.c | 43 | ||||
-rw-r--r-- | tests/check/libs/videodecoder.c | 52 |
2 files changed, 82 insertions, 13 deletions
diff --git a/gst-libs/gst/video/gstvideodecoder.c b/gst-libs/gst/video/gstvideodecoder.c index 671a66b5e..87c78d9df 100644 --- a/gst-libs/gst/video/gstvideodecoder.c +++ b/gst-libs/gst/video/gstvideodecoder.c @@ -439,6 +439,8 @@ static void gst_video_decoder_reset (GstVideoDecoder * decoder, gboolean full, static GstFlowReturn gst_video_decoder_decode_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame); +static void gst_video_decoder_push_event_list (GstVideoDecoder * decoder, + GList * events); static GstClockTime gst_video_decoder_get_frame_duration (GstVideoDecoder * decoder, GstVideoCodecFrame * frame); static GstVideoCodecFrame *gst_video_decoder_new_frame (GstVideoDecoder * @@ -1222,6 +1224,8 @@ gst_video_decoder_sink_event_default (GstVideoDecoder * decoder, { GstFlowReturn flow_ret = GST_FLOW_OK; gboolean needs_reconfigure = FALSE; + GList *events; + GList *frame_events; flow_ret = gst_video_decoder_drain_out (decoder, FALSE); ret = (flow_ret == GST_FLOW_OK); @@ -1247,8 +1251,19 @@ gst_video_decoder_sink_event_default (GstVideoDecoder * decoder, gst_pad_mark_reconfigure (decoder->srcpad); } } + + GST_DEBUG_OBJECT (decoder, "Pushing all pending serialized events" + " before the gap"); + events = decoder->priv->pending_events; + frame_events = decoder->priv->current_frame_events; + decoder->priv->pending_events = NULL; + decoder->priv->current_frame_events = NULL; + GST_VIDEO_DECODER_STREAM_UNLOCK (decoder); + gst_video_decoder_push_event_list (decoder, events); + gst_video_decoder_push_event_list (decoder, frame_events); + /* Forward GAP immediately. Everything is drained after * the GAP event and we can forward this event immediately * now without having buffers out of order. @@ -2544,6 +2559,19 @@ gst_video_decoder_new_frame (GstVideoDecoder * decoder) } static void +gst_video_decoder_push_event_list (GstVideoDecoder * decoder, GList * events) +{ + GList *l; + + /* events are stored in reverse order */ + for (l = g_list_last (events); l; l = g_list_previous (l)) { + GST_LOG_OBJECT (decoder, "pushing %s event", GST_EVENT_TYPE_NAME (l->data)); + gst_video_decoder_push_event (decoder, l->data); + } + g_list_free (events); +} + +static void gst_video_decoder_prepare_finish_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame, gboolean dropping) { @@ -2584,21 +2612,10 @@ gst_video_decoder_prepare_finish_frame (GstVideoDecoder * decoder->priv->pending_events = g_list_concat (decoder->priv->pending_events, events); } else { - for (l = g_list_last (decoder->priv->pending_events); l; - l = g_list_previous (l)) { - GST_LOG_OBJECT (decoder, "pushing %s event", - GST_EVENT_TYPE_NAME (l->data)); - gst_video_decoder_push_event (decoder, l->data); - } - g_list_free (decoder->priv->pending_events); + gst_video_decoder_push_event_list (decoder, decoder->priv->pending_events); decoder->priv->pending_events = NULL; - for (l = g_list_last (events); l; l = g_list_previous (l)) { - GST_LOG_OBJECT (decoder, "pushing %s event", - GST_EVENT_TYPE_NAME (l->data)); - gst_video_decoder_push_event (decoder, l->data); - } - g_list_free (events); + gst_video_decoder_push_event_list (decoder, events); } /* Check if the data should not be displayed. For example altref/invisible diff --git a/tests/check/libs/videodecoder.c b/tests/check/libs/videodecoder.c index bd3531fb6..1fc9f36bf 100644 --- a/tests/check/libs/videodecoder.c +++ b/tests/check/libs/videodecoder.c @@ -680,6 +680,57 @@ GST_START_TEST (videodecoder_buffer_after_segment) GST_END_TEST; +/* make sure that the segment event is pushed before the gap */ +GST_START_TEST (videodecoder_first_data_is_gap) +{ + GstSegment segment; + GList *events_iter; + + setup_videodecodertester (NULL, NULL); + + 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 a gap */ + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_gap (0, + GST_SECOND))); + 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); + } + + /* Make sure the gap was pushed */ + { + GstEvent *gap = events_iter->data; + fail_unless (GST_EVENT_TYPE (gap) == GST_EVENT_GAP); + events_iter = g_list_next (events_iter); + } + fail_unless (events_iter == NULL); + + cleanup_videodecodertest (); +} + +GST_END_TEST; GST_START_TEST (videodecoder_backwards_playback) { @@ -1041,6 +1092,7 @@ gst_videodecoder_suite (void) tcase_add_test (tc, videodecoder_playback_with_events); tcase_add_test (tc, videodecoder_playback_first_frames_not_decoded); tcase_add_test (tc, videodecoder_buffer_after_segment); + tcase_add_test (tc, videodecoder_first_data_is_gap); tcase_add_test (tc, videodecoder_backwards_playback); tcase_add_test (tc, videodecoder_backwards_buffer_after_segment); |