From: Marton Balint <cus@passwd.hu>
To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Subject: Re: [FFmpeg-devel] [PATCH 001/289 v4] Add a new channel layout API
Date: Mon, 17 Jan 2022 21:53:59 +0100 (CET)
Message-ID: <2f8bb21a-1bc6-1927-d0ec-744d665b06a@passwd.hu> (raw)
In-Reply-To: <20220117183056.2125-1-jamrial@gmail.com>
On Mon, 17 Jan 2022, James Almer wrote:
[...]
> -static const char *get_channel_name(int channel_id)
> +static const char *get_channel_name(enum AVChannel channel_id)
> {
> - if (channel_id < 0 || channel_id >= FF_ARRAY_ELEMS(channel_names))
> + if ((unsigned) channel_id >= FF_ARRAY_ELEMS(channel_names) ||
> + !channel_names[channel_id].name)
> return NULL;
> return channel_names[channel_id].name;
> }
>
> -static const struct {
> +void av_channel_name_bprint(AVBPrint *bp, enum AVChannel channel_id)
> +{
> + av_bprint_clear(bp);
Clearing should not be done here. Maybe the user wants to construct a
string, and the channel name is only a part of it. If not, the user can
clear the bprint buffer himself before calling this.
> +
> + if ((unsigned)channel_id < FF_ARRAY_ELEMS(channel_names))
> + av_bprintf(bp, "%s", channel_names[channel_id].name);
> + else
> + av_bprintf(bp, "USR%d", channel_id);
> +}
> +
> +int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel_id)
> +{
> + AVBPrint bp;
> +
> + if (!buf && buf_size)
> + return AVERROR(EINVAL);
> +
> + av_bprint_init_for_buffer(&bp, buf, buf_size);
> + av_channel_name_bprint(&bp, channel_id);
> +
> + return bp.len;
> +}
> +
> +void av_channel_description_bprint(AVBPrint *bp, enum AVChannel channel_id)
> +{
> + av_bprint_clear(bp);
Same here.
> +
> + if ((unsigned)channel_id < FF_ARRAY_ELEMS(channel_names))
> + av_bprintf(bp, "%s", channel_names[channel_id].description);
> + else
> + av_bprintf(bp, "user %d", channel_id);
> +}
> +
> +int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel_id)
> +{
> + AVBPrint bp;
> +
> + if (!buf && buf_size)
> + return AVERROR(EINVAL);
> +
> + av_bprint_init_for_buffer(&bp, buf, buf_size);
> + av_channel_description_bprint(&bp, channel_id);
> +
> + return bp.len;
> +}
[...]
> +int av_channel_layout_from_string(AVChannelLayout *channel_layout,
> + const char *str)
> +{
> + int i;
> + int channels = 0, native = 1;
> + enum AVChannel highest_channel = AV_CHAN_NONE;
> + const char *dup = str;
> + char *end;
> + uint64_t mask = 0;
> +
> + /* channel layout names */
> + for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) {
> + if (channel_layout_map[i].name && !strcmp(str, channel_layout_map[i].name)) {
> + *channel_layout = channel_layout_map[i].layout;
> + return 0;
> + }
> + }
> +
> + /* channel names */
> + while (*dup) {
> + char *chname = av_get_token(&dup, "+");
> + if (!chname)
> + return AVERROR(ENOMEM);
> + if (*dup)
> + dup++; // skip separator
> + for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
> + if (channel_names[i].name && !strcmp(chname, channel_names[i].name)) {
> + if (i < highest_channel || mask & (1ULL << i))
> + native = 0; // Not a native layout, use a custom one
> + highest_channel = i;
> + mask |= 1ULL << i;
> + break;
> + }
> + }
> +
> + if (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(chname);
> + }
> + if (mask && native) {
> + av_channel_layout_from_mask(channel_layout, mask);
> + return 0;
> + }
> +
> + /* custom layout of channel names */
> + if (channels && !native) {
> + int idx = 0;
> +
> + channel_layout->u.map = av_calloc(channels, sizeof(*channel_layout->u.map));
> + if (!channel_layout->u.map)
> + return AVERROR(ENOMEM);
> +
> + channel_layout->order = AV_CHANNEL_ORDER_CUSTOM;
> + channel_layout->nb_channels = channels;
> +
> + dup = str;
> + while (*dup) {
> + char *chname = av_get_token(&dup, "+");
> + if (!chname) {
> + av_freep(&channel_layout->u.map);
> + return AVERROR(ENOMEM);
> + }
> + if (*dup)
> + dup++; // skip separator
> + for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
> + if (channel_names[i].name && !strcmp(chname, channel_names[i].name)) {
> + channel_layout->u.map[idx++].id = i;
> + break;
> + }
> + }
> + if (i >= FF_ARRAY_ELEMS(channel_names)) {
> + const char *p = chname + 3;
> + channel_layout->u.map[idx++].id = strtol(p, NULL, 0);
> + }
> + av_free(chname);
> + }
> +
> + return 0;
> + }
> +
> + /* channel layout mask */
> + if (!strncmp(str, "0x", 2) && sscanf(str + 2, "%"SCNx64, &mask) == 1) {
> + av_channel_layout_from_mask(channel_layout, mask);
> + return 0;
> + }
> +
> + errno = 0;
> + channels = strtol(str, &end, 10);
> +
> + /* number of channels */
> + if (!errno && *end == 'c' && !*(end + 1) && channels >= 0) {
> + av_channel_layout_default(channel_layout, channels);
> + return 0;
> + }
> +
> + /* number of unordered channels */
> + if (!errno && (!*end || (*end == 'C' && !*(end + 1)) || av_strnstr(str, "channels", strlen(str)))
> + && channels >= 0) {
> + channel_layout->order = AV_CHANNEL_ORDER_UNSPEC;
> + channel_layout->nb_channels = channels;
> + return 0;
> + }
> +
> + return AVERROR_INVALIDDATA;
rather AVERROR(EINVAL), no?
> +}
> +
> +void av_channel_layout_uninit(AVChannelLayout *channel_layout)
> +{
> + if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM)
> + av_freep(&channel_layout->u.map);
> + memset(channel_layout, 0, sizeof(*channel_layout));
> +}
> +
> +int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src)
> +{
> + av_channel_layout_uninit(dst);
> + *dst = *src;
> + if (src->order == AV_CHANNEL_ORDER_CUSTOM) {
> + dst->u.map = av_malloc_array(src->nb_channels, sizeof(*dst->u.map));
> + if (!dst->u.map)
> + return AVERROR(ENOMEM);
> + memcpy(dst->u.map, src->u.map, src->nb_channels * sizeof(*src->u.map));
> + }
> + return 0;
> +}
> +
> +int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout,
> + AVBPrint *bp)
> +{
> + int i;
> +
> + av_bprint_clear(bp);
Same as above, clearing should not be done.
Thanks,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
prev parent reply other threads:[~2022-01-17 20:54 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-17 18:30 James Almer
2022-01-17 20:53 ` Marton Balint [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2f8bb21a-1bc6-1927-d0ec-744d665b06a@passwd.hu \
--to=cus@passwd.hu \
--cc=ffmpeg-devel@ffmpeg.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git