@@ -1633,7 +1633,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,6 +1644,17 @@ 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,
@@ -1887,9 +1898,53 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
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);
+ memcpy(&st->codecpar->extradata[21], opus_channel_map_a[channels - 1], channels);
} else {
- avpriv_request_sample(fc, "Opus in MPEG-TS - channel_config_code > 0x8");
+ if (channel_config_code == 0x81) {
+ channels = get8(pp, desc_end);
+ st->codecpar->extradata_size = 22 + channels;
+ size_t extradata_size = (22 + channels) * sizeof(uint8_t);
+ uint8_t *extradata = av_malloc(extradata_size);
+ if (!extradata)
+ return AVERROR(ENOMEM);
+ for (i = 0; i <= (22+channels); i++) {
+ if (i < 9) {
+ extradata[i] = opus_default_extradata[i];
+ }
+ else {
+ extradata[i] = 0;
+ }
+ }
+ memcpy(st->codecpar->extradata, extradata, sizeof(extradata));
+ av_free(extradata);
+ st->codecpar->extradata[9] = channels;
+ st->codecpar->extradata[18] = 255;
+ st->codecpar->extradata[19] = channels;
+ st->codecpar->extradata[20] = 0;
+ size_t channel_map_size = channels * sizeof(uint8_t);
+ uint8_t *opus_channel_map255 = av_malloc(channel_map_size);
+ if (!opus_channel_map255)
+ return AVERROR(ENOMEM);
+ uint8_t j;
+ for (j = 0; j < channels; j++) {
+ opus_channel_map255[j] = j;
+ }
+ memcpy(&st->codecpar->extradata[21], opus_channel_map255, channels);
+ av_free(opus_channel_map255);
+ } else {
+ if ((channel_config_code >= 0x82) && (channel_config_code <= 0x88)) {
+ channels = get8(pp, desc_end);
+ 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");
+ }
+
+ }
}
st->need_parsing = AVSTREAM_PARSE_FULL;
st->internal->need_context_update = 1;
@@ -421,8 +421,8 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
*q++ = 'D';
}
if (st->codecpar->codec_id==AV_CODEC_ID_OPUS) {
- /* 6 bytes registration descriptor, 4 bytes Opus audio descriptor */
- if (q - data > SECTION_LENGTH - 6 - 4) {
+ /* 6 bytes registration descriptor, 6 bytes Opus audio descriptor */
+ if (q - data > SECTION_LENGTH - 6 - 6) {
err = 1;
break;
}
@@ -435,7 +435,7 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
*q++ = 's';
*q++ = 0x7f; /* DVB extension descriptor */
- *q++ = 2;
+ *q++ = 4;
*q++ = 0x80;
if (st->codecpar->extradata && st->codecpar->extradata_size >= 19) {
@@ -483,9 +483,14 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
*q++ = 0xff;
}
} else {
- /* Unsupported */
- av_log(s, AV_LOG_ERROR, "Unsupported Opus channel mapping for family %d", st->codecpar->extradata[18]);
- *q++ = 0xff;
+ /* mapping family 255 , set channel_config_code to 0x81 */
+ if (st->codecpar->extradata[18] == 255) {
+ *q++ = 0x81;
+ } else {
+ /* Unsupported */
+ av_log(s, AV_LOG_ERROR, "Unsupported Opus channel mapping for family %d", st->codecpar->extradata[18]);
+ *q++ = 0xff;
+ }
}
} else if (st->codecpar->channels <= 2) {
/* Assume RTP mapping family */
@@ -495,6 +500,8 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
av_log(s, AV_LOG_ERROR, "Unsupported Opus channel mapping");
*q++ = 0xff;
}
+ *q++ = st->codecpar->extradata[9];
+ *q++ = st->codecpar->extradata[18];
}
if (lang) {