From 9d2ac6e90b9bd2bb3c0b037a05292be2c23446c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 16 Mar 2023 14:05:43 +0200 Subject: [PATCH] mpegtsmux: Allow writing arbitrary Opus channel mapping families and up to 255 channels And fix writing of dual-mono special cases. Part-of: --- .../docs/plugins/gst_plugins_cache.json | 2 +- .../gst/mpegtsmux/gstbasetsmux.c | 52 ++++++++++++++++--- .../gst/mpegtsmux/gstmpegtsmux.c | 3 +- .../gst/mpegtsmux/tsmux/tsmuxstream.c | 2 +- .../gst/mpegtsmux/tsmux/tsmuxstream.h | 4 +- 5 files changed, 50 insertions(+), 13 deletions(-) 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 f16d270510..c32ff76de6 100644 --- a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json @@ -214237,7 +214237,7 @@ "long-name": "MPEG Transport Stream Muxer", "pad-templates": { "sink_%%d": { - "caps": "video/mpeg:\n parsed: true\n mpegversion: { (int)1, (int)2, (int)4 }\n systemstream: false\nvideo/x-dirac:\nimage/x-jpc:\n alignment: frame\nvideo/x-h264:\n stream-format: byte-stream\n alignment: { (string)au, (string)nal }\nvideo/x-h265:\n stream-format: byte-stream\n alignment: { (string)au, (string)nal }\naudio/mpeg:\n parsed: true\n mpegversion: 1\naudio/mpeg:\n framed: true\n mpegversion: { (int)2, (int)4 }\n stream-format: { (string)adts, (string)raw }\naudio/x-lpcm:\n width: { (int)16, (int)20, (int)24 }\n rate: { (int)48000, (int)96000 }\n channels: [ 1, 8 ]\n dynamic_range: [ 0, 255 ]\n emphasis: { (boolean)false, (boolean)true }\n mute: { (boolean)false, (boolean)true }\naudio/x-ac3:\n framed: true\naudio/x-dts:\n framed: true\naudio/x-opus:\n channels: [ 1, 8 ]\nchannel-mapping-family: { (int)0, (int)1 }\nsubpicture/x-dvb:\napplication/x-teletext:\nmeta/x-klv:\n parsed: true\nimage/x-jpc:\n alignment: frame\n profile: [ 0, 49151 ]\n", + "caps": "video/mpeg:\n parsed: true\n mpegversion: { (int)1, (int)2, (int)4 }\n systemstream: false\nvideo/x-dirac:\nimage/x-jpc:\n alignment: frame\nvideo/x-h264:\n stream-format: byte-stream\n alignment: { (string)au, (string)nal }\nvideo/x-h265:\n stream-format: byte-stream\n alignment: { (string)au, (string)nal }\naudio/mpeg:\n parsed: true\n mpegversion: 1\naudio/mpeg:\n framed: true\n mpegversion: { (int)2, (int)4 }\n stream-format: { (string)adts, (string)raw }\naudio/x-lpcm:\n width: { (int)16, (int)20, (int)24 }\n rate: { (int)48000, (int)96000 }\n channels: [ 1, 8 ]\n dynamic_range: [ 0, 255 ]\n emphasis: { (boolean)false, (boolean)true }\n mute: { (boolean)false, (boolean)true }\naudio/x-ac3:\n framed: true\naudio/x-dts:\n framed: true\naudio/x-opus:\n channels: [ 1, 255 ]\nsubpicture/x-dvb:\napplication/x-teletext:\nmeta/x-klv:\n parsed: true\nimage/x-jpc:\n alignment: frame\n profile: [ 0, 49151 ]\n", "direction": "sink", "presence": "request", "type": "GstBaseTsMuxPad" diff --git a/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.c b/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.c index 880d4d5b9e..21c949c945 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmux.c @@ -78,6 +78,7 @@ #include #include #include +#include #include "gstbasetsmux.h" #include "gstbasetsmuxaac.h" @@ -384,7 +385,8 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux, const gchar *mt; const GValue *value = NULL; GstBuffer *codec_data = NULL; - guint8 opus_channel_config_code = 0; + guint8 opus_channel_config[1 + 2 + 1 + 1 + 255] = { 0, }; + gsize opus_channel_config_len = 0; guint16 profile = GST_JPEG2000_PARSE_PROFILE_NONE; guint8 main_level = 0; guint32 max_rate = 0; @@ -524,11 +526,14 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux, } if (channels <= 2 && mapping_family == 0) { - opus_channel_config_code = channels; - } else if (channels == 2 && mapping_family == 255 && stream_count == 1 - && coupled_count == 1) { + opus_channel_config[0] = channels; + opus_channel_config_len = 1; + } else if (channels == 2 && mapping_family == 255 && ((stream_count == 1 + && coupled_count == 1) || (stream_count == 2 + && coupled_count == 0))) { /* Dual mono */ - opus_channel_config_code = 0; + opus_channel_config[0] = coupled_count == 0 ? 0x80 : 0x00; + opus_channel_config_len = 1; } else if (channels >= 2 && channels <= 8 && mapping_family == 1) { static const guint8 coupled_stream_counts[9] = { 1, 0, 1, 1, 2, 2, 2, 3, 3 @@ -559,16 +564,45 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux, coupled_count == coupled_stream_counts[channels] && memcmp (channel_mapping, channel_map_a[channels - 1], channels) == 0) { - opus_channel_config_code = channels; + opus_channel_config[0] = channels; + opus_channel_config_len = 1; } else if (stream_count == channels - coupled_stream_counts[channels] && coupled_count == coupled_stream_counts[channels] && memcmp (channel_mapping, channel_map_b[channels - 1], channels) == 0) { - opus_channel_config_code = channels | 0x80; + opus_channel_config[0] = channels | 0x80; + opus_channel_config_len = 1; } else { GST_FIXME_OBJECT (ts_pad, "Opus channel mapping not handled"); goto not_negotiated; } + } else { + GstBitWriter writer; + guint i; + guint n_bits; + + gst_bit_writer_init_with_data (&writer, opus_channel_config, + sizeof (opus_channel_config), FALSE); + gst_bit_writer_put_bits_uint8_unchecked (&writer, 0x81, 8); + gst_bit_writer_put_bits_uint8_unchecked (&writer, channels, 8); + gst_bit_writer_put_bits_uint8_unchecked (&writer, mapping_family, 8); + + n_bits = g_bit_storage (channels); + gst_bit_writer_put_bits_uint8_unchecked (&writer, stream_count - 1, + n_bits); + n_bits = g_bit_storage (stream_count + 1); + gst_bit_writer_put_bits_uint8_unchecked (&writer, coupled_count, n_bits); + + n_bits = g_bit_storage (stream_count + coupled_count + 1); + for (i = 0; i < channels; i++) { + gst_bit_writer_put_bits_uint8_unchecked (&writer, channel_mapping[i], + n_bits); + } + + gst_bit_writer_align_bytes_unchecked (&writer, 0); + g_assert (writer.bit_size % 8 == 0); + + opus_channel_config_len = writer.bit_size / 8; } st = TSMUX_ST_PS_OPUS; @@ -727,7 +761,9 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux, ts_pad->stream->max_bitrate = max_rate; ts_pad->stream->profile_and_level = profile | main_level; - ts_pad->stream->opus_channel_config_code = opus_channel_config_code; + memcpy (ts_pad->stream->opus_channel_config, opus_channel_config, + sizeof (opus_channel_config)); + ts_pad->stream->opus_channel_config_len = opus_channel_config_len; tsmux_stream_set_buffer_release_func (ts_pad->stream, release_buffer_cb); diff --git a/subprojects/gst-plugins-bad/gst/mpegtsmux/gstmpegtsmux.c b/subprojects/gst-plugins-bad/gst/mpegtsmux/gstmpegtsmux.c index 44c952e512..9d17088866 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsmux/gstmpegtsmux.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsmux/gstmpegtsmux.c @@ -123,8 +123,7 @@ static GstStaticPadTemplate gst_mpeg_ts_mux_sink_factory = "audio/x-ac3, framed = (boolean) TRUE;" "audio/x-dts, framed = (boolean) TRUE;" "audio/x-opus, " - "channels = (int) [1, 8], " - "channel-mapping-family = (int) {0, 1};" + "channels = (int) [1, 255];" "subpicture/x-dvb; application/x-teletext; meta/x-klv, parsed=true;" "image/x-jpc, alignment = (string) frame, profile = (int)[0, 49151];")); diff --git a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.c b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.c index 953287131c..e82bf9d682 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.c @@ -1033,7 +1033,7 @@ tsmux_stream_default_get_es_descrs (TsMuxStream * stream, descriptor = gst_mpegts_descriptor_from_custom_with_extension (GST_MTS_DESC_DVB_EXTENSION, 0x80, - &stream->opus_channel_config_code, 1); + stream->opus_channel_config, stream->opus_channel_config_len); g_ptr_array_add (pmt_stream->descriptors, descriptor); } diff --git a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.h b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.h index 3920e4076a..54cb6fe5c1 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.h +++ b/subprojects/gst-plugins-bad/gst/mpegtsmux/tsmux/tsmuxstream.h @@ -209,7 +209,9 @@ struct TsMuxStream { /* Opus */ gboolean is_opus; - guint8 opus_channel_config_code; + guint8 opus_channel_config[1 + 2 + 1 + 1 + 255]; + gsize opus_channel_config_len; + /* Jpeg2000 */ gint32 horizontal_size; gint32 vertical_size;