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
This commit is contained in:
Mark Nauwelaerts 2012-07-11 13:45:14 +02:00
parent 76ddd498e2
commit 76b147e803
3 changed files with 52 additions and 4 deletions

View file

@ -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);

View file

@ -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. */

View file

@ -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