From patchwork Wed Dec 8 01:06:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 32135 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:cd86:0:0:0:0:0 with SMTP id d128csp7047146iog; Tue, 7 Dec 2021 17:12:04 -0800 (PST) X-Google-Smtp-Source: ABdhPJzkChki77+VvleaxL/U+/rqlGTnhPjfQS7LcPOOq52PUAOFakrqs2nBmsTe/BymMzZjA4P+ X-Received: by 2002:a05:6402:50cf:: with SMTP id h15mr14682563edb.90.1638925924662; Tue, 07 Dec 2021 17:12:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1638925924; cv=none; d=google.com; s=arc-20160816; b=mevhT7KBBhL4TcP1+j2BgpNoEbXOkpLBPixy+HMmyys3cjb6MaiVTbBh4ImqPHzuqb 2JA31KtDFOaCm45UnaYBeRTHbcP9otIpqbDysoc7i4Zo/8vKW+PRrmSAq5IC6/rFXA8I D7Tek330Joyr1XqmYDCv5M1lNTRnGUFkUML1TdAAGaUmyuNN0MxssgwrqOwwdSGHpCML NXGK4ic99ty9Y5JQbKPvMgnYCrywq//pd1b4CMtlR1f08xrRsNXDR4FwHXqpAW9XzMN3 aVxcpe7/V7ii6+Xhqs2hO1MhLhnSzv9qBYZCLVwP8RhJe53pjw/2ua1RFS2UGXGqlWUa 9bhw== 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=6T3lRPrSAQTKxJ/6tKQWPnrWnmdt1tykQqrJ5/Hsvms=; b=lTuyWg7pSy+/PTVXv23/Hqi31LFZ3ATxCYMyBYzUS3tBZiq9gD1/iF0GskT5VoPtJR tJSsf7x+IKhXANCmftHY8SsAa3VSaZmItn19iTkGib3RIvIDilG2KhfxEZUWSKNQ8Kew 5QWg8orpJ4787qLQ5gCR9FAfIyiK+v2PNnmys5lWHNMKe1SLLTncLMEBU50xYfSj3svE o42b5kLTXifK46Ai7B78K3ERt3hWmh4s2uAZ7HHe13zSs9qMofmiGauCagrZj5G+D0yk mhwszZ3OaVwnz/M0IpBQPO7Jicso1BrLYtxuGAyBhtXhhSTod8l3YEb/7GjzLyhP0ZNg zbUQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=lirapaB0; 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 u3si2190565ejz.294.2021.12.07.17.11.55; Tue, 07 Dec 2021 17:12:04 -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=lirapaB0; 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 B422068AF6D; Wed, 8 Dec 2021 03:08:07 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ua1-f53.google.com (mail-ua1-f53.google.com [209.85.222.53]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3668F68AF45 for ; Wed, 8 Dec 2021 03:08:04 +0200 (EET) Received: by mail-ua1-f53.google.com with SMTP id t13so1882941uad.9 for ; Tue, 07 Dec 2021 17:08:04 -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=Jb8dvNLrTrtWZ7Wbm6Sa28PsMEQOM58R6dIrBYOosAo=; b=lirapaB0xxoFiQiCvBCn7rq4dB6EHvgOyNC3MzVBktVDUPwELgYLKry/yV03FQ1zW3 9IRiI8RZMXrxl4hm6sCd9JVsJlcgpDvVoKQBXwj7GK7xjItK15I9wKezE0ChiFEJvkDN czz1LM+Lu8LEIkj3qoWem0T67KZp++AuXFaIFeLLjtrCuq9daEKjYnKkQmf/NtvyDhRc tZ2ts0j2xzItfl8dcdXUJbv76Gtwd8pez/mTeVw5Q4qxch2sbCKlLt/aOaZiRmchpuMn ArW0SEiWJZNl3+vDei9JIXyvUqHapn6hMepRc1FNInRwrdT3as122F0+9baeiYUacm3N i92g== 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=Jb8dvNLrTrtWZ7Wbm6Sa28PsMEQOM58R6dIrBYOosAo=; b=JL/EwHg51BqoeqS2YgNVlMUjuVzGWAvCIvSoFRI+EPcyj3YEJqLvCAcbyIwt6UKgXd khjIVgfH0JutHrz4oB9IoMQQvFM7rq4Cb6EqOGFOdnZn1BiCsuLUPobWm2GPmGPqvdGt +6T9ztJjDa4pRCJH7HC/K5LgqE+eiEs8JVatwGH9gAyAbhg1oqVSALocykdKCEJpM0XQ cYNKWu6ZxxStDq61yX4iazHWAI6JHIPRhtq24H/9sCg+GsOVUvj5ZDfr7+tbfZDQPhGo V0FXtLw7/Qei0bAgexCL6TPC6rUKYfo7z+yLm4Qqw769VAehUxBsWOnGIJxo1b9jP9AL APZA== X-Gm-Message-State: AOAM533Xyp0aXnm3f8i+NYP2W1z2ins+8khwqMRHZGjiCPu4G/fQdCi9 +BoVRjUpLb/ZNfbsN0GK6RxHoM6ptPlFnCxT X-Received: by 2002:a05:6102:c16:: with SMTP id x22mr50048790vss.69.1638925682041; Tue, 07 Dec 2021 17:08:02 -0800 (PST) Received: from localhost.localdomain ([181.170.250.138]) by smtp.gmail.com with ESMTPSA id b8sm949898vsl.19.2021.12.07.17.08.00 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Dec 2021 17:08:01 -0800 (PST) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Tue, 7 Dec 2021 22:06:43 -0300 Message-Id: <20211208010649.381-28-jamrial@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20211208010649.381-1-jamrial@gmail.com> References: <20211208010649.381-1-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 273/279] swresample: 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: m2dxLkObPHO0 Signed-off-by: James Almer --- libswresample/options.c | 33 +++- libswresample/rematrix.c | 227 ++++++++++++++++++---------- libswresample/rematrix_template.c | 7 +- libswresample/swresample.c | 158 ++++++++++++++++--- libswresample/swresample.h | 63 ++++++++ libswresample/swresample_frame.c | 65 +++++++- libswresample/swresample_internal.h | 10 +- 7 files changed, 443 insertions(+), 120 deletions(-) diff --git a/libswresample/options.c b/libswresample/options.c index 6911709157..ffa27c590d 100644 --- a/libswresample/options.c +++ b/libswresample/options.c @@ -34,12 +34,19 @@ #define OFFSET(x) offsetof(SwrContext,x) #define PARAM AV_OPT_FLAG_AUDIO_PARAM +#define DEPREC AV_OPT_FLAG_DEPRECATED static const AVOption options[]={ -{"ich" , "set input channel count" , OFFSET(user_in_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"in_channel_count" , "set input channel count" , OFFSET(user_in_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"och" , "set output channel count" , OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"out_channel_count" , "set output channel count" , OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, +#if FF_API_OLD_CHANNEL_LAYOUT +{"ich" , "set input channel count (Deprecated, use ichl)", + OFFSET(user_in_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, +{"in_channel_count" , "set input channel count (Deprecated, use in_chlayout)", + OFFSET(user_in_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, +{"och" , "set output channel count (Deprecated, use ochl)", + OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, +{"out_channel_count" , "set output channel count (Deprecated, use out_chlayout)", + OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, +#endif {"uch" , "set used channel count" , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, {"used_channel_count" , "set used channel count" , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, {"isr" , "set input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, @@ -52,10 +59,20 @@ static const AVOption options[]={ {"out_sample_fmt" , "set output sample format" , OFFSET(out_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, {"tsf" , "set internal sample format" , OFFSET(user_int_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, {"internal_sample_fmt" , "set internal sample format" , OFFSET(user_int_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, -{"icl" , "set input channel layout" , OFFSET(user_in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"}, -{"in_channel_layout" , "set input channel layout" , OFFSET(user_in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"}, -{"ocl" , "set output channel layout" , OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"}, -{"out_channel_layout" , "set output channel layout" , OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"}, +#if FF_API_OLD_CHANNEL_LAYOUT +{"icl" , "set input channel layout (Deprecated, use ichl)", + OFFSET(user_in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"}, +{"in_channel_layout" , "set input channel layout (Deprecated, use in_chlayout)", + OFFSET(user_in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"}, +{"ocl" , "set output channel layout (Deprecated, use ochl)", + OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"}, +{"out_channel_layout" , "set output channel layout (Deprecated, use out_chlayout)", + OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"}, +#endif +{"ichl" , "set input channel layout" , OFFSET(user_in_chlayout ), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, +{"in_chlayout" , "set input channel layout" , OFFSET(user_in_chlayout ), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, +{"ochl" , "set output channel layout" , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, +{"out_chlayout" , "set output channel layout" , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, {"clev" , "set center mix level" , OFFSET(clev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, {"center_mix_level" , "set center mix level" , OFFSET(clev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, {"slev" , "set surround mix level" , OFFSET(slev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c index 94b3de88f6..106ab88454 100644 --- a/libswresample/rematrix.c +++ b/libswresample/rematrix.c @@ -64,15 +64,31 @@ int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride) { int nb_in, nb_out, in, out; + int user_in_chlayout_nb_channels, user_out_chlayout_nb_channels; if (!s || s->in_convert) // s needs to be allocated but not initialized return AVERROR(EINVAL); memset(s->matrix, 0, sizeof(s->matrix)); memset(s->matrix_flt, 0, sizeof(s->matrix_flt)); + +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + user_in_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_in_ch_layout); +FF_ENABLE_DEPRECATION_WARNINGS + if (!user_in_chlayout_nb_channels) +#endif + user_in_chlayout_nb_channels = s->user_in_chlayout.nb_channels; nb_in = (s->user_in_ch_count > 0) ? s->user_in_ch_count : - av_get_channel_layout_nb_channels(s->user_in_ch_layout); + user_in_chlayout_nb_channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + user_out_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_out_ch_layout); +FF_ENABLE_DEPRECATION_WARNINGS + if (!user_out_chlayout_nb_channels) +#endif + user_out_chlayout_nb_channels = s->user_out_chlayout.nb_channels; nb_out = (s->user_out_ch_count > 0) ? s->user_out_ch_count : - av_get_channel_layout_nb_channels(s->user_out_ch_layout); + user_out_chlayout_nb_channels; for (out = 0; out < nb_out; out++) { for (in = 0; in < nb_in; in++) s->matrix_flt[out][in] = s->matrix[out][in] = matrix[in]; @@ -88,95 +104,141 @@ static int even(int64_t layout){ return 0; } -static int64_t clean_layout(void *s, int64_t layout){ - if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) { +static int clean_layout(AVChannelLayout *out, const AVChannelLayout *in, void *s) +{ + int ret = 0; + + if(av_channel_layout_index_from_channel(in, AV_CH_FRONT_CENTER) < 0 && in->nb_channels == 1) { char buf[128]; - av_get_channel_layout_string(buf, sizeof(buf), -1, layout); + av_channel_layout_describe(in, buf, sizeof(buf)); av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf); - return AV_CH_FRONT_CENTER; - } + *out = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; + } else + ret = av_channel_layout_copy(out, in); - return layout; + return ret; } -static int sane_layout(int64_t layout){ - if(!(layout & AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker +static int sane_layout(AVChannelLayout *ch_layout) { + if (ch_layout->order != AV_CHANNEL_ORDER_NATIVE) + return 0; + if(!av_channel_layout_subset(ch_layout, AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker return 0; - if(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymetric front + if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)))) // no asymetric front return 0; - if(!even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT))) // no asymetric side + if(!even(av_channel_layout_subset(ch_layout, (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))) // no asymetric side return 0; - if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT))) + if(!even(av_channel_layout_subset(ch_layout, (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))) return 0; - if(!even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER))) + if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)))) return 0; - if(av_get_channel_layout_nb_channels(layout) >= SWR_CH_MAX) + if(ch_layout->nb_channels >= SWR_CH_MAX) return 0; return 1; } +#if FF_API_OLD_CHANNEL_LAYOUT av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout_param, double center_mix_level, double surround_mix_level, double lfe_mix_level, double maxval, double rematrix_volume, double *matrix_param, int stride, enum AVMatrixEncoding matrix_encoding, void *log_context) { - int i, j, out_i; + AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 }; + int ret; + + ret = av_channel_layout_from_mask(&in_ch_layout, in_ch_layout_param); + ret |= av_channel_layout_from_mask(&out_ch_layout, out_ch_layout_param); + if (ret < 0) + return ret; + + return swr_build_matrix2(&in_ch_layout, &out_ch_layout, center_mix_level, surround_mix_level, + lfe_mix_level, maxval, rematrix_volume, matrix_param, + stride, matrix_encoding, log_context); +} +#endif + +av_cold int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double maxval, + double rematrix_volume, double *matrix_param, + ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, void *log_context) +{ + int i, j, out_i, ret; + AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 }; double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}}; - int64_t unaccounted, in_ch_layout, out_ch_layout; + int64_t unaccounted; double maxcoef=0; char buf[128]; - in_ch_layout = clean_layout(log_context, in_ch_layout_param); - out_ch_layout = clean_layout(log_context, out_ch_layout_param); - - if( out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX - && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 - ) - out_ch_layout = AV_CH_LAYOUT_STEREO; + ret = clean_layout(&in_ch_layout, in_layout, log_context); + ret |= clean_layout(&out_ch_layout, out_layout, log_context); + if (ret < 0) + goto fail; - if( in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX - && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 - ) - in_ch_layout = AV_CH_LAYOUT_STEREO; - - if (in_ch_layout == AV_CH_LAYOUT_22POINT2 && - out_ch_layout != AV_CH_LAYOUT_22POINT2) { - in_ch_layout = (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER); - av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout); + if( !av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX) + && !av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX) + ) { + av_channel_layout_uninit(&out_ch_layout); + out_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; + } + if( !av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX) + && !av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX) + ) { + av_channel_layout_uninit(&in_ch_layout); + in_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; + } + if (!av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2) && + av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2)) { + av_channel_layout_from_mask(&in_ch_layout, (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER)); + av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf)); av_log(log_context, AV_LOG_WARNING, "Full-on remixing from 22.2 has not yet been implemented! " "Processing the input as '%s'\n", buf); } - if(!sane_layout(in_ch_layout)){ - av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param); + if(!av_channel_layout_check(&in_ch_layout)) { + av_log(log_context, AV_LOG_ERROR, "Input channel layout is invalid\n"); + ret = AVERROR(EINVAL); + goto fail; + } + if(!sane_layout(&in_ch_layout)) { + av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf)); av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } - if(!sane_layout(out_ch_layout)){ - av_get_channel_layout_string(buf, sizeof(buf), -1, out_ch_layout_param); + if(!av_channel_layout_check(&out_ch_layout)) { + av_log(log_context, AV_LOG_ERROR, "Output channel layout is invalid\n"); + ret = AVERROR(EINVAL); + goto fail; + } + if(!sane_layout(&out_ch_layout)) { + av_channel_layout_describe(&out_ch_layout, buf, sizeof(buf)); av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } for(i=0; i= 0 + && av_channel_layout_index_from_channel(&out_ch_layout, i) == idx) matrix[i][i]= 1.0; } - unaccounted= in_ch_layout & ~out_ch_layout; + unaccounted = in_ch_layout.u.mask & ~out_ch_layout.u.mask; //FIXME implement dolby surround //FIXME implement full ac3 if(unaccounted & AV_CH_FRONT_CENTER){ - if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){ - if(in_ch_layout & AV_CH_LAYOUT_STEREO) { + if(av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){ + if(av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO)) { matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level; matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level; } else { @@ -187,23 +249,23 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout av_assert0(0); } if(unaccounted & AV_CH_LAYOUT_STEREO){ - if(out_ch_layout & AV_CH_FRONT_CENTER){ + if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){ matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2; matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2; - if(in_ch_layout & AV_CH_FRONT_CENTER) + if(av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2); }else av_assert0(0); } if(unaccounted & AV_CH_BACK_CENTER){ - if(out_ch_layout & AV_CH_BACK_LEFT){ + if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0){ matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2; - }else if(out_ch_layout & AV_CH_SIDE_LEFT){ + }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){ matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2; - }else if(out_ch_layout & AV_CH_FRONT_LEFT){ + }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY || matrix_encoding == AV_MATRIX_ENCODING_DPLII) { if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) { @@ -217,24 +279,24 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; } - }else if(out_ch_layout & AV_CH_FRONT_CENTER){ + }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){ matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_BACK_LEFT){ - if(out_ch_layout & AV_CH_BACK_CENTER){ + if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0){ matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2; - }else if(out_ch_layout & AV_CH_SIDE_LEFT){ - if(in_ch_layout & AV_CH_SIDE_LEFT){ + }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){ + if(av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_SIDE_LEFT) >= 0){ matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2; }else{ matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0; matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0; } - }else if(out_ch_layout & AV_CH_FRONT_LEFT){ + }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2; matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2; @@ -249,7 +311,7 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level; matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level; } - }else if(out_ch_layout & AV_CH_FRONT_CENTER){ + }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){ matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2; matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2; }else @@ -257,20 +319,20 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout } if(unaccounted & AV_CH_SIDE_LEFT){ - if(out_ch_layout & AV_CH_BACK_LEFT){ + if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0){ /* if back channels do not exist in the input, just copy side channels to back channels, otherwise mix side into back */ - if (in_ch_layout & AV_CH_BACK_LEFT) { + if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_BACK_LEFT) >= 0) { matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2; matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2; } else { matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0; matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0; } - }else if(out_ch_layout & AV_CH_BACK_CENTER){ + }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0){ matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2; - }else if(out_ch_layout & AV_CH_FRONT_LEFT){ + }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2; matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2; @@ -285,7 +347,7 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level; matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level; } - }else if(out_ch_layout & AV_CH_FRONT_CENTER){ + }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){ matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2; matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2; }else @@ -293,10 +355,10 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout } if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){ - if(out_ch_layout & AV_CH_FRONT_LEFT){ + if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0){ matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0; matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0; - }else if(out_ch_layout & AV_CH_FRONT_CENTER){ + }else if(av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0){ matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2; matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2; }else @@ -304,9 +366,9 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout } /* mix LFE into front left/right or center */ if (unaccounted & AV_CH_LOW_FREQUENCY) { - if (out_ch_layout & AV_CH_FRONT_CENTER) { + if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level; - } else if (out_ch_layout & AV_CH_FRONT_LEFT) { + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2; } else @@ -316,15 +378,19 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout for(out_i=i=0; i<64; i++){ double sum=0; int in_i=0; - if((out_ch_layout & (1ULL<= 0 + && av_channel_layout_index_from_channel(&out_ch_layout, i) == idx); + } sum += fabs(matrix_param[stride*out_i + in_i]); in_i++; } @@ -350,17 +416,22 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout } av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n"); - for(i=0; imatrix, 0, sizeof(s->matrix)); - ret = swr_build_matrix(s->in_ch_layout, s->out_ch_layout, + ret = swr_build_matrix2(&s->in_ch_layout, &s->out_ch_layout, s->clev, s->slev, s->lfe_mix_level, maxval, s->rematrix_volume, (double*)s->matrix, s->matrix[1] - s->matrix[0], s->matrix_encoding, s); @@ -519,8 +590,8 @@ int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus off = len1 * out->bps; } - av_assert0(!s->out_ch_layout || out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout)); - av_assert0(!s-> in_ch_layout || in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout)); + av_assert0(s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || out->ch_count == s->out_ch_layout.nb_channels); + av_assert0(s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || in ->ch_count == s->in_ch_layout.nb_channels); for(out_i=0; out_ich_count; out_i++){ switch(s->matrix_ch[out_i][0]){ diff --git a/libswresample/rematrix_template.c b/libswresample/rematrix_template.c index add65e3155..f5a508361c 100644 --- a/libswresample/rematrix_template.c +++ b/libswresample/rematrix_template.c @@ -88,13 +88,16 @@ static void RENAME(mix8to2)(SAMPLE **out, const SAMPLE **in, COEFF *coeffp, inte } static RENAME(mix_any_func_type) *RENAME(get_mix_any_func)(SwrContext *s){ - if( s->out_ch_layout == AV_CH_LAYOUT_STEREO && (s->in_ch_layout == AV_CH_LAYOUT_5POINT1 || s->in_ch_layout == AV_CH_LAYOUT_5POINT1_BACK) + if( !av_channel_layout_compare(&s->out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO) + && ( !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1) + || !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK)) && s->matrix[0][2] == s->matrix[1][2] && s->matrix[0][3] == s->matrix[1][3] && !s->matrix[0][1] && !s->matrix[0][5] && !s->matrix[1][0] && !s->matrix[1][4] ) return RENAME(mix6to2); - if( s->out_ch_layout == AV_CH_LAYOUT_STEREO && s->in_ch_layout == AV_CH_LAYOUT_7POINT1 + if( !av_channel_layout_compare(&s->out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO) + && !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1) && s->matrix[0][2] == s->matrix[1][2] && s->matrix[0][3] == s->matrix[1][3] && !s->matrix[0][1] && !s->matrix[0][5] && !s->matrix[1][0] && !s->matrix[1][4] && !s->matrix[0][7] && !s->matrix[1][6] diff --git a/libswresample/swresample.c b/libswresample/swresample.c index c03fe5528f..fe75e847af 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -56,6 +56,8 @@ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map){ return 0; } +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, @@ -97,6 +99,58 @@ fail: swr_free(&s); return NULL; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + +int swr_alloc_set_opts2(struct SwrContext **ps, + AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx) { + struct SwrContext *s = *ps; + int ret; + + if (!s) s = swr_alloc(); + if (!s) return AVERROR(ENOMEM); + + s->log_level_offset= log_offset; + s->log_ctx= log_ctx; + + if ((ret = av_opt_set_chlayout(s, "ochl", out_ch_layout, 0)) < 0) + goto fail; + + if ((ret = av_opt_set_int(s, "osf", out_sample_fmt, 0)) < 0) + goto fail; + + if ((ret = av_opt_set_int(s, "osr", out_sample_rate, 0)) < 0) + goto fail; + + if ((ret = av_opt_set_chlayout(s, "ichl", in_ch_layout, 0)) < 0) + goto fail; + + if ((ret = av_opt_set_int(s, "isf", in_sample_fmt, 0)) < 0) + goto fail; + + if ((ret = av_opt_set_int(s, "isr", in_sample_rate, 0)) < 0) + goto fail; + + av_opt_set_int(s, "uch", 0, 0); + +#if FF_API_OLD_CHANNEL_LAYOUT + // Clear old API values so they don't take precedence in swr_init() + av_opt_set_int(s, "icl", 0, 0); + av_opt_set_int(s, "ocl", 0, 0); + av_opt_set_int(s, "ich", 0, 0); + av_opt_set_int(s, "och", 0, 0); +#endif + + *ps = s; + + return 0; +fail: + av_log(s, AV_LOG_ERROR, "Failed to set option\n"); + swr_free(ps); + return ret; +} static void set_audiodata_fmt(AudioData *a, enum AVSampleFormat fmt){ a->fmt = fmt; @@ -125,6 +179,8 @@ static void clear_context(SwrContext *s){ free_temp(&s->drop_temp); free_temp(&s->dither.noise); free_temp(&s->dither.temp); + av_channel_layout_uninit(&s->in_ch_layout); + av_channel_layout_uninit(&s->out_ch_layout); swri_audio_convert_free(&s-> in_convert); swri_audio_convert_free(&s->out_convert); swri_audio_convert_free(&s->full_convert); @@ -138,6 +194,9 @@ av_cold void swr_free(SwrContext **ss){ SwrContext *s= *ss; if(s){ clear_context(s); + av_channel_layout_uninit(&s->user_in_chlayout); + av_channel_layout_uninit(&s->user_out_chlayout); + if (s->resampler) s->resampler->free(&s->resample); } @@ -172,25 +231,72 @@ av_cold int swr_init(struct SwrContext *s){ av_log(s, AV_LOG_ERROR, "Requested output sample rate %d is invalid\n", s->out_sample_rate); return AVERROR(EINVAL); } + s->used_ch_count = s->user_used_ch_count; +#if FF_API_OLD_CHANNEL_LAYOUT s->out.ch_count = s-> user_out_ch_count; s-> in.ch_count = s-> user_in_ch_count; - s->used_ch_count = s->user_used_ch_count; - s-> in_ch_layout = s-> user_in_ch_layout; - s->out_ch_layout = s->user_out_ch_layout; + // if the old/new fields are set inconsistently, prefer the old ones + if ((s->user_in_ch_count && s->user_in_ch_count != s->user_in_chlayout.nb_channels) || + (s->user_in_ch_layout && (s->user_in_chlayout.order != AV_CHANNEL_ORDER_NATIVE || + s->user_in_chlayout.u.mask != s->user_in_ch_layout))) { + av_channel_layout_uninit(&s->in_ch_layout); + if (s->user_in_ch_layout) + av_channel_layout_from_mask(&s->in_ch_layout, s->user_in_ch_layout); + else { + s->in_ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + s->in_ch_layout.nb_channels = s->user_in_ch_count; + } + } else + av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout); + + if ((s->user_out_ch_count && s->user_out_ch_count != s->user_out_chlayout.nb_channels) || + (s->user_out_ch_layout && (s->user_out_chlayout.order != AV_CHANNEL_ORDER_NATIVE || + s->user_out_chlayout.u.mask != s->user_out_ch_layout))) { + av_channel_layout_uninit(&s->out_ch_layout); + if (s->user_out_ch_layout) + av_channel_layout_from_mask(&s->out_ch_layout, s->user_out_ch_layout); + else { + s->out_ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + s->out_ch_layout.nb_channels = s->user_out_ch_count; + } + } else + av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout); + + if (!s->out.ch_count && !s->user_out_ch_layout) + s->out.ch_count = s->out_ch_layout.nb_channels; + if (!s-> in.ch_count && !s-> user_in_ch_layout) + s-> in.ch_count = s->in_ch_layout.nb_channels; +#else + s->out.ch_count = s-> user_out_chlayout.nb_channels; + s-> in.ch_count = s-> user_in_chlayout.nb_channels; + + ret = av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout); + ret |= av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout); + if (ret < 0) + return ret; +#endif s->int_sample_fmt= s->user_int_sample_fmt; s->dither.method = s->user_dither_method; - if(av_get_channel_layout_nb_channels(s-> in_ch_layout) > SWR_CH_MAX) { - av_log(s, AV_LOG_WARNING, "Input channel layout 0x%"PRIx64" is invalid or unsupported.\n", s-> in_ch_layout); - s->in_ch_layout = 0; + if(!av_channel_layout_check(&s->in_ch_layout) || + s->in_ch_layout.nb_channels > SWR_CH_MAX || + ( s->in_ch_layout.order != AV_CHANNEL_ORDER_NATIVE + && s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC)) { + av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1)); + av_log(s, AV_LOG_WARNING, "Input channel layout \"%s\" is invalid or unsupported.\n", l1); + av_channel_layout_uninit(&s->in_ch_layout); } - if(av_get_channel_layout_nb_channels(s->out_ch_layout) > SWR_CH_MAX) { - av_log(s, AV_LOG_WARNING, "Output channel layout 0x%"PRIx64" is invalid or unsupported.\n", s->out_ch_layout); - s->out_ch_layout = 0; + if(!av_channel_layout_check(&s->out_ch_layout) || + s->out_ch_layout.nb_channels > SWR_CH_MAX || + ( s->out_ch_layout.order != AV_CHANNEL_ORDER_NATIVE + && s->out_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC)) { + av_channel_layout_describe(&s->out_ch_layout, l2, sizeof(l2)); + av_log(s, AV_LOG_WARNING, "Output channel layout \"%s\" is invalid or unsupported.\n", l2); + av_channel_layout_uninit(&s->out_ch_layout); } switch(s->engine){ @@ -206,17 +312,18 @@ av_cold int swr_init(struct SwrContext *s){ if(!s->used_ch_count) s->used_ch_count= s->in.ch_count; - if(s->used_ch_count && s-> in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){ + if(s->used_ch_count && s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels){ av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n"); - s-> in_ch_layout= 0; + av_channel_layout_uninit(&s->in_ch_layout); } - if(!s-> in_ch_layout) - s-> in_ch_layout= av_get_default_channel_layout(s->used_ch_count); - if(!s->out_ch_layout) - s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count); + if(!s->in_ch_layout.nb_channels || s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&s->in_ch_layout, s->used_ch_count); + if(!s->out_ch_layout.nb_channels || s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&s->out_ch_layout, s->out.ch_count); - s->rematrix= s->out_ch_layout !=s->in_ch_layout || s->rematrix_volume!=1.0 || + s->rematrix= av_channel_layout_compare(&s->out_ch_layout, &s->in_ch_layout) || + s->rematrix_volume!=1.0 || s->rematrix_custom; if(s->int_sample_fmt == AV_SAMPLE_FMT_NONE){ @@ -291,33 +398,36 @@ av_cold int swr_init(struct SwrContext *s){ #define RSC 1 //FIXME finetune if(!s-> in.ch_count) - s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout); + s-> in.ch_count = s->in_ch_layout.nb_channels; if(!s->used_ch_count) s->used_ch_count= s->in.ch_count; if(!s->out.ch_count) - s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout); + s->out.ch_count = s->out_ch_layout.nb_channels; if(!s-> in.ch_count){ - av_assert0(!s->in_ch_layout); + av_assert0(s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC); av_log(s, AV_LOG_ERROR, "Input channel count and layout are unset\n"); ret = AVERROR(EINVAL); goto fail; } - av_get_channel_layout_string(l1, sizeof(l1), s-> in.ch_count, s-> in_ch_layout); - av_get_channel_layout_string(l2, sizeof(l2), s->out.ch_count, s->out_ch_layout); - if (s->out_ch_layout && s->out.ch_count != av_get_channel_layout_nb_channels(s->out_ch_layout)) { +#if FF_API_OLD_CHANNEL_LAYOUT + av_channel_layout_describe(&s->out_ch_layout, l1, sizeof(l1)); + if (s->out_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->out.ch_count != s->out_ch_layout.nb_channels) { av_log(s, AV_LOG_ERROR, "Output channel layout %s mismatches specified channel count %d\n", l2, s->out.ch_count); ret = AVERROR(EINVAL); goto fail; } - if (s->in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s->in_ch_layout)) { +#endif + av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1)); + if (s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels) { av_log(s, AV_LOG_ERROR, "Input channel layout %s mismatches specified channel count %d\n", l1, s->used_ch_count); ret = AVERROR(EINVAL); goto fail; } - if ((!s->out_ch_layout || !s->in_ch_layout) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) { + if (( s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC + || s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) { av_log(s, AV_LOG_ERROR, "Rematrix is needed between %s and %s " "but there is not enough information to do it\n", l1, l2); ret = AVERROR(EINVAL); diff --git a/libswresample/swresample.h b/libswresample/swresample.h index c7b84fbcac..c6ff2345e9 100644 --- a/libswresample/swresample.h +++ b/libswresample/swresample.h @@ -227,6 +227,7 @@ int swr_init(struct SwrContext *s); */ int swr_is_initialized(struct SwrContext *s); +#if FF_API_OLD_CHANNEL_LAYOUT /** * Allocate SwrContext if needed and set/reset common parameters. * @@ -246,12 +247,40 @@ int swr_is_initialized(struct SwrContext *s); * * @see swr_init(), swr_free() * @return NULL on error, allocated context otherwise + * @deprecated use @ref swr_alloc_set_opts2() */ +attribute_deprecated struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx); +#endif +/** + * Allocate SwrContext if needed and set/reset common parameters. + * + * This function does not require s to be allocated with swr_alloc(). On the + * other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters + * on the allocated context. + * + * @param ps Pointer to an existing Swr context if available, or to NULL if not. + * On success, *ps will be set the allocated context. + * @param out_ch_layout output channel layout (AV_CH_LAYOUT_*) + * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). + * @param out_sample_rate output sample rate (frequency in Hz) + * @param in_ch_layout input channel layout (AV_CH_LAYOUT_*) + * @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*). + * @param in_sample_rate input sample rate (frequency in Hz) + * @param log_offset logging level offset + * @param log_ctx parent logging context, can be NULL + * + * @see swr_init(), swr_free() + * @return 0 on success, a negative AVERROR code on error. + */ +int swr_alloc_set_opts2(struct SwrContext **ps, + AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx); /** * @} * @@ -362,6 +391,7 @@ int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensatio */ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); +#if FF_API_OLD_CHANNEL_LAYOUT /** * Generate a channel mixing matrix. * @@ -384,13 +414,46 @@ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) * @param log_ctx parent logging context, can be NULL * @return 0 on success, negative AVERROR code on failure + * @deprecated use @ref swr_build_matrix2() */ +attribute_deprecated int swr_build_matrix(uint64_t in_layout, uint64_t out_layout, double center_mix_level, double surround_mix_level, double lfe_mix_level, double rematrix_maxval, double rematrix_volume, double *matrix, int stride, enum AVMatrixEncoding matrix_encoding, void *log_ctx); +#endif + +/** + * Generate a channel mixing matrix. + * + * This function is the one used internally by libswresample for building the + * default mixing matrix. It is made public just as a utility function for + * building custom matrices. + * + * @param in_layout input channel layout + * @param out_layout output channel layout + * @param center_mix_level mix level for the center channel + * @param surround_mix_level mix level for the surround channel(s) + * @param lfe_mix_level mix level for the low-frequency effects channel + * @param rematrix_maxval if 1.0, coefficients will be normalized to prevent + * overflow. if INT_MAX, coefficients will not be + * normalized. + * @param[out] matrix mixing coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o. + * @param stride distance between adjacent input channels in the + * matrix array + * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) + * @param log_ctx parent logging context, can be NULL + * @return 0 on success, negative AVERROR code on failure + */ +int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double maxval, + double rematrix_volume, double *matrix_param, + ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, + void *log_context); /** * Set a customized remix matrix. diff --git a/libswresample/swresample_frame.c b/libswresample/swresample_frame.c index d95c1cc537..747cf119a9 100644 --- a/libswresample/swresample_frame.c +++ b/libswresample/swresample_frame.c @@ -29,7 +29,19 @@ int swr_config_frame(SwrContext *s, const AVFrame *out, const AVFrame *in) swr_close(s); if (in) { - if (av_opt_set_int(s, "icl", in->channel_layout, 0) < 0) + AVChannelLayout in_ch_layout = { 0 }; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + // if the old/new fields are set inconsistently, prefer the old ones + if ((in->channel_layout && (in->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + in->ch_layout.u.mask != in->channel_layout))) { + av_channel_layout_from_mask(&in_ch_layout, in->channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS + } else +#endif + if (av_channel_layout_copy(&in_ch_layout, &in->ch_layout) < 0) + goto fail; + if (av_opt_set_chlayout(s, "ichl", &in_ch_layout, 0) < 0) goto fail; if (av_opt_set_int(s, "isf", in->format, 0) < 0) goto fail; @@ -38,7 +50,19 @@ int swr_config_frame(SwrContext *s, const AVFrame *out, const AVFrame *in) } if (out) { - if (av_opt_set_int(s, "ocl", out->channel_layout, 0) < 0) + AVChannelLayout out_ch_layout = { 0 }; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + // if the old/new fields are set inconsistently, prefer the old ones + if ((out->channel_layout && (out->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + out->ch_layout.u.mask != out->channel_layout))) { + av_channel_layout_from_mask(&out_ch_layout, out->channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS + } else +#endif + if (av_channel_layout_copy(&out_ch_layout, &out->ch_layout) < 0) + goto fail; + if (av_opt_set_chlayout(s, "ochl", &out_ch_layout, 0) < 0) goto fail; if (av_opt_set_int(s, "osf", out->format, 0) < 0) goto fail; @@ -58,7 +82,19 @@ static int config_changed(SwrContext *s, int ret = 0; if (in) { - if (s->in_ch_layout != in->channel_layout || + AVChannelLayout in_ch_layout = { 0 }; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + // if the old/new fields are set inconsistently, prefer the old ones + if ((in->channel_layout && (in->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + in->ch_layout.u.mask != in->channel_layout))) { + av_channel_layout_from_mask(&in_ch_layout, in->channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS + } else +#endif + if ((ret = av_channel_layout_copy(&in_ch_layout, &in->ch_layout)) < 0) + return ret; + if (av_channel_layout_compare(&s->in_ch_layout, &in_ch_layout) || s->in_sample_rate != in->sample_rate || s->in_sample_fmt != in->format) { ret |= AVERROR_INPUT_CHANGED; @@ -66,7 +102,19 @@ static int config_changed(SwrContext *s, } if (out) { - if (s->out_ch_layout != out->channel_layout || + AVChannelLayout out_ch_layout = { 0 }; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + // if the old/new fields are set inconsistently, prefer the old ones + if ((out->channel_layout && (out->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + out->ch_layout.u.mask != out->channel_layout))) { + av_channel_layout_from_mask(&out_ch_layout, out->channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS + } else +#endif + if ((ret = av_channel_layout_copy(&out_ch_layout, &out->ch_layout)) < 0) + return ret; + if (av_channel_layout_compare(&s->out_ch_layout, &out_ch_layout) || s->out_sample_rate != out->sample_rate || s->out_sample_fmt != out->format) { ret |= AVERROR_OUTPUT_CHANGED; @@ -116,7 +164,14 @@ static inline int available_samples(AVFrame *out) if (av_sample_fmt_is_planar(out->format)) { return samples; } else { - int channels = av_get_channel_layout_nb_channels(out->channel_layout); + int channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + channels = av_get_channel_layout_nb_channels(out->channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS + if (!channels) +#endif + channels = out->ch_layout.nb_channels; return samples / channels; } } diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h index f2ea5a226d..262a0e2b8c 100644 --- a/libswresample/swresample_internal.h +++ b/libswresample/swresample_internal.h @@ -99,8 +99,8 @@ struct SwrContext { enum AVSampleFormat in_sample_fmt; ///< input sample format enum AVSampleFormat int_sample_fmt; ///< internal sample format (AV_SAMPLE_FMT_FLTP or AV_SAMPLE_FMT_S16P) enum AVSampleFormat out_sample_fmt; ///< output sample format - int64_t in_ch_layout; ///< input channel layout - int64_t out_ch_layout; ///< output channel layout + AVChannelLayout in_ch_layout; ///< input channel layout + AVChannelLayout out_ch_layout; ///< output channel layout int in_sample_rate; ///< input sample rate int out_sample_rate; ///< output sample rate int flags; ///< miscellaneous flags such as SWR_FLAG_RESAMPLE @@ -114,11 +114,15 @@ struct SwrContext { int used_ch_count; ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count) int engine; + int user_used_ch_count; ///< User set used channel count +#if FF_API_OLD_CHANNEL_LAYOUT int user_in_ch_count; ///< User set input channel count int user_out_ch_count; ///< User set output channel count - int user_used_ch_count; ///< User set used channel count int64_t user_in_ch_layout; ///< User set input channel layout int64_t user_out_ch_layout; ///< User set output channel layout +#endif + AVChannelLayout user_in_chlayout; ///< User set input channel layout + AVChannelLayout user_out_chlayout; ///< User set output channel layout enum AVSampleFormat user_int_sample_fmt; ///< User set internal sample format int user_dither_method; ///< User set dither method