[FFmpeg-devel] [PATCH] avcodec/libopusenc: add support for mapping family 2
James Almer
jamrial at gmail.com
Thu Oct 17 05:44:08 EEST 2024
Signed-off-by: James Almer <jamrial at gmail.com>
---
libavcodec/libopusenc.c | 55 +++++++++++++++++++++++++++++++----------
1 file changed, 42 insertions(+), 13 deletions(-)
diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c
index 6b8b2cda0e..fcd0254be3 100644
--- a/libavcodec/libopusenc.c
+++ b/libavcodec/libopusenc.c
@@ -191,21 +191,25 @@ static int libopus_check_max_channels(AVCodecContext *avctx,
}
static int libopus_check_vorbis_layout(AVCodecContext *avctx, int mapping_family) {
- av_assert2(avctx->ch_layout.nb_channels < FF_ARRAY_ELEMS(ff_vorbis_ch_layouts));
-
if (avctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
av_log(avctx, AV_LOG_WARNING,
"No channel layout specified. Opus encoder will use Vorbis "
"channel layout for %d channels.\n", avctx->ch_layout.nb_channels);
- } else if (av_channel_layout_compare(&avctx->ch_layout, &ff_vorbis_ch_layouts[avctx->ch_layout.nb_channels - 1])) {
- char name[32];
-
- av_channel_layout_describe(&avctx->ch_layout, name, sizeof(name));
- av_log(avctx, AV_LOG_ERROR,
- "Invalid channel layout %s for specified mapping family %d.\n",
- name, mapping_family);
-
- return AVERROR(EINVAL);
+ } else if (avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) {
+ av_assert2(avctx->ch_layout.nb_channels < FF_ARRAY_ELEMS(ff_vorbis_ch_layouts));
+ if (av_channel_layout_compare(&avctx->ch_layout, &ff_vorbis_ch_layouts[avctx->ch_layout.nb_channels - 1])) {
+ char name[32];
+ av_channel_layout_describe(&avctx->ch_layout, name, sizeof(name));
+ av_log(avctx, AV_LOG_ERROR,
+ "Invalid channel layout %s for specified mapping family %d.\n",
+ name, mapping_family);
+
+ return AVERROR(EINVAL);
+ }
+ } else if (avctx->ch_layout.order != AV_CHANNEL_ORDER_AMBISONIC) {
+ av_log(avctx, AV_LOG_WARNING,
+ "Unsupported channel layout specified. Opus encoder will use Vorbis "
+ "channel layout for %d channels.\n", avctx->ch_layout.nb_channels);
}
return 0;
@@ -221,7 +225,8 @@ static int libopus_validate_layout_and_get_channel_map(
switch (mapping_family) {
case -1:
- ret = libopus_check_max_channels(avctx, 8);
+ ret = libopus_check_max_channels(avctx, avctx->ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC
+ ? 227 : 8);
if (ret == 0) {
ret = libopus_check_vorbis_layout(avctx, mapping_family);
/* Channels do not need to be reordered. */
@@ -242,6 +247,9 @@ static int libopus_validate_layout_and_get_channel_map(
channel_map = ff_vorbis_channel_layout_offsets[avctx->ch_layout.nb_channels - 1];
}
break;
+ case 2:
+ ret = libopus_check_max_channels(avctx, 227);
+ break;
case 255:
ret = libopus_check_max_channels(avctx, 254);
break;
@@ -345,7 +353,7 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx)
return av_ret;
}
- if (opus->opts.mapping_family == -1) {
+ if (opus->opts.mapping_family == -1 && avctx->ch_layout.order != AV_CHANNEL_ORDER_AMBISONIC) {
/* By default, use mapping family 1 for the header but use the older
* libopus multistream API to avoid surround masking. */
@@ -367,6 +375,27 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx)
* mapping and coupled stream counts to its internal defaults and will
* use surround masking analysis to save bits. */
mapping_family = opus->opts.mapping_family;
+ if (mapping_family == -1) {
+ int ambisonic_order, non_diegetic_channels;
+
+ mapping_family = 2;
+ av_assert2(avctx->ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC);
+ ambisonic_order = av_channel_layout_ambisonic_order(&avctx->ch_layout);
+ if (ambisonic_order < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid ambisonic channel layout for mapping channel 2\n");
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ non_diegetic_channels = channels - (ambisonic_order + 1) * (ambisonic_order + 1);
+ if (non_diegetic_channels &&
+ (non_diegetic_channels != 2 ||
+ av_channel_layout_subset(&avctx->ch_layout, AV_CH_LAYOUT_STEREO) != AV_CH_LAYOUT_STEREO)) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid amount of non-diegetic channels for mapping channel 2\n");
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+ }
enc = opus_multistream_surround_encoder_create(
avctx->sample_rate, channels, mapping_family,
&opus->stream_count, &coupled_stream_count, libopus_channel_mapping,
--
2.46.2
More information about the ffmpeg-devel
mailing list