annotate ffmpeg/libavfilter/f_ebur128.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Copyright (c) 2012 Clément Bœsch
yading@10 3 *
yading@10 4 * This file is part of FFmpeg.
yading@10 5 *
yading@10 6 * FFmpeg is free software; you can redistribute it and/or modify
yading@10 7 * it under the terms of the GNU General Public License as published by
yading@10 8 * the Free Software Foundation; either version 2 of the License, or
yading@10 9 * (at your option) any later version.
yading@10 10 *
yading@10 11 * FFmpeg is distributed in the hope that it will be useful,
yading@10 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
yading@10 14 * GNU General Public License for more details.
yading@10 15 *
yading@10 16 * You should have received a copy of the GNU General Public License along
yading@10 17 * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
yading@10 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
yading@10 19 */
yading@10 20
yading@10 21 /**
yading@10 22 * @file
yading@10 23 * EBU R.128 implementation
yading@10 24 * @see http://tech.ebu.ch/loudness
yading@10 25 * @see https://www.youtube.com/watch?v=iuEtQqC-Sqo "EBU R128 Introduction - Florian Camerer"
yading@10 26 * @todo True Peak
yading@10 27 * @todo implement start/stop/reset through filter command injection
yading@10 28 * @todo support other frequencies to avoid resampling
yading@10 29 */
yading@10 30
yading@10 31 #include <math.h>
yading@10 32
yading@10 33 #include "libavutil/avassert.h"
yading@10 34 #include "libavutil/avstring.h"
yading@10 35 #include "libavutil/channel_layout.h"
yading@10 36 #include "libavutil/dict.h"
yading@10 37 #include "libavutil/xga_font_data.h"
yading@10 38 #include "libavutil/opt.h"
yading@10 39 #include "libavutil/timestamp.h"
yading@10 40 #include "audio.h"
yading@10 41 #include "avfilter.h"
yading@10 42 #include "formats.h"
yading@10 43 #include "internal.h"
yading@10 44
yading@10 45 #define MAX_CHANNELS 63
yading@10 46
yading@10 47 /* pre-filter coefficients */
yading@10 48 #define PRE_B0 1.53512485958697
yading@10 49 #define PRE_B1 -2.69169618940638
yading@10 50 #define PRE_B2 1.19839281085285
yading@10 51 #define PRE_A1 -1.69065929318241
yading@10 52 #define PRE_A2 0.73248077421585
yading@10 53
yading@10 54 /* RLB-filter coefficients */
yading@10 55 #define RLB_B0 1.0
yading@10 56 #define RLB_B1 -2.0
yading@10 57 #define RLB_B2 1.0
yading@10 58 #define RLB_A1 -1.99004745483398
yading@10 59 #define RLB_A2 0.99007225036621
yading@10 60
yading@10 61 #define ABS_THRES -70 ///< silence gate: we discard anything below this absolute (LUFS) threshold
yading@10 62 #define ABS_UP_THRES 10 ///< upper loud limit to consider (ABS_THRES being the minimum)
yading@10 63 #define HIST_GRAIN 100 ///< defines histogram precision
yading@10 64 #define HIST_SIZE ((ABS_UP_THRES - ABS_THRES) * HIST_GRAIN + 1)
yading@10 65
yading@10 66 /**
yading@10 67 * An histogram is an array of HIST_SIZE hist_entry storing all the energies
yading@10 68 * recorded (with an accuracy of 1/HIST_GRAIN) of the loudnesses from ABS_THRES
yading@10 69 * (at 0) to ABS_UP_THRES (at HIST_SIZE-1).
yading@10 70 * This fixed-size system avoids the need of a list of energies growing
yading@10 71 * infinitely over the time and is thus more scalable.
yading@10 72 */
yading@10 73 struct hist_entry {
yading@10 74 int count; ///< how many times the corresponding value occurred
yading@10 75 double energy; ///< E = 10^((L + 0.691) / 10)
yading@10 76 double loudness; ///< L = -0.691 + 10 * log10(E)
yading@10 77 };
yading@10 78
yading@10 79 struct integrator {
yading@10 80 double *cache[MAX_CHANNELS]; ///< window of filtered samples (N ms)
yading@10 81 int cache_pos; ///< focus on the last added bin in the cache array
yading@10 82 double sum[MAX_CHANNELS]; ///< sum of the last N ms filtered samples (cache content)
yading@10 83 int filled; ///< 1 if the cache is completely filled, 0 otherwise
yading@10 84 double rel_threshold; ///< relative threshold
yading@10 85 double sum_kept_powers; ///< sum of the powers (weighted sums) above absolute threshold
yading@10 86 int nb_kept_powers; ///< number of sum above absolute threshold
yading@10 87 struct hist_entry *histogram; ///< histogram of the powers, used to compute LRA and I
yading@10 88 };
yading@10 89
yading@10 90 struct rect { int x, y, w, h; };
yading@10 91
yading@10 92 typedef struct {
yading@10 93 const AVClass *class; ///< AVClass context for log and options purpose
yading@10 94
yading@10 95 /* video */
yading@10 96 int do_video; ///< 1 if video output enabled, 0 otherwise
yading@10 97 int w, h; ///< size of the video output
yading@10 98 struct rect text; ///< rectangle for the LU legend on the left
yading@10 99 struct rect graph; ///< rectangle for the main graph in the center
yading@10 100 struct rect gauge; ///< rectangle for the gauge on the right
yading@10 101 AVFrame *outpicref; ///< output picture reference, updated regularly
yading@10 102 int meter; ///< select a EBU mode between +9 and +18
yading@10 103 int scale_range; ///< the range of LU values according to the meter
yading@10 104 int y_zero_lu; ///< the y value (pixel position) for 0 LU
yading@10 105 int *y_line_ref; ///< y reference values for drawing the LU lines in the graph and the gauge
yading@10 106
yading@10 107 /* audio */
yading@10 108 int nb_channels; ///< number of channels in the input
yading@10 109 double *ch_weighting; ///< channel weighting mapping
yading@10 110 int sample_count; ///< sample count used for refresh frequency, reset at refresh
yading@10 111
yading@10 112 /* Filter caches.
yading@10 113 * The mult by 3 in the following is for X[i], X[i-1] and X[i-2] */
yading@10 114 double x[MAX_CHANNELS * 3]; ///< 3 input samples cache for each channel
yading@10 115 double y[MAX_CHANNELS * 3]; ///< 3 pre-filter samples cache for each channel
yading@10 116 double z[MAX_CHANNELS * 3]; ///< 3 RLB-filter samples cache for each channel
yading@10 117
yading@10 118 #define I400_BINS (48000 * 4 / 10)
yading@10 119 #define I3000_BINS (48000 * 3)
yading@10 120 struct integrator i400; ///< 400ms integrator, used for Momentary loudness (M), and Integrated loudness (I)
yading@10 121 struct integrator i3000; ///< 3s integrator, used for Short term loudness (S), and Loudness Range (LRA)
yading@10 122
yading@10 123 /* I and LRA specific */
yading@10 124 double integrated_loudness; ///< integrated loudness in LUFS (I)
yading@10 125 double loudness_range; ///< loudness range in LU (LRA)
yading@10 126 double lra_low, lra_high; ///< low and high LRA values
yading@10 127
yading@10 128 /* misc */
yading@10 129 int loglevel; ///< log level for frame logging
yading@10 130 int metadata; ///< whether or not to inject loudness results in frames
yading@10 131 } EBUR128Context;
yading@10 132
yading@10 133 #define OFFSET(x) offsetof(EBUR128Context, x)
yading@10 134 #define A AV_OPT_FLAG_AUDIO_PARAM
yading@10 135 #define V AV_OPT_FLAG_VIDEO_PARAM
yading@10 136 #define F AV_OPT_FLAG_FILTERING_PARAM
yading@10 137 static const AVOption ebur128_options[] = {
yading@10 138 { "video", "set video output", OFFSET(do_video), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, V|F },
yading@10 139 { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x480"}, 0, 0, V|F },
yading@10 140 { "meter", "set scale meter (+9 to +18)", OFFSET(meter), AV_OPT_TYPE_INT, {.i64 = 9}, 9, 18, V|F },
yading@10 141 { "framelog", "force frame logging level", OFFSET(loglevel), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, A|V|F, "level" },
yading@10 142 { "info", "information logging level", 0, AV_OPT_TYPE_CONST, {.i64 = AV_LOG_INFO}, INT_MIN, INT_MAX, A|V|F, "level" },
yading@10 143 { "verbose", "verbose logging level", 0, AV_OPT_TYPE_CONST, {.i64 = AV_LOG_VERBOSE}, INT_MIN, INT_MAX, A|V|F, "level" },
yading@10 144 { "metadata", "inject metadata in the filtergraph", OFFSET(metadata), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, A|V|F },
yading@10 145 { NULL },
yading@10 146 };
yading@10 147
yading@10 148 AVFILTER_DEFINE_CLASS(ebur128);
yading@10 149
yading@10 150 static const uint8_t graph_colors[] = {
yading@10 151 0xdd, 0x66, 0x66, // value above 0LU non reached
yading@10 152 0x66, 0x66, 0xdd, // value below 0LU non reached
yading@10 153 0x96, 0x33, 0x33, // value above 0LU reached
yading@10 154 0x33, 0x33, 0x96, // value below 0LU reached
yading@10 155 0xdd, 0x96, 0x96, // value above 0LU line non reached
yading@10 156 0x96, 0x96, 0xdd, // value below 0LU line non reached
yading@10 157 0xdd, 0x33, 0x33, // value above 0LU line reached
yading@10 158 0x33, 0x33, 0xdd, // value below 0LU line reached
yading@10 159 };
yading@10 160
yading@10 161 static const uint8_t *get_graph_color(const EBUR128Context *ebur128, int v, int y)
yading@10 162 {
yading@10 163 const int below0 = y > ebur128->y_zero_lu;
yading@10 164 const int reached = y >= v;
yading@10 165 const int line = ebur128->y_line_ref[y] || y == ebur128->y_zero_lu;
yading@10 166 const int colorid = 4*line + 2*reached + below0;
yading@10 167 return graph_colors + 3*colorid;
yading@10 168 }
yading@10 169
yading@10 170 static inline int lu_to_y(const EBUR128Context *ebur128, double v)
yading@10 171 {
yading@10 172 v += 2 * ebur128->meter; // make it in range [0;...]
yading@10 173 v = av_clipf(v, 0, ebur128->scale_range); // make sure it's in the graph scale
yading@10 174 v = ebur128->scale_range - v; // invert value (y=0 is on top)
yading@10 175 return v * ebur128->graph.h / ebur128->scale_range; // rescale from scale range to px height
yading@10 176 }
yading@10 177
yading@10 178 #define FONT8 0
yading@10 179 #define FONT16 1
yading@10 180
yading@10 181 static const uint8_t font_colors[] = {
yading@10 182 0xdd, 0xdd, 0x00,
yading@10 183 0x00, 0x96, 0x96,
yading@10 184 };
yading@10 185
yading@10 186 static void drawtext(AVFrame *pic, int x, int y, int ftid, const uint8_t *color, const char *fmt, ...)
yading@10 187 {
yading@10 188 int i;
yading@10 189 char buf[128] = {0};
yading@10 190 const uint8_t *font;
yading@10 191 int font_height;
yading@10 192 va_list vl;
yading@10 193
yading@10 194 if (ftid == FONT16) font = avpriv_vga16_font, font_height = 16;
yading@10 195 else if (ftid == FONT8) font = avpriv_cga_font, font_height = 8;
yading@10 196 else return;
yading@10 197
yading@10 198 va_start(vl, fmt);
yading@10 199 vsnprintf(buf, sizeof(buf), fmt, vl);
yading@10 200 va_end(vl);
yading@10 201
yading@10 202 for (i = 0; buf[i]; i++) {
yading@10 203 int char_y, mask;
yading@10 204 uint8_t *p = pic->data[0] + y*pic->linesize[0] + (x + i*8)*3;
yading@10 205
yading@10 206 for (char_y = 0; char_y < font_height; char_y++) {
yading@10 207 for (mask = 0x80; mask; mask >>= 1) {
yading@10 208 if (font[buf[i] * font_height + char_y] & mask)
yading@10 209 memcpy(p, color, 3);
yading@10 210 else
yading@10 211 memcpy(p, "\x00\x00\x00", 3);
yading@10 212 p += 3;
yading@10 213 }
yading@10 214 p += pic->linesize[0] - 8*3;
yading@10 215 }
yading@10 216 }
yading@10 217 }
yading@10 218
yading@10 219 static void drawline(AVFrame *pic, int x, int y, int len, int step)
yading@10 220 {
yading@10 221 int i;
yading@10 222 uint8_t *p = pic->data[0] + y*pic->linesize[0] + x*3;
yading@10 223
yading@10 224 for (i = 0; i < len; i++) {
yading@10 225 memcpy(p, "\x00\xff\x00", 3);
yading@10 226 p += step;
yading@10 227 }
yading@10 228 }
yading@10 229
yading@10 230 static int config_video_output(AVFilterLink *outlink)
yading@10 231 {
yading@10 232 int i, x, y;
yading@10 233 uint8_t *p;
yading@10 234 AVFilterContext *ctx = outlink->src;
yading@10 235 EBUR128Context *ebur128 = ctx->priv;
yading@10 236 AVFrame *outpicref;
yading@10 237
yading@10 238 /* check if there is enough space to represent everything decently */
yading@10 239 if (ebur128->w < 640 || ebur128->h < 480) {
yading@10 240 av_log(ctx, AV_LOG_ERROR, "Video size %dx%d is too small, "
yading@10 241 "minimum size is 640x480\n", ebur128->w, ebur128->h);
yading@10 242 return AVERROR(EINVAL);
yading@10 243 }
yading@10 244 outlink->w = ebur128->w;
yading@10 245 outlink->h = ebur128->h;
yading@10 246
yading@10 247 #define PAD 8
yading@10 248
yading@10 249 /* configure text area position and size */
yading@10 250 ebur128->text.x = PAD;
yading@10 251 ebur128->text.y = 40;
yading@10 252 ebur128->text.w = 3 * 8; // 3 characters
yading@10 253 ebur128->text.h = ebur128->h - PAD - ebur128->text.y;
yading@10 254
yading@10 255 /* configure gauge position and size */
yading@10 256 ebur128->gauge.w = 20;
yading@10 257 ebur128->gauge.h = ebur128->text.h;
yading@10 258 ebur128->gauge.x = ebur128->w - PAD - ebur128->gauge.w;
yading@10 259 ebur128->gauge.y = ebur128->text.y;
yading@10 260
yading@10 261 /* configure graph position and size */
yading@10 262 ebur128->graph.x = ebur128->text.x + ebur128->text.w + PAD;
yading@10 263 ebur128->graph.y = ebur128->gauge.y;
yading@10 264 ebur128->graph.w = ebur128->gauge.x - ebur128->graph.x - PAD;
yading@10 265 ebur128->graph.h = ebur128->gauge.h;
yading@10 266
yading@10 267 /* graph and gauge share the LU-to-pixel code */
yading@10 268 av_assert0(ebur128->graph.h == ebur128->gauge.h);
yading@10 269
yading@10 270 /* prepare the initial picref buffer */
yading@10 271 av_frame_free(&ebur128->outpicref);
yading@10 272 ebur128->outpicref = outpicref =
yading@10 273 ff_get_video_buffer(outlink, outlink->w, outlink->h);
yading@10 274 if (!outpicref)
yading@10 275 return AVERROR(ENOMEM);
yading@10 276 outlink->sample_aspect_ratio = (AVRational){1,1};
yading@10 277
yading@10 278 /* init y references values (to draw LU lines) */
yading@10 279 ebur128->y_line_ref = av_calloc(ebur128->graph.h + 1, sizeof(*ebur128->y_line_ref));
yading@10 280 if (!ebur128->y_line_ref)
yading@10 281 return AVERROR(ENOMEM);
yading@10 282
yading@10 283 /* black background */
yading@10 284 memset(outpicref->data[0], 0, ebur128->h * outpicref->linesize[0]);
yading@10 285
yading@10 286 /* draw LU legends */
yading@10 287 drawtext(outpicref, PAD, PAD+16, FONT8, font_colors+3, " LU");
yading@10 288 for (i = ebur128->meter; i >= -ebur128->meter * 2; i--) {
yading@10 289 y = lu_to_y(ebur128, i);
yading@10 290 x = PAD + (i < 10 && i > -10) * 8;
yading@10 291 ebur128->y_line_ref[y] = i;
yading@10 292 y -= 4; // -4 to center vertically
yading@10 293 drawtext(outpicref, x, y + ebur128->graph.y, FONT8, font_colors+3,
yading@10 294 "%c%d", i < 0 ? '-' : i > 0 ? '+' : ' ', FFABS(i));
yading@10 295 }
yading@10 296
yading@10 297 /* draw graph */
yading@10 298 ebur128->y_zero_lu = lu_to_y(ebur128, 0);
yading@10 299 p = outpicref->data[0] + ebur128->graph.y * outpicref->linesize[0]
yading@10 300 + ebur128->graph.x * 3;
yading@10 301 for (y = 0; y < ebur128->graph.h; y++) {
yading@10 302 const uint8_t *c = get_graph_color(ebur128, INT_MAX, y);
yading@10 303
yading@10 304 for (x = 0; x < ebur128->graph.w; x++)
yading@10 305 memcpy(p + x*3, c, 3);
yading@10 306 p += outpicref->linesize[0];
yading@10 307 }
yading@10 308
yading@10 309 /* draw fancy rectangles around the graph and the gauge */
yading@10 310 #define DRAW_RECT(r) do { \
yading@10 311 drawline(outpicref, r.x, r.y - 1, r.w, 3); \
yading@10 312 drawline(outpicref, r.x, r.y + r.h, r.w, 3); \
yading@10 313 drawline(outpicref, r.x - 1, r.y, r.h, outpicref->linesize[0]); \
yading@10 314 drawline(outpicref, r.x + r.w, r.y, r.h, outpicref->linesize[0]); \
yading@10 315 } while (0)
yading@10 316 DRAW_RECT(ebur128->graph);
yading@10 317 DRAW_RECT(ebur128->gauge);
yading@10 318
yading@10 319 outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
yading@10 320
yading@10 321 return 0;
yading@10 322 }
yading@10 323
yading@10 324 static int config_audio_input(AVFilterLink *inlink)
yading@10 325 {
yading@10 326 AVFilterContext *ctx = inlink->dst;
yading@10 327 EBUR128Context *ebur128 = ctx->priv;
yading@10 328
yading@10 329 /* force 100ms framing in case of metadata injection: the frames must have
yading@10 330 * a granularity of the window overlap to be accurately exploited */
yading@10 331 if (ebur128->metadata)
yading@10 332 inlink->min_samples =
yading@10 333 inlink->max_samples =
yading@10 334 inlink->partial_buf_size = inlink->sample_rate / 10;
yading@10 335 return 0;
yading@10 336 }
yading@10 337
yading@10 338 static int config_audio_output(AVFilterLink *outlink)
yading@10 339 {
yading@10 340 int i;
yading@10 341 int idx_bitposn = 0;
yading@10 342 AVFilterContext *ctx = outlink->src;
yading@10 343 EBUR128Context *ebur128 = ctx->priv;
yading@10 344 const int nb_channels = av_get_channel_layout_nb_channels(outlink->channel_layout);
yading@10 345
yading@10 346 #define BACK_MASK (AV_CH_BACK_LEFT |AV_CH_BACK_CENTER |AV_CH_BACK_RIGHT| \
yading@10 347 AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_BACK_RIGHT| \
yading@10 348 AV_CH_SIDE_LEFT |AV_CH_SIDE_RIGHT| \
yading@10 349 AV_CH_SURROUND_DIRECT_LEFT |AV_CH_SURROUND_DIRECT_RIGHT)
yading@10 350
yading@10 351 ebur128->nb_channels = nb_channels;
yading@10 352 ebur128->ch_weighting = av_calloc(nb_channels, sizeof(*ebur128->ch_weighting));
yading@10 353 if (!ebur128->ch_weighting)
yading@10 354 return AVERROR(ENOMEM);
yading@10 355
yading@10 356 for (i = 0; i < nb_channels; i++) {
yading@10 357
yading@10 358 /* find the next bit that is set starting from the right */
yading@10 359 while ((outlink->channel_layout & 1ULL<<idx_bitposn) == 0 && idx_bitposn < 63)
yading@10 360 idx_bitposn++;
yading@10 361
yading@10 362 /* channel weighting */
yading@10 363 if ((1ULL<<idx_bitposn & AV_CH_LOW_FREQUENCY) ||
yading@10 364 (1ULL<<idx_bitposn & AV_CH_LOW_FREQUENCY_2)) {
yading@10 365 ebur128->ch_weighting[i] = 0;
yading@10 366 } else if (1ULL<<idx_bitposn & BACK_MASK) {
yading@10 367 ebur128->ch_weighting[i] = 1.41;
yading@10 368 } else {
yading@10 369 ebur128->ch_weighting[i] = 1.0;
yading@10 370 }
yading@10 371
yading@10 372 idx_bitposn++;
yading@10 373
yading@10 374 if (!ebur128->ch_weighting[i])
yading@10 375 continue;
yading@10 376
yading@10 377 /* bins buffer for the two integration window (400ms and 3s) */
yading@10 378 ebur128->i400.cache[i] = av_calloc(I400_BINS, sizeof(*ebur128->i400.cache[0]));
yading@10 379 ebur128->i3000.cache[i] = av_calloc(I3000_BINS, sizeof(*ebur128->i3000.cache[0]));
yading@10 380 if (!ebur128->i400.cache[i] || !ebur128->i3000.cache[i])
yading@10 381 return AVERROR(ENOMEM);
yading@10 382 }
yading@10 383
yading@10 384 outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
yading@10 385
yading@10 386 return 0;
yading@10 387 }
yading@10 388
yading@10 389 #define ENERGY(loudness) (pow(10, ((loudness) + 0.691) / 10.))
yading@10 390 #define LOUDNESS(energy) (-0.691 + 10 * log10(energy))
yading@10 391
yading@10 392 static struct hist_entry *get_histogram(void)
yading@10 393 {
yading@10 394 int i;
yading@10 395 struct hist_entry *h = av_calloc(HIST_SIZE, sizeof(*h));
yading@10 396
yading@10 397 if (!h)
yading@10 398 return NULL;
yading@10 399 for (i = 0; i < HIST_SIZE; i++) {
yading@10 400 h[i].loudness = i / (double)HIST_GRAIN + ABS_THRES;
yading@10 401 h[i].energy = ENERGY(h[i].loudness);
yading@10 402 }
yading@10 403 return h;
yading@10 404 }
yading@10 405
yading@10 406 static av_cold int init(AVFilterContext *ctx)
yading@10 407 {
yading@10 408 EBUR128Context *ebur128 = ctx->priv;
yading@10 409 AVFilterPad pad;
yading@10 410
yading@10 411 if (ebur128->loglevel != AV_LOG_INFO &&
yading@10 412 ebur128->loglevel != AV_LOG_VERBOSE) {
yading@10 413 if (ebur128->do_video || ebur128->metadata)
yading@10 414 ebur128->loglevel = AV_LOG_VERBOSE;
yading@10 415 else
yading@10 416 ebur128->loglevel = AV_LOG_INFO;
yading@10 417 }
yading@10 418
yading@10 419 // if meter is +9 scale, scale range is from -18 LU to +9 LU (or 3*9)
yading@10 420 // if meter is +18 scale, scale range is from -36 LU to +18 LU (or 3*18)
yading@10 421 ebur128->scale_range = 3 * ebur128->meter;
yading@10 422
yading@10 423 ebur128->i400.histogram = get_histogram();
yading@10 424 ebur128->i3000.histogram = get_histogram();
yading@10 425 if (!ebur128->i400.histogram || !ebur128->i3000.histogram)
yading@10 426 return AVERROR(ENOMEM);
yading@10 427
yading@10 428 ebur128->integrated_loudness = ABS_THRES;
yading@10 429 ebur128->loudness_range = 0;
yading@10 430
yading@10 431 /* insert output pads */
yading@10 432 if (ebur128->do_video) {
yading@10 433 pad = (AVFilterPad){
yading@10 434 .name = av_strdup("out0"),
yading@10 435 .type = AVMEDIA_TYPE_VIDEO,
yading@10 436 .config_props = config_video_output,
yading@10 437 };
yading@10 438 if (!pad.name)
yading@10 439 return AVERROR(ENOMEM);
yading@10 440 ff_insert_outpad(ctx, 0, &pad);
yading@10 441 }
yading@10 442 pad = (AVFilterPad){
yading@10 443 .name = av_asprintf("out%d", ebur128->do_video),
yading@10 444 .type = AVMEDIA_TYPE_AUDIO,
yading@10 445 .config_props = config_audio_output,
yading@10 446 };
yading@10 447 if (!pad.name)
yading@10 448 return AVERROR(ENOMEM);
yading@10 449 ff_insert_outpad(ctx, ebur128->do_video, &pad);
yading@10 450
yading@10 451 /* summary */
yading@10 452 av_log(ctx, AV_LOG_VERBOSE, "EBU +%d scale\n", ebur128->meter);
yading@10 453
yading@10 454 return 0;
yading@10 455 }
yading@10 456
yading@10 457 #define HIST_POS(power) (int)(((power) - ABS_THRES) * HIST_GRAIN)
yading@10 458
yading@10 459 /* loudness and power should be set such as loudness = -0.691 +
yading@10 460 * 10*log10(power), we just avoid doing that calculus two times */
yading@10 461 static int gate_update(struct integrator *integ, double power,
yading@10 462 double loudness, int gate_thres)
yading@10 463 {
yading@10 464 int ipower;
yading@10 465 double relative_threshold;
yading@10 466 int gate_hist_pos;
yading@10 467
yading@10 468 /* update powers histograms by incrementing current power count */
yading@10 469 ipower = av_clip(HIST_POS(loudness), 0, HIST_SIZE - 1);
yading@10 470 integ->histogram[ipower].count++;
yading@10 471
yading@10 472 /* compute relative threshold and get its position in the histogram */
yading@10 473 integ->sum_kept_powers += power;
yading@10 474 integ->nb_kept_powers++;
yading@10 475 relative_threshold = integ->sum_kept_powers / integ->nb_kept_powers;
yading@10 476 if (!relative_threshold)
yading@10 477 relative_threshold = 1e-12;
yading@10 478 integ->rel_threshold = LOUDNESS(relative_threshold) + gate_thres;
yading@10 479 gate_hist_pos = av_clip(HIST_POS(integ->rel_threshold), 0, HIST_SIZE - 1);
yading@10 480
yading@10 481 return gate_hist_pos;
yading@10 482 }
yading@10 483
yading@10 484 static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
yading@10 485 {
yading@10 486 int i, ch, idx_insample;
yading@10 487 AVFilterContext *ctx = inlink->dst;
yading@10 488 EBUR128Context *ebur128 = ctx->priv;
yading@10 489 const int nb_channels = ebur128->nb_channels;
yading@10 490 const int nb_samples = insamples->nb_samples;
yading@10 491 const double *samples = (double *)insamples->data[0];
yading@10 492 AVFrame *pic = ebur128->outpicref;
yading@10 493
yading@10 494 for (idx_insample = 0; idx_insample < nb_samples; idx_insample++) {
yading@10 495 const int bin_id_400 = ebur128->i400.cache_pos;
yading@10 496 const int bin_id_3000 = ebur128->i3000.cache_pos;
yading@10 497
yading@10 498 #define MOVE_TO_NEXT_CACHED_ENTRY(time) do { \
yading@10 499 ebur128->i##time.cache_pos++; \
yading@10 500 if (ebur128->i##time.cache_pos == I##time##_BINS) { \
yading@10 501 ebur128->i##time.filled = 1; \
yading@10 502 ebur128->i##time.cache_pos = 0; \
yading@10 503 } \
yading@10 504 } while (0)
yading@10 505
yading@10 506 MOVE_TO_NEXT_CACHED_ENTRY(400);
yading@10 507 MOVE_TO_NEXT_CACHED_ENTRY(3000);
yading@10 508
yading@10 509 for (ch = 0; ch < nb_channels; ch++) {
yading@10 510 double bin;
yading@10 511
yading@10 512 ebur128->x[ch * 3] = *samples++; // set X[i]
yading@10 513
yading@10 514 if (!ebur128->ch_weighting[ch])
yading@10 515 continue;
yading@10 516
yading@10 517 /* Y[i] = X[i]*b0 + X[i-1]*b1 + X[i-2]*b2 - Y[i-1]*a1 - Y[i-2]*a2 */
yading@10 518 #define FILTER(Y, X, name) do { \
yading@10 519 double *dst = ebur128->Y + ch*3; \
yading@10 520 double *src = ebur128->X + ch*3; \
yading@10 521 dst[2] = dst[1]; \
yading@10 522 dst[1] = dst[0]; \
yading@10 523 dst[0] = src[0]*name##_B0 + src[1]*name##_B1 + src[2]*name##_B2 \
yading@10 524 - dst[1]*name##_A1 - dst[2]*name##_A2; \
yading@10 525 } while (0)
yading@10 526
yading@10 527 // TODO: merge both filters in one?
yading@10 528 FILTER(y, x, PRE); // apply pre-filter
yading@10 529 ebur128->x[ch * 3 + 2] = ebur128->x[ch * 3 + 1];
yading@10 530 ebur128->x[ch * 3 + 1] = ebur128->x[ch * 3 ];
yading@10 531 FILTER(z, y, RLB); // apply RLB-filter
yading@10 532
yading@10 533 bin = ebur128->z[ch * 3] * ebur128->z[ch * 3];
yading@10 534
yading@10 535 /* add the new value, and limit the sum to the cache size (400ms or 3s)
yading@10 536 * by removing the oldest one */
yading@10 537 ebur128->i400.sum [ch] = ebur128->i400.sum [ch] + bin - ebur128->i400.cache [ch][bin_id_400];
yading@10 538 ebur128->i3000.sum[ch] = ebur128->i3000.sum[ch] + bin - ebur128->i3000.cache[ch][bin_id_3000];
yading@10 539
yading@10 540 /* override old cache entry with the new value */
yading@10 541 ebur128->i400.cache [ch][bin_id_400 ] = bin;
yading@10 542 ebur128->i3000.cache[ch][bin_id_3000] = bin;
yading@10 543 }
yading@10 544
yading@10 545 /* For integrated loudness, gating blocks are 400ms long with 75%
yading@10 546 * overlap (see BS.1770-2 p5), so a re-computation is needed each 100ms
yading@10 547 * (4800 samples at 48kHz). */
yading@10 548 if (++ebur128->sample_count == 4800) {
yading@10 549 double loudness_400, loudness_3000;
yading@10 550 double power_400 = 1e-12, power_3000 = 1e-12;
yading@10 551 AVFilterLink *outlink = ctx->outputs[0];
yading@10 552 const int64_t pts = insamples->pts +
yading@10 553 av_rescale_q(idx_insample, (AVRational){ 1, inlink->sample_rate },
yading@10 554 outlink->time_base);
yading@10 555
yading@10 556 ebur128->sample_count = 0;
yading@10 557
yading@10 558 #define COMPUTE_LOUDNESS(m, time) do { \
yading@10 559 if (ebur128->i##time.filled) { \
yading@10 560 /* weighting sum of the last <time> ms */ \
yading@10 561 for (ch = 0; ch < nb_channels; ch++) \
yading@10 562 power_##time += ebur128->ch_weighting[ch] * ebur128->i##time.sum[ch]; \
yading@10 563 power_##time /= I##time##_BINS; \
yading@10 564 } \
yading@10 565 loudness_##time = LOUDNESS(power_##time); \
yading@10 566 } while (0)
yading@10 567
yading@10 568 COMPUTE_LOUDNESS(M, 400);
yading@10 569 COMPUTE_LOUDNESS(S, 3000);
yading@10 570
yading@10 571 /* Integrated loudness */
yading@10 572 #define I_GATE_THRES -10 // initially defined to -8 LU in the first EBU standard
yading@10 573
yading@10 574 if (loudness_400 >= ABS_THRES) {
yading@10 575 double integrated_sum = 0;
yading@10 576 int nb_integrated = 0;
yading@10 577 int gate_hist_pos = gate_update(&ebur128->i400, power_400,
yading@10 578 loudness_400, I_GATE_THRES);
yading@10 579
yading@10 580 /* compute integrated loudness by summing the histogram values
yading@10 581 * above the relative threshold */
yading@10 582 for (i = gate_hist_pos; i < HIST_SIZE; i++) {
yading@10 583 const int nb_v = ebur128->i400.histogram[i].count;
yading@10 584 nb_integrated += nb_v;
yading@10 585 integrated_sum += nb_v * ebur128->i400.histogram[i].energy;
yading@10 586 }
yading@10 587 if (nb_integrated)
yading@10 588 ebur128->integrated_loudness = LOUDNESS(integrated_sum / nb_integrated);
yading@10 589 }
yading@10 590
yading@10 591 /* LRA */
yading@10 592 #define LRA_GATE_THRES -20
yading@10 593 #define LRA_LOWER_PRC 10
yading@10 594 #define LRA_HIGHER_PRC 95
yading@10 595
yading@10 596 /* XXX: example code in EBU 3342 is ">=" but formula in BS.1770
yading@10 597 * specs is ">" */
yading@10 598 if (loudness_3000 >= ABS_THRES) {
yading@10 599 int nb_powers = 0;
yading@10 600 int gate_hist_pos = gate_update(&ebur128->i3000, power_3000,
yading@10 601 loudness_3000, LRA_GATE_THRES);
yading@10 602
yading@10 603 for (i = gate_hist_pos; i < HIST_SIZE; i++)
yading@10 604 nb_powers += ebur128->i3000.histogram[i].count;
yading@10 605 if (nb_powers) {
yading@10 606 int n, nb_pow;
yading@10 607
yading@10 608 /* get lower loudness to consider */
yading@10 609 n = 0;
yading@10 610 nb_pow = LRA_LOWER_PRC * nb_powers / 100. + 0.5;
yading@10 611 for (i = gate_hist_pos; i < HIST_SIZE; i++) {
yading@10 612 n += ebur128->i3000.histogram[i].count;
yading@10 613 if (n >= nb_pow) {
yading@10 614 ebur128->lra_low = ebur128->i3000.histogram[i].loudness;
yading@10 615 break;
yading@10 616 }
yading@10 617 }
yading@10 618
yading@10 619 /* get higher loudness to consider */
yading@10 620 n = nb_powers;
yading@10 621 nb_pow = LRA_HIGHER_PRC * nb_powers / 100. + 0.5;
yading@10 622 for (i = HIST_SIZE - 1; i >= 0; i--) {
yading@10 623 n -= ebur128->i3000.histogram[i].count;
yading@10 624 if (n < nb_pow) {
yading@10 625 ebur128->lra_high = ebur128->i3000.histogram[i].loudness;
yading@10 626 break;
yading@10 627 }
yading@10 628 }
yading@10 629
yading@10 630 // XXX: show low & high on the graph?
yading@10 631 ebur128->loudness_range = ebur128->lra_high - ebur128->lra_low;
yading@10 632 }
yading@10 633 }
yading@10 634
yading@10 635 #define LOG_FMT "M:%6.1f S:%6.1f I:%6.1f LUFS LRA:%6.1f LU"
yading@10 636
yading@10 637 /* push one video frame */
yading@10 638 if (ebur128->do_video) {
yading@10 639 int x, y, ret;
yading@10 640 uint8_t *p;
yading@10 641
yading@10 642 const int y_loudness_lu_graph = lu_to_y(ebur128, loudness_3000 + 23);
yading@10 643 const int y_loudness_lu_gauge = lu_to_y(ebur128, loudness_400 + 23);
yading@10 644
yading@10 645 /* draw the graph using the short-term loudness */
yading@10 646 p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3;
yading@10 647 for (y = 0; y < ebur128->graph.h; y++) {
yading@10 648 const uint8_t *c = get_graph_color(ebur128, y_loudness_lu_graph, y);
yading@10 649
yading@10 650 memmove(p, p + 3, (ebur128->graph.w - 1) * 3);
yading@10 651 memcpy(p + (ebur128->graph.w - 1) * 3, c, 3);
yading@10 652 p += pic->linesize[0];
yading@10 653 }
yading@10 654
yading@10 655 /* draw the gauge using the momentary loudness */
yading@10 656 p = pic->data[0] + ebur128->gauge.y*pic->linesize[0] + ebur128->gauge.x*3;
yading@10 657 for (y = 0; y < ebur128->gauge.h; y++) {
yading@10 658 const uint8_t *c = get_graph_color(ebur128, y_loudness_lu_gauge, y);
yading@10 659
yading@10 660 for (x = 0; x < ebur128->gauge.w; x++)
yading@10 661 memcpy(p + x*3, c, 3);
yading@10 662 p += pic->linesize[0];
yading@10 663 }
yading@10 664
yading@10 665 /* draw textual info */
yading@10 666 drawtext(pic, PAD, PAD - PAD/2, FONT16, font_colors,
yading@10 667 LOG_FMT " ", // padding to erase trailing characters
yading@10 668 loudness_400, loudness_3000,
yading@10 669 ebur128->integrated_loudness, ebur128->loudness_range);
yading@10 670
yading@10 671 /* set pts and push frame */
yading@10 672 pic->pts = pts;
yading@10 673 ret = ff_filter_frame(outlink, av_frame_clone(pic));
yading@10 674 if (ret < 0)
yading@10 675 return ret;
yading@10 676 }
yading@10 677
yading@10 678 if (ebur128->metadata) { /* happens only once per filter_frame call */
yading@10 679 char metabuf[128];
yading@10 680 #define SET_META(name, var) do { \
yading@10 681 snprintf(metabuf, sizeof(metabuf), "%.3f", var); \
yading@10 682 av_dict_set(&insamples->metadata, "lavfi.r128." name, metabuf, 0); \
yading@10 683 } while (0)
yading@10 684 SET_META("M", loudness_400);
yading@10 685 SET_META("S", loudness_3000);
yading@10 686 SET_META("I", ebur128->integrated_loudness);
yading@10 687 SET_META("LRA", ebur128->loudness_range);
yading@10 688 SET_META("LRA.low", ebur128->lra_low);
yading@10 689 SET_META("LRA.high", ebur128->lra_high);
yading@10 690 }
yading@10 691
yading@10 692 av_log(ctx, ebur128->loglevel, "t: %-10s " LOG_FMT "\n",
yading@10 693 av_ts2timestr(pts, &outlink->time_base),
yading@10 694 loudness_400, loudness_3000,
yading@10 695 ebur128->integrated_loudness, ebur128->loudness_range);
yading@10 696 }
yading@10 697 }
yading@10 698
yading@10 699 return ff_filter_frame(ctx->outputs[ebur128->do_video], insamples);
yading@10 700 }
yading@10 701
yading@10 702 static int query_formats(AVFilterContext *ctx)
yading@10 703 {
yading@10 704 EBUR128Context *ebur128 = ctx->priv;
yading@10 705 AVFilterFormats *formats;
yading@10 706 AVFilterChannelLayouts *layouts;
yading@10 707 AVFilterLink *inlink = ctx->inputs[0];
yading@10 708 AVFilterLink *outlink = ctx->outputs[0];
yading@10 709
yading@10 710 static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_NONE };
yading@10 711 static const int input_srate[] = {48000, -1}; // ITU-R BS.1770 provides coeff only for 48kHz
yading@10 712 static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE };
yading@10 713
yading@10 714 /* set optional output video format */
yading@10 715 if (ebur128->do_video) {
yading@10 716 formats = ff_make_format_list(pix_fmts);
yading@10 717 if (!formats)
yading@10 718 return AVERROR(ENOMEM);
yading@10 719 ff_formats_ref(formats, &outlink->in_formats);
yading@10 720 outlink = ctx->outputs[1];
yading@10 721 }
yading@10 722
yading@10 723 /* set input and output audio formats
yading@10 724 * Note: ff_set_common_* functions are not used because they affect all the
yading@10 725 * links, and thus break the video format negociation */
yading@10 726 formats = ff_make_format_list(sample_fmts);
yading@10 727 if (!formats)
yading@10 728 return AVERROR(ENOMEM);
yading@10 729 ff_formats_ref(formats, &inlink->out_formats);
yading@10 730 ff_formats_ref(formats, &outlink->in_formats);
yading@10 731
yading@10 732 layouts = ff_all_channel_layouts();
yading@10 733 if (!layouts)
yading@10 734 return AVERROR(ENOMEM);
yading@10 735 ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts);
yading@10 736 ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts);
yading@10 737
yading@10 738 formats = ff_make_format_list(input_srate);
yading@10 739 if (!formats)
yading@10 740 return AVERROR(ENOMEM);
yading@10 741 ff_formats_ref(formats, &inlink->out_samplerates);
yading@10 742 ff_formats_ref(formats, &outlink->in_samplerates);
yading@10 743
yading@10 744 return 0;
yading@10 745 }
yading@10 746
yading@10 747 static av_cold void uninit(AVFilterContext *ctx)
yading@10 748 {
yading@10 749 int i;
yading@10 750 EBUR128Context *ebur128 = ctx->priv;
yading@10 751
yading@10 752 av_log(ctx, AV_LOG_INFO, "Summary:\n\n"
yading@10 753 " Integrated loudness:\n"
yading@10 754 " I: %5.1f LUFS\n"
yading@10 755 " Threshold: %5.1f LUFS\n\n"
yading@10 756 " Loudness range:\n"
yading@10 757 " LRA: %5.1f LU\n"
yading@10 758 " Threshold: %5.1f LUFS\n"
yading@10 759 " LRA low: %5.1f LUFS\n"
yading@10 760 " LRA high: %5.1f LUFS\n",
yading@10 761 ebur128->integrated_loudness, ebur128->i400.rel_threshold,
yading@10 762 ebur128->loudness_range, ebur128->i3000.rel_threshold,
yading@10 763 ebur128->lra_low, ebur128->lra_high);
yading@10 764
yading@10 765 av_freep(&ebur128->y_line_ref);
yading@10 766 av_freep(&ebur128->ch_weighting);
yading@10 767 av_freep(&ebur128->i400.histogram);
yading@10 768 av_freep(&ebur128->i3000.histogram);
yading@10 769 for (i = 0; i < ebur128->nb_channels; i++) {
yading@10 770 av_freep(&ebur128->i400.cache[i]);
yading@10 771 av_freep(&ebur128->i3000.cache[i]);
yading@10 772 }
yading@10 773 for (i = 0; i < ctx->nb_outputs; i++)
yading@10 774 av_freep(&ctx->output_pads[i].name);
yading@10 775 av_frame_free(&ebur128->outpicref);
yading@10 776 }
yading@10 777
yading@10 778 static const AVFilterPad ebur128_inputs[] = {
yading@10 779 {
yading@10 780 .name = "default",
yading@10 781 .type = AVMEDIA_TYPE_AUDIO,
yading@10 782 .get_audio_buffer = ff_null_get_audio_buffer,
yading@10 783 .filter_frame = filter_frame,
yading@10 784 .config_props = config_audio_input,
yading@10 785 },
yading@10 786 { NULL }
yading@10 787 };
yading@10 788
yading@10 789 AVFilter avfilter_af_ebur128 = {
yading@10 790 .name = "ebur128",
yading@10 791 .description = NULL_IF_CONFIG_SMALL("EBU R128 scanner."),
yading@10 792 .priv_size = sizeof(EBUR128Context),
yading@10 793 .init = init,
yading@10 794 .uninit = uninit,
yading@10 795 .query_formats = query_formats,
yading@10 796 .inputs = ebur128_inputs,
yading@10 797 .outputs = NULL,
yading@10 798 .priv_class = &ebur128_class,
yading@10 799 .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
yading@10 800 };