Message ID | 0c33b65c-295a-01e2-1463-f4444613abb4@gmail.com |
---|---|
State | Superseded |
Headers | show |
On Sun, Oct 29, 2017 at 11:11:43PM +0100, pkv.stream wrote: > minor change, adding a test for number of channels for > mapping_family 1 when channel_config_code is > 0x82 > Passes fate + patcheck. > Regards > pkv > mpegts.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------- > 1 file changed, 70 insertions(+), 14 deletions(-) > 6648bab53735f1efaf0d6cd698dbc2398b483c3f 0002-libavf-mpegts-opus-demuxing-for-mapping-family-255.patch > From 2e0504728b81e0f35ba856c24cff14fa70680d8b Mon Sep 17 00:00:00 2001 > From: pkviet <pkv.stream@gmail.com> > Date: Sun, 29 Oct 2017 22:57:25 +0100 > Subject: [PATCH 2/2] libavf/mpegts: opus demuxing for mapping family 255 > > Adds to mpegts muxer the capability to demux libopus with mapping > family 255, following the provisional spec for opus in mepg-ts > (https://people.xiph.org/~tterribe/opus/ETSI_TS_opus-v0.1.3-draft.doc). > > Signed-off-by: pkviet <pkv.stream@gmail.com> > --- > libavformat/mpegts.c | 84 +++++++++++++++++++++++++++++++++++++++++++--------- > 1 file changed, 70 insertions(+), 14 deletions(-) > > diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c > index 53cbcfb..3aa06f0 100644 > --- a/libavformat/mpegts.c > +++ b/libavformat/mpegts.c > @@ -37,6 +37,7 @@ > #include "avio_internal.h" > #include "mpeg.h" > #include "isom.h" > +#include "math.h" > > /* maximum size in which we look for synchronization if > * synchronization is lost */ > @@ -1633,7 +1634,7 @@ static const uint8_t opus_stream_cnt[9] = { > 1, 1, 1, 2, 2, 3, 4, 4, 5, > }; > > -static const uint8_t opus_channel_map[8][8] = { > +static const uint8_t opus_channel_map_a[8][8] = { > { 0 }, > { 0,1 }, > { 0,2,1 }, > @@ -1644,13 +1645,25 @@ static const uint8_t opus_channel_map[8][8] = { > { 0,6,1,2,3,4,5,7 }, > }; > > +static const uint8_t opus_channel_map_b[8][8] = { > + { 0 }, > + { 0,1 }, > + { 0,1,2 }, > + { 0,1,2,3 }, > + { 0,1,2,3,4 }, > + { 0,1,2,3,4,5 }, > + { 0,1,2,3,4,5,6 }, > + { 0,1,2,3,4,5,6,7 }, > +}; > + > int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type, > const uint8_t **pp, const uint8_t *desc_list_end, > Mp4Descr *mp4_descr, int mp4_descr_count, int pid, > MpegTSContext *ts) > { > const uint8_t *desc_end; > - int desc_len, desc_tag, desc_es_id, ext_desc_tag, channels, channel_config_code; > + int desc_len, desc_tag, desc_es_id, ext_desc_tag, channels, channel_config_code, channel_count, mapping_family, stream_count, coupled_stream_count; > + GetBitContext gb; > char language[252]; > int i; > > @@ -1660,6 +1673,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type > desc_len = get8(pp, desc_list_end); > if (desc_len < 0) > return AVERROR_INVALIDDATA; > + > desc_end = *pp + desc_len; > if (desc_end > desc_list_end) > return AVERROR_INVALIDDATA; > @@ -1871,26 +1885,68 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type > if (st->codecpar->codec_id == AV_CODEC_ID_OPUS && > ext_desc_tag == 0x80) { /* User defined (provisional Opus) */ > if (!st->codecpar->extradata) { > - st->codecpar->extradata = av_mallocz(sizeof(opus_default_extradata) + > - AV_INPUT_BUFFER_PADDING_SIZE); > - if (!st->codecpar->extradata) > - return AVERROR(ENOMEM); > - > - st->codecpar->extradata_size = sizeof(opus_default_extradata); > - memcpy(st->codecpar->extradata, opus_default_extradata, sizeof(opus_default_extradata)); > - > channel_config_code = get8(pp, desc_end); > if (channel_config_code < 0) > return AVERROR_INVALIDDATA; > + > + if (channel_config_code != 0x81) { > + st->codecpar->extradata = av_mallocz(sizeof(opus_default_extradata) + > + AV_INPUT_BUFFER_PADDING_SIZE); > + if (!st->codecpar->extradata) > + return AVERROR(ENOMEM); > + st->codecpar->extradata_size = sizeof(opus_default_extradata); > + memcpy(st->codecpar->extradata, opus_default_extradata, sizeof(opus_default_extradata)); > + } > + > if (channel_config_code <= 0x8) { > st->codecpar->extradata[9] = channels = channel_config_code ? channel_config_code : 2; > st->codecpar->extradata[18] = channel_config_code ? (channels > 2) : /* Dual Mono */ 255; > st->codecpar->extradata[19] = opus_stream_cnt[channel_config_code]; > st->codecpar->extradata[20] = opus_coupled_stream_cnt[channel_config_code]; > - memcpy(&st->codecpar->extradata[21], opus_channel_map[channels - 1], channels); > - } else { > - avpriv_request_sample(fc, "Opus in MPEG-TS - channel_config_code > 0x8"); > - } > + memcpy(&st->codecpar->extradata[21], opus_channel_map_a[channels - 1], channels); > + } else if (channel_config_code == 0x81) { > + channel_count = get8(pp, desc_end); > + mapping_family = get8(pp, desc_end); > + if (channel_count < 0 || channel_count > 255) > + return AVERROR_INVALIDDATA; > + if (mapping_family < 0 || mapping_family > 255) > + return AVERROR_INVALIDDATA; > 255 is impossible i think > + st->codecpar->extradata_size = 22 + channel_count; > + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); > + if (!st->codecpar->extradata) > + return AVERROR(ENOMEM); > + for (i = 0; i < 9; i++) { > + st->codecpar->extradata[i] = opus_default_extradata[i]; > + } > + st->codecpar->extradata[9] = channel_count; > + st->codecpar->extradata[18] = mapping_family; > + init_get_bits(&gb, *pp, (channel_count + 2 + AV_INPUT_BUFFER_PADDING_SIZE) * 8); The AV_INPUT_BUFFER_PADDING_SIZE looks odd here > + stream_count = get_bits(&gb, av_ceil_log2_c(channel_count)) + 1; > + coupled_stream_count = get_bits(&gb, av_ceil_log2_c(stream_count + 1)); > + if (stream_count < 0 || stream_count > channel_count) > + return AVERROR_INVALIDDATA; > + if (coupled_stream_count < 0 || coupled_stream_count > stream_count) > + return AVERROR_INVALIDDATA; get_bits shouldnt return negative numbers > + st->codecpar->extradata[19] = stream_count; > + st->codecpar->extradata[20] = coupled_stream_count; > + for (i = 0; i < channel_count; i++) { > + st->codecpar->extradata[21 + i] = get_bits(&gb, av_ceil_log2_c(stream_count + coupled_stream_count + 1)); > + if (st->codecpar->extradata[21 + i] > stream_count + coupled_stream_count > + || st->codecpar->extradata[21 + i] > (int)(pow(2, stream_count + coupled_stream_count + 1) -1)) > + return AVERROR_INVALIDDATA; pow(2 can be changed to a simple shift also a temporary variable would be cleaner than using st->codecpar->extradata[21 + i] 3 times [...]
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 53cbcfb..3aa06f0 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -37,6 +37,7 @@ #include "avio_internal.h" #include "mpeg.h" #include "isom.h" +#include "math.h" /* maximum size in which we look for synchronization if * synchronization is lost */ @@ -1633,7 +1634,7 @@ static const uint8_t opus_stream_cnt[9] = { 1, 1, 1, 2, 2, 3, 4, 4, 5, }; -static const uint8_t opus_channel_map[8][8] = { +static const uint8_t opus_channel_map_a[8][8] = { { 0 }, { 0,1 }, { 0,2,1 }, @@ -1644,13 +1645,25 @@ static const uint8_t opus_channel_map[8][8] = { { 0,6,1,2,3,4,5,7 }, }; +static const uint8_t opus_channel_map_b[8][8] = { + { 0 }, + { 0,1 }, + { 0,1,2 }, + { 0,1,2,3 }, + { 0,1,2,3,4 }, + { 0,1,2,3,4,5 }, + { 0,1,2,3,4,5,6 }, + { 0,1,2,3,4,5,6,7 }, +}; + int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type, const uint8_t **pp, const uint8_t *desc_list_end, Mp4Descr *mp4_descr, int mp4_descr_count, int pid, MpegTSContext *ts) { const uint8_t *desc_end; - int desc_len, desc_tag, desc_es_id, ext_desc_tag, channels, channel_config_code; + int desc_len, desc_tag, desc_es_id, ext_desc_tag, channels, channel_config_code, channel_count, mapping_family, stream_count, coupled_stream_count; + GetBitContext gb; char language[252]; int i; @@ -1660,6 +1673,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type desc_len = get8(pp, desc_list_end); if (desc_len < 0) return AVERROR_INVALIDDATA; + desc_end = *pp + desc_len; if (desc_end > desc_list_end) return AVERROR_INVALIDDATA; @@ -1871,26 +1885,68 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type if (st->codecpar->codec_id == AV_CODEC_ID_OPUS && ext_desc_tag == 0x80) { /* User defined (provisional Opus) */ if (!st->codecpar->extradata) { - st->codecpar->extradata = av_mallocz(sizeof(opus_default_extradata) + - AV_INPUT_BUFFER_PADDING_SIZE); - if (!st->codecpar->extradata) - return AVERROR(ENOMEM); - - st->codecpar->extradata_size = sizeof(opus_default_extradata); - memcpy(st->codecpar->extradata, opus_default_extradata, sizeof(opus_default_extradata)); - channel_config_code = get8(pp, desc_end); if (channel_config_code < 0) return AVERROR_INVALIDDATA; + + if (channel_config_code != 0x81) { + st->codecpar->extradata = av_mallocz(sizeof(opus_default_extradata) + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) + return AVERROR(ENOMEM); + st->codecpar->extradata_size = sizeof(opus_default_extradata); + memcpy(st->codecpar->extradata, opus_default_extradata, sizeof(opus_default_extradata)); + } + if (channel_config_code <= 0x8) { st->codecpar->extradata[9] = channels = channel_config_code ? channel_config_code : 2; st->codecpar->extradata[18] = channel_config_code ? (channels > 2) : /* Dual Mono */ 255; st->codecpar->extradata[19] = opus_stream_cnt[channel_config_code]; st->codecpar->extradata[20] = opus_coupled_stream_cnt[channel_config_code]; - memcpy(&st->codecpar->extradata[21], opus_channel_map[channels - 1], channels); - } else { - avpriv_request_sample(fc, "Opus in MPEG-TS - channel_config_code > 0x8"); - } + memcpy(&st->codecpar->extradata[21], opus_channel_map_a[channels - 1], channels); + } else if (channel_config_code == 0x81) { + channel_count = get8(pp, desc_end); + mapping_family = get8(pp, desc_end); + if (channel_count < 0 || channel_count > 255) + return AVERROR_INVALIDDATA; + if (mapping_family < 0 || mapping_family > 255) + return AVERROR_INVALIDDATA; + st->codecpar->extradata_size = 22 + channel_count; + st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!st->codecpar->extradata) + return AVERROR(ENOMEM); + for (i = 0; i < 9; i++) { + st->codecpar->extradata[i] = opus_default_extradata[i]; + } + st->codecpar->extradata[9] = channel_count; + st->codecpar->extradata[18] = mapping_family; + init_get_bits(&gb, *pp, (channel_count + 2 + AV_INPUT_BUFFER_PADDING_SIZE) * 8); + stream_count = get_bits(&gb, av_ceil_log2_c(channel_count)) + 1; + coupled_stream_count = get_bits(&gb, av_ceil_log2_c(stream_count + 1)); + if (stream_count < 0 || stream_count > channel_count) + return AVERROR_INVALIDDATA; + if (coupled_stream_count < 0 || coupled_stream_count > stream_count) + return AVERROR_INVALIDDATA; + st->codecpar->extradata[19] = stream_count; + st->codecpar->extradata[20] = coupled_stream_count; + for (i = 0; i < channel_count; i++) { + st->codecpar->extradata[21 + i] = get_bits(&gb, av_ceil_log2_c(stream_count + coupled_stream_count + 1)); + if (st->codecpar->extradata[21 + i] > stream_count + coupled_stream_count + || st->codecpar->extradata[21 + i] > (int)(pow(2, stream_count + coupled_stream_count + 1) -1)) + return AVERROR_INVALIDDATA; + } + } else if ((channel_config_code >= 0x82) && (channel_config_code <= 0x88)) { + channels = get8(pp, desc_end); + if (channels < 0 || channels > 8) + return AVERROR_INVALIDDATA; + st->codecpar->extradata[9] = channels; + st->codecpar->extradata[18] = 1; + st->codecpar->extradata[19] = channels; + st->codecpar->extradata[20] = 0; + memcpy(&st->codecpar->extradata[21], opus_channel_map_b[channels - 1], channels); + } else { + avpriv_request_sample(fc, "Opus in MPEG-TS - channel_config_code %i", channel_config_code); + } st->need_parsing = AVSTREAM_PARSE_FULL; st->internal->need_context_update = 1; }