From 3d09a3b18ab52e72c4c73b2b2e8dc7033d6c8b36 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Wed, 1 Dec 2010 06:01:15 +0200 Subject: [PATCH] dvbsuboverlay: Implement subtitle queueing and syncing with video Push incoming subtitle pages in a FIFO queue (pending_subtitles) and dequeue the head when it's time to show it (when video running time reaches the subtitle page running time). Keep the subtitle page, that is supposed to be blended on top of video currently, in a separate object variable (current_subtitle). As a next step we can then pre-render current_subtitle to a better to blend format. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 37 +++++++++++++++++++++++----- gst/dvbsuboverlay/gstdvbsuboverlay.h | 12 +++------ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index c62957a2af..9d86c78366 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -234,6 +234,9 @@ gst_dvbsub_overlay_init (GstDVBSubOverlay * render, render->subtitle_mutex = g_mutex_new (); render->subtitle_cond = g_cond_new (); + render->current_subtitle = NULL; + render->pending_subtitles = g_queue_new (); + render->renderer_init_ok = FALSE; render->enable = TRUE; @@ -270,6 +273,11 @@ gst_dvbsub_overlay_finalize (GObject * object) if (overlay->subtitle_cond) g_cond_free (overlay->subtitle_cond); + if (overlay->pending_subtitles) { + /* FIXME: Free up contents */ + g_queue_free (overlay->pending_subtitles); + } + if (overlay->dvb_sub) { g_object_unref (overlay->dvb_sub); } @@ -930,7 +938,7 @@ new_dvb_subtitles_cb (DvbSub * dvb_sub, DVBSubtitles * subs, gpointer user_data) subs->page_time_out, subs->num_rects, subs->pts, GST_TIME_ARGS (subs->pts)); //GST_OBJECT_LOCK (overlay); - overlay->subtitle_buffer = subs->num_rects; + g_queue_push_tail (overlay->pending_subtitles, subs); //GST_OBJECT_UNLOCK (overlay); } @@ -1045,8 +1053,6 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) GST_DEBUG_OBJECT (overlay, "SUBTITLE real running time: %" GST_TIME_FORMAT, GST_TIME_ARGS (sub_running_time)); - overlay->subtitle_buffer = 0; /*buffer FIXME: Need to do buffering elsewhere */ - /* That's a new text buffer we need to render */ /*overlay->need_render = TRUE; *//* FIXME: Actually feed it to libdvbsub and set need_render on a callback */ @@ -1067,6 +1073,7 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (GST_PAD_PARENT (pad)); GstFlowReturn ret = GST_FLOW_OK; gint64 start, stop; + GstClockTime vid_running_time; if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) goto missing_timestamp; @@ -1086,13 +1093,29 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) stop = start + GST_BUFFER_DURATION (buffer); } + vid_running_time = + gst_segment_to_running_time (&overlay->video_segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buffer)); + + GST_DEBUG_OBJECT (overlay, "Video running time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (vid_running_time)); + /* FIXME: Probably update last_stop somewhere */ /* FIXME: Segment clipping code */ - if (overlay->subtitle_buffer > 0) { - GST_DEBUG_OBJECT (overlay, "Should be rendering %u regions", - overlay->subtitle_buffer); + if (!g_queue_is_empty (overlay->pending_subtitles)) { + DVBSubtitles *pending_sub = g_queue_peek_head (overlay->pending_subtitles); + if (vid_running_time >= pending_sub->pts) { + GST_DEBUG_OBJECT (overlay, + "Time to show the next subtitle page (%" GST_TIME_FORMAT " >= %" + GST_TIME_FORMAT ") - it has %u regions", + GST_TIME_ARGS (vid_running_time), GST_TIME_ARGS (pending_sub->pts), + pending_sub->num_rects); + dvb_subtitles_free (overlay->current_subtitle); + overlay->current_subtitle = g_queue_pop_head (overlay->pending_subtitles); + /* FIXME: Pre-convert current_subtitle to a quick-blend format, num_rects=0 means that there are no regions, e.g, a subtitle "clear" happened */ + } } ret = gst_pad_push (overlay->srcpad, buffer); @@ -1216,6 +1239,8 @@ gst_dvbsub_overlay_event_text (GstPad * pad, GstEvent * event) break; case GST_EVENT_FLUSH_START: GST_DEBUG_OBJECT (render, "begin flushing"); + + /* FIXME: Reset subtitles queue and any other state */ #if 0 // FIXME g_mutex_lock (render->ass_mutex); if (render->ass_track) { diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.h b/gst/dvbsuboverlay/gstdvbsuboverlay.h index bf4c97825e..62290c777e 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.h +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.h @@ -54,14 +54,10 @@ struct _GstDVBSubOverlay gint fps_n, fps_d; GstAssRenderBlitFunction blit; - guint subtitle_buffer; /* FIXME: This should hold the pre-rendered - * subtitle regions for fast blending on top - * of each frame. Currently just a number of - * active regions that ought to get blended, - * to get all the timing code working, - * leaving the actual conversion from - * libdvbsub to a suitable cache format and - * blending to later */ + DVBSubtitles *current_subtitle; /* The currently active set of subtitle regions, if any */ + GQueue *pending_subtitles; /* A queue of raw subtitle region sets with + * metadata that are waiting their running time */ + GMutex *subtitle_mutex; GCond *subtitle_cond; /* to signal removal of a queued text * buffer, arrival of a text buffer,