diff --git a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json index aeeb7f4f31..a2d84a4907 100644 --- a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json @@ -214420,7 +214420,22 @@ "GObject" ], "kind": "object", - "properties": {}, + "properties": { + "stream-number": { + "blurb": "stream number", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "0", + "max": "31", + "min": "0", + "mutable": "null", + "readable": true, + "type": "gint", + "writable": true + } + }, "signals": {} } }, diff --git a/subprojects/gst-plugins-bad/gst/mpegtsmux/gstatscmux.c b/subprojects/gst-plugins-bad/gst/mpegtsmux/gstatscmux.c index a3b5fd7b30..33124be92e 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsmux/gstatscmux.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsmux/gstatscmux.c @@ -292,9 +292,9 @@ gst_atsc_mux_stream_get_es_descrs (TsMuxStream * stream, static TsMuxStream * gst_atsc_mux_create_new_stream (guint16 new_pid, - TsMuxStreamType stream_type, GstBaseTsMux * mpegtsmux) + TsMuxStreamType stream_type, guint stream_number, GstBaseTsMux * mpegtsmux) { - TsMuxStream *ret = tsmux_stream_new (new_pid, stream_type); + TsMuxStream *ret = tsmux_stream_new (new_pid, stream_type, stream_number); if (stream_type == ATSCMUX_ST_PS_AUDIO_EAC3) { ret->id = 0xBD; diff --git a/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.c b/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.c index 4cdd7e0236..655af51ebb 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.c @@ -93,6 +93,15 @@ GST_DEBUG_CATEGORY (gst_base_ts_mux_debug); G_DEFINE_TYPE (GstBaseTsMuxPad, gst_base_ts_mux_pad, GST_TYPE_AGGREGATOR_PAD); +#define DEFAULT_PAD_STREAM_NUMBER 0 + +enum +{ + PAD_PROP_0, + PAD_PROP_STREAM_NUMBER, +}; + + /* Internals */ static void @@ -163,6 +172,38 @@ gst_base_ts_mux_pad_dispose (GObject * obj) G_OBJECT_CLASS (gst_base_ts_mux_pad_parent_class)->dispose (obj); } +static void +gst_base_ts_mux_pad_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBaseTsMuxPad *ts_pad = GST_BASE_TS_MUX_PAD (object); + + switch (prop_id) { + case PAD_PROP_STREAM_NUMBER: + ts_pad->stream_number = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_ts_mux_pad_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstBaseTsMuxPad *ts_pad = GST_BASE_TS_MUX_PAD (object); + + switch (prop_id) { + case PAD_PROP_STREAM_NUMBER: + g_value_set_int (value, ts_pad->stream_number); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static void gst_base_ts_mux_pad_class_init (GstBaseTsMuxPadClass * klass) { @@ -170,9 +211,30 @@ gst_base_ts_mux_pad_class_init (GstBaseTsMuxPadClass * klass) GstAggregatorPadClass *gstaggpad_class = GST_AGGREGATOR_PAD_CLASS (klass); gobject_class->dispose = gst_base_ts_mux_pad_dispose; + gobject_class->set_property = gst_base_ts_mux_pad_set_property; + gobject_class->get_property = gst_base_ts_mux_pad_get_property; + gstaggpad_class->flush = gst_base_ts_mux_pad_flush; gst_type_mark_as_plugin_api (GST_TYPE_BASE_TS_MUX, 0); + + /** + * GstBaseTsMuxPad:stream-number: + * + * Set stream number for AVC video stream + * or AAC audio streams. + * + * video stream number is stored in 4 bits + * audio stream number is stored in 5 bits. + * See Table 2-22 of ITU-T H222.0 for details on AAC and AVC stream numbers + * + * Since: 1.24 + */ + g_object_class_install_property (gobject_class, PAD_PROP_STREAM_NUMBER, + g_param_spec_int ("stream-number", "stream number", + "stream number", 0x0, 0x1F, DEFAULT_PAD_STREAM_NUMBER, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + } static void @@ -728,9 +790,12 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux, } if (ts_pad->stream == NULL) { + gint stream_number = DEFAULT_PAD_STREAM_NUMBER; + + g_object_get (ts_pad, "stream-number", &stream_number, NULL); ts_pad->stream = - tsmux_create_stream (mux->tsmux, st, ts_pad->pid, ts_pad->language, - ts_pad->bitrate, ts_pad->max_bitrate); + tsmux_create_stream (mux->tsmux, st, stream_number, ts_pad->pid, + ts_pad->language, ts_pad->bitrate, ts_pad->max_bitrate); if (ts_pad->stream == NULL) goto error; } diff --git a/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.h b/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.h index f154d550b4..26ed74128d 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.h +++ b/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.h @@ -130,6 +130,7 @@ struct _GstBaseTsMuxPad gchar *language; gint bitrate; gint max_bitrate; + gint stream_number; }; struct _GstBaseTsMuxPadClass diff --git a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmux.c b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmux.c index bb3bc5475a..45c2272508 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmux.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmux.c @@ -703,9 +703,10 @@ tsmux_get_new_pid (TsMux * mux) * tsmux_create_stream: * @mux: a #TsMux * @stream_type: the stream type + * @stream_number: stream number * @pid: the PID of the new stream. * - * Create a new stream of @stream_type in the muxer session @mux. + * Create a new stream of @stream_type with @stream_number in the muxer session @mux. * * When @pid is set to #TSMUX_PID_AUTO, a new free PID will automatically * be allocated for the new stream. @@ -713,8 +714,8 @@ tsmux_get_new_pid (TsMux * mux) * Returns: a new #TsMuxStream. */ TsMuxStream * -tsmux_create_stream (TsMux * mux, guint stream_type, guint16 pid, - gchar * language, guint bitrate, guint max_bitrate) +tsmux_create_stream (TsMux * mux, guint stream_type, guint stream_number, + guint16 pid, gchar * language, guint bitrate, guint max_bitrate) { TsMuxStream *stream; guint16 new_pid; @@ -732,7 +733,9 @@ tsmux_create_stream (TsMux * mux, guint stream_type, guint16 pid, if (tsmux_find_stream (mux, new_pid)) return NULL; - stream = mux->new_stream_func (new_pid, stream_type, mux->new_stream_data); + stream = + mux->new_stream_func (new_pid, stream_type, stream_number, + mux->new_stream_data); mux->streams = g_list_prepend (mux->streams, stream); mux->nb_streams++; diff --git a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmux.h b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmux.h index 765f78f3d8..da90f51380 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmux.h +++ b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmux.h @@ -84,7 +84,7 @@ typedef struct TsMux TsMux; typedef gboolean (*TsMuxWriteFunc) (GstBuffer * buf, void *user_data, gint64 new_pcr); typedef void (*TsMuxAllocFunc) (GstBuffer ** buf, void *user_data); -typedef TsMuxStream * (*TsMuxNewStreamFunc) (guint16 new_pid, guint stream_type, void *user_data); +typedef TsMuxStream * (*TsMuxNewStreamFunc) (guint16 new_pid, guint stream_type, guint stream_number, void *user_data); struct TsMuxSection { TsMuxPacketInfo pi; @@ -223,7 +223,7 @@ gboolean tsmux_add_mpegts_si_section (TsMux * mux, GstMpegtsSection * gboolean tsmux_send_section (TsMux *mux, GstMpegtsSection *section); /* stream management */ -TsMuxStream * tsmux_create_stream (TsMux *mux, guint stream_type, guint16 pid, gchar *language, guint bitrate, guint max_bitrate); +TsMuxStream * tsmux_create_stream (TsMux *mux, guint stream_type, guint stream_number, guint16 pid, gchar *language, guint bitrate, guint max_bitrate); TsMuxStream * tsmux_find_stream (TsMux *mux, guint16 pid); gboolean tsmux_remove_stream (TsMux *mux, guint16 pid, TsMuxProgram *program); diff --git a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.c b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.c index a0905a4d35..f9f2f95274 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.c @@ -100,15 +100,18 @@ struct TsMuxStreamBuffer * tsmux_stream_new: * @pid: a PID * @stream_type: the stream type + * @stream_number: stream number * - * Create a new stream with PID of @pid and @stream_type. + * Create a new stream with PID of @pid and @stream_type, + * with stream number @stream_number. * * Returns: a new #TsMuxStream. */ TsMuxStream * -tsmux_stream_new (guint16 pid, guint stream_type) +tsmux_stream_new (guint16 pid, guint stream_type, guint stream_number) { TsMuxStream *stream = g_new0 (TsMuxStream, 1); + gboolean supports_user_specified_stream_number = FALSE; stream->state = TSMUX_STREAM_STATE_HEADER; stream->pi.pid = pid; @@ -125,10 +128,16 @@ tsmux_stream_new (guint16 pid, guint stream_type) case TSMUX_ST_VIDEO_MPEG4: case TSMUX_ST_VIDEO_H264: case TSMUX_ST_VIDEO_HEVC: - /* FIXME: Assign sequential IDs? */ - stream->id = 0xE0; + if (stream_number > 0xF) { + GST_WARNING + ("video stream number %d is greater than 0xF. Setting to 0.", + stream_number); + stream_number = 0; + } + stream->id = 0xE0 | stream_number; stream->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER; stream->is_video_stream = TRUE; + supports_user_specified_stream_number = TRUE; break; case TSMUX_ST_VIDEO_JP2K: stream->id = 0xBD; @@ -138,10 +147,16 @@ tsmux_stream_new (guint16 pid, guint stream_type) case TSMUX_ST_AUDIO_AAC: case TSMUX_ST_AUDIO_MPEG1: case TSMUX_ST_AUDIO_MPEG2: - /* FIXME: Assign sequential IDs? */ + if (stream_number > 0x1F) { + GST_WARNING + ("audio stream number %d is greater than 0x1F. Setting to 0.", + stream_number); + stream_number = 0; + } stream->is_audio = TRUE; - stream->id = 0xC0; + stream->id = 0xC0 | stream_number; stream->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER; + supports_user_specified_stream_number = TRUE; break; case TSMUX_ST_VIDEO_DIRAC: case TSMUX_ST_PS_AUDIO_LPCM: @@ -209,6 +224,12 @@ tsmux_stream_new (guint16 pid, guint stream_type) break; } + if (!supports_user_specified_stream_number && stream_number != 0) { + GST_WARNING + ("Attempt to set stream number %d for unsupported stream type %d", + stream_number, stream_type); + } + stream->first_ts = GST_CLOCK_STIME_NONE; stream->last_pts = GST_CLOCK_STIME_NONE; diff --git a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.h b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.h index 54cb6fe5c1..d0eaf1d0b2 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.h +++ b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.h @@ -225,7 +225,7 @@ struct TsMuxStream { }; /* stream management */ -TsMuxStream * tsmux_stream_new (guint16 pid, guint stream_type); +TsMuxStream * tsmux_stream_new (guint16 pid, guint stream_type, guint stream_number); void tsmux_stream_free (TsMuxStream *stream); guint16 tsmux_stream_get_pid (TsMuxStream *stream);