diff options
author | Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> | 2012-07-09 18:07:24 +0200 |
---|---|---|
committer | Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> | 2012-07-09 18:19:12 +0200 |
commit | a926d6d1186410ff83e234877cd59af6db6c2613 (patch) | |
tree | bc383cf341b4c9d2012d68eddeeff1fe94dae715 | |
parent | a908339fee1e641961764f3281720aca1e414630 (diff) |
dvbsuboverlay: properly force end-of-display-set
... which is upon receiving new data with different PTS spec-wise,
or optionally upon each packet of subtitle data if desired by property.
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=669310
-rw-r--r-- | gst/dvbsuboverlay/dvb-sub.c | 14 | ||||
-rw-r--r-- | gst/dvbsuboverlay/gstdvbsuboverlay.c | 36 | ||||
-rw-r--r-- | gst/dvbsuboverlay/gstdvbsuboverlay.h | 6 |
3 files changed, 52 insertions, 4 deletions
diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index 097268bee..403dcb3ae 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -1185,7 +1185,7 @@ _dvb_sub_parse_display_definition_segment (DvbSub * dvb_sub, guint8 * buf, static gint _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, - guint8 * buf, gint buf_size, guint64 pts) + guint64 pts) { DVBSubRegionDisplay *display; DVBSubtitles *sub; @@ -1193,7 +1193,7 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, guint32 *clut_table; int i; - GST_DEBUG ("DISPLAY SET END: page_id = %u, length = %d", page_id, buf_size); + GST_DEBUG ("DISPLAY SET END: page_id = %u, length = %d", page_id); sub = g_slice_new0 (DVBSubtitles); @@ -1384,7 +1384,13 @@ dvb_sub_feed_with_pts (DvbSub * dvb_sub, guint64 pts, guint8 * data, gint len) GST_DEBUG ("pts=%" G_GUINT64_FORMAT " and length %d", pts, len); - g_return_val_if_fail (data != NULL, -1); + g_return_val_if_fail (data != NULL || len == 0, -1); + + if (G_UNLIKELY (data == NULL)) { + GST_DEBUG ("no data; forcing end-of-display-set"); + _dvb_sub_parse_end_of_display_set (dvb_sub, 0, pts); + return 0; + } if (len <= 3) { /* len(0x20 0x00 end_of_PES_data_field_marker) */ GST_WARNING ("Data length too short"); @@ -1451,7 +1457,7 @@ dvb_sub_feed_with_pts (DvbSub * dvb_sub, guint64 pts, guint8 * data, gint len) break; case DVB_SUB_SEGMENT_END_OF_DISPLAY_SET: GST_DEBUG ("End of display set at buffer pos %u", pos); - _dvb_sub_parse_end_of_display_set (dvb_sub, page_id, data + pos, segment_len, pts); /* FIXME: Not sure about args */ + _dvb_sub_parse_end_of_display_set (dvb_sub, page_id, pts); /* FIXME: Not sure about args */ break; default: GST_FIXME ("Unhandled segment type 0x%x", segment_type); diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 5cd7a7fb8..80f0ea25a 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -57,10 +57,12 @@ enum PROP_0, PROP_ENABLE, PROP_MAX_PAGE_TIMEOUT, + PROP_FORCE_END }; #define DEFAULT_ENABLE (TRUE) #define DEFAULT_MAX_PAGE_TIMEOUT (0) +#define DEFAULT_FORCE_END (FALSE) static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, @@ -153,6 +155,11 @@ gst_dvbsub_overlay_class_init (GstDVBSubOverlayClass * klass) 0, G_MAXINT, DEFAULT_MAX_PAGE_TIMEOUT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_FORCE_END, + g_param_spec_boolean ("force-end", "Force End", + "Assume PES-aligned subtitles and force end-of-display", + DEFAULT_FORCE_END, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_change_state); } @@ -181,6 +188,9 @@ gst_dvbsub_overlay_flush_subtitles (GstDVBSubOverlay * render) dvb_sub_set_callbacks (render->dvb_sub, &dvbsub_callbacks, render); } + render->last_text_pts = GST_CLOCK_TIME_NONE; + render->pending_sub = FALSE; + g_mutex_unlock (render->dvbsub_mutex); } @@ -234,6 +244,7 @@ gst_dvbsub_overlay_init (GstDVBSubOverlay * render, render->enable = DEFAULT_ENABLE; render->max_page_timeout = DEFAULT_MAX_PAGE_TIMEOUT; + render->force_end = DEFAULT_FORCE_END; render->dvbsub_mutex = g_mutex_new (); gst_dvbsub_overlay_flush_subtitles (render); @@ -281,6 +292,9 @@ gst_dvbsub_overlay_set_property (GObject * object, guint prop_id, case PROP_MAX_PAGE_TIMEOUT: g_atomic_int_set (&overlay->max_page_timeout, g_value_get_int (value)); break; + case PROP_FORCE_END: + g_atomic_int_set (&overlay->force_end, g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -300,6 +314,9 @@ gst_dvbsub_overlay_get_property (GObject * object, guint prop_id, case PROP_MAX_PAGE_TIMEOUT: g_value_set_int (value, g_atomic_int_get (&overlay->max_page_timeout)); break; + case PROP_FORCE_END: + g_value_set_boolean (value, g_atomic_int_get (&overlay->force_end)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -717,8 +734,15 @@ gst_dvbsub_overlay_process_text (GstDVBSubOverlay * overlay, GstBuffer * buffer, GST_DEBUG_OBJECT (overlay, "Feeding %u bytes to libdvbsub", size); g_mutex_lock (overlay->dvbsub_mutex); dvb_sub_feed_with_pts (overlay->dvb_sub, pts, data, size); + overlay->pending_sub = TRUE; g_mutex_unlock (overlay->dvbsub_mutex); gst_buffer_unref (buffer); + + if (overlay->pending_sub && overlay->force_end) { + GST_DEBUG_OBJECT (overlay, "forcing subtitle end"); + dvb_sub_feed_with_pts (overlay->dvb_sub, overlay->last_text_pts, NULL, 0); + g_assert (overlay->pending_sub == FALSE); + } } static void @@ -738,6 +762,7 @@ new_dvb_subtitles_cb (DvbSub * dvb_sub, DVBSubtitles * subs, gpointer user_data) GST_TIME_ARGS (subs->pts)); g_queue_push_tail (overlay->pending_subtitles, subs); + overlay->pending_sub = FALSE; } static GstFlowReturn @@ -785,6 +810,17 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) return GST_FLOW_OK; } + /* spec states multiple PES packets may have same PTS, + * and same PTS packets make up a display set */ + if (overlay->pending_sub && + overlay->last_text_pts != GST_BUFFER_TIMESTAMP (buffer)) { + GST_DEBUG_OBJECT (overlay, "finishing previous subtitle"); + dvb_sub_feed_with_pts (overlay->dvb_sub, overlay->last_text_pts, NULL, 0); + overlay->pending_sub = FALSE; + } + + overlay->last_text_pts = GST_BUFFER_TIMESTAMP (buffer); + /* As the passed start and stop is equal, we shouldn't need to care about out of segment at all, * the subtitle data for the PTS is completely out of interest to us. A given display set must * carry the same PTS value. */ diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.h b/gst/dvbsuboverlay/gstdvbsuboverlay.h index 012c728eb..2e30b4e3a 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.h +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.h @@ -45,6 +45,7 @@ struct _GstDVBSubOverlay /* properties */ gboolean enable; gint max_page_timeout; + gboolean force_end; /* <private> */ GstSegment video_segment; @@ -61,6 +62,11 @@ struct _GstDVBSubOverlay GMutex *dvbsub_mutex; /* protects the queue and the DvbSub instance */ DvbSub *dvb_sub; + + /* subtitle data submitted to dvb_sub but no sub received yet */ + gboolean pending_sub; + /* last text pts */ + GstClockTime last_text_pts; }; struct _GstDVBSubOverlayClass |