From patchwork Sat May 6 10:31:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 41506 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:dca6:b0:f3:34fa:f187 with SMTP id ky38csp1070729pzb; Sat, 6 May 2023 03:32:04 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6sZMiQNHJj2XFR03GRsy8s6UOcGEobEy3ZY+bPH6W9co1rZAaR9kG8SViO/Jn/FLrwqweR X-Received: by 2002:a05:6402:2044:b0:50b:c77e:b071 with SMTP id bc4-20020a056402204400b0050bc77eb071mr4109744edb.18.1683369124440; Sat, 06 May 2023 03:32:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683369124; cv=none; d=google.com; s=arc-20160816; b=blPmkIIF7p/s9g1vWwRKQK60YySZ4Pil8EkEEYHwecuM3KwtcI/QsklQgwU2reO8Y0 kKyoHcLR9JYecdAFoMgPIFHsQD3UmyOLyZiYLApbnLXb586JLhK463AzxyR/lNbcbfu5 oubUKvK8s3Z8i8RXn5twgJlTtNcU8WhkuPPqSWE6SZiHWVq1a/LGE3BN4toZ8RSqjlXP XtMO3eAfzj3JO3SG1HhPsDuA9/IRYz96tZw5YK/Q+w11631HJ0buj8uNMdODmqvqZl3y S3lh6Ie7SvR1NV3nY7TUwfTCmozeE7RPWp6gOsk+jjxC++oZtTs+ClejgNyC7PDgBp8g PHhw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject:to :message-id:date:from:mime-version:dkim-signature:delivered-to; bh=fh2GnGYpXgmiqXTo49yiMzcvTyZXaTyOh9gPVtmZd18=; b=0vA8Kjath04yJ7hPhJVrs45RZfpCcOjFHdh/YzCLkxchsf2WWR9auE8+d1oosj2+jA mzIRITlGZYT4W/PAqRZFnx0x+kD0Q7E/GtvOwDTKHQ2iJGYbA0MbPMNpHEfjGuESWGh0 nKqOvOVMUKl25zOIT7ZYJWV6AtTRKSBSIXvFtCQZHhqMpcqvmnNH1jifemi6aqn4vK6Q YF+T+k4nbAtC9cOqR2ak+QtcCjCSivZhc4JMo9L6aeGpC3qQwfHAFg0q+3NOULHXQfmC 0xul/8tt4pkoz7TZrknIsbOWykVmlibD0OuDHk4gpJuPZv1OwS17s/QoXGJkl3wFvlGs vRFg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20221208 header.b=AtpbdwQB; 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 k18-20020a05640212d200b0050bc679275esi6032597edx.208.2023.05.06.03.32.03; Sat, 06 May 2023 03:32:04 -0700 (PDT) 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=20221208 header.b=AtpbdwQB; 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 3248368C042; Sat, 6 May 2023 13:31:59 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-vk1-f176.google.com (mail-vk1-f176.google.com [209.85.221.176]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id D95B268BFF2 for ; Sat, 6 May 2023 13:31:52 +0300 (EEST) Received: by mail-vk1-f176.google.com with SMTP id 71dfb90a1353d-44faec9af51so918041e0c.1 for ; Sat, 06 May 2023 03:31:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683369111; x=1685961111; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=yMwVfDNQXmXXBdB7AnPGM74j2C2i03XJESAFDVOH6DU=; b=AtpbdwQBtCtS/47su8BtCrZ4jbGTXin70G/US8DIrnIMhPqvJAQnbtOVCiGVtI19Yp mROxr4uGY7m/k9Y11HualZNkoMtbMrF7ut1XZSJ0+q331xCS7OI16oYyD2ysuSIsCz5U upDYp+iswrhUWjngRouLGsaFWS+jO00KZbJ7hUqzo6t5TCLOKty2KSzFHI3WOMx1NNMu IZdSSSBWyDUXC4a/1XXzO0xUE0/+DdZ3/GTazZqp9wsdyiqPsqAvp09yCjrfEByU/lHO A30xzDCfhfLPfrkn7svX3dB1bMd9b4oMvtnMixEFFn9DOBmc4RyLikUgwF+ENP5H6ReO cC0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683369111; x=1685961111; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=yMwVfDNQXmXXBdB7AnPGM74j2C2i03XJESAFDVOH6DU=; b=UtUI1SsN0t8MmJvuh/+IUljDGJOodRuP0oY4KRSSsj7L0HZC19+/XOGFeY3bqt0FEP beL+u/WL1mvWPNTFBTP0Joru8v0VdqHAxOScJWemMhJg0yuroVkLcXcKo0WCVF+GD1bp vtzXaZUTxDeOsr/ikRsPYtS/O4jG5WOJGVCv0fzfNhqXNWqLlVV2pE64vZydJMILNQZw RBMqruHhZAnyaoInF1dyZnShTycGcruKiCYkW0Z0HVCKlElQwMCDWxEcQw03KCVRTEfn PayAiaCO9UqCVUUZCb0wXMcia2jDyJqWhT6eoqb/dudqW7+Gu0FBqZ2rPe1BAj3go/x3 ODwA== X-Gm-Message-State: AC+VfDwGs8deKlRctGXCaRUA91p2gm1ZDEJ4NhCdtKMSFFZZ1NbhE9Lu ztH+HHOtWZX9AL8+XyNLnRHWq/g/G6RL8+TtwWAhA4nR X-Received: by 2002:a67:f90b:0:b0:434:5563:35f4 with SMTP id t11-20020a67f90b000000b00434556335f4mr955813vsq.35.1683369111055; Sat, 06 May 2023 03:31:51 -0700 (PDT) MIME-Version: 1.0 From: Paul B Mahol Date: Sat, 6 May 2023 12:31:24 +0200 Message-ID: To: FFmpeg development discussions and patches X-Content-Filtered-By: Mailman/MimeDel 2.1.29 Subject: [FFmpeg-devel] [PATCH] avfilter/f_ebur128: export results into read-only options 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: 4lOlsZdCnIWw Attached. From fd7b20023fd8fe19d9559c23f5927a66e75513c1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 6 May 2023 12:28:10 +0200 Subject: [PATCH] avfilter/f_ebur128: export results into read-only options Signed-off-by: Paul B Mahol --- doc/filters.texi | 18 ++++++++++++++++++ libavfilter/f_ebur128.c | 42 +++++++++++++++++++++++++++++------------ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index f5fc0811d7..8b443c24e9 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -28733,6 +28733,24 @@ live mixing). Sets the display scale for the loudness. Valid parameters are @code{absolute} (in LUFS) or @code{relative} (LU) relative to the target. This only affects the video output, not the summary or continuous log output. + +@item integrated +Read-only exported value for measured integrated loudness, in LUFS. + +@item range +Read-only exported value for measured loudness range, in LU. + +@item lra_low +Read-only exported value for measured LRA low, in LUFS. + +@item lra_high +Read-only exported value for measured LRA high, in LUFS. + +@item sample_peak +Read-only exported value for measured sample peak, in dBFS. + +@item true_peak +Read-only exported value for measured true peak, in dBFS. @end table @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 38e7e0b295..dfa62f0a36 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -26,6 +26,7 @@ * @todo implement start/stop/reset through filter command injection */ +#include #include #include "libavutil/avassert.h" @@ -80,7 +81,9 @@ typedef struct EBUR128Context { /* peak metering */ int peak_mode; ///< enabled peak modes + double true_peak; ///< global true peak double *true_peaks; ///< true peaks per channel + double sample_peak; ///< global sample peak double *sample_peaks; ///< sample peaks per channel double *true_peaks_per_frame; ///< true peaks in a frame per channel #if CONFIG_SWRESAMPLE @@ -159,6 +162,8 @@ enum { #define A AV_OPT_FLAG_AUDIO_PARAM #define V AV_OPT_FLAG_VIDEO_PARAM #define F AV_OPT_FLAG_FILTERING_PARAM +#define X AV_OPT_FLAG_EXPORT +#define R AV_OPT_FLAG_READONLY static const AVOption ebur128_options[] = { { "video", "set video output", OFFSET(do_video), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, V|F }, { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x480"}, 0, 0, V|F }, @@ -185,6 +190,12 @@ static const AVOption ebur128_options[] = { { "LUFS", "display absolute values (LUFS)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_ABSOLUTE}, INT_MIN, INT_MAX, V|F, "scaletype" }, { "relative", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, { "LU", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, + { "integrated", "integrated loudness (LUFS)", OFFSET(integrated_loudness), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, + { "range", "loudness range (LU)", OFFSET(loudness_range), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, + { "lra_low", "LRA low (LUFS)", OFFSET(lra_low), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, + { "lra_high", "LRA high (LUFS)", OFFSET(lra_high), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, + { "sample_peak", "sample peak (dBFS)", OFFSET(sample_peak), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, + { "true_peak", "true peak (dBFS)", OFFSET(true_peak), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, { NULL }, }; @@ -701,6 +712,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) ebur128->i3000.cache[ch][bin_id_3000] = bin; } +#define FIND_PEAK(global, sp, ptype) do { \ + int ch; \ + double maxpeak; \ + maxpeak = 0.0; \ + if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \ + for (ch = 0; ch < ebur128->nb_channels; ch++) \ + maxpeak = FFMAX(maxpeak, sp[ch]); \ + global = DBFS(maxpeak); \ + } \ +} while (0) + + FIND_PEAK(ebur128->sample_peak, ebur128->sample_peaks, SAMPLES); + FIND_PEAK(ebur128->true_peak, ebur128->true_peaks, TRUE); + /* For integrated loudness, gating blocks are 400ms long with 75% * overlap (see BS.1770-2 p5), so a re-computation is needed each 100ms * (4800 samples at 48kHz). */ @@ -1023,7 +1048,6 @@ static int query_formats(AVFilterContext *ctx) static av_cold void uninit(AVFilterContext *ctx) { - int i; EBUR128Context *ebur128 = ctx->priv; /* dual-mono correction */ @@ -1047,21 +1071,15 @@ static av_cold void uninit(AVFilterContext *ctx) ebur128->loudness_range, ebur128->i3000.rel_threshold, ebur128->lra_low, ebur128->lra_high); -#define PRINT_PEAK_SUMMARY(str, sp, ptype) do { \ - int ch; \ - double maxpeak; \ - maxpeak = 0.0; \ +#define PRINT_PEAK_SUMMARY(str, value, ptype) do { \ if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \ - for (ch = 0; ch < ebur128->nb_channels; ch++) \ - maxpeak = FFMAX(maxpeak, sp[ch]); \ av_log(ctx, AV_LOG_INFO, "\n\n " str " peak:\n" \ - " Peak: %5.1f dBFS", \ - DBFS(maxpeak)); \ + " Peak: %5.1f dBFS", value); \ } \ } while (0) - PRINT_PEAK_SUMMARY("Sample", ebur128->sample_peaks, SAMPLES); - PRINT_PEAK_SUMMARY("True", ebur128->true_peaks, TRUE); + PRINT_PEAK_SUMMARY("Sample", ebur128->sample_peak, SAMPLES); + PRINT_PEAK_SUMMARY("True", ebur128->true_peak, TRUE); av_log(ctx, AV_LOG_INFO, "\n"); av_freep(&ebur128->y_line_ref); @@ -1076,7 +1094,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&ebur128->i3000.sum); av_freep(&ebur128->i400.histogram); av_freep(&ebur128->i3000.histogram); - for (i = 0; i < ebur128->nb_channels; i++) { + for (int i = 0; i < ebur128->nb_channels; i++) { if (ebur128->i400.cache) av_freep(&ebur128->i400.cache[i]); if (ebur128->i3000.cache) -- 2.39.1