mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
mpegtsmux: Allow writing arbitrary Opus channel mapping families and up to 255 channels
And fix writing of dual-mono special cases. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4180>
This commit is contained in:
parent
b1cb36e74c
commit
9d2ac6e90b
5 changed files with 50 additions and 13 deletions
|
@ -214237,7 +214237,7 @@
|
||||||
"long-name": "MPEG Transport Stream Muxer",
|
"long-name": "MPEG Transport Stream Muxer",
|
||||||
"pad-templates": {
|
"pad-templates": {
|
||||||
"sink_%%d": {
|
"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",
|
"direction": "sink",
|
||||||
"presence": "request",
|
"presence": "request",
|
||||||
"type": "GstBaseTsMuxPad"
|
"type": "GstBaseTsMuxPad"
|
||||||
|
|
|
@ -78,6 +78,7 @@
|
||||||
#include <gst/pbutils/pbutils.h>
|
#include <gst/pbutils/pbutils.h>
|
||||||
#include <gst/videoparsers/gstjpeg2000parse.h>
|
#include <gst/videoparsers/gstjpeg2000parse.h>
|
||||||
#include <gst/video/video-color.h>
|
#include <gst/video/video-color.h>
|
||||||
|
#include <gst/base/base.h>
|
||||||
|
|
||||||
#include "gstbasetsmux.h"
|
#include "gstbasetsmux.h"
|
||||||
#include "gstbasetsmuxaac.h"
|
#include "gstbasetsmuxaac.h"
|
||||||
|
@ -384,7 +385,8 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux,
|
||||||
const gchar *mt;
|
const gchar *mt;
|
||||||
const GValue *value = NULL;
|
const GValue *value = NULL;
|
||||||
GstBuffer *codec_data = 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;
|
guint16 profile = GST_JPEG2000_PARSE_PROFILE_NONE;
|
||||||
guint8 main_level = 0;
|
guint8 main_level = 0;
|
||||||
guint32 max_rate = 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) {
|
if (channels <= 2 && mapping_family == 0) {
|
||||||
opus_channel_config_code = channels;
|
opus_channel_config[0] = channels;
|
||||||
} else if (channels == 2 && mapping_family == 255 && stream_count == 1
|
opus_channel_config_len = 1;
|
||||||
&& coupled_count == 1) {
|
} else if (channels == 2 && mapping_family == 255 && ((stream_count == 1
|
||||||
|
&& coupled_count == 1) || (stream_count == 2
|
||||||
|
&& coupled_count == 0))) {
|
||||||
/* Dual mono */
|
/* 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) {
|
} else if (channels >= 2 && channels <= 8 && mapping_family == 1) {
|
||||||
static const guint8 coupled_stream_counts[9] = {
|
static const guint8 coupled_stream_counts[9] = {
|
||||||
1, 0, 1, 1, 2, 2, 2, 3, 3
|
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] &&
|
coupled_count == coupled_stream_counts[channels] &&
|
||||||
memcmp (channel_mapping, channel_map_a[channels - 1],
|
memcmp (channel_mapping, channel_map_a[channels - 1],
|
||||||
channels) == 0) {
|
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] &&
|
} else if (stream_count == channels - coupled_stream_counts[channels] &&
|
||||||
coupled_count == coupled_stream_counts[channels] &&
|
coupled_count == coupled_stream_counts[channels] &&
|
||||||
memcmp (channel_mapping, channel_map_b[channels - 1],
|
memcmp (channel_mapping, channel_map_b[channels - 1],
|
||||||
channels) == 0) {
|
channels) == 0) {
|
||||||
opus_channel_config_code = channels | 0x80;
|
opus_channel_config[0] = channels | 0x80;
|
||||||
|
opus_channel_config_len = 1;
|
||||||
} else {
|
} else {
|
||||||
GST_FIXME_OBJECT (ts_pad, "Opus channel mapping not handled");
|
GST_FIXME_OBJECT (ts_pad, "Opus channel mapping not handled");
|
||||||
goto not_negotiated;
|
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;
|
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->max_bitrate = max_rate;
|
||||||
ts_pad->stream->profile_and_level = profile | main_level;
|
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);
|
tsmux_stream_set_buffer_release_func (ts_pad->stream, release_buffer_cb);
|
||||||
|
|
||||||
|
|
|
@ -123,8 +123,7 @@ static GstStaticPadTemplate gst_mpeg_ts_mux_sink_factory =
|
||||||
"audio/x-ac3, framed = (boolean) TRUE;"
|
"audio/x-ac3, framed = (boolean) TRUE;"
|
||||||
"audio/x-dts, framed = (boolean) TRUE;"
|
"audio/x-dts, framed = (boolean) TRUE;"
|
||||||
"audio/x-opus, "
|
"audio/x-opus, "
|
||||||
"channels = (int) [1, 8], "
|
"channels = (int) [1, 255];"
|
||||||
"channel-mapping-family = (int) {0, 1};"
|
|
||||||
"subpicture/x-dvb; application/x-teletext; meta/x-klv, parsed=true;"
|
"subpicture/x-dvb; application/x-teletext; meta/x-klv, parsed=true;"
|
||||||
"image/x-jpc, alignment = (string) frame, profile = (int)[0, 49151];"));
|
"image/x-jpc, alignment = (string) frame, profile = (int)[0, 49151];"));
|
||||||
|
|
||||||
|
|
|
@ -1033,7 +1033,7 @@ tsmux_stream_default_get_es_descrs (TsMuxStream * stream,
|
||||||
descriptor =
|
descriptor =
|
||||||
gst_mpegts_descriptor_from_custom_with_extension
|
gst_mpegts_descriptor_from_custom_with_extension
|
||||||
(GST_MTS_DESC_DVB_EXTENSION, 0x80,
|
(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);
|
g_ptr_array_add (pmt_stream->descriptors, descriptor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,7 +209,9 @@ struct TsMuxStream {
|
||||||
|
|
||||||
/* Opus */
|
/* Opus */
|
||||||
gboolean is_opus;
|
gboolean is_opus;
|
||||||
guint8 opus_channel_config_code;
|
guint8 opus_channel_config[1 + 2 + 1 + 1 + 255];
|
||||||
|
gsize opus_channel_config_len;
|
||||||
|
|
||||||
/* Jpeg2000 */
|
/* Jpeg2000 */
|
||||||
gint32 horizontal_size;
|
gint32 horizontal_size;
|
||||||
gint32 vertical_size;
|
gint32 vertical_size;
|
||||||
|
|
Loading…
Reference in a new issue