From patchwork Thu Jan 13 02:05:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 33498 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:cd86:0:0:0:0:0 with SMTP id d128csp41990iog; Wed, 12 Jan 2022 18:42:33 -0800 (PST) X-Google-Smtp-Source: ABdhPJyI3b/HEC7mSrdKPIvFiV6LtwuxqK9RMVCXgjNJx4ShSK+ENricDYApVSnjBSpLchkvKujj X-Received: by 2002:a05:6402:5194:: with SMTP id q20mr2305841edd.113.1642041753169; Wed, 12 Jan 2022 18:42:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642041753; cv=none; d=google.com; s=arc-20160816; b=dK+dV7QWq+qFE1Hh0MwAeolOBhQZ6iwmq3SmwAi+PhadTRW2+Iyc1nJ9Zzut5hzDDO 3KGf2iKoc3rZ5cXJT49c7n8U0L8KtCbyVFlPIYDbZy0BR6Z0hMN7X1KifX1HpHhpdob3 7vuroAIOxji0LTnf0bM+q4F1w3x7OqEVD5qplUUgAV2MPWvVQRmc7yXTyK9xzEVipRF6 UHjkY2YRnLFrpKIL9Z3543UKIMnRmgiYjE01AZlzWl9++xsy8wx8sQ2COJj22RRnpKqY mrU7ARDLP5h+PDerZgJJXwcxhXjGHDwNNZVRFkKgTv1JCXvLKKZrGUfHONfl2Zhzfqbx eTGA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to; bh=7HC9+4sXOyBAS1OZNgSfNNEAUEB4VuLxgideMd4Jmn8=; b=ymrNydtTaQ650CZmnh8jPqhfxw8Hcg7/YoWkaUp0CCC/9+HqTciAEwc79kg9M9jq5S PTvIlqG8PdG8P8wlL7xmLPTdN2pBhLNCS/ZlBc0dg5wnLU0kjHqnkmUkzJpQmlWcJmAc Z53Ww6FvSAdlhEI5w6oTw5YwYQwUCEgkSNOLn5i5P7QgKRDlCezQaK14T8EvsdNiAiqe TF42WPAqKLn31lQr4OFaXrr1DzaYZOC0PJz+bwxKgn4f8kzs27Is5M07cNhcryuDh2/e zLZpV1dSb33Z2EoN5rSuRtmpthuTbv7cp9gwK9bMO3TVN0zUUEbmLhCY/Mn541qcv3aV p/vg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=evlO6O5g; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id w13si1043222ede.535.2022.01.12.18.42.32; Wed, 12 Jan 2022 18:42:33 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=evlO6O5g; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B3D8B68B8D7; Thu, 13 Jan 2022 04:05:59 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qk1-f182.google.com (mail-qk1-f182.google.com [209.85.222.182]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A90C468B8C9 for ; Thu, 13 Jan 2022 04:05:56 +0200 (EET) Received: by mail-qk1-f182.google.com with SMTP id c190so3934348qkg.9 for ; Wed, 12 Jan 2022 18:05:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=iUSrdHDdl1UQffS/mRULU4lG3KtZwns9O4xgiD2FIVQ=; b=evlO6O5g7HE7k3EQgNnpPr1Fav3cpCWCRzM6dnWMAdUrPH0TXfxGn6aL3EkUgdXJ/r Btw09ru98lfZMx0hhWq3A1/wYzch0a85XwhVVfP7lqe/8ahoKh55LpdY/qz7/3P3IrPt vd1Aohf7TyONhCiwyKCJRIXoAtzok6YQXg0629mnwwCjCF7W2fX7YT9bq0hy+LjOuS93 WyiVzvYs7qtXXcXlQrz7t28ZIC8cKkKjJRq6pu7sCgEwjuQOKGHQuR+Qz3mC3n6V2K2J ntyb5QlGfEKA24GLsPnW/+wJptTezttRY9poMI3HTfjD1NsAEOwgnBaaV1HdpD0qMUs0 yjlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=iUSrdHDdl1UQffS/mRULU4lG3KtZwns9O4xgiD2FIVQ=; b=iqnOm8tXOFFM6YWh2hJRI4zZX+qQV9HUwiJnClwSPp3lbpNq7ltJza4wRe9J/iu+H/ 8JEPuAAo1t62o3AI0xKALamqQKqd+buAr74sMVRsj8Sub15sbZAx6SZ9ZAx5Ja7W29+Q oVgWQ9M8eePAg/MwLiezSayl9hPXto10lLrx0J/n/68HVn+aUE+EyIKAflsA/s5lxw61 UtF+31vC7lwJ/gtoeQcrOukrISaN19wfrjX/OldcB0Hd43Rdp8EtGGSPHcv6w/Fwlbiy TZBkjO5yi+eEHfcDzC41OGByeagraWXtwJom0YNYuhXTAYPzD98BiZ0rpDcQT90G8c0W qhNw== X-Gm-Message-State: AOAM530DiO40BOmEofxh+bK3+Mtte63f8hFam+ggBOGEzh3oUALtm4kG c8yslcowht5QxTG91/lfCjV3YnOT+Eo= X-Received: by 2002:a05:620a:170e:: with SMTP id az14mr1759047qkb.635.1642039554741; Wed, 12 Jan 2022 18:05:54 -0800 (PST) Received: from localhost.localdomain ([186.136.131.95]) by smtp.gmail.com with ESMTPSA id k9sm1264556qko.29.2022.01.12.18.05.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 12 Jan 2022 18:05:54 -0800 (PST) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Wed, 12 Jan 2022 23:05:08 -0300 Message-Id: <20220113020518.730-20-jamrial@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220113015101.4-1-jamrial@gmail.com> References: <20220113015101.4-1-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 229/281] libopus: convert to new channel layout API X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: gTWhXABRwb9q From: Anton Khirnov Signed-off-by: James Almer --- libavcodec/libopusdec.c | 39 +++++++++++++----------- libavcodec/libopusenc.c | 65 ++++++++++++++++++++++------------------ libavcodec/vorbis.h | 3 ++ libavcodec/vorbis_data.c | 18 +++++++++++ 4 files changed, 79 insertions(+), 46 deletions(-) diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c index 86ef715205..abffd5f463 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] : (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..401a2c17c8 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,21 +190,26 @@ 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]) { - char name[32]; - av_get_channel_layout_string(name, sizeof(name), avctx->channels, - avctx->channel_layout); - av_log(avctx, AV_LOG_ERROR, - "Invalid channel layout %s for specified mapping family %d.\n", - name, mapping_family); + "channel layout for %d channels.\n", avctx->ch_layout.nb_channels); + } else { + AVChannelLayout chl; + av_channel_layout_copy(&chl, &ff_vorbis_ch_layouts[avctx->ch_layout.nb_channels - 1]); - return AVERROR(EINVAL); + if (av_channel_layout_compare(&avctx->ch_layout, &chl)) { + 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 ? name : "", mapping_family); + + return AVERROR(EINVAL); + } } return 0; @@ -238,7 +243,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 +266,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 +354,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 +372,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 +391,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 +406,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 +415,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 +462,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 +476,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,