From patchwork Sat Mar 9 21:54:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 46927 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:dc95:b0:1a1:738b:6bc0 with SMTP id ky21csp442417pzb; Sat, 9 Mar 2024 13:55:35 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXL5hFjnLn+sI451eIAo9W1Xn06gFSqmogxKXR7WObxKPpM6eyIwILTihqxL6SFbJYQrGBqVvlKqERg8yD0MUr2WWhMcnZhBEqfvg== X-Google-Smtp-Source: AGHT+IFh5XAF/nc6A7k62lNjSBEjEroeTm2UROOSnJlk7d2wVu6zRYpnZ+cq4jd6JcY2oXlqtVom X-Received: by 2002:a17:907:1004:b0:a45:1850:e6ed with SMTP id ox4-20020a170907100400b00a451850e6edmr1548101ejb.6.1710021335145; Sat, 09 Mar 2024 13:55:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1710021335; cv=none; d=google.com; s=arc-20160816; b=zdu9ZQ34TusfWRBKCzhPLASFt671jydzCBcmijOn+5TiOezl1tF+AFOD+In9L/GI1b LSE0CfmhEEbFXh4ExT+afxJUVHyNTOgffueVxq5vJo5+Uu1W0LV2edcb0jMsrDLUhm1w zrRTBYEBFXsNHup3CvhAYddKa8iIqplzUvcGBtoH+k1Horo5NVAsA7hXNV25yYtPZE0b s/s1Qf3iptQztkFi04cBTG07aobkfm6lN9m0lUBfi1Ph3RmcL+onz3jB+yJqghRv9ugS PkkkSrJYDyQtBK5UEW8nkb+MMP/fZTmJxshSSeoKdlzdh2QlwASisg1qsr7XU/xGx5sK Uwpg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc: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:delivered-to; bh=Z4JSpDxfu9DwUiQYqr/a0J/WClYq+w0aPT5xWdQpwgs=; fh=s+G8Ss4JbeMFkWPSp2LmIH/LXFyBlALRiww1j3FPjHY=; b=lxcw5Qf0f4aQpq2ysmtlQwmmDauFePmqLkzE0yBWQbXl/K5Xo+ciQnePfS7RbXoKQ7 +Y2iKx3b+Qi6A6mWP2rzAbjxEJui9u6RmeZntzxScKHBw48mBrKkkPfxmfzSXUK/nDra Mw2WtTcuJ+/c8M+0Tz+SYTbl6JXT2LdSuzs8ttQIQzFawcASOkdQHK9Dpq38PLZLDqCU YfD5NNa/en+7loHHZQtSvKNUOnQBi68nPXhvHoigMSb2GCGFgAkVNHVXrXbP9hNqU/D1 10lEjYPqT0PHk5V7h4Qv+T8w5o+Co1yLVs8J3EP00t4thgEJd5TUFrk9Ke8tTcVGk4x/ /NRw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id g20-20020a170906539400b00a45cc26906csi1036153ejo.557.2024.03.09.13.55.34; Sat, 09 Mar 2024 13:55:35 -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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6B1B368CF41; Sat, 9 Mar 2024 23:54:55 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 80EAC68CF0B for ; Sat, 9 Mar 2024 23:54:46 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 6FD47E8EA0; Sat, 9 Mar 2024 22:54:46 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id iX1yR4AzRGDD; Sat, 9 Mar 2024 22:54:43 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id C06CFE8EC5; Sat, 9 Mar 2024 22:54:41 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Sat, 9 Mar 2024 22:54:12 +0100 Message-Id: <20240309215414.26699-5-cus@passwd.hu> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240309215414.26699-1-cus@passwd.hu> References: <20240309215414.26699-1-cus@passwd.hu> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 5/7] avutil/channel_layout: factorize parsing list of channel names 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 Cc: Marton Balint Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: rteDW0NDynE7 Also make use of the av_channel_from_string() function to determine the channel id. This fixes some parse issues in av_channel_layout_from_string(). Signed-off-by: Marton Balint --- libavutil/channel_layout.c | 172 ++++++++++++---------------------- tests/ref/fate/channel_layout | 8 +- 2 files changed, 62 insertions(+), 118 deletions(-) diff --git a/libavutil/channel_layout.c b/libavutil/channel_layout.c index d3abb2dc42..5db4cc9df0 100644 --- a/libavutil/channel_layout.c +++ b/libavutil/channel_layout.c @@ -239,13 +239,58 @@ int av_channel_layout_from_mask(AVChannelLayout *channel_layout, return 0; } +static int parse_channel_list(AVChannelLayout *ch_layout, const char *str) +{ + int ret; + int nb_channels = 0; + AVChannelCustom *map = NULL; + AVChannelCustom custom = {0}; + + while (*str) { + char *channel, *chname; + int ret = av_opt_get_key_value(&str, "@", "+", AV_OPT_FLAG_IMPLICIT_KEY, &channel, &chname); + if (ret < 0) { + av_freep(&map); + return ret; + } + if (*str) + str++; // skip separator + if (!channel) { + channel = chname; + chname = NULL; + } + av_strlcpy(custom.name, chname ? chname : "", sizeof(custom.name)); + custom.id = av_channel_from_string(channel); + av_free(channel); + av_free(chname); + if (custom.id == AV_CHAN_NONE) { + av_freep(&map); + return AVERROR(EINVAL); + } + + av_dynarray2_add((void **)&map, &nb_channels, sizeof(custom), (void *)&custom); + if (!map) + return AVERROR(ENOMEM); + } + + if (!nb_channels) + return AVERROR(EINVAL); + + ch_layout->order = AV_CHANNEL_ORDER_CUSTOM; + ch_layout->u.map = map; + ch_layout->nb_channels = nb_channels; + + ret = av_channel_layout_retype(ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL); + av_assert0(ret == 0); + + return 0; +} + int av_channel_layout_from_string(AVChannelLayout *channel_layout, const char *str) { - int i; - int channels = 0, nb_channels = 0, native = 1; - enum AVChannel highest_channel = AV_CHAN_NONE; - const char *dup; + int i, matches, ret; + int channels = 0, nb_channels = 0; char *chlist, *end; uint64_t mask = 0; @@ -321,121 +366,20 @@ int av_channel_layout_from_string(AVChannelLayout *channel_layout, return AVERROR(ENOMEM); /* channel names */ - av_sscanf(str, "%d channels (%[^)]", &nb_channels, chlist); - end = strchr(str, ')'); - - dup = chlist; - while (*dup) { - char *channel, *chname; - int ret = av_opt_get_key_value(&dup, "@", "+", AV_OPT_FLAG_IMPLICIT_KEY, &channel, &chname); - if (ret < 0) { - av_free(chlist); - return ret; - } - if (*dup) - dup++; // skip separator - if (channel && !*channel) - av_freep(&channel); - for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) { - if (channel_names[i].name && !strcmp(channel ? channel : chname, channel_names[i].name)) { - if (channel || i < highest_channel || mask & (1ULL << i)) - native = 0; // Not a native layout, use a custom one - highest_channel = i; - mask |= 1ULL << i; - break; - } - } - - if (!channel && i >= FF_ARRAY_ELEMS(channel_names)) { - char *endptr = chname; - enum AVChannel id = AV_CHAN_NONE; - - if (!strncmp(chname, "USR", 3)) { - const char *p = chname + 3; - id = strtol(p, &endptr, 0); - } - if (id < 0 || *endptr) { - native = 0; // Unknown channel name - channels = 0; - mask = 0; - av_free(chname); - break; - } - if (id > 63) - native = 0; // Not a native layout, use a custom one - else { - if (id < highest_channel || mask & (1ULL << id)) - native = 0; // Not a native layout, use a custom one - highest_channel = id; - mask |= 1ULL << id; - } - } - channels++; - av_free(channel); - av_free(chname); - } - - if (mask && native) { - av_free(chlist); - if (nb_channels && ((nb_channels != channels) || (!end || *++end))) - return AVERROR(EINVAL); - av_channel_layout_from_mask(channel_layout, mask); - return 0; - } - - /* custom layout of channel names */ - if (channels && !native) { - int idx = 0; + matches = av_sscanf(str, "%d channels (%[^)]", &nb_channels, chlist); + ret = parse_channel_list(channel_layout, chlist); + av_freep(&chlist); + if (ret < 0 && ret != AVERROR(EINVAL)) + return ret; - if (nb_channels && ((nb_channels != channels) || (!end || *++end))) { - av_free(chlist); + if (ret >= 0) { + end = strchr(str, ')'); + if (matches == 2 && (nb_channels != channel_layout->nb_channels || !end || *++end)) { + av_channel_layout_uninit(channel_layout); return AVERROR(EINVAL); } - - channel_layout->u.map = av_calloc(channels, sizeof(*channel_layout->u.map)); - if (!channel_layout->u.map) { - av_free(chlist); - return AVERROR(ENOMEM); - } - - channel_layout->order = AV_CHANNEL_ORDER_CUSTOM; - channel_layout->nb_channels = channels; - - dup = chlist; - while (*dup) { - char *channel, *chname; - int ret = av_opt_get_key_value(&dup, "@", "+", AV_OPT_FLAG_IMPLICIT_KEY, &channel, &chname); - if (ret < 0) { - av_freep(&channel_layout->u.map); - av_free(chlist); - return ret; - } - if (*dup) - dup++; // skip separator - for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) { - if (channel_names[i].name && !strcmp(channel ? channel : chname, channel_names[i].name)) { - channel_layout->u.map[idx].id = i; - if (channel) - av_strlcpy(channel_layout->u.map[idx].name, chname, sizeof(channel_layout->u.map[idx].name)); - idx++; - break; - } - } - if (i >= FF_ARRAY_ELEMS(channel_names)) { - const char *p = (channel ? channel : chname) + 3; - channel_layout->u.map[idx].id = strtol(p, NULL, 0); - if (channel) - av_strlcpy(channel_layout->u.map[idx].name, chname, sizeof(channel_layout->u.map[idx].name)); - idx++; - } - av_free(channel); - av_free(chname); - } - av_free(chlist); - return 0; } - av_freep(&chlist); errno = 0; mask = strtoull(str, &end, 0); diff --git a/tests/ref/fate/channel_layout b/tests/ref/fate/channel_layout index ea7ec6fa3c..117a5fd84d 100644 --- a/tests/ref/fate/channel_layout +++ b/tests/ref/fate/channel_layout @@ -129,7 +129,7 @@ On "5.1(side)" layout with AV_CH_LAYOUT_4POINT1: 0xf Testing av_channel_layout_from_string With "FL+FR+FC+BL+BR+LFE": 6 channels (FL+FR+FC+BL+BR+LFE) With "2 channels (FR+FL)": 2 channels (FR+FL) -With "2 channels (AMBI1023+FL)": fail +With "2 channels (AMBI1023+FL)": 2 channels (AMBI1023+FL) With "3 channels (FR+FL)": fail With "-3 channels (FR+FL)": fail With "0 channels ()": fail @@ -143,12 +143,12 @@ With "stereo@Boo": fail With "": fail With "@": fail With "@Dummy": fail -With "@FL": 1 channels (FL) +With "@FL": fail With "Dummy": fail With "Dummy@FL": fail With "FR+Dummy": fail -With "FR+Dummy@FL": 1 channels (FR) -With "FR+@FL": 2 channels (FR+FL@FL) +With "FR+Dummy@FL": fail +With "FR+@FL": fail With "FL+@": fail With "FR+FL@Foo+USR63@Foo": 3 channels (FR+FL@Foo+USR63@Foo)