diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-scte-section.c b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-scte-section.c index 88e99aac13..e711f2d33e 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-scte-section.c +++ b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-scte-section.c @@ -43,12 +43,18 @@ static GstMpegtsSCTESpliceEvent * _gst_mpegts_scte_splice_event_copy (GstMpegtsSCTESpliceEvent * event) { - return g_slice_dup (GstMpegtsSCTESpliceEvent, event); + GstMpegtsSCTESpliceEvent *copy = + g_slice_dup (GstMpegtsSCTESpliceEvent, event); + + copy->components = g_ptr_array_ref (event->components); + + return copy; } static void _gst_mpegts_scte_splice_event_free (GstMpegtsSCTESpliceEvent * event) { + g_ptr_array_unref (event->components); g_slice_free (GstMpegtsSCTESpliceEvent, event); } @@ -56,6 +62,71 @@ G_DEFINE_BOXED_TYPE (GstMpegtsSCTESpliceEvent, gst_mpegts_scte_splice_event, (GBoxedCopyFunc) _gst_mpegts_scte_splice_event_copy, (GFreeFunc) _gst_mpegts_scte_splice_event_free); +static GstMpegtsSCTESpliceComponent * +_gst_mpegts_scte_splice_component_copy (GstMpegtsSCTESpliceComponent * + component) +{ + return g_slice_dup (GstMpegtsSCTESpliceComponent, component); +} + +static void +_gst_mpegts_scte_splice_component_free (GstMpegtsSCTESpliceComponent * + component) +{ + g_slice_free (GstMpegtsSCTESpliceComponent, component); +} + +G_DEFINE_BOXED_TYPE (GstMpegtsSCTESpliceComponent, + gst_mpegts_scte_splice_component, + (GBoxedCopyFunc) _gst_mpegts_scte_splice_component_copy, + (GFreeFunc) _gst_mpegts_scte_splice_component_free); + +static GstMpegtsSCTESpliceComponent * +_parse_splice_component (GstMpegtsSCTESpliceEvent * event, guint8 ** orig_data, + guint8 * end) +{ + GstMpegtsSCTESpliceComponent *component = + g_slice_new0 (GstMpegtsSCTESpliceComponent); + guint8 *data = *orig_data; + + if (data + 1 + 6 > end) + goto error; + + component->tag = *data; + data += 1; + + if (event->insert_event && event->splice_immediate_flag == 0) { + component->splice_time_specified = *data >> 7; + if (component->splice_time_specified) { + component->splice_time = ((guint64) (*data & 0x01)) << 32; + data += 1; + component->splice_time += GST_READ_UINT32_BE (data); + data += 4; + GST_LOG ("component %u splice_time %" G_GUINT64_FORMAT " (%" + GST_TIME_FORMAT ")", component->tag, component->splice_time, + GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (component->splice_time))); + } else { + data += 1; + } + } else if (!event->insert_event) { + component->utc_splice_time = GST_READ_UINT32_BE (data); + GST_LOG ("component %u utc_splice_time %u", component->tag, + component->utc_splice_time); + data += 4; + } + + *orig_data = data; + + return component; + +error: + { + if (event) + _gst_mpegts_scte_splice_event_free (event); + return NULL; + } +} + static GstMpegtsSCTESpliceEvent * _parse_splice_event (guint8 ** orig_data, guint8 * end, gboolean insert_event) { @@ -66,6 +137,9 @@ _parse_splice_event (guint8 ** orig_data, guint8 * end, gboolean insert_event) if (data + 5 + 6 > end) goto error; + event->components = g_ptr_array_new_with_free_func ((GDestroyNotify) + _gst_mpegts_scte_splice_component_free); + event->insert_event = insert_event; event->splice_event_id = GST_READ_UINT32_BE (data); GST_LOG ("splice_event_id: 0x%08x", event->splice_event_id); @@ -97,26 +171,36 @@ _parse_splice_event (guint8 ** orig_data, guint8 * end, gboolean insert_event) data += 1; if (event->program_splice_flag == 0) { - GST_ERROR ("Component splice flag not supported !"); - goto error; - } + guint component_count = *data; + guint i; - if (insert_event && event->splice_immediate_flag == 0) { - event->program_splice_time_specified = *data >> 7; - if (event->program_splice_time_specified) { - event->program_splice_time = ((guint64) (*data & 0x01)) << 32; - data += 1; - event->program_splice_time += GST_READ_UINT32_BE (data); + data += 1; + + for (i = 0; i < component_count; i++) { + GstMpegtsSCTESpliceComponent *component = + _parse_splice_component (event, &data, end); + if (component == NULL) + goto error; + g_ptr_array_add (event->components, component); + } + } else { + if (insert_event && event->splice_immediate_flag == 0) { + event->program_splice_time_specified = *data >> 7; + if (event->program_splice_time_specified) { + event->program_splice_time = ((guint64) (*data & 0x01)) << 32; + data += 1; + event->program_splice_time += GST_READ_UINT32_BE (data); + data += 4; + GST_LOG ("program_splice_time %" G_GUINT64_FORMAT " (%" + GST_TIME_FORMAT ")", event->program_splice_time, + GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (event->program_splice_time))); + } else + data += 1; + } else if (!insert_event) { + event->utc_splice_time = GST_READ_UINT32_BE (data); + GST_LOG ("utc_splice_time %u", event->utc_splice_time); data += 4; - GST_LOG ("program_splice_time %" G_GUINT64_FORMAT " (%" GST_TIME_FORMAT - ")", event->program_splice_time, - GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (event->program_splice_time))); - } else - data += 1; - } else if (!insert_event) { - event->utc_splice_time = GST_READ_UINT32_BE (data); - GST_LOG ("utc_splice_time %u", event->utc_splice_time); - data += 4; + } } if (event->duration_flag) { @@ -513,10 +597,33 @@ gst_mpegts_scte_splice_event_new (void) /* Non-0 Default values */ event->program_splice_flag = TRUE; + event->components = g_ptr_array_new_with_free_func ((GDestroyNotify) + _gst_mpegts_scte_splice_component_free); + return event; } +/** + * gst_mpegts_scte_splice_component_new: + * tag: the elementary PID stream identifier + * + * Allocates and initializes a #GstMpegtsSCTESpliceComponent. + * + * Returns: (transfer full): A newly allocated #GstMpegtsSCTESpliceComponent + * Since: 1.20 + */ +GstMpegtsSCTESpliceComponent * +gst_mpegts_scte_splice_component_new (guint8 tag) +{ + GstMpegtsSCTESpliceComponent *component = + g_slice_new0 (GstMpegtsSCTESpliceComponent); + + component->tag = tag; + + return component; +} + static gboolean _packetize_sit (GstMpegtsSection * section) { diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-scte-section.h b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-scte-section.h index 26946263ff..498df348b6 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-scte-section.h +++ b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-scte-section.h @@ -103,6 +103,18 @@ typedef enum { } GstMpegtsSectionSCTETableID; +#define GST_TYPE_MPEGTS_SCTE_SPLICE_COMPONENT (gst_mpegts_scte_splice_component_get_type()) +typedef struct _GstMpegtsSCTESpliceComponent GstMpegtsSCTESpliceComponent; + +struct _GstMpegtsSCTESpliceComponent { + guint8 tag; + + gboolean splice_time_specified; /* Only valid for insert_event */ + guint64 splice_time; /* Only valid for insert_event */ + + guint32 utc_splice_time; /* Only valid for !insert_event (schedule) */ +}; + /* Splice Information Table (SIT) */ #define GST_TYPE_MPEGTS_SCTE_SPLICE_EVENT (gst_mpegts_scte_splice_event_get_type()) typedef struct _GstMpegtsSCTESpliceEvent GstMpegtsSCTESpliceEvent; @@ -116,14 +128,17 @@ struct _GstMpegtsSCTESpliceEvent { /* If splice_event_cancel_indicator == 0 */ gboolean out_of_network_indicator; - gboolean program_splice_flag; /* NOTE: Only program splice are supported */ + gboolean program_splice_flag; gboolean duration_flag; gboolean splice_immediate_flag; /* Only valid for insert_event */ - gboolean program_splice_time_specified; /* Only valid for insert_event */ - guint64 program_splice_time; /* Only valid for insert_event */ - guint32 utc_splice_time; /* Only valid for !insert_event (schedule) */ + gboolean program_splice_time_specified; /* Only valid for insert_event && program_splice */ + guint64 program_splice_time; /* Only valid for insert_event && program_splice */ + + guint32 utc_splice_time; /* Only valid for !insert_event (schedule) && program_splice */ + + GPtrArray *components; /* Only valid for !program_splice */ gboolean break_duration_auto_return; guint64 break_duration; @@ -219,6 +234,12 @@ const GstMpegtsSCTESIT *gst_mpegts_section_get_scte_sit (GstMpegtsSection *secti GST_MPEGTS_API GstMpegtsSection *gst_mpegts_section_from_scte_sit (GstMpegtsSCTESIT * sit, guint16 pid); +GST_MPEGTS_API +GType gst_mpegts_scte_splice_component_get_type (void); + +GST_MPEGTS_API +GstMpegtsSCTESpliceComponent *gst_mpegts_scte_splice_component_new (guint8 tag); + G_END_DECLS