mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
tsdemux: Expose send-scte35-events property
When enabled, SCTE 35 sections (eg ad placement opportunities) are forwarded as events donwstream. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/913>
This commit is contained in:
parent
b2718ed6cf
commit
1ca08bff57
3 changed files with 128 additions and 0 deletions
|
@ -210818,6 +210818,18 @@
|
|||
"readable": true,
|
||||
"type": "gint",
|
||||
"writable": true
|
||||
},
|
||||
"send-scte35-events": {
|
||||
"blurb": "Whether SCTE 35 sections should be forwarded as events",
|
||||
"conditionally-available": false,
|
||||
"construct": false,
|
||||
"construct-only": false,
|
||||
"controllable": false,
|
||||
"default": "false",
|
||||
"mutable": "null",
|
||||
"readable": true,
|
||||
"type": "gboolean",
|
||||
"writable": true
|
||||
}
|
||||
},
|
||||
"rank": "primary",
|
||||
|
|
|
@ -297,6 +297,7 @@ enum
|
|||
PROP_PROGRAM_NUMBER,
|
||||
PROP_EMIT_STATS,
|
||||
PROP_LATENCY,
|
||||
PROP_SEND_SCTE35_EVENTS,
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
|
@ -340,6 +341,7 @@ static gboolean push_event (MpegTSBase * base, GstEvent * event);
|
|||
static gboolean sink_query (MpegTSBase * base, GstQuery * query);
|
||||
static void gst_ts_demux_check_and_sync_streams (GstTSDemux * demux,
|
||||
GstClockTime time);
|
||||
static void handle_psi (MpegTSBase * base, GstMpegtsSection * section);
|
||||
|
||||
static void
|
||||
_extra_init (void)
|
||||
|
@ -395,6 +397,22 @@ gst_ts_demux_class_init (GstTSDemuxClass * klass)
|
|||
"Emit messages for every pcr/opcr/pts/dts", FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* mpegtsdemux:send-scte35-events:
|
||||
*
|
||||
* Whether SCTE 35 sections should be forwarded as events.
|
||||
*
|
||||
* When forwarding those, potential splice times are converted
|
||||
* to running time, and can be used by a downstream muxer to reinject
|
||||
* the sections.
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_SEND_SCTE35_EVENTS,
|
||||
g_param_spec_boolean ("send-scte35-events", "Send SCTE 35 events",
|
||||
"Whether SCTE 35 sections should be forwarded as events", FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_LATENCY,
|
||||
g_param_spec_int ("latency", "Latency",
|
||||
"Latency to add for smooth demuxing (in ms)", -1,
|
||||
|
@ -422,6 +440,7 @@ gst_ts_demux_class_init (GstTSDemuxClass * klass)
|
|||
ts_class->reset = GST_DEBUG_FUNCPTR (gst_ts_demux_reset);
|
||||
ts_class->push = GST_DEBUG_FUNCPTR (gst_ts_demux_push);
|
||||
ts_class->push_event = GST_DEBUG_FUNCPTR (push_event);
|
||||
ts_class->handle_psi = GST_DEBUG_FUNCPTR (handle_psi);
|
||||
ts_class->sink_query = GST_DEBUG_FUNCPTR (sink_query);
|
||||
ts_class->program_started = GST_DEBUG_FUNCPTR (gst_ts_demux_program_started);
|
||||
ts_class->program_stopped = GST_DEBUG_FUNCPTR (gst_ts_demux_program_stopped);
|
||||
|
@ -495,6 +514,9 @@ gst_ts_demux_set_property (GObject * object, guint prop_id,
|
|||
case PROP_EMIT_STATS:
|
||||
demux->emit_statistics = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_SEND_SCTE35_EVENTS:
|
||||
demux->send_scte35_events = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_LATENCY:
|
||||
demux->latency = g_value_get_int (value);
|
||||
break;
|
||||
|
@ -516,6 +538,9 @@ gst_ts_demux_get_property (GObject * object, guint prop_id,
|
|||
case PROP_EMIT_STATS:
|
||||
g_value_set_boolean (value, demux->emit_statistics);
|
||||
break;
|
||||
case PROP_SEND_SCTE35_EVENTS:
|
||||
g_value_set_boolean (value, demux->send_scte35_events);
|
||||
break;
|
||||
case PROP_LATENCY:
|
||||
g_value_set_int (value, demux->latency);
|
||||
break;
|
||||
|
@ -1055,6 +1080,96 @@ push_event (MpegTSBase * base, GstEvent * event)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static GstMpegtsSCTESpliceEvent *
|
||||
copy_splice (GstMpegtsSCTESpliceEvent * splice)
|
||||
{
|
||||
return g_boxed_copy (GST_TYPE_MPEGTS_SCTE_SPLICE_EVENT, splice);
|
||||
}
|
||||
|
||||
static GstMpegtsSCTESIT *
|
||||
deep_copy_sit (const GstMpegtsSCTESIT * sit)
|
||||
{
|
||||
GstMpegtsSCTESIT *sit_copy = g_boxed_copy (GST_TYPE_MPEGTS_SCTE_SIT, sit);
|
||||
GPtrArray *splices_copy =
|
||||
g_ptr_array_copy (sit_copy->splices, (GCopyFunc) copy_splice, NULL);
|
||||
|
||||
g_ptr_array_unref (sit_copy->splices);
|
||||
sit_copy->splices = splices_copy;
|
||||
|
||||
return sit_copy;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_psi (MpegTSBase * base, GstMpegtsSection * section)
|
||||
{
|
||||
GstTSDemux *demux = (GstTSDemux *) base;
|
||||
|
||||
if (section->section_type == GST_MPEGTS_SECTION_SCTE_SIT) {
|
||||
GList *tmp;
|
||||
gboolean forward = FALSE;
|
||||
|
||||
if (demux->send_scte35_events) {
|
||||
for (tmp = demux->program->stream_list; tmp; tmp = tmp->next) {
|
||||
TSDemuxStream *stream = (TSDemuxStream *) tmp->data;
|
||||
|
||||
if (stream->stream.pid == section->pid) {
|
||||
forward = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a new section to travel through the pipeline, with splice
|
||||
* times translated from local time to running time */
|
||||
if (forward) {
|
||||
GstEvent *event;
|
||||
GstClockTime pts;
|
||||
guint i = 0;
|
||||
const GstMpegtsSCTESIT *sit = gst_mpegts_section_get_scte_sit (section);
|
||||
GstMpegtsSCTESIT *sit_copy = deep_copy_sit (sit);
|
||||
GstMpegtsSection *new_section;
|
||||
|
||||
if (sit_copy->splice_time_specified) {
|
||||
pts =
|
||||
mpegts_packetizer_pts_to_ts (base->packetizer,
|
||||
MPEGTIME_TO_GSTTIME (sit_copy->splice_time +
|
||||
sit_copy->pts_adjustment), demux->program->pcr_pid);
|
||||
sit_copy->splice_time =
|
||||
gst_segment_to_running_time (&base->out_segment, GST_FORMAT_TIME,
|
||||
pts);
|
||||
}
|
||||
|
||||
for (i = 0; i < sit_copy->splices->len; i++) {
|
||||
GstMpegtsSCTESpliceEvent *sevent =
|
||||
g_ptr_array_index (sit_copy->splices, i);
|
||||
if (sevent->program_splice_time_specified) {
|
||||
pts =
|
||||
mpegts_packetizer_pts_to_ts (base->packetizer,
|
||||
MPEGTIME_TO_GSTTIME (sevent->program_splice_time),
|
||||
demux->program->pcr_pid);
|
||||
sevent->program_splice_time =
|
||||
gst_segment_to_running_time (&base->out_segment, GST_FORMAT_TIME,
|
||||
pts);
|
||||
if (sevent->duration_flag) {
|
||||
sevent->break_duration =
|
||||
MPEGTIME_TO_GSTTIME (sevent->break_duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sit_copy->pts_adjustment = 0;
|
||||
|
||||
new_section = gst_mpegts_section_from_scte_sit (sit_copy, section->pid);
|
||||
|
||||
event = gst_event_new_mpegts_section (new_section);
|
||||
|
||||
gst_mpegts_section_unref (new_section);
|
||||
|
||||
push_event (base, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sink_query (MpegTSBase * base, GstQuery * query)
|
||||
{
|
||||
|
|
|
@ -76,6 +76,7 @@ struct _GstTSDemux
|
|||
gint requested_program_number; /* Required program number (ignore:-1) */
|
||||
guint program_number;
|
||||
gboolean emit_statistics;
|
||||
gboolean send_scte35_events;
|
||||
gint latency; /* latency in ms */
|
||||
|
||||
/*< private >*/
|
||||
|
|
Loading…
Reference in a new issue