diff options
author | Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> | 2011-01-12 16:39:22 +0000 |
---|---|---|
committer | Tim-Philipp Müller <tim.muller@collabora.co.uk> | 2011-01-14 00:28:41 +0000 |
commit | 0b790b663c1423948794302b6ed88cefab236cff (patch) | |
tree | 13670bc0baf0fba1cc326df016bc7e5239871350 | |
parent | b55775a9d39513d41da2cdc7cc6dc6b9013a769f (diff) |
kate: ensure the kate pad does not shoot ahead of the video pad
Sync both pads by waiting in the kate chain function.
Do not reset our internal segment from segment updates, in order
to be able to map video running time to kate running time, to
give libtiger the timestamp it expects. This allows us to use
running time to sync to video, which is The Right Way.
https://bugzilla.gnome.org/show_bug.cgi?id=600929
-rw-r--r-- | ext/kate/gstkatetiger.c | 50 | ||||
-rw-r--r-- | ext/kate/gstkatetiger.h | 1 | ||||
-rw-r--r-- | ext/kate/gstkateutil.c | 10 |
3 files changed, 57 insertions, 4 deletions
diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index 932bb4259..81ac6f755 100644 --- a/ext/kate/gstkatetiger.c +++ b/ext/kate/gstkatetiger.c @@ -309,6 +309,7 @@ gst_kate_tiger_init (GstKateTiger * tiger, GstKateTigerClass * gclass) GST_DEBUG_OBJECT (tiger, "gst_kate_tiger_init"); tiger->mutex = g_mutex_new (); + tiger->cond = g_cond_new (); tiger->katesinkpad = gst_pad_new_from_static_template (&kate_sink_factory, "subtitle_sink"); @@ -371,6 +372,9 @@ gst_kate_tiger_dispose (GObject * object) tiger->default_font_desc = NULL; } + g_cond_free (tiger->cond); + tiger->cond = NULL; + g_mutex_free (tiger->mutex); tiger->mutex = NULL; @@ -631,6 +635,34 @@ gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf) gst_object_unref (tagpad); } + /* we want to avoid shooting ahead of the video stream, or we will + get segment updates which will place us ahead of it, and we won't + be able to convert a video timestamp back into a kate timestamp */ + if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) { + while (1) { + gint64 kate_time, video_time; + kate_time = + gst_segment_to_running_time (&tiger->decoder.kate_segment, + GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf)); + video_time = + gst_segment_to_running_time (&tiger->video_segment, GST_FORMAT_TIME, + tiger->video_segment.last_stop); + GST_DEBUG_OBJECT (tiger, "Kate time %.2f, video time %.2f (kts %ld)", + kate_time / (float) GST_SECOND, video_time / (float) GST_SECOND, + (long) GST_BUFFER_TIMESTAMP (buf)); + if (kate_time <= video_time) { + break; + } + GST_LOG_OBJECT (tiger, "Waiting to return from chain function"); + g_cond_wait (tiger->cond, tiger->mutex); + if (tiger->decoder.kate_flushing) { + GST_DEBUG_OBJECT (tiger, "Flushing while waiting"); + break; + } + GST_LOG_OBJECT (tiger, "Woken up, checking time again"); + } + } + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); gst_object_unref (tiger); @@ -669,8 +701,13 @@ gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps) static gdouble gst_kate_tiger_get_time (GstKateTiger * tiger) { - return gst_segment_to_running_time (&tiger->video_segment, GST_FORMAT_TIME, - tiger->video_segment.last_stop) / (gdouble) GST_SECOND; + gint64 rt = + gst_segment_to_running_time (&tiger->video_segment, GST_FORMAT_TIME, + tiger->video_segment.last_stop); + gint64 pos = + gst_segment_to_position (&tiger->decoder.kate_segment, GST_FORMAT_TIME, + rt); + return pos / (gdouble) GST_SECOND; } static GstFlowReturn @@ -695,6 +732,7 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf) if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) { gst_segment_set_last_stop (&tiger->video_segment, GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf)); + g_cond_broadcast (tiger->cond); } /* draw on it */ @@ -755,6 +793,8 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG_OBJECT (tiger, "PAUSED -> READY, clearing kate state"); GST_KATE_TIGER_MUTEX_LOCK (tiger); + gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE); + g_cond_broadcast (tiger->cond); if (tiger->tr) { tiger_renderer_destroy (tiger->tr); tiger->tr = NULL; @@ -904,6 +944,7 @@ gst_kate_tiger_handle_kate_event (GstPad * pad, GstEvent * event) case GST_EVENT_NEWSEGMENT: GST_INFO_OBJECT (tiger, "New segment on Kate pad"); GST_KATE_TIGER_MUTEX_LOCK (tiger); + g_cond_broadcast (tiger->cond); gst_kate_util_decoder_base_new_segment_event (&tiger->decoder, event); GST_KATE_TIGER_MUTEX_UNLOCK (tiger); gst_event_unref (event); @@ -912,6 +953,7 @@ gst_kate_tiger_handle_kate_event (GstPad * pad, GstEvent * event) GST_KATE_TIGER_MUTEX_LOCK (tiger); gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE); GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + g_cond_broadcast (tiger->cond); gst_event_unref (event); break; case GST_EVENT_FLUSH_STOP: @@ -924,6 +966,9 @@ gst_kate_tiger_handle_kate_event (GstPad * pad, GstEvent * event) /* we ignore this, it just means we don't have anymore Kate packets, but the Tiger renderer will still draw (if appropriate) on incoming video */ GST_INFO_OBJECT (tiger, "EOS on Kate pad"); + GST_KATE_TIGER_MUTEX_LOCK (tiger); + g_cond_broadcast (tiger->cond); + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); gst_event_unref (event); break; default: @@ -1000,6 +1045,7 @@ gst_kate_tiger_handle_video_event (GstPad * pad, GstEvent * event) gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED); tiger->video_flushing = TRUE; GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + g_cond_broadcast (tiger->cond); res = gst_pad_event_default (pad, event); break; case GST_EVENT_FLUSH_STOP: diff --git a/ext/kate/gstkatetiger.h b/ext/kate/gstkatetiger.h index 48884b1c2..d3880b32b 100644 --- a/ext/kate/gstkatetiger.h +++ b/ext/kate/gstkatetiger.h @@ -94,6 +94,7 @@ struct _GstKateTiger gboolean swap_rgb; GMutex *mutex; + GCond *cond; GstSegment video_segment; gboolean video_flushing; diff --git a/ext/kate/gstkateutil.c b/ext/kate/gstkateutil.c index b873d0aca..46ae19b9d 100644 --- a/ext/kate/gstkateutil.c +++ b/ext/kate/gstkateutil.c @@ -454,8 +454,14 @@ gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder, " %" GST_TIME_FORMAT " position %" GST_TIME_FORMAT, update, rate, arate, format, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time)); - gst_segment_set_newsegment_full (&decoder->kate_segment, update, rate, - arate, format, start, stop, time); + if (!update) { + /* Tiger uses this segment is used to remap the video running time to the + Kate running time. The sending of segment updates to keep streams in sync + does kinda rain on our parade though, and since we don't need these, + we just ignore those here */ + gst_segment_set_newsegment_full (&decoder->kate_segment, update, rate, + arate, format, start, stop, time); + } } gboolean |