From patchwork Wed Jan 19 18:43:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lacko X-Patchwork-Id: 33662 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:cd86:0:0:0:0:0 with SMTP id d128csp5062366iog; Wed, 19 Jan 2022 10:44:07 -0800 (PST) X-Google-Smtp-Source: ABdhPJxiCSRCaERVma650SilnMC6N0GpZkqPP2c+HaUDOYyha8WxFk27gB8pIIJFCK8CAJZ5LlrB X-Received: by 2002:a17:906:4fcb:: with SMTP id i11mr26987675ejw.297.1642617847404; Wed, 19 Jan 2022 10:44:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642617847; cv=none; d=google.com; s=arc-20160816; b=qm1JqRI0/V9KvQenPcFQ4LdTJSyi0ua7xRjL8ZlRoHMdT/3chNw377WHhq7clXcDmF pdg24j+L+fUI//BDoHIwMvbrUoAAmp24VHdM1czFR8wjVE1o4MN91uidi6OZbfRlX5aK 7+SPGEI8E8wxv86CUvWZZGfq2YKqtAjUXNP/JL2oGU1LUtSE/6tZ5Mfrcr9zvcCsLPzy YhQwNtBbDOD2HIO5ETUmGxqW4JZgepm4kRFvWoiUrS6rxEPJxZNNnlkb7k2m6u9bWmKL 9XZ88WXwlSICaos30kdhrytiZtFE2z4mjF5ickXtGCfou/IFERHrbgInBrMURjHoYv+7 yYAw== 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:message-id:date:to:from :dkim-signature:delivered-to; bh=shpHsxtYnoPznHFdA/O9lsji0YoRw0YTw3XzHE9exh4=; b=PcdHiqQoMg2WLWmBX3MoVhBHKRD3TKIcP90JujvURURaRTCn1Z3MdMvW04A8CrHcUQ 3E5lmVb/yxw32VIQuGOosMop84BsB9HV9cEMKARaKY5T9Z0H3phdS0tpJLyGlO2uUn/D xadnEuPGq5Rl9FgEGAJZmJNFOGhSnAOMudlBq1vXXr4w6DTPM11fQ9aU6mvb4aS8ZobD 5daB4Us1EPwEZ77Yw82elzjuwqbsgmZDPlC0MXVfdPCRZ7QHATRs39d1/bUzMb7m+IQc ZcnvhMRDxoA6his6/Zaf/UAc982DTodZ2V2paU8549WabS1lJ2NZmn2Gw/zt4jnKTZ9K L7gA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=kH1NAQqs; 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 nd29si466116ejc.75.2022.01.19.10.44.06; Wed, 19 Jan 2022 10:44:07 -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=kH1NAQqs; 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 16DD168B0A8; Wed, 19 Jan 2022 20:44:03 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ed1-f50.google.com (mail-ed1-f50.google.com [209.85.208.50]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id CC50068B0A8 for ; Wed, 19 Jan 2022 20:43:55 +0200 (EET) Received: by mail-ed1-f50.google.com with SMTP id j2so17501534edj.8 for ; Wed, 19 Jan 2022 10:43:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=SVKGS6sWxuZQXsG9iqHLsmyBl+raE4CqnbSOdJrBhBY=; b=kH1NAQqsgwIIEMsQhVot5BMWpAakdjtRz+UBXKPiPhMetD1QZwIb/oIFnh6aFq0Ya7 W05xd4Lkuo9XO8kS0sdUvBq+ktkFdDLEDVbjR4OZNrobm2RJbKLyeMjv3mw5OPIX0qJZ x+GX2MTweb49g4e80KJs5w0Do2BBq29kTBdku1ie7APfhTRA3s3HJnPXQ+KR/MGHWJnv 3UaFQ8yCMgi4qw0gPx1vpCTZ9bGGOiPpKB2bGnCidUiIwf0TCRQOeNE0uplFXSszbCug dRKeVaNmI9jAABA/jLikq+bPch5kNp9l5GlycVKj00mfjVpO0rAiXtkoOliMPo76i9HF 6XNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=SVKGS6sWxuZQXsG9iqHLsmyBl+raE4CqnbSOdJrBhBY=; b=CTDmAxESh4tigFhJ9SLtvo0KpAsv2ElB05JmWOLZ77SZYpvDqdEhXArDI0L7H8uhtp Crp0AaWfybYbFQXm121UPHt5xA++MrXDI8WYxB8stizODlM/m/REot8GdWyUjbxbhKvE MjXRFlkhxc9oR4rruOnpuhAK2JEN0YacVWJsRRnAPU0BvR6agfUyTYtrKwXJBKopoyGR kLZ5iRN1B4QF87nq34VxMztTfco+ZKWSBnSg0dBMf7jQ9YPy3jtPj8+OTaHTKZE8jBsX m0GPfjSfXlyRyoiMSh0zJzuWMGaOJ70sZGjNH41bToTkSGyg06P9USI1MXdOWl23i2oa aZSg== X-Gm-Message-State: AOAM531AVL18u7OEhql1s9UX0Y62b7oJ3RRPtg8nVS363pZcvRnMBtdr apF9FUvY3+bRhcZE2mfrkFszVMUHmyoS3A== X-Received: by 2002:a05:6402:51cf:: with SMTP id r15mr8133923edd.213.1642617834915; Wed, 19 Jan 2022 10:43:54 -0800 (PST) Received: from DEIWO-PC.brno. (ip-94-113-225-198.net.upcbroadband.cz. [94.113.225.198]) by smtp.gmail.com with ESMTPSA id t13sm156161ejs.187.2022.01.19.10.43.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Jan 2022 10:43:54 -0800 (PST) From: David Lacko To: ffmpeg-devel@ffmpeg.org Date: Wed, 19 Jan 2022 19:43:32 +0100 Message-Id: <20220119184332.289047-1-deiwo101@gmail.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avfilter/adelay: Add command support 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: David Lacko Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: yv7odragq3dd Adds command 'delays' to the adelay filter. This command accepts same values as option with one difference, to apply delay to all channels prefix 'all:' to the arguments is accepted. Signed-off-by: David Lacko --- libavfilter/af_adelay.c | 183 ++++++++++++++++++++++++++++++++++------ 1 file changed, 157 insertions(+), 26 deletions(-) diff --git a/libavfilter/af_adelay.c b/libavfilter/af_adelay.c index ed8a8ae739..1e13cf7fb0 100644 --- a/libavfilter/af_adelay.c +++ b/libavfilter/af_adelay.c @@ -31,6 +31,7 @@ typedef struct ChanDelay { int64_t delay; size_t delay_index; size_t index; + unsigned int samples_size; uint8_t *samples; } ChanDelay; @@ -48,13 +49,14 @@ typedef struct AudioDelayContext { void (*delay_channel)(ChanDelay *d, int nb_samples, const uint8_t *src, uint8_t *dst); + int (*resize_channel_samples)(ChanDelay *d, int64_t new_delay); } AudioDelayContext; #define OFFSET(x) offsetof(AudioDelayContext, x) #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption adelay_options[] = { - { "delays", "set list of delays for each channel", OFFSET(delays), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A }, + { "delays", "set list of delays for each channel", OFFSET(delays), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A | AV_OPT_FLAG_RUNTIME_PARAM }, { "all", "use last available delay for remained channels", OFFSET(all), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A }, { NULL } }; @@ -96,11 +98,92 @@ DELAY(s32, int32_t, 0) DELAY(flt, float, 0) DELAY(dbl, double, 0) +#define CHANGE_DELAY(name, type, fill) \ +static int resize_samples_## name ##p(ChanDelay *d, int64_t new_delay) \ +{ \ + type *samples = (type *)d->samples; \ + \ + if (new_delay == d->delay) { \ + return 0; \ + } \ + \ + if (new_delay == 0) { \ + av_freep(&d->samples); \ + d->samples_size = 0; \ + d->delay = 0; \ + d->index = 0; \ + return 0; \ + } \ + \ + d->samples = av_fast_realloc(d->samples, &d->samples_size, new_delay * sizeof(type)); \ + if (!d->samples) { \ + av_freep(samples); \ + return AVERROR(ENOMEM); \ + } \ + samples = (type *)d->samples; \ + if (new_delay < d->delay) { \ + if (d->index > new_delay) { \ + d->index -= new_delay; \ + memmove(samples, &samples[new_delay], d->index * sizeof(type)); \ + } else if (d->delay_index > d->index) { \ + memmove(&samples[d->index], &samples[d->index+(d->delay-new_delay)], \ + (new_delay - d->index) * sizeof(type)); \ + } \ + d->delay_index = new_delay; \ + } else { \ + size_t block_size; \ + if (d->delay_index >= d->delay) { \ + block_size = (d->delay - d->index) * sizeof(type); \ + memmove(&samples[d->index+(new_delay - d->delay)], &samples[d->index], block_size); \ + d->delay_index = new_delay; \ + } else { \ + d->delay_index += new_delay - d->delay; \ + } \ + block_size = (new_delay - d->delay) * sizeof(type); \ + memset(&samples[d->index], fill, block_size); \ + } \ + d->delay = new_delay; \ + d->samples = (void *) samples; \ + return 0; \ +} + +CHANGE_DELAY(u8, uint8_t, 0x80) +CHANGE_DELAY(s16, int16_t, 0) +CHANGE_DELAY(s32, int32_t, 0) +CHANGE_DELAY(flt, float, 0) +CHANGE_DELAY(dbl, double, 0) + +static int parse_delays(char *p, char **saveptr, int64_t *result, AVFilterContext *ctx, int sample_rate) { + float delay, div; + int ret; + char *arg; + char type = 0; + + if (!(arg = av_strtok(p, "|", saveptr))) + return 1; + + ret = av_sscanf(arg, "%"SCNd64"%c", result, &type); + if (ret != 2 || type != 'S') { + div = type == 's' ? 1.0 : 1000.0; + if (av_sscanf(arg, "%f", &delay) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid syntax for delay.\n"); + return AVERROR(EINVAL); + } + *result = delay * sample_rate / div; + } + + if (*result < 0) { + av_log(ctx, AV_LOG_ERROR, "Delay must be non negative number.\n"); + return AVERROR(EINVAL); + } + return 0; +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; AudioDelayContext *s = ctx->priv; - char *p, *arg, *saveptr = NULL; + char *p, *saveptr = NULL; int i; s->chandelay = av_calloc(inlink->channels, sizeof(*s->chandelay)); @@ -112,29 +195,14 @@ static int config_input(AVFilterLink *inlink) p = s->delays; for (i = 0; i < s->nb_delays; i++) { ChanDelay *d = &s->chandelay[i]; - float delay, div; - char type = 0; int ret; - if (!(arg = av_strtok(p, "|", &saveptr))) + ret = parse_delays(p, &saveptr, &d->delay, ctx, inlink->sample_rate); + if (ret == 1) break; - + else if (ret < 0) + return ret; p = NULL; - - ret = av_sscanf(arg, "%"SCNd64"%c", &d->delay, &type); - if (ret != 2 || type != 'S') { - div = type == 's' ? 1.0 : 1000.0; - if (av_sscanf(arg, "%f", &delay) != 1) { - av_log(ctx, AV_LOG_ERROR, "Invalid syntax for delay.\n"); - return AVERROR(EINVAL); - } - d->delay = delay * inlink->sample_rate / div; - } - - if (d->delay < 0) { - av_log(ctx, AV_LOG_ERROR, "Delay must be non negative number.\n"); - return AVERROR(EINVAL); - } } if (s->all && i) { @@ -171,21 +239,83 @@ static int config_input(AVFilterLink *inlink) d->samples = av_malloc_array(d->delay, s->block_align); if (!d->samples) return AVERROR(ENOMEM); + d->samples_size = d->delay * s->block_align; s->max_delay = FFMAX(s->max_delay, d->delay); } switch (inlink->format) { - case AV_SAMPLE_FMT_U8P : s->delay_channel = delay_channel_u8p ; break; - case AV_SAMPLE_FMT_S16P: s->delay_channel = delay_channel_s16p; break; - case AV_SAMPLE_FMT_S32P: s->delay_channel = delay_channel_s32p; break; - case AV_SAMPLE_FMT_FLTP: s->delay_channel = delay_channel_fltp; break; - case AV_SAMPLE_FMT_DBLP: s->delay_channel = delay_channel_dblp; break; + case AV_SAMPLE_FMT_U8P : s->delay_channel = delay_channel_u8p ; + s->resize_channel_samples = resize_samples_u8p; break; + case AV_SAMPLE_FMT_S16P: s->delay_channel = delay_channel_s16p; + s->resize_channel_samples = resize_samples_s16p; break; + case AV_SAMPLE_FMT_S32P: s->delay_channel = delay_channel_s32p; + s->resize_channel_samples = resize_samples_s32p; break; + case AV_SAMPLE_FMT_FLTP: s->delay_channel = delay_channel_fltp; + s->resize_channel_samples = resize_samples_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->delay_channel = delay_channel_dblp; + s->resize_channel_samples = resize_samples_dblp; break; } return 0; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret = AVERROR(ENOSYS); + AVFilterLink *inlink = ctx->inputs[0]; + AudioDelayContext *s = ctx->priv; + + if (!strcmp(cmd, "delays")) { + int64_t delay; + char *p, *saveptr = NULL; + int64_t all_delay = -1; + int64_t max_delay = 0; + char *args_cpy = av_strdup(args); + if (args_cpy == NULL) { + return AVERROR(ENOMEM); + } + + ret = 0; + p = args_cpy; + + if (!strncmp(args, "all:", 4)) { + p = &args_cpy[4]; + ret = parse_delays(p, &saveptr, &all_delay, ctx, inlink->sample_rate); + av_log(ctx, AV_LOG_INFO, "All delay: %ld\n", all_delay); + if (ret == 1) + ret = AVERROR(EINVAL); + else if (ret == 0) + delay = all_delay; + } + + if (!ret) { + for (int i = 0; i < s->nb_delays; i++) { + ChanDelay *d = &s->chandelay[i]; + + if (all_delay < 0) { + ret = parse_delays(p, &saveptr, &delay, ctx, inlink->sample_rate); + if (ret != 0) { + ret = 0; + break; + } + p = NULL; + } + + ret = s->resize_channel_samples(d, delay); + av_log(ctx, AV_LOG_INFO, "Resize samples: %d\n", ret); + if (ret) + break; + max_delay = FFMAX(max_delay, d->delay); + } + s->max_delay = FFMAX(s->max_delay, max_delay); + } + av_freep(&args_cpy); + } + return ret; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; @@ -330,4 +460,5 @@ const AVFilter ff_af_adelay = { FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = process_command, };