Signed-off-by: Vittorio Giovara <vittorio.giov...@gmail.com> --- libavcodec/opus.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-)
diff --git a/libavcodec/opus.c b/libavcodec/opus.c index 308d104212..6aebb40155 100644 --- a/libavcodec/opus.c +++ b/libavcodec/opus.c @@ -347,7 +347,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, streams = 1; stereo_streams = channels - 1; channel_map = default_channel_map; - } else if (map_type == 1 || map_type == 255) { + } else if (map_type == 1 || map_type == 2 || map_type == 255) { if (extradata_size < 21 + channels) { av_log(avctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", extradata_size); @@ -363,6 +363,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } + layout = 0; if (map_type == 1) { if (channels > 8) { av_log(avctx, AV_LOG_ERROR, @@ -371,8 +372,24 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, } layout = ff_vorbis_ch_layouts[channels - 1].u.mask; channel_reorder = channel_reorder_vorbis; - } else - layout = 0; + } else if (map_type == 2) { + int ambisonic_order = ff_sqrt(channels) - 1; + int idx = (ambisonic_order + 1) * (ambisonic_order + 1); + if (channels <= 227 && (channels == idx || channels == idx + 2)) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout.order = AV_CHANNEL_ORDER_AMBISONIC; + avctx->ch_layout.nb_channels = channels; + + /* ACN order, followed by two optional channels of non-diegetic stereo */ + if (idx != channels) + avctx->ch_layout.u.mask = AV_CH_LAYOUT_STEREO; + } else { + av_log(avctx, AV_LOG_ERROR, "Channel map 2 is only valid for " + "channel counts equal to (n + 1)^2 + 2j for {n,j} >= 0 " + "(max 227 channels).\n"); + return AVERROR_INVALIDDATA; + } + } channel_map = extradata + 21; } else { @@ -415,11 +432,14 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, } } - av_channel_layout_uninit(&avctx->ch_layout); - if (layout) - av_channel_layout_from_mask(&avctx->ch_layout, layout); - else - av_channel_layout_default(&avctx->ch_layout, channels); + if (avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) { + av_channel_layout_uninit(&avctx->ch_layout); + if (layout) + av_channel_layout_from_mask(&avctx->ch_layout, layout); + else + av_channel_layout_default(&avctx->ch_layout, channels); + } + s->nb_streams = streams; s->nb_stereo_streams = stereo_streams; -- 2.13.1 _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel