summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst-libs/gst/video/gstvideodecoder.c43
-rw-r--r--tests/check/libs/videodecoder.c52
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);