| @@ -26,6 +26,7 @@ · 25 unmodified lines |
| 26 | * @todo implement start/stop/reset through filter command injection | 26 | * @todo implement start/stop/reset through filter command injection |
| 27 | */ | 27 | */ |
| 28 | | 28 | |
| | 29 | #include <float.h> |
| 29 | #include <math.h> | 30 | #include <math.h> |
| 30 | | 31 | |
| 31 | #include "libavutil/avassert.h" | 32 | #include "libavutil/avassert.h" |
| @@ -80,7 +81,9 @@ typedef struct EBUR128Context { · 48 unmodified lines |
| 80 | | 81 | |
| 81 | /* peak metering */ | 82 | /* peak metering */ |
| 82 | int peak_mode; ///< enabled peak modes | 83 | int peak_mode; ///< enabled peak modes |
| | 84 | double true_peak; ///< global true peak |
| 83 | double *true_peaks; ///< true peaks per channel | 85 | double *true_peaks; ///< true peaks per channel |
| | 86 | double sample_peak; ///< global sample peak |
| 84 | double *sample_peaks; ///< sample peaks per channel | 87 | double *sample_peaks; ///< sample peaks per channel |
| 85 | double *true_peaks_per_frame; ///< true peaks in a frame per channel | 88 | double *true_peaks_per_frame; ///< true peaks in a frame per channel |
| 86 | #if CONFIG_SWRESAMPLE | 89 | #if CONFIG_SWRESAMPLE |
| @@ -159,6 +162,8 @@ enum { · 72 unmodified lines |
| 159 | #define A AV_OPT_FLAG_AUDIO_PARAM | 162 | #define A AV_OPT_FLAG_AUDIO_PARAM |
| 160 | #define V AV_OPT_FLAG_VIDEO_PARAM | 163 | #define V AV_OPT_FLAG_VIDEO_PARAM |
| 161 | #define F AV_OPT_FLAG_FILTERING_PARAM | 164 | #define F AV_OPT_FLAG_FILTERING_PARAM |
| | 165 | #define X AV_OPT_FLAG_EXPORT |
| | 166 | #define R AV_OPT_FLAG_READONLY |
| 162 | static const AVOption ebur128_options[] = { | 167 | static const AVOption ebur128_options[] = { |
| 163 | { "video", "set video output", OFFSET(do_video), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, V|F }, | 168 | { "video", "set video output", OFFSET(do_video), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, V|F }, |
| 164 | { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x480"}, 0, 0, V|F }, | 169 | { "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[] = { · 20 unmodified lines |
| 185 | { "LUFS", "display absolute values (LUFS)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_ABSOLUTE}, INT_MIN, INT_MAX, V|F, "scaletype" }, | 190 | { "LUFS", "display absolute values (LUFS)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_ABSOLUTE}, INT_MIN, INT_MAX, V|F, "scaletype" }, |
| 186 | { "relative", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, | 191 | { "relative", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, |
| 187 | { "LU", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, | 192 | { "LU", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, |
| | 193 | { "integrated", "integrated loudness (LUFS)", OFFSET(integrated_loudness), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, |
| | 194 | { "range", "loudness range (LU)", OFFSET(loudness_range), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, |
| | 195 | { "lra_low", "LRA low (LUFS)", OFFSET(lra_low), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, |
| | 196 | { "lra_high", "LRA high (LUFS)", OFFSET(lra_high), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, |
| | 197 | { "sample_peak", "sample peak (dBFS)", OFFSET(sample_peak), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, |
| | 198 | { "true_peak", "true peak (dBFS)", OFFSET(true_peak), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, |
| 188 | { NULL }, | 199 | { NULL }, |
| 189 | }; | 200 | }; |
| 190 | | 201 | |
| @@ -701,6 +712,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) · 510 unmodified lines |
| 701 | ebur128->i3000.cache[ch][bin_id_3000] = bin; | 712 | ebur128->i3000.cache[ch][bin_id_3000] = bin; |
| 702 | } | 713 | } |
| 703 | | 714 | |
| | 715 | #define FIND_PEAK(global, sp, ptype) do { \ |
| | 716 | int ch; \ |
| | 717 | double maxpeak; \ |
| | 718 | maxpeak = 0.0; \ |
| | 719 | if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \ |
| | 720 | for (ch = 0; ch < ebur128->nb_channels; ch++) \ |
| | 721 | maxpeak = FFMAX(maxpeak, sp[ch]); \ |
| | 722 | global = DBFS(maxpeak); \ |
| | 723 | } \ |
| | 724 | } while (0) |
| | 725 | |
| | 726 | FIND_PEAK(ebur128->sample_peak, ebur128->sample_peaks, SAMPLES); |
| | 727 | FIND_PEAK(ebur128->true_peak, ebur128->true_peaks, TRUE); |
| | 728 | |
| 704 | /* For integrated loudness, gating blocks are 400ms long with 75% | 729 | /* For integrated loudness, gating blocks are 400ms long with 75% |
| 705 | * overlap (see BS.1770-2 p5), so a re-computation is needed each 100ms | 730 | * overlap (see BS.1770-2 p5), so a re-computation is needed each 100ms |
| 706 | * (4800 samples at 48kHz). */ | 731 | * (4800 samples at 48kHz). */ |
| @@ -1023,7 +1048,6 @@ static int query_formats(AVFilterContext *ctx) · 316 unmodified lines |
| 1023 | | 1048 | |
| 1024 | static av_cold void uninit(AVFilterContext *ctx) | 1049 | static av_cold void uninit(AVFilterContext *ctx) |
| 1025 | { | 1050 | { |
| 1026 | int i; | | |
| 1027 | EBUR128Context *ebur128 = ctx->priv; | 1051 | EBUR128Context *ebur128 = ctx->priv; |
| 1028 | | 1052 | |
| 1029 | /* dual-mono correction */ | 1053 | /* dual-mono correction */ |
| @@ -1047,21 +1071,15 @@ static av_cold void uninit(AVFilterContext *ctx) · 17 unmodified lines |
| 1047 | ebur128->loudness_range, ebur128->i3000.rel_threshold, | 1071 | ebur128->loudness_range, ebur128->i3000.rel_threshold, |
| 1048 | ebur128->lra_low, ebur128->lra_high); | 1072 | ebur128->lra_low, ebur128->lra_high); |
| 1049 | | 1073 | |
| 1050 | #define PRINT_PEAK_SUMMARY(str, sp, ptype) do { \ | 1074 | #define PRINT_PEAK_SUMMARY(str, value, ptype) do { \ |
| 1051 | int ch; \ | | |
| 1052 | double maxpeak; \ | | |
| 1053 | maxpeak = 0.0; \ | | |
| 1054 | if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \ | 1075 | if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \ |
| 1055 | for (ch = 0; ch < ebur128->nb_channels; ch++) \ | | |
| 1056 | maxpeak = FFMAX(maxpeak, sp[ch]); \ | | |
| 1057 | av_log(ctx, AV_LOG_INFO, "\n\n " str " peak:\n" \ | 1076 | av_log(ctx, AV_LOG_INFO, "\n\n " str " peak:\n" \ |
| 1058 | " Peak: %5.1f dBFS", \ | 1077 | " Peak: %5.1f dBFS", value); \ |
| 1059 | DBFS(maxpeak)); \ | | |
| 1060 | } \ | 1078 | } \ |
| 1061 | } while (0) | 1079 | } while (0) |
| 1062 | | 1080 | |
| 1063 | PRINT_PEAK_SUMMARY("Sample", ebur128->sample_peaks, SAMPLES); | 1081 | PRINT_PEAK_SUMMARY("Sample", ebur128->sample_peak, SAMPLES); |
| 1064 | PRINT_PEAK_SUMMARY("True", ebur128->true_peaks, TRUE); | 1082 | PRINT_PEAK_SUMMARY("True", ebur128->true_peak, TRUE); |
| 1065 | av_log(ctx, AV_LOG_INFO, "\n"); | 1083 | av_log(ctx, AV_LOG_INFO, "\n"); |
| 1066 | | 1084 | |
| 1067 | av_freep(&ebur128->y_line_ref); | 1085 | av_freep(&ebur128->y_line_ref); |
| @@ -1076,7 +1094,7 @@ static av_cold void uninit(AVFilterContext *ctx) · 8 unmodified lines |
| 1076 | av_freep(&ebur128->i3000.sum); | 1094 | av_freep(&ebur128->i3000.sum); |
| 1077 | av_freep(&ebur128->i400.histogram); | 1095 | av_freep(&ebur128->i400.histogram); |
| 1078 | av_freep(&ebur128->i3000.histogram); | 1096 | av_freep(&ebur128->i3000.histogram); |
| 1079 | for (i = 0; i < ebur128->nb_channels; i++) { | 1097 | for (int i = 0; i < ebur128->nb_channels; i++) { |
| 1080 | if (ebur128->i400.cache) | 1098 | if (ebur128->i400.cache) |
| 1081 | av_freep(&ebur128->i400.cache[i]); | 1099 | av_freep(&ebur128->i400.cache[i]); |
| 1082 | if (ebur128->i3000.cache) | 1100 | if (ebur128->i3000.cache) |