summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2012-07-09 18:07:24 +0200
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2012-07-09 18:19:12 +0200
commita926d6d1186410ff83e234877cd59af6db6c2613 (patch)
treebc383cf341b4c9d2012d68eddeeff1fe94dae715
parenta908339fee1e641961764f3281720aca1e414630 (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.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 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