From e869c06ef58c8574b1ba06fdc15ea643229f8ff7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 3 Jun 2019 17:54:20 +0200 Subject: libopus: convert to new channel layout API Signed-off-by: James Almer --- libavcodec/libopusdec.c | 39 +++++++++++++++++++++---------------- libavcodec/libopusenc.c | 50 +++++++++++++++++++++++++----------------------- libavcodec/vorbis.h | 3 +++ libavcodec/vorbis_data.c | 18 +++++++++++++++++ 4 files changed, 69 insertions(+), 41 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c index 86ef715205..e4d127ad74 100644 --- a/libavcodec/libopusdec.c +++ b/libavcodec/libopusdec.c @@ -50,55 +50,60 @@ struct libopus_context { static av_cold int libopus_decode_init(AVCodecContext *avc) { struct libopus_context *opus = avc->priv_data; - int ret, channel_map = 0, gain_db = 0, nb_streams, nb_coupled; + int ret, channel_map = 0, gain_db = 0, nb_streams, nb_coupled, channels; uint8_t mapping_arr[8] = { 0, 1 }, *mapping; - avc->channels = avc->extradata_size >= 10 ? avc->extradata[9] : (avc->channels == 1) ? 1 : 2; - if (avc->channels <= 0) { + channels = avc->extradata_size >= 10 ? avc->extradata[9] : (avc->ch_layout.nb_channels == 1) ? 1 : 2; + if (channels <= 0) { av_log(avc, AV_LOG_WARNING, - "Invalid number of channels %d, defaulting to stereo\n", avc->channels); - avc->channels = 2; + "Invalid number of channels %d, defaulting to stereo\n", channels); + channels = 2; } avc->sample_rate = 48000; avc->sample_fmt = avc->request_sample_fmt == AV_SAMPLE_FMT_FLT ? AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16; - avc->channel_layout = avc->channels > 8 ? 0 : - ff_vorbis_channel_layouts[avc->channels - 1]; + av_channel_layout_uninit(&avc->ch_layout); + if (channels > 8) { + avc->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avc->ch_layout.nb_channels = channels; + } else { + av_channel_layout_copy(&avc->ch_layout, &ff_vorbis_ch_layouts[channels - 1]); + } if (avc->extradata_size >= OPUS_HEAD_SIZE) { opus->pre_skip = AV_RL16(avc->extradata + 10); gain_db = sign_extend(AV_RL16(avc->extradata + 16), 16); channel_map = AV_RL8 (avc->extradata + 18); } - if (avc->extradata_size >= OPUS_HEAD_SIZE + 2 + avc->channels) { + if (avc->extradata_size >= OPUS_HEAD_SIZE + 2 + channels) { nb_streams = avc->extradata[OPUS_HEAD_SIZE + 0]; nb_coupled = avc->extradata[OPUS_HEAD_SIZE + 1]; - if (nb_streams + nb_coupled != avc->channels) + if (nb_streams + nb_coupled != channels) av_log(avc, AV_LOG_WARNING, "Inconsistent channel mapping.\n"); mapping = avc->extradata + OPUS_HEAD_SIZE + 2; } else { - if (avc->channels > 2 || channel_map) { + if (channels > 2 || channel_map) { av_log(avc, AV_LOG_ERROR, - "No channel mapping for %d channels.\n", avc->channels); + "No channel mapping for %d channels.\n", channels); return AVERROR(EINVAL); } nb_streams = 1; - nb_coupled = avc->channels > 1; + nb_coupled = channels > 1; mapping = mapping_arr; } - if (avc->channels > 2 && avc->channels <= 8) { - const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[avc->channels - 1]; + if (channels > 2 && channels <= 8) { + const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[channels - 1]; int ch; /* Remap channels from Vorbis order to ffmpeg order */ - for (ch = 0; ch < avc->channels; ch++) + for (ch = 0; ch < channels; ch++) mapping_arr[ch] = mapping[vorbis_offset[ch]]; mapping = mapping_arr; } - opus->dec = opus_multistream_decoder_create(avc->sample_rate, avc->channels, + opus->dec = opus_multistream_decoder_create(avc->sample_rate, channels, nb_streams, nb_coupled, mapping, &ret); if (!opus->dec) { @@ -178,7 +183,7 @@ static int libopus_decode(AVCodecContext *avc, void *data, #ifndef OPUS_SET_GAIN { - int i = avc->channels * nb_samples; + int i = avc->ch_layout.nb_channels * nb_samples; if (avc->sample_fmt == AV_SAMPLE_FMT_FLT) { float *pcm = (float *)frame->data[0]; for (; i > 0; i--, pcm++) diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c index 45b23fcbb5..d63d630328 100644 --- a/libavcodec/libopusenc.c +++ b/libavcodec/libopusenc.c @@ -91,7 +91,7 @@ static void libopus_write_header(AVCodecContext *avctx, int stream_count, const uint8_t *channel_mapping) { uint8_t *p = avctx->extradata; - int channels = avctx->channels; + int channels = avctx->ch_layout.nb_channels; bytestream_put_buffer(&p, "OpusHead", 8); bytestream_put_byte(&p, 1); /* Version */ @@ -180,9 +180,9 @@ static int libopus_configure_encoder(AVCodecContext *avctx, OpusMSEncoder *enc, static int libopus_check_max_channels(AVCodecContext *avctx, int max_channels) { - if (avctx->channels > max_channels) { + if (avctx->ch_layout.nb_channels > max_channels) { av_log(avctx, AV_LOG_ERROR, "Opus mapping family undefined for %d channels.\n", - avctx->channels); + avctx->ch_layout.nb_channels); return AVERROR(EINVAL); } @@ -190,16 +190,16 @@ static int libopus_check_max_channels(AVCodecContext *avctx, } static int libopus_check_vorbis_layout(AVCodecContext *avctx, int mapping_family) { - av_assert2(avctx->channels < FF_ARRAY_ELEMS(ff_vorbis_channel_layouts)); + av_assert2(avctx->ch_layout.nb_channels < FF_ARRAY_ELEMS(ff_vorbis_ch_layouts)); - if (!avctx->channel_layout) { + 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->channels); - } else if (avctx->channel_layout != ff_vorbis_channel_layouts[avctx->channels - 1]) { + "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_get_channel_layout_string(name, sizeof(name), avctx->channels, - avctx->channel_layout); + + 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); @@ -238,7 +238,7 @@ static int libopus_validate_layout_and_get_channel_map( ret = libopus_check_max_channels(avctx, 8); if (ret == 0) { ret = libopus_check_vorbis_layout(avctx, mapping_family); - channel_map = ff_vorbis_channel_layout_offsets[avctx->channels - 1]; + channel_map = ff_vorbis_channel_layout_offsets[avctx->ch_layout.nb_channels - 1]; } break; case 255: @@ -261,6 +261,7 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) OpusMSEncoder *enc; uint8_t libopus_channel_mapping[255]; int ret = OPUS_OK; + int channels = avctx->ch_layout.nb_channels; int av_ret; int coupled_stream_count, header_size, frame_size; int mapping_family; @@ -348,17 +349,17 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) * libopus multistream API to avoid surround masking. */ /* Set the mapping family so that the value is correct in the header */ - mapping_family = avctx->channels > 2 ? 1 : 0; - coupled_stream_count = opus_coupled_streams[avctx->channels - 1]; - opus->stream_count = avctx->channels - coupled_stream_count; + mapping_family = channels > 2 ? 1 : 0; + coupled_stream_count = opus_coupled_streams[channels - 1]; + opus->stream_count = channels - coupled_stream_count; memcpy(libopus_channel_mapping, - opus_vorbis_channel_map[avctx->channels - 1], - avctx->channels * sizeof(*libopus_channel_mapping)); + opus_vorbis_channel_map[channels - 1], + channels * sizeof(*libopus_channel_mapping)); enc = opus_multistream_encoder_create( - avctx->sample_rate, avctx->channels, opus->stream_count, + avctx->sample_rate, channels, opus->stream_count, coupled_stream_count, - libavcodec_libopus_channel_map[avctx->channels - 1], + libavcodec_libopus_channel_map[channels - 1], opus->opts.application, &ret); } else { /* Use the newer multistream API. The encoder will set the channel @@ -366,7 +367,7 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) * use surround masking analysis to save bits. */ mapping_family = opus->opts.mapping_family; enc = opus_multistream_surround_encoder_create( - avctx->sample_rate, avctx->channels, mapping_family, + avctx->sample_rate, channels, mapping_family, &opus->stream_count, &coupled_stream_count, libopus_channel_mapping, opus->opts.application, &ret); } @@ -385,10 +386,10 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) "No bit rate set. Defaulting to %"PRId64" bps.\n", avctx->bit_rate); } - if (avctx->bit_rate < 500 || avctx->bit_rate > 256000 * avctx->channels) { + if (avctx->bit_rate < 500 || avctx->bit_rate > 256000 * channels) { av_log(avctx, AV_LOG_ERROR, "The bit rate %"PRId64" bps is unsupported. " "Please choose a value between 500 and %d.\n", avctx->bit_rate, - 256000 * avctx->channels); + 256000 * channels); ret = AVERROR(EINVAL); goto fail; } @@ -400,7 +401,7 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) } /* Header includes channel mapping table if and only if mapping family is NOT 0 */ - header_size = 19 + (mapping_family == 0 ? 0 : 2 + avctx->channels); + header_size = 19 + (mapping_family == 0 ? 0 : 2 + channels); avctx->extradata = av_malloc(header_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate extradata.\n"); @@ -409,7 +410,7 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) } avctx->extradata_size = header_size; - opus->samples = av_calloc(frame_size, avctx->channels * + opus->samples = av_calloc(frame_size, channels * av_get_bytes_per_sample(avctx->sample_fmt)); if (!opus->samples) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate samples buffer.\n"); @@ -456,7 +457,8 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt, { LibopusEncContext *opus = avctx->priv_data; const int bytes_per_sample = av_get_bytes_per_sample(avctx->sample_fmt); - const int sample_size = avctx->channels * bytes_per_sample; + const int channels = avctx->ch_layout.nb_channels; + const int sample_size = channels * bytes_per_sample; uint8_t *audio; int ret; int discard_padding; @@ -469,7 +471,7 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt, audio = opus->samples; libopus_copy_samples_with_channel_map( audio, frame->data[0], opus->encoder_channel_map, - avctx->channels, frame->nb_samples, bytes_per_sample); + channels, frame->nb_samples, bytes_per_sample); } else if (frame->nb_samples < opus->opts.packet_size) { audio = opus->samples; memcpy(audio, frame->data[0], frame->nb_samples * sample_size); diff --git a/libavcodec/vorbis.h b/libavcodec/vorbis.h index 69ddbd2982..f80187feee 100644 --- a/libavcodec/vorbis.h +++ b/libavcodec/vorbis.h @@ -26,7 +26,10 @@ extern const float ff_vorbis_floor1_inverse_db_table[256]; extern const float * const ff_vorbis_vwin[8]; extern const uint8_t ff_vorbis_channel_layout_offsets[8][8]; +#if FF_API_OLD_CHANNEL_LAYOUT extern const uint64_t ff_vorbis_channel_layouts[9]; +#endif +extern const AVChannelLayout ff_vorbis_ch_layouts[9]; typedef struct vorbis_floor1_entry { uint16_t x; diff --git a/libavcodec/vorbis_data.c b/libavcodec/vorbis_data.c index fd7e291de2..4f4ea03f15 100644 --- a/libavcodec/vorbis_data.c +++ b/libavcodec/vorbis_data.c @@ -34,6 +34,7 @@ const uint8_t ff_vorbis_channel_layout_offsets[8][8] = { { 0, 2, 1, 7, 5, 6, 3, 4 }, }; +#if FF_API_OLD_CHANNEL_LAYOUT const uint64_t ff_vorbis_channel_layouts[9] = { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, @@ -45,6 +46,23 @@ const uint64_t ff_vorbis_channel_layouts[9] = { AV_CH_LAYOUT_7POINT1, 0 }; +#endif + +const AVChannelLayout ff_vorbis_ch_layouts[9] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_QUAD, + AV_CHANNEL_LAYOUT_5POINT0_BACK, + AV_CHANNEL_LAYOUT_5POINT1_BACK, + { + .nb_channels = 7, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_5POINT1 | AV_CH_BACK_CENTER, + }, + AV_CHANNEL_LAYOUT_7POINT1, + { 0 } +}; DECLARE_ALIGNED(16, static const float, vwin64)[32] = { 0.0009460463F, 0.0085006468F, 0.0235352254F, 0.0458950567F, -- cgit v1.2.3