summaryrefslogtreecommitdiff
path: root/gst/dvbsuboverlay
diff options
context:
space:
mode:
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2012-07-11 13:45:14 +0200
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2012-07-11 13:45:14 +0200
commit76b147e803792da1a6cc11dd78fc2ea7c765c90a (patch)
treeb69d063f5dc669933db8802aa382a8bd51371c69 /gst/dvbsuboverlay
parent76ddd498e2198aa3c879e0248acdd2fe286c206a (diff)
downloadgstreamer-plugins-bad-76b147e803792da1a6cc11dd78fc2ea7c765c90a.tar.gz
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 Conflicts: gst/dvbsuboverlay/gstdvbsuboverlay.c
Diffstat (limited to 'gst/dvbsuboverlay')
-rw-r--r--gst/dvbsuboverlay/dvb-sub.c14
-rw-r--r--gst/dvbsuboverlay/gstdvbsuboverlay.c36
-rw-r--r--gst/dvbsuboverlay/gstdvbsuboverlay.h6
3 files changed, 52 insertions, 4 deletions
diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c
index 21061a358..a1326b4ec 100644
--- a/gst/dvbsuboverlay/dvb-sub.c
+++ b/gst/dvbsuboverlay/dvb-sub.c
@@ -1187,7 +1187,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;
@@ -1195,7 +1195,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);
@@ -1386,7 +1386,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");
@@ -1453,7 +1459,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 41edd5785..35f1950cf 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,
@@ -138,6 +140,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);
@@ -178,6 +185,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);
}
@@ -220,6 +230,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;
g_mutex_init (&render->dvbsub_mutex);
gst_dvbsub_overlay_flush_subtitles (render);
@@ -266,6 +277,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;
@@ -285,6 +299,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;
@@ -718,10 +735,17 @@ gst_dvbsub_overlay_process_text (GstDVBSubOverlay * overlay, GstBuffer * buffer,
g_mutex_lock (&overlay->dvbsub_mutex);
dvb_sub_feed_with_pts (overlay->dvb_sub, pts, map.data, map.size);
+ overlay->pending_sub = TRUE;
g_mutex_unlock (&overlay->dvbsub_mutex);
gst_buffer_unmap (buffer, &map);
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
@@ -741,6 +765,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
@@ -768,6 +793,17 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstObject * parent,
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 b2b79005c..b8cf482a5 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;
@@ -58,6 +59,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