PR #24042 opened by anders-mjoll URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24042 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24042.patch
# Summary of changes Adds a `file` option to `showinfo` and `ashowinfo` so their per-frame output can be written to an avio destination instead of the log, mirroring the `file` option the `metadata`/`ametadata` filters already have. In the log the output is interleaved with unrelated messages and gated by the global log level, which makes it impractical to consume programmatically. With `file` set, the output goes to a plain file, `-` for standard output, or any writable URL, and is flushed after every frame so a second process can follow it while filtering is still running. Behaviour is unchanged when the option is unset. * `libavfilter/vf_showinfo.c`, `libavfilter/af_ashowinfo.c`: the per-frame `av_log(ctx, AV_LOG_INFO, ...)` calls now go through a `write_info()` helper, which writes to the AVIOContext when `file` is set and falls back to `av_vlog()` otherwise. * Side-data dumps that used to abort a half-written line with an `AV_LOG_ERROR`/`AV_LOG_WARNING` message now write that text into the same stream. Splitting one logical line across two log levels never produced coherent output — under a raised log level you got the fragment without its context — and with `file` set the reason would land in a different sink than the line it belongs to. * Write failures are reported but deliberately not fatal: the information stream is diagnostic, so losing its consumer should not abort filtering. * `configure`: declare the `avformat` dependency for both filters, as they now use avio. * `doc/filters.texi`: document the option for both filters. Testing: exercised with a plain file, `-`/`pipe:1` and `tcp://` destinations; killing the reader mid-stream logs the write error and lets the transcode finis built with `--disable-static --enable-shared` and checked `libavfilter.so` for undefined symbols to validate the configure change; man and HTML documentation build and render correctly. Two notes for reviewers: * As the option value is part of a filtergraph description, `:` in a URL has to be escaped (`file=tcp\\://127.0.0.1\\:42000`). This is mentioned in the documentation, next to the same caveat the `zmq` and `lv2` filters carry. * `fg_create()` in `fftools/ffmpeg_filter.c` builds a throwaway graph to determine the kinds of inputs and outputs, so `init()` runs twice and the destination is opened, closed and reopened. This is invisible for a file, but listener that accepts a single connection will see two. The `metadata` filters behave the same way today, so no attempt is made to change it here. <!-- If this PR requires new FATE test samples, attach them to the PR and list their target paths below (relative to the fate-suite root). Attached filenames must match the sample's filename: ```fate-samples # e.g. vorbis/new-sample.ogg ``` --> From 09f619ed1dbb69319d3ceadb31c094e5fd37a040 Mon Sep 17 00:00:00 2001 From: Anders Rein <[email protected]> Date: Fri, 7 Aug 2026 11:27:29 +0200 Subject: [PATCH] avfilter/{vf,af}_showinfo: add support for file output showinfo and ashowinfo could so far only write their per-frame information to the log, where it is interleaved with other logging and subject to the global log level, which makes it inconvenient to consume programmatically. Add a file option to both filters that redirects the output to any destination avio can write to: a plain file, "-" for standard output or a URL such as tcp://. The destination is flushed after every frame, so that another process can follow the output while filtering is still in progress. When the option is unset, the information is written to the log as before. The option mirrors the file option of the metadata filters. --- configure | 4 + doc/filters.texi | 22 ++ libavfilter/af_ashowinfo.c | 202 +++++++++----- libavfilter/vf_showinfo.c | 528 +++++++++++++++++++++---------------- 4 files changed, 455 insertions(+), 301 deletions(-) diff --git a/configure b/configure index f2896b81c7..e1b54ca874 100755 --- a/configure +++ b/configure @@ -4138,6 +4138,7 @@ libzmq_protocol_select="network" ametadata_filter_deps="avformat" amovie_filter_deps="avcodec avformat" aresample_filter_deps="swresample" +ashowinfo_filter_deps="avformat" asr_filter_deps="pocketsphinx" ass_filter_deps="libass" avgblur_opencl_filter_deps="opencl" @@ -4261,6 +4262,7 @@ select_filter_select="scene_sad" sharpness_vaapi_filter_deps="vaapi" showcqt_filter_deps="avformat swscale" showcqt_filter_suggest="libfontconfig libfreetype" +showinfo_filter_deps="avformat" signature_filter_deps="gpl avcodec avformat" smartblur_filter_deps="gpl swscale" sobel_opencl_filter_deps="opencl" @@ -8342,6 +8344,7 @@ enabled zlib && add_cppflags -DZLIB_CONST # conditional library dependencies, in any order enabled amovie_filter && prepend avfilter_deps "avformat avcodec" enabled aresample_filter && prepend avfilter_deps "swresample" +enabled ashowinfo_filter && prepend avfilter_deps "avformat" enabled cover_rect_filter && prepend avfilter_deps "avformat avcodec" enabled ebur128_filter && enabled swresample && prepend avfilter_deps "swresample" enabled elbg_filter && prepend avfilter_deps "avcodec" @@ -8357,6 +8360,7 @@ enabled sab_filter && prepend avfilter_deps "swscale" enabled scale_filter && prepend avfilter_deps "swscale" enabled scale2ref_filter && prepend avfilter_deps "swscale" enabled showcqt_filter && prepend avfilter_deps "avformat swscale" +enabled showinfo_filter && prepend avfilter_deps "avformat" enabled signature_filter && prepend avfilter_deps "avcodec avformat" enabled smartblur_filter && prepend avfilter_deps "swscale" enabled spp_filter && prepend avfilter_deps "avcodec" diff --git a/doc/filters.texi b/doc/filters.texi index 985a1615a9..505e030ed8 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3222,6 +3222,19 @@ Set the output sample rate. Default is 44100 Hz. Show a line containing various information for each input audio frame. The input audio is not modified. +This filter supports the following options: + +@table @option +@item file +Write the information to the given destination instead of the log. Besides a +plain file name, any URL that can be written to is accepted, and ``-'' is a +shorthand for standard output. The destination is flushed after every audio +frame, so another process can read the information while the filter is still +running. If this option is not set, the information is written to the log. +Note that a URL usually contains ':' signs, which have to be escaped (see +@ref{filtergraph escaping}). +@end table + The shown line contains a sequence of key/value pairs of the form @var{key}:@var{value}. @@ -22453,6 +22466,15 @@ Calculate checksums of each plane. By default enabled. @item udu_sei_as_ascii Try to print user data unregistered SEI as ascii character when possible, in hex format otherwise. + +@item file +Write the information to the given destination instead of the log. Besides a +plain file name, any URL that can be written to is accepted, and ``-'' is a +shorthand for standard output. The destination is flushed after every frame, so +another process can read the information while the filter is still running. If +this option is not set, the information is written to the log. +Note that a URL usually contains ':' signs, which have to be escaped (see +@ref{filtergraph escaping}). @end table The shown line contains a sequence of key/value pairs of the form diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c index 2653d0d089..328f12607e 100644 --- a/libavfilter/af_ashowinfo.c +++ b/libavfilter/af_ashowinfo.c @@ -31,9 +31,11 @@ #include "libavutil/downmix_info.h" #include "libavutil/iamf.h" #include "libavutil/mem.h" +#include "libavutil/opt.h" #include "libavutil/replaygain.h" #include "libavutil/timestamp.h" #include "libavutil/samplefmt.h" +#include "libavformat/avio.h" #include "libavcodec/defs.h" @@ -42,39 +44,95 @@ #include "filters.h" typedef struct AShowInfoContext { + const AVClass *class; /** * Scratch space for individual plane checksums for planar audio */ uint32_t *plane_checksums; + char* file_str; + AVIOContext* avio_context; } AShowInfoContext; +#define OFFSET(x) offsetof(AShowInfoContext, x) +#define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption ashowinfo_options[] = { + { "file", "Dump information to file instead of writing to log", + OFFSET(file_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(ashowinfo); + +static av_cold int init(AVFilterContext *ctx) { + int ret; + AShowInfoContext *s = ctx->priv; + + if (s->file_str != NULL) { + if (!strcmp("-", s->file_str)) { + ret = avio_open(&s->avio_context, "pipe:1", AVIO_FLAG_WRITE); + } else { + ret = avio_open(&s->avio_context, s->file_str, AVIO_FLAG_WRITE); + } + + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Could not open %s: %s\n", + s->file_str, av_err2str(ret)); + return ret; + } + } + + return 0; +} + static av_cold void uninit(AVFilterContext *ctx) { + int ret; AShowInfoContext *s = ctx->priv; av_freep(&s->plane_checksums); + + if (s->avio_context) { + ret = avio_close(s->avio_context); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to close file: %s\n", s->file_str); + } + } } +static void write_info(AVFilterContext *ctx, const char *fmt, ...) { + AShowInfoContext *s = ctx->priv; + va_list vl; + va_start(vl, fmt); + if (s->avio_context != NULL) { + avio_vprintf(s->avio_context, fmt, vl); + } else { + av_vlog(ctx, AV_LOG_INFO, fmt, vl); + } + va_end(vl); +} + + static void dump_matrixenc(AVFilterContext *ctx, AVFrameSideData *sd) { enum AVMatrixEncoding enc; - av_log(ctx, AV_LOG_INFO, "matrix encoding: "); + write_info(ctx, "matrix encoding: "); if (sd->size < sizeof(enum AVMatrixEncoding)) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + write_info(ctx, "invalid data"); return; } enc = *(enum AVMatrixEncoding *)sd->data; switch (enc) { - case AV_MATRIX_ENCODING_NONE: av_log(ctx, AV_LOG_INFO, "none"); break; - case AV_MATRIX_ENCODING_DOLBY: av_log(ctx, AV_LOG_INFO, "Dolby Surround"); break; - case AV_MATRIX_ENCODING_DPLII: av_log(ctx, AV_LOG_INFO, "Dolby Pro Logic II"); break; - case AV_MATRIX_ENCODING_DPLIIX: av_log(ctx, AV_LOG_INFO, "Dolby Pro Logic IIx"); break; - case AV_MATRIX_ENCODING_DPLIIZ: av_log(ctx, AV_LOG_INFO, "Dolby Pro Logic IIz"); break; - case AV_MATRIX_ENCODING_DOLBYEX: av_log(ctx, AV_LOG_INFO, "Dolby EX"); break; - case AV_MATRIX_ENCODING_DOLBYHEADPHONE: av_log(ctx, AV_LOG_INFO, "Dolby Headphone"); break; - default: av_log(ctx, AV_LOG_WARNING, "unknown"); break; + case AV_MATRIX_ENCODING_NONE: write_info(ctx, "none"); break; + case AV_MATRIX_ENCODING_DOLBY: write_info(ctx, "Dolby Surround"); break; + case AV_MATRIX_ENCODING_DPLII: write_info(ctx, "Dolby Pro Logic II"); break; + case AV_MATRIX_ENCODING_DPLIIX: write_info(ctx, "Dolby Pro Logic IIx"); break; + case AV_MATRIX_ENCODING_DPLIIZ: write_info(ctx, "Dolby Pro Logic IIz"); break; + case AV_MATRIX_ENCODING_DOLBYEX: write_info(ctx, "Dolby EX"); break; + case AV_MATRIX_ENCODING_DOLBYHEADPHONE: write_info(ctx, "Dolby Headphone"); break; + default: write_info(ctx, "unknown"); break; } } @@ -82,23 +140,23 @@ static void dump_downmix(AVFilterContext *ctx, AVFrameSideData *sd) { AVDownmixInfo *di; - av_log(ctx, AV_LOG_INFO, "downmix: "); + write_info(ctx, "downmix: "); if (sd->size < sizeof(*di)) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + write_info(ctx, "invalid data"); return; } di = (AVDownmixInfo *)sd->data; - av_log(ctx, AV_LOG_INFO, "preferred downmix type - "); + write_info(ctx, "preferred downmix type - "); switch (di->preferred_downmix_type) { - case AV_DOWNMIX_TYPE_LORO: av_log(ctx, AV_LOG_INFO, "Lo/Ro"); break; - case AV_DOWNMIX_TYPE_LTRT: av_log(ctx, AV_LOG_INFO, "Lt/Rt"); break; - case AV_DOWNMIX_TYPE_DPLII: av_log(ctx, AV_LOG_INFO, "Dolby Pro Logic II"); break; - default: av_log(ctx, AV_LOG_WARNING, "unknown"); break; + case AV_DOWNMIX_TYPE_LORO: write_info(ctx, "Lo/Ro"); break; + case AV_DOWNMIX_TYPE_LTRT: write_info(ctx, "Lt/Rt"); break; + case AV_DOWNMIX_TYPE_DPLII: write_info(ctx, "Dolby Pro Logic II"); break; + default: write_info(ctx, "unknown"); break; } - av_log(ctx, AV_LOG_INFO, " Mix levels: center %f (%f ltrt) - " + write_info(ctx, " Mix levels: center %f (%f ltrt) - " "surround %f (%f ltrt) - lfe %f", di->center_mix_level, di->center_mix_level_ltrt, di->surround_mix_level, di->surround_mix_level_ltrt, @@ -117,57 +175,57 @@ static void dump_downmix_matrix(AVFilterContext *ctx, AVFrameSideData *sd, AVCha AVDownmixMatrix *dm = (AVDownmixMatrix *)sd->data; char buf[128]; - av_log(ctx, AV_LOG_INFO, "downmix matrix: "); + write_info(ctx, "downmix matrix: "); if (dm->in_ch_count != ch_layout->nb_channels) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + write_info(ctx, "invalid data"); return; } - av_log(ctx, AV_LOG_INFO, "downmix type - "); + write_info(ctx, "downmix type - "); switch (dm->downmix_type) { - case AV_DOWNMIX_TYPE_LORO: av_log(ctx, AV_LOG_INFO, "Lo/Ro\n"); break; - case AV_DOWNMIX_TYPE_LTRT: av_log(ctx, AV_LOG_INFO, "Lt/Rt\n"); break; - case AV_DOWNMIX_TYPE_DPLII: av_log(ctx, AV_LOG_INFO, "Dolby Pro Logic II\n"); break; - default: av_log(ctx, AV_LOG_WARNING, "invalid data"); return; + case AV_DOWNMIX_TYPE_LORO: write_info(ctx, "Lo/Ro\n"); break; + case AV_DOWNMIX_TYPE_LTRT: write_info(ctx, "Lt/Rt\n"); break; + case AV_DOWNMIX_TYPE_DPLII: write_info(ctx, "Dolby Pro Logic II\n"); break; + default: write_info(ctx, "invalid data"); return; } for (int i = 0; i < downmix_type_map[dm->downmix_type]; i++) { - av_log(ctx, AV_LOG_INFO, "[%s] = { ", i ? "FR" : "FL"); + write_info(ctx, "[%s] = { ", i ? "FR" : "FL"); for (int j = 0; j < dm->in_ch_count; j++) { av_channel_name(buf, sizeof(buf), av_channel_layout_channel_from_index(ch_layout, j)); - av_log(ctx, AV_LOG_INFO, ".%s = %f, ", buf, *av_downmix_matrix_coeff(dm, i, j)); + write_info(ctx, ".%s = %f, ", buf, *av_downmix_matrix_coeff(dm, i, j)); } - av_log(ctx, AV_LOG_INFO, "}%s", i == downmix_type_map[dm->downmix_type] - 1 ? "" : ",\n"); + write_info(ctx, "}%s", i == downmix_type_map[dm->downmix_type] - 1 ? "" : ",\n"); } } static void print_gain(AVFilterContext *ctx, const char *str, int32_t gain) { - av_log(ctx, AV_LOG_INFO, "%s - ", str); + write_info(ctx, "%s - ", str); if (gain == INT32_MIN) - av_log(ctx, AV_LOG_INFO, "unknown"); + write_info(ctx, "unknown"); else - av_log(ctx, AV_LOG_INFO, "%f", gain / 100000.0f); - av_log(ctx, AV_LOG_INFO, ", "); + write_info(ctx, "%f", gain / 100000.0f); + write_info(ctx, ", "); } static void print_peak(AVFilterContext *ctx, const char *str, uint32_t peak) { - av_log(ctx, AV_LOG_INFO, "%s - ", str); + write_info(ctx, "%s - ", str); if (!peak) - av_log(ctx, AV_LOG_INFO, "unknown"); + write_info(ctx, "unknown"); else - av_log(ctx, AV_LOG_INFO, "%f", peak / 100000.0f); - av_log(ctx, AV_LOG_INFO, ", "); + write_info(ctx, "%f", peak / 100000.0f); + write_info(ctx, ", "); } static void dump_replaygain(AVFilterContext *ctx, AVFrameSideData *sd) { AVReplayGain *rg; - av_log(ctx, AV_LOG_INFO, "replaygain: "); + write_info(ctx, "replaygain: "); if (sd->size < sizeof(*rg)) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + write_info(ctx, "invalid data"); return; } rg = (AVReplayGain*)sd->data; @@ -182,23 +240,23 @@ static void dump_audio_service_type(AVFilterContext *ctx, AVFrameSideData *sd) { enum AVAudioServiceType *ast; - av_log(ctx, AV_LOG_INFO, "audio service type: "); + write_info(ctx, "audio service type: "); if (sd->size < sizeof(*ast)) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + write_info(ctx, "invalid data"); return; } ast = (enum AVAudioServiceType*)sd->data; switch (*ast) { - case AV_AUDIO_SERVICE_TYPE_MAIN: av_log(ctx, AV_LOG_INFO, "Main Audio Service"); break; - case AV_AUDIO_SERVICE_TYPE_EFFECTS: av_log(ctx, AV_LOG_INFO, "Effects"); break; - case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED: av_log(ctx, AV_LOG_INFO, "Visually Impaired"); break; - case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED: av_log(ctx, AV_LOG_INFO, "Hearing Impaired"); break; - case AV_AUDIO_SERVICE_TYPE_DIALOGUE: av_log(ctx, AV_LOG_INFO, "Dialogue"); break; - case AV_AUDIO_SERVICE_TYPE_COMMENTARY: av_log(ctx, AV_LOG_INFO, "Commentary"); break; - case AV_AUDIO_SERVICE_TYPE_EMERGENCY: av_log(ctx, AV_LOG_INFO, "Emergency"); break; - case AV_AUDIO_SERVICE_TYPE_VOICE_OVER: av_log(ctx, AV_LOG_INFO, "Voice Over"); break; - case AV_AUDIO_SERVICE_TYPE_KARAOKE: av_log(ctx, AV_LOG_INFO, "Karaoke"); break; - default: av_log(ctx, AV_LOG_INFO, "unknown"); break; + case AV_AUDIO_SERVICE_TYPE_MAIN: write_info(ctx, "Main Audio Service"); break; + case AV_AUDIO_SERVICE_TYPE_EFFECTS: write_info(ctx, "Effects"); break; + case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED: write_info(ctx, "Visually Impaired"); break; + case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED: write_info(ctx, "Hearing Impaired"); break; + case AV_AUDIO_SERVICE_TYPE_DIALOGUE: write_info(ctx, "Dialogue"); break; + case AV_AUDIO_SERVICE_TYPE_COMMENTARY: write_info(ctx, "Commentary"); break; + case AV_AUDIO_SERVICE_TYPE_EMERGENCY: write_info(ctx, "Emergency"); break; + case AV_AUDIO_SERVICE_TYPE_VOICE_OVER: write_info(ctx, "Voice Over"); break; + case AV_AUDIO_SERVICE_TYPE_KARAOKE: write_info(ctx, "Karaoke"); break; + default: write_info(ctx, "unknown"); break; } } @@ -208,21 +266,21 @@ static void dump_iamf_parameter_definition(AVFilterContext *ctx, const AVFrameSi switch (param->type) { case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: - av_log(ctx, AV_LOG_INFO, "iamf mix gain parameters: "); + write_info(ctx, "iamf mix gain parameters: "); break; case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: - av_log(ctx, AV_LOG_INFO, "iamf demixing parameters: "); + write_info(ctx, "iamf demixing parameters: "); break; case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: - av_log(ctx, AV_LOG_INFO, "iamf recon gain parameters: "); + write_info(ctx, "iamf recon gain parameters: "); break; default: - av_log(ctx, AV_LOG_ERROR, "unknown iamf parameter definition type: %d", + write_info(ctx, "unknown iamf parameter definition type: %d", param->type); return; } - av_log(ctx, AV_LOG_INFO, + write_info(ctx, "nb_subblocks=%d, " "parameter_id=%d, " "parameter_rate=%d, " @@ -238,11 +296,11 @@ static void dump_iamf_parameter_definition(AVFilterContext *ctx, const AVFrameSi for (unsigned i = 0; i < param->nb_subblocks; i++) { const void *subblock = av_iamf_param_definition_get_subblock(param, i); - av_log(ctx, AV_LOG_INFO, " subblock[%d]={ ", i); + write_info(ctx, " subblock[%d]={ ", i); switch (param->type) { case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: { const AVIAMFMixGain *mix = subblock; - av_log(ctx, AV_LOG_INFO, + write_info(ctx, "subblock_duration=%d, " "animation_type=%d, " "start_point_value=%d/%d, " @@ -260,7 +318,7 @@ static void dump_iamf_parameter_definition(AVFilterContext *ctx, const AVFrameSi } case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: { const AVIAMFDemixingInfo *demix = subblock; - av_log(ctx, AV_LOG_INFO, + write_info(ctx, "subblock_duration=%d, " "dmixp_mode=%d", demix->subblock_duration, @@ -270,20 +328,20 @@ static void dump_iamf_parameter_definition(AVFilterContext *ctx, const AVFrameSi } case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: { const AVIAMFReconGain *recon = subblock; - av_log(ctx, AV_LOG_INFO, + write_info(ctx, "subblock_duration=%d", recon->subblock_duration ); break; } } - av_log(ctx, AV_LOG_INFO, (i == param->nb_subblocks - 1) ? " }" : " },"); + write_info(ctx, (i == param->nb_subblocks - 1) ? " }" : " },"); } } static void dump_unknown(AVFilterContext *ctx, AVFrameSideData *sd) { - av_log(ctx, AV_LOG_INFO, "unknown side data type: %d, size " + write_info(ctx, "unknown side data type: %d, size " "%zu bytes", sd->type, sd->size); } @@ -316,7 +374,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) av_channel_layout_describe(&buf->ch_layout, chlayout_str, sizeof(chlayout_str)); - av_log(ctx, AV_LOG_INFO, + write_info(ctx, "n:%"PRId64" pts:%s pts_time:%s " "fmt:%s channels:%d chlayout:%s rate:%d nb_samples:%d " "checksum:%08"PRIX32" ", @@ -326,15 +384,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) buf->sample_rate, buf->nb_samples, checksum); - av_log(ctx, AV_LOG_INFO, "plane_checksums: [ "); + write_info(ctx, "plane_checksums: [ "); for (i = 0; i < planes; i++) - av_log(ctx, AV_LOG_INFO, "%08"PRIX32" ", s->plane_checksums[i]); - av_log(ctx, AV_LOG_INFO, "]\n"); + write_info(ctx, "%08"PRIX32" ", s->plane_checksums[i]); + write_info(ctx, "]\n"); for (i = 0; i < buf->nb_side_data; i++) { AVFrameSideData *sd = buf->side_data[i]; - av_log(ctx, AV_LOG_INFO, " side data - "); + write_info(ctx, " side data - "); switch (sd->type) { case AV_FRAME_DATA_MATRIXENCODING: dump_matrixenc (ctx, sd); break; case AV_FRAME_DATA_DOWNMIX_INFO: dump_downmix (ctx, sd); break; @@ -349,7 +407,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) default: dump_unknown (ctx, sd); break; } - av_log(ctx, AV_LOG_INFO, "\n"); + write_info(ctx, "\n"); + } + + if (s->avio_context) { + avio_flush(s->avio_context); + if (s->avio_context->error < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to write to %s: %s\n", + s->file_str, av_err2str(s->avio_context->error)); + } } return ff_filter_frame(inlink->dst->outputs[0], buf); @@ -366,8 +432,10 @@ static const AVFilterPad inputs[] = { const FFFilter ff_af_ashowinfo = { .p.name = "ashowinfo", .p.description = NULL_IF_CONFIG_SMALL("Show textual information for each audio frame."), + .p.priv_class = &ashowinfo_class, .p.flags = AVFILTER_FLAG_METADATA_ONLY, .priv_size = sizeof(AShowInfoContext), + .init = init, .uninit = uninit, FILTER_INPUTS(inputs), FILTER_OUTPUTS(ff_audio_default_filterpad), diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index 4ac3d45dc0..0c6d855873 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -46,6 +46,7 @@ #include "libavutil/detection_bbox.h" #include "libavutil/ambient_viewing_environment.h" #include "libavutil/uuid.h" +#include "libavformat/avio.h" #include "avfilter.h" #include "filters.h" @@ -55,6 +56,8 @@ typedef struct ShowInfoContext { const AVClass *class; int calculate_checksums; int udu_sei_as_ascii; + char* file_str; + AVIOContext* avio_context; } ShowInfoContext; #define OFFSET(x) offsetof(ShowInfoContext, x) @@ -64,33 +67,47 @@ static const AVOption showinfo_options[] = { { "checksum", "calculate checksums", OFFSET(calculate_checksums), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, VF }, { "udu_sei_as_ascii", "try to print user data unregistered SEI as ascii character when possible", OFFSET(udu_sei_as_ascii), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VF }, + { "file", "Dump information to file instead of writing to log", + OFFSET(file_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VF }, { NULL } }; AVFILTER_DEFINE_CLASS(showinfo); +static void write_info(AVFilterContext *ctx, const char *fmt, ...) { + ShowInfoContext *s = ctx->priv; + va_list vl; + va_start(vl, fmt); + if (s->avio_context != NULL) { + avio_vprintf(s->avio_context, fmt, vl); + } else { + av_vlog(ctx, AV_LOG_INFO, fmt, vl); + } + va_end(vl); +} + static void dump_spherical(AVFilterContext *ctx, AVFrame *frame, const AVFrameSideData *sd) { const AVSphericalMapping *spherical = (const AVSphericalMapping *)sd->data; double yaw, pitch, roll; - av_log(ctx, AV_LOG_INFO, "%s ", av_spherical_projection_name(spherical->projection)); + write_info(ctx, "%s ", av_spherical_projection_name(spherical->projection)); if (spherical->yaw || spherical->pitch || spherical->roll) { yaw = ((double)spherical->yaw) / (1 << 16); pitch = ((double)spherical->pitch) / (1 << 16); roll = ((double)spherical->roll) / (1 << 16); - av_log(ctx, AV_LOG_INFO, "(%f/%f/%f) ", yaw, pitch, roll); + write_info(ctx, "(%f/%f/%f) ", yaw, pitch, roll); } if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) { size_t l, t, r, b; av_spherical_tile_bounds(spherical, frame->width, frame->height, &l, &t, &r, &b); - av_log(ctx, AV_LOG_INFO, "[%zu, %zu, %zu, %zu] ", + write_info(ctx, "[%zu, %zu, %zu, %zu] ", l, t, r, b); } else if (spherical->projection == AV_SPHERICAL_CUBEMAP) { - av_log(ctx, AV_LOG_INFO, "[pad %"PRIu32"] ", spherical->padding); + write_info(ctx, "[pad %"PRIu32"] ", spherical->padding); } } @@ -98,20 +115,20 @@ static void dump_stereo3d(AVFilterContext *ctx, const AVFrameSideData *sd) { const AVStereo3D *stereo = (const AVStereo3D *)sd->data; - av_log(ctx, AV_LOG_INFO, "type - %s", av_stereo3d_type_name(stereo->type)); + write_info(ctx, "type - %s", av_stereo3d_type_name(stereo->type)); if (stereo->flags & AV_STEREO3D_FLAG_INVERT) - av_log(ctx, AV_LOG_INFO, " (inverted)"); + write_info(ctx, " (inverted)"); - av_log(ctx, AV_LOG_INFO, ", view - %s, primary_eye - %s", av_stereo3d_view_name(stereo->view), + write_info(ctx, ", view - %s, primary_eye - %s", av_stereo3d_view_name(stereo->view), av_stereo3d_primary_eye_name(stereo->primary_eye)); if (stereo->baseline) - av_log(ctx, AV_LOG_INFO, ", baseline: %"PRIu32"", stereo->baseline); + write_info(ctx, ", baseline: %"PRIu32"", stereo->baseline); if (stereo->horizontal_disparity_adjustment.num && stereo->horizontal_disparity_adjustment.den) - av_log(ctx, AV_LOG_INFO, ", horizontal_disparity_adjustment: %0.4f", + write_info(ctx, ", horizontal_disparity_adjustment: %0.4f", av_q2d(stereo->horizontal_disparity_adjustment)); if (stereo->horizontal_field_of_view.num && stereo->horizontal_field_of_view.den) - av_log(ctx, AV_LOG_INFO, ", horizontal_field_of_view: %0.3f", av_q2d(stereo->horizontal_field_of_view)); + write_info(ctx, ", horizontal_field_of_view: %0.3f", av_q2d(stereo->horizontal_field_of_view)); } static void dump_s12m_timecode(AVFilterContext *ctx, AVFilterLink *inlink, const AVFrameSideData *sd) @@ -120,14 +137,14 @@ static void dump_s12m_timecode(AVFilterContext *ctx, AVFilterLink *inlink, const const uint32_t *tc = (const uint32_t *)sd->data; if ((sd->size != sizeof(uint32_t) * 4) || (tc[0] > 3)) { - av_log(ctx, AV_LOG_ERROR, "invalid data\n"); + write_info(ctx, "invalid data\n"); return; } for (int j = 1; j <= tc[0]; j++) { char tcbuf[AV_TIMECODE_STR_SIZE]; av_timecode_make_smpte_tc_string2(tcbuf, l->frame_rate, tc[j], 0, 0); - av_log(ctx, AV_LOG_INFO, "timecode - %s%s", tcbuf, j != tc[0] ? ", " : ""); + write_info(ctx, "timecode - %s%s", tcbuf, j != tc[0] ? ", " : ""); } } @@ -140,14 +157,14 @@ static void dump_roi(AVFilterContext *ctx, const AVFrameSideData *sd) roi = (const AVRegionOfInterest *)sd->data; roi_size = roi->self_size; if (!roi_size || sd->size % roi_size != 0) { - av_log(ctx, AV_LOG_ERROR, "Invalid AVRegionOfInterest.self_size.\n"); + write_info(ctx, "Invalid AVRegionOfInterest.self_size.\n"); return; } nb_rois = sd->size / roi_size; for (int i = 0; i < nb_rois; i++) { roi = (const AVRegionOfInterest *)(sd->data + roi_size * i); - av_log(ctx, AV_LOG_INFO, "index: %d, region: (%d, %d) -> (%d, %d), qp offset: %d/%d.\n", + write_info(ctx, "index: %d, region: (%d, %d) -> (%d, %d), qp offset: %d/%d.\n", i, roi->left, roi->top, roi->right, roi->bottom, roi->qoffset.num, roi->qoffset.den); } } @@ -157,7 +174,7 @@ static void dump_tdrdi(AVFilterContext *ctx, const AVFrameSideData *sd) const AV3DReferenceDisplaysInfo *tdrdi = (const AV3DReferenceDisplaysInfo *)sd->data; - av_log(ctx, AV_LOG_INFO, "number of reference displays: %u", tdrdi->num_ref_displays); + write_info(ctx, "number of reference displays: %u", tdrdi->num_ref_displays); } static void dump_detection_bbox(AVFilterContext *ctx, const AVFrameSideData *sd) @@ -168,16 +185,16 @@ static void dump_detection_bbox(AVFilterContext *ctx, const AVFrameSideData *sd) header = (const AVDetectionBBoxHeader *)sd->data; nb_bboxes = header->nb_bboxes; - av_log(ctx, AV_LOG_INFO, "source: %s\n", header->source); + write_info(ctx, "source: %s\n", header->source); for (int i = 0; i < nb_bboxes; i++) { bbox = av_get_detection_bbox(header, i); - av_log(ctx, AV_LOG_INFO, "index: %d,\tregion: (%d, %d) -> (%d, %d), label: %s, confidence: %d/%d.\n", + write_info(ctx, "index: %d,\tregion: (%d, %d) -> (%d, %d), label: %s, confidence: %d/%d.\n", i, bbox->x, bbox->y, bbox->x + bbox->w, bbox->y + bbox->h, bbox->detect_label, bbox->detect_confidence.num, bbox->detect_confidence.den); if (bbox->classify_count > 0) { for (int j = 0; j < bbox->classify_count; j++) { - av_log(ctx, AV_LOG_INFO, "\t\tclassify: label: %s, confidence: %d/%d.\n", + write_info(ctx, "\t\tclassify: label: %s, confidence: %d/%d.\n", bbox->classify_labels[j], bbox->classify_confidences[j].num, bbox->classify_confidences[j].den); } } @@ -189,13 +206,13 @@ static void dump_mastering_display(AVFilterContext *ctx, const AVFrameSideData * const AVMasteringDisplayMetadata *mastering_display; if (sd->size < sizeof(*mastering_display)) { - av_log(ctx, AV_LOG_ERROR, "invalid data\n"); + write_info(ctx, "invalid data\n"); return; } mastering_display = (const AVMasteringDisplayMetadata *)sd->data; - av_log(ctx, AV_LOG_INFO, "has_primaries:%d has_luminance:%d " + write_info(ctx, "has_primaries:%d has_luminance:%d " "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f) " "min_luminance=%f, max_luminance=%f", mastering_display->has_primaries, mastering_display->has_luminance, @@ -214,97 +231,97 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) AVDynamicHDRPlus *hdr_plus; if (sd->size < sizeof(*hdr_plus)) { - av_log(ctx, AV_LOG_ERROR, "invalid data\n"); + write_info(ctx, "invalid data\n"); return; } hdr_plus = (AVDynamicHDRPlus *)sd->data; - av_log(ctx, AV_LOG_INFO, "application version: %d, ", hdr_plus->application_version); - av_log(ctx, AV_LOG_INFO, "num_windows: %d, ", hdr_plus->num_windows); + write_info(ctx, "application version: %d, ", hdr_plus->application_version); + write_info(ctx, "num_windows: %d, ", hdr_plus->num_windows); for (int w = 1; w < hdr_plus->num_windows; w++) { AVHDRPlusColorTransformParams *params = &hdr_plus->params[w]; - av_log(ctx, AV_LOG_INFO, w > 1 ? ", window %d { " : "window %d { ", w); - av_log(ctx, AV_LOG_INFO, "window_upper_left_corner: (%5.4f,%5.4f),", + write_info(ctx, w > 1 ? ", window %d { " : "window %d { ", w); + write_info(ctx, "window_upper_left_corner: (%5.4f,%5.4f),", av_q2d(params->window_upper_left_corner_x), av_q2d(params->window_upper_left_corner_y)); - av_log(ctx, AV_LOG_INFO, "window_lower_right_corner: (%5.4f,%5.4f), ", + write_info(ctx, "window_lower_right_corner: (%5.4f,%5.4f), ", av_q2d(params->window_lower_right_corner_x), av_q2d(params->window_lower_right_corner_y)); - av_log(ctx, AV_LOG_INFO, "window_upper_left_corner: (%5.4f, %5.4f), ", + write_info(ctx, "window_upper_left_corner: (%5.4f, %5.4f), ", av_q2d(params->window_upper_left_corner_x), av_q2d(params->window_upper_left_corner_y)); - av_log(ctx, AV_LOG_INFO, "center_of_ellipse_x: (%d,%d), ", + write_info(ctx, "center_of_ellipse_x: (%d,%d), ", params->center_of_ellipse_x, params->center_of_ellipse_y); - av_log(ctx, AV_LOG_INFO, "rotation_angle: %d, ", + write_info(ctx, "rotation_angle: %d, ", params->rotation_angle); - av_log(ctx, AV_LOG_INFO, "semimajor_axis_internal_ellipse: %d, ", + write_info(ctx, "semimajor_axis_internal_ellipse: %d, ", params->semimajor_axis_internal_ellipse); - av_log(ctx, AV_LOG_INFO, "semimajor_axis_external_ellipse: %d, ", + write_info(ctx, "semimajor_axis_external_ellipse: %d, ", params->semimajor_axis_external_ellipse); - av_log(ctx, AV_LOG_INFO, "semiminor_axis_external_ellipse: %d, ", + write_info(ctx, "semiminor_axis_external_ellipse: %d, ", params->semiminor_axis_external_ellipse); - av_log(ctx, AV_LOG_INFO, "overlap_process_option: %d}", + write_info(ctx, "overlap_process_option: %d}", params->overlap_process_option); } - av_log(ctx, AV_LOG_INFO, "targeted_system_display_maximum_luminance: %9.4f, ", + write_info(ctx, "targeted_system_display_maximum_luminance: %9.4f, ", av_q2d(hdr_plus->targeted_system_display_maximum_luminance)); if (hdr_plus->targeted_system_display_actual_peak_luminance_flag) { - av_log(ctx, AV_LOG_INFO, "targeted_system_display_actual_peak_luminance: {"); + write_info(ctx, "targeted_system_display_actual_peak_luminance: {"); for (int i = 0; i < hdr_plus->num_rows_targeted_system_display_actual_peak_luminance; i++) { - av_log(ctx, AV_LOG_INFO, "("); + write_info(ctx, "("); for (int j = 0; j < hdr_plus->num_cols_targeted_system_display_actual_peak_luminance; j++) { - av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f", + write_info(ctx, i ? ",%5.4f" : "%5.4f", av_q2d(hdr_plus->targeted_system_display_actual_peak_luminance[i][j])); } - av_log(ctx, AV_LOG_INFO, ")"); + write_info(ctx, ")"); } - av_log(ctx, AV_LOG_INFO, "}, "); + write_info(ctx, "}, "); } for (int w = 0; w < hdr_plus->num_windows; w++) { AVHDRPlusColorTransformParams *params = &hdr_plus->params[w]; - av_log(ctx, AV_LOG_INFO, "window %d {maxscl: {", w); + write_info(ctx, "window %d {maxscl: {", w); for (int i = 0; i < 3; i++) { - av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f",av_q2d(params->maxscl[i])); + write_info(ctx, i ? ",%5.4f" : "%5.4f",av_q2d(params->maxscl[i])); } - av_log(ctx, AV_LOG_INFO, "}, average_maxrgb: %5.4f, ", + write_info(ctx, "}, average_maxrgb: %5.4f, ", av_q2d(params->average_maxrgb)); - av_log(ctx, AV_LOG_INFO, "distribution_maxrgb: {"); + write_info(ctx, "distribution_maxrgb: {"); for (int i = 0; i < params->num_distribution_maxrgb_percentiles; i++) { - av_log(ctx, AV_LOG_INFO, "(%d,%5.4f)", + write_info(ctx, "(%d,%5.4f)", params->distribution_maxrgb[i].percentage, av_q2d(params->distribution_maxrgb[i].percentile)); } - av_log(ctx, AV_LOG_INFO, "}, fraction_bright_pixels: %5.4f", + write_info(ctx, "}, fraction_bright_pixels: %5.4f", av_q2d(params->fraction_bright_pixels)); if (params->tone_mapping_flag) { - av_log(ctx, AV_LOG_INFO, ", knee_point: (%5.4f,%5.4f), ", av_q2d(params->knee_point_x), av_q2d(params->knee_point_y)); - av_log(ctx, AV_LOG_INFO, "bezier_curve_anchors: {"); + write_info(ctx, ", knee_point: (%5.4f,%5.4f), ", av_q2d(params->knee_point_x), av_q2d(params->knee_point_y)); + write_info(ctx, "bezier_curve_anchors: {"); for (int i = 0; i < params->num_bezier_curve_anchors; i++) { - av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f", + write_info(ctx, i ? ",%5.4f" : "%5.4f", av_q2d(params->bezier_curve_anchors[i])); } - av_log(ctx, AV_LOG_INFO, "}"); + write_info(ctx, "}"); } if (params->color_saturation_mapping_flag) { - av_log(ctx, AV_LOG_INFO, ", color_saturation_weight: %5.4f", + write_info(ctx, ", color_saturation_weight: %5.4f", av_q2d(params->color_saturation_weight)); } - av_log(ctx, AV_LOG_INFO, "}"); + write_info(ctx, "}"); } if (hdr_plus->mastering_display_actual_peak_luminance_flag) { - av_log(ctx, AV_LOG_INFO, ", mastering_display_actual_peak_luminance: {"); + write_info(ctx, ", mastering_display_actual_peak_luminance: {"); for (int i = 0; i < hdr_plus->num_rows_mastering_display_actual_peak_luminance; i++) { - av_log(ctx, AV_LOG_INFO, "("); + write_info(ctx, "("); for (int j = 0; j < hdr_plus->num_cols_mastering_display_actual_peak_luminance; j++) { - av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f", + write_info(ctx, i ? ",%5.4f" : "%5.4f", av_q2d(hdr_plus->mastering_display_actual_peak_luminance[i][j])); } - av_log(ctx, AV_LOG_INFO, ")"); + write_info(ctx, ")"); } - av_log(ctx, AV_LOG_INFO, "}"); + write_info(ctx, "}"); } } @@ -313,77 +330,77 @@ static void dump_dynamic_hdr_vivid(AVFilterContext *ctx, AVFrameSideData *sd) AVDynamicHDRVivid *hdr_vivid; if (sd->size < sizeof(*hdr_vivid)) { - av_log(ctx, AV_LOG_ERROR, "invalid hdr vivid data\n"); + write_info(ctx, "invalid hdr vivid data\n"); return; } hdr_vivid = (AVDynamicHDRVivid *)sd->data; - av_log(ctx, AV_LOG_INFO, "system_start_code: %d, ", hdr_vivid->system_start_code); - av_log(ctx, AV_LOG_INFO, "num_windows: %d, ", hdr_vivid->num_windows); + write_info(ctx, "system_start_code: %d, ", hdr_vivid->system_start_code); + write_info(ctx, "num_windows: %d, ", hdr_vivid->num_windows); for (int w = 0; w < hdr_vivid->num_windows; w++) { const AVHDRVividColorTransformParams *params = &hdr_vivid->params[w]; - av_log(ctx, AV_LOG_INFO, "minimum_maxrgb[%d]: %.4f, ", w, av_q2d(params->minimum_maxrgb)); - av_log(ctx, AV_LOG_INFO, "average_maxrgb[%d]: %.4f, ", w, av_q2d(params->average_maxrgb)); - av_log(ctx, AV_LOG_INFO, "variance_maxrgb[%d]:%.4f, ", w, av_q2d(params->variance_maxrgb)); - av_log(ctx, AV_LOG_INFO, "maximum_maxrgb[%d]: %.4f, ", w, av_q2d(params->maximum_maxrgb)); + write_info(ctx, "minimum_maxrgb[%d]: %.4f, ", w, av_q2d(params->minimum_maxrgb)); + write_info(ctx, "average_maxrgb[%d]: %.4f, ", w, av_q2d(params->average_maxrgb)); + write_info(ctx, "variance_maxrgb[%d]:%.4f, ", w, av_q2d(params->variance_maxrgb)); + write_info(ctx, "maximum_maxrgb[%d]: %.4f, ", w, av_q2d(params->maximum_maxrgb)); } for (int w = 0; w < hdr_vivid->num_windows; w++) { const AVHDRVividColorTransformParams *params = &hdr_vivid->params[w]; - av_log(ctx, AV_LOG_INFO, "tone_mapping_mode_flag[%d]: %d, ", w, params->tone_mapping_mode_flag); - av_log(ctx, AV_LOG_INFO, "tone_mapping_param_num[%d]: %d, ", w, params->tone_mapping_param_num); + write_info(ctx, "tone_mapping_mode_flag[%d]: %d, ", w, params->tone_mapping_mode_flag); + write_info(ctx, "tone_mapping_param_num[%d]: %d, ", w, params->tone_mapping_param_num); if (params->tone_mapping_mode_flag) { for (int i = 0; i < params->tone_mapping_param_num; i++) { const AVHDRVividColorToneMappingParams *tm_params = ¶ms->tm_params[i]; - av_log(ctx, AV_LOG_INFO, "targeted_system_display_maximum_luminance[%d][%d]: %.4f, ", + write_info(ctx, "targeted_system_display_maximum_luminance[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->targeted_system_display_maximum_luminance)); - av_log(ctx, AV_LOG_INFO, "base_enable_flag[%d][%d]: %d, ", + write_info(ctx, "base_enable_flag[%d][%d]: %d, ", w, i, tm_params->base_enable_flag); if (tm_params->base_enable_flag) { - av_log(ctx, AV_LOG_INFO, "base_param_m_p[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_p)); - av_log(ctx, AV_LOG_INFO, "base_param_m_m[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_m)); - av_log(ctx, AV_LOG_INFO, "base_param_m_a[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_a)); - av_log(ctx, AV_LOG_INFO, "base_param_m_b[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_b)); - av_log(ctx, AV_LOG_INFO, "base_param_m_n[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_n)); - av_log(ctx, AV_LOG_INFO, "base_param_k1[%d][%d]: %d, ", w, i, tm_params->base_param_k1); - av_log(ctx, AV_LOG_INFO, "base_param_k2[%d][%d]: %d, ", w, i, tm_params->base_param_k2); - av_log(ctx, AV_LOG_INFO, "base_param_k3[%d][%d]: %d, ", w, i, tm_params->base_param_k3); - av_log(ctx, AV_LOG_INFO, "base_param_Delta_enable_mode[%d][%d]: %d, ", w, i, + write_info(ctx, "base_param_m_p[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_p)); + write_info(ctx, "base_param_m_m[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_m)); + write_info(ctx, "base_param_m_a[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_a)); + write_info(ctx, "base_param_m_b[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_b)); + write_info(ctx, "base_param_m_n[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_n)); + write_info(ctx, "base_param_k1[%d][%d]: %d, ", w, i, tm_params->base_param_k1); + write_info(ctx, "base_param_k2[%d][%d]: %d, ", w, i, tm_params->base_param_k2); + write_info(ctx, "base_param_k3[%d][%d]: %d, ", w, i, tm_params->base_param_k3); + write_info(ctx, "base_param_Delta_enable_mode[%d][%d]: %d, ", w, i, tm_params->base_param_Delta_enable_mode); - av_log(ctx, AV_LOG_INFO, "base_param_Delta[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_Delta)); + write_info(ctx, "base_param_Delta[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_Delta)); } - av_log(ctx, AV_LOG_INFO, "3Spline_enable_flag[%d][%d]: %d, ", + write_info(ctx, "3Spline_enable_flag[%d][%d]: %d, ", w, i, tm_params->three_Spline_enable_flag); if (tm_params->three_Spline_enable_flag) { for (int j = 0; j < tm_params->three_Spline_num; j++) { const AVHDRVivid3SplineParams *three_spline = &tm_params->three_spline[j]; - av_log(ctx, AV_LOG_INFO, "3Spline_TH_mode[%d][%d]: %d, ", w, i, three_spline->th_mode); + write_info(ctx, "3Spline_TH_mode[%d][%d]: %d, ", w, i, three_spline->th_mode); if (three_spline->th_mode == 0 || three_spline->th_mode == 2) - av_log(ctx, AV_LOG_INFO, "3Spline_TH_enable_MB[%d][%d][%d]: %.4f, ", + write_info(ctx, "3Spline_TH_enable_MB[%d][%d][%d]: %.4f, ", w, i, j, av_q2d(three_spline->th_enable_mb)); - av_log(ctx, AV_LOG_INFO, "3Spline_TH_enable[%d][%d][%d]: %.4f, ", + write_info(ctx, "3Spline_TH_enable[%d][%d][%d]: %.4f, ", w, i, j, av_q2d(three_spline->th_enable)); - av_log(ctx, AV_LOG_INFO, "3Spline_TH_Delta1[%d][%d][%d]: %.4f, ", + write_info(ctx, "3Spline_TH_Delta1[%d][%d][%d]: %.4f, ", w, i, j, av_q2d(three_spline->th_delta1)); - av_log(ctx, AV_LOG_INFO, "3Spline_TH_Delta2[%d][%d][%d]: %.4f, ", + write_info(ctx, "3Spline_TH_Delta2[%d][%d][%d]: %.4f, ", w, i, j, av_q2d(three_spline->th_delta2)); - av_log(ctx, AV_LOG_INFO, "3Spline_enable_Strength[%d][%d][%d]: %.4f, ", + write_info(ctx, "3Spline_enable_Strength[%d][%d][%d]: %.4f, ", w, i, j, av_q2d(three_spline->enable_strength)); } } } } - av_log(ctx, AV_LOG_INFO, "color_saturation_mapping_flag[%d]: %d", + write_info(ctx, "color_saturation_mapping_flag[%d]: %d", w, params->color_saturation_mapping_flag); if (params->color_saturation_mapping_flag) { - av_log(ctx, AV_LOG_INFO, ", color_saturation_num[%d]: %d", + write_info(ctx, ", color_saturation_num[%d]: %d", w, params->color_saturation_num); for (int i = 0; i < params->color_saturation_num; i++) { - av_log(ctx, AV_LOG_INFO, ", color_saturation_gain[%d][%d]: %.4f", + write_info(ctx, ", color_saturation_gain[%d][%d]: %.4f", w, i, av_q2d(params->color_saturation_gain[i])); } } @@ -395,7 +412,7 @@ static void dump_content_light_metadata(AVFilterContext *ctx, AVFrameSideData *s { const AVContentLightMetadata *metadata = (const AVContentLightMetadata *)sd->data; - av_log(ctx, AV_LOG_INFO, + write_info(ctx, "MaxCLL=%d, MaxFALL=%d", metadata->MaxCLL, metadata->MaxFALL); } @@ -405,18 +422,18 @@ static void dump_video_enc_params(AVFilterContext *ctx, const AVFrameSideData *s const AVVideoEncParams *par = (const AVVideoEncParams *)sd->data; int plane, acdc; - av_log(ctx, AV_LOG_INFO, "type %d; ", par->type); + write_info(ctx, "type %d; ", par->type); if (par->qp) - av_log(ctx, AV_LOG_INFO, "qp=%d; ", par->qp); + write_info(ctx, "qp=%d; ", par->qp); for (plane = 0; plane < FF_ARRAY_ELEMS(par->delta_qp); plane++) for (acdc = 0; acdc < FF_ARRAY_ELEMS(par->delta_qp[plane]); acdc++) { int delta_qp = par->delta_qp[plane][acdc]; if (delta_qp) - av_log(ctx, AV_LOG_INFO, "delta_qp[%d][%d]=%d; ", + write_info(ctx, "delta_qp[%d][%d]=%d; ", plane, acdc, delta_qp); } if (par->nb_blocks) - av_log(ctx, AV_LOG_INFO, "%u blocks; ", par->nb_blocks); + write_info(ctx, "%u blocks; ", par->nb_blocks); } static void dump_sei_unregistered_metadata(AVFilterContext *ctx, const AVFrameSideData *sd) @@ -425,22 +442,22 @@ static void dump_sei_unregistered_metadata(AVFilterContext *ctx, const AVFrameSi ShowInfoContext *s = ctx->priv; if (sd->size < AV_UUID_LEN) { - av_log(ctx, AV_LOG_ERROR, "invalid data (%zu < UUID(%d-bytes))\n", + write_info(ctx, "invalid data (%zu < UUID(%d-bytes))\n", sd->size, AV_UUID_LEN); return; } - av_log(ctx, AV_LOG_INFO, "UUID=" AV_PRI_UUID "\n", AV_UUID_ARG(user_data)); + write_info(ctx, "UUID=" AV_PRI_UUID "\n", AV_UUID_ARG(user_data)); - av_log(ctx, AV_LOG_INFO, "User Data="); + write_info(ctx, "User Data="); for (size_t i = 16; i < sd->size; i++) { const char *format = "%02x"; if (s->udu_sei_as_ascii) format = isprint(user_data[i]) ? "%c" : "\\x%02x"; - av_log(ctx, AV_LOG_INFO, format, user_data[i]); + write_info(ctx, format, user_data[i]); } - av_log(ctx, AV_LOG_INFO, "\n"); + write_info(ctx, "\n"); } static void dump_sei_film_grain_params_metadata(AVFilterContext *ctx, const AVFrameSideData *sd) @@ -458,22 +475,22 @@ static void dump_sei_film_grain_params_metadata(AVFilterContext *ctx, const AVFr const char *colorspace_str = av_color_space_name(fgp->color_space); if (fgp->type >= FF_ARRAY_ELEMS(film_grain_type_names)) { - av_log(ctx, AV_LOG_ERROR, "invalid data\n"); + write_info(ctx, "invalid data\n"); return; } - av_log(ctx, AV_LOG_INFO, "type %s; ", film_grain_type_names[fgp->type]); - av_log(ctx, AV_LOG_INFO, "seed=%"PRIu64"; ", fgp->seed); - av_log(ctx, AV_LOG_INFO, "width=%d; ", fgp->width); - av_log(ctx, AV_LOG_INFO, "height=%d; ", fgp->height); - av_log(ctx, AV_LOG_INFO, "subsampling_x=%d; ", fgp->subsampling_x); - av_log(ctx, AV_LOG_INFO, "subsampling_y=%d; ", fgp->subsampling_y); - av_log(ctx, AV_LOG_INFO, "color_range=%s; ", color_range_str ? color_range_str : "unknown"); - av_log(ctx, AV_LOG_INFO, "color_primaries=%s; ", color_primaries_str ? color_primaries_str : "unknown"); - av_log(ctx, AV_LOG_INFO, "color_trc=%s; ", color_trc_str ? color_trc_str : "unknown"); - av_log(ctx, AV_LOG_INFO, "color_space=%s; ", colorspace_str ? colorspace_str : "unknown"); - av_log(ctx, AV_LOG_INFO, "bit_depth_luma=%d; ", fgp->bit_depth_luma); - av_log(ctx, AV_LOG_INFO, "bit_depth_chroma=%d; ", fgp->bit_depth_chroma); + write_info(ctx, "type %s; ", film_grain_type_names[fgp->type]); + write_info(ctx, "seed=%"PRIu64"; ", fgp->seed); + write_info(ctx, "width=%d; ", fgp->width); + write_info(ctx, "height=%d; ", fgp->height); + write_info(ctx, "subsampling_x=%d; ", fgp->subsampling_x); + write_info(ctx, "subsampling_y=%d; ", fgp->subsampling_y); + write_info(ctx, "color_range=%s; ", color_range_str ? color_range_str : "unknown"); + write_info(ctx, "color_primaries=%s; ", color_primaries_str ? color_primaries_str : "unknown"); + write_info(ctx, "color_trc=%s; ", color_trc_str ? color_trc_str : "unknown"); + write_info(ctx, "color_space=%s; ", colorspace_str ? colorspace_str : "unknown"); + write_info(ctx, "bit_depth_luma=%d; ", fgp->bit_depth_luma); + write_info(ctx, "bit_depth_chroma=%d; ", fgp->bit_depth_chroma); switch (fgp->type) { case AV_FILM_GRAIN_PARAMS_NONE: @@ -482,52 +499,52 @@ static void dump_sei_film_grain_params_metadata(AVFilterContext *ctx, const AVFr const AVFilmGrainAOMParams *aom = &fgp->codec.aom; const int num_ar_coeffs_y = 2 * aom->ar_coeff_lag * (aom->ar_coeff_lag + 1); const int num_ar_coeffs_uv = num_ar_coeffs_y + !!aom->num_y_points; - av_log(ctx, AV_LOG_INFO, "y_points={ "); + write_info(ctx, "y_points={ "); for (int i = 0; i < aom->num_y_points; i++) - av_log(ctx, AV_LOG_INFO, "(%d,%d) ", aom->y_points[i][0], aom->y_points[i][1]); - av_log(ctx, AV_LOG_INFO, "}; chroma_scaling_from_luma=%d; ", aom->chroma_scaling_from_luma); + write_info(ctx, "(%d,%d) ", aom->y_points[i][0], aom->y_points[i][1]); + write_info(ctx, "}; chroma_scaling_from_luma=%d; ", aom->chroma_scaling_from_luma); for (int uv = 0; uv < 2; uv++) { - av_log(ctx, AV_LOG_INFO, "uv_points[%d]={ ", uv); + write_info(ctx, "uv_points[%d]={ ", uv); for (int i = 0; i < aom->num_uv_points[uv]; i++) - av_log(ctx, AV_LOG_INFO, "(%d,%d) ", aom->uv_points[uv][i][0], aom->uv_points[uv][i][1]); - av_log(ctx, AV_LOG_INFO, "}; "); + write_info(ctx, "(%d,%d) ", aom->uv_points[uv][i][0], aom->uv_points[uv][i][1]); + write_info(ctx, "}; "); } - av_log(ctx, AV_LOG_INFO, "scaling_shift=%d; ", aom->scaling_shift); - av_log(ctx, AV_LOG_INFO, "ar_coeff_lag=%d; ", aom->ar_coeff_lag); + write_info(ctx, "scaling_shift=%d; ", aom->scaling_shift); + write_info(ctx, "ar_coeff_lag=%d; ", aom->ar_coeff_lag); if (num_ar_coeffs_y) { - av_log(ctx, AV_LOG_INFO, "ar_coeffs_y={ "); + write_info(ctx, "ar_coeffs_y={ "); for (int i = 0; i < num_ar_coeffs_y; i++) - av_log(ctx, AV_LOG_INFO, "%d ", aom->ar_coeffs_y[i]); - av_log(ctx, AV_LOG_INFO, "}; "); + write_info(ctx, "%d ", aom->ar_coeffs_y[i]); + write_info(ctx, "}; "); } for (int uv = 0; num_ar_coeffs_uv && uv < 2; uv++) { - av_log(ctx, AV_LOG_INFO, "ar_coeffs_uv[%d]={ ", uv); + write_info(ctx, "ar_coeffs_uv[%d]={ ", uv); for (int i = 0; i < num_ar_coeffs_uv; i++) - av_log(ctx, AV_LOG_INFO, "%d ", aom->ar_coeffs_uv[uv][i]); - av_log(ctx, AV_LOG_INFO, "}; "); + write_info(ctx, "%d ", aom->ar_coeffs_uv[uv][i]); + write_info(ctx, "}; "); } - av_log(ctx, AV_LOG_INFO, "ar_coeff_shift=%d; ", aom->ar_coeff_shift); - av_log(ctx, AV_LOG_INFO, "grain_scale_shift=%d; ", aom->grain_scale_shift); + write_info(ctx, "ar_coeff_shift=%d; ", aom->ar_coeff_shift); + write_info(ctx, "grain_scale_shift=%d; ", aom->grain_scale_shift); for (int uv = 0; uv < 2; uv++) { - av_log(ctx, AV_LOG_INFO, "uv_mult[%d] = %d; ", uv, aom->uv_mult[uv]); - av_log(ctx, AV_LOG_INFO, "uv_mult_luma[%d] = %d; ", uv, aom->uv_mult_luma[uv]); - av_log(ctx, AV_LOG_INFO, "uv_offset[%d] = %d; ", uv, aom->uv_offset[uv]); + write_info(ctx, "uv_mult[%d] = %d; ", uv, aom->uv_mult[uv]); + write_info(ctx, "uv_mult_luma[%d] = %d; ", uv, aom->uv_mult_luma[uv]); + write_info(ctx, "uv_offset[%d] = %d; ", uv, aom->uv_offset[uv]); } - av_log(ctx, AV_LOG_INFO, "overlap_flag=%d; ", aom->overlap_flag); - av_log(ctx, AV_LOG_INFO, "limit_output_range=%d; ", aom->limit_output_range); + write_info(ctx, "overlap_flag=%d; ", aom->overlap_flag); + write_info(ctx, "limit_output_range=%d; ", aom->limit_output_range); break; } case AV_FILM_GRAIN_PARAMS_H274: { const AVFilmGrainH274Params *h274 = &fgp->codec.h274; - av_log(ctx, AV_LOG_INFO, "model_id=%d; ", h274->model_id); - av_log(ctx, AV_LOG_INFO, "blending_mode_id=%d; ", h274->blending_mode_id); - av_log(ctx, AV_LOG_INFO, "log2_scale_factor=%d; ", h274->log2_scale_factor); + write_info(ctx, "model_id=%d; ", h274->model_id); + write_info(ctx, "blending_mode_id=%d; ", h274->blending_mode_id); + write_info(ctx, "log2_scale_factor=%d; ", h274->log2_scale_factor); for (int c = 0; c < 3; c++) if (h274->component_model_present[c] && (h274->num_model_values[c] > 6 || h274->num_intensity_intervals[c] < 1 || h274->num_intensity_intervals[c] > 256)) { - av_log(ctx, AV_LOG_ERROR, "invalid data\n"); + write_info(ctx, "invalid data\n"); return; } @@ -535,15 +552,15 @@ static void dump_sei_film_grain_params_metadata(AVFilterContext *ctx, const AVFr if (!h274->component_model_present[c]) continue; - av_log(ctx, AV_LOG_INFO, "num_intensity_intervals[%d]=%u; ", c, h274->num_intensity_intervals[c]); - av_log(ctx, AV_LOG_INFO, "num_model_values[%d]=%u; ", c, h274->num_model_values[c]); + write_info(ctx, "num_intensity_intervals[%d]=%u; ", c, h274->num_intensity_intervals[c]); + write_info(ctx, "num_model_values[%d]=%u; ", c, h274->num_model_values[c]); for (int i = 0; i < h274->num_intensity_intervals[c]; i++) { - av_log(ctx, AV_LOG_INFO, "intensity_interval_lower_bound[%d][%d]=%u; ", + write_info(ctx, "intensity_interval_lower_bound[%d][%d]=%u; ", c, i, h274->intensity_interval_lower_bound[c][i]); - av_log(ctx, AV_LOG_INFO, "intensity_interval_upper_bound[%d][%d]=%u; ", + write_info(ctx, "intensity_interval_upper_bound[%d][%d]=%u; ", c, i, h274->intensity_interval_upper_bound[c][i]); for (int j = 0; j < h274->num_model_values[c]; j++) - av_log(ctx, AV_LOG_INFO, "comp_model_value[%d][%d][%d]=%d; ", + write_info(ctx, "comp_model_value[%d][%d][%d]=%d; ", c, i, j, h274->comp_model_value[c][i][j]); } } @@ -559,100 +576,100 @@ static void dump_dovi_metadata(AVFilterContext *ctx, const AVFrameSideData *sd) const AVDOVIDataMapping *mapping = av_dovi_get_mapping(dovi); const AVDOVIColorMetadata *color = av_dovi_get_color(dovi); - av_log(ctx, AV_LOG_INFO, " rpu_type=%"PRIu8"; ", hdr->rpu_type); - av_log(ctx, AV_LOG_INFO, "rpu_format=%"PRIu16"; ", hdr->rpu_format); - av_log(ctx, AV_LOG_INFO, "vdr_rpu_profile=%"PRIu8"; ", hdr->vdr_rpu_profile); - av_log(ctx, AV_LOG_INFO, "vdr_rpu_level=%"PRIu8"; ", hdr->vdr_rpu_level); - av_log(ctx, AV_LOG_INFO, "chroma_resampling_explicit_filter_flag=%"PRIu8"; ", hdr->chroma_resampling_explicit_filter_flag); - av_log(ctx, AV_LOG_INFO, "coef_data_type=%"PRIu8"; ", hdr->coef_data_type); - av_log(ctx, AV_LOG_INFO, "coef_log2_denom=%"PRIu8"; ", hdr->coef_log2_denom); - av_log(ctx, AV_LOG_INFO, "vdr_rpu_normalized_idc=%"PRIu8"; ", hdr->vdr_rpu_normalized_idc); - av_log(ctx, AV_LOG_INFO, "bl_video_full_range_flag=%"PRIu8"; ", hdr->bl_video_full_range_flag); - av_log(ctx, AV_LOG_INFO, "bl_bit_depth=%"PRIu8"; ", hdr->bl_bit_depth); - av_log(ctx, AV_LOG_INFO, "el_bit_depth=%"PRIu8"; ", hdr->el_bit_depth); - av_log(ctx, AV_LOG_INFO, "vdr_bit_depth=%"PRIu8"; ", hdr->vdr_bit_depth); - av_log(ctx, AV_LOG_INFO, "spatial_resampling_filter_flag=%"PRIu8"; ", hdr->spatial_resampling_filter_flag); - av_log(ctx, AV_LOG_INFO, "el_spatial_resampling_filter_flag=%"PRIu8"; ", hdr->el_spatial_resampling_filter_flag); - av_log(ctx, AV_LOG_INFO, "disable_residual_flag=%"PRIu8"\n", hdr->disable_residual_flag); + write_info(ctx, " rpu_type=%"PRIu8"; ", hdr->rpu_type); + write_info(ctx, "rpu_format=%"PRIu16"; ", hdr->rpu_format); + write_info(ctx, "vdr_rpu_profile=%"PRIu8"; ", hdr->vdr_rpu_profile); + write_info(ctx, "vdr_rpu_level=%"PRIu8"; ", hdr->vdr_rpu_level); + write_info(ctx, "chroma_resampling_explicit_filter_flag=%"PRIu8"; ", hdr->chroma_resampling_explicit_filter_flag); + write_info(ctx, "coef_data_type=%"PRIu8"; ", hdr->coef_data_type); + write_info(ctx, "coef_log2_denom=%"PRIu8"; ", hdr->coef_log2_denom); + write_info(ctx, "vdr_rpu_normalized_idc=%"PRIu8"; ", hdr->vdr_rpu_normalized_idc); + write_info(ctx, "bl_video_full_range_flag=%"PRIu8"; ", hdr->bl_video_full_range_flag); + write_info(ctx, "bl_bit_depth=%"PRIu8"; ", hdr->bl_bit_depth); + write_info(ctx, "el_bit_depth=%"PRIu8"; ", hdr->el_bit_depth); + write_info(ctx, "vdr_bit_depth=%"PRIu8"; ", hdr->vdr_bit_depth); + write_info(ctx, "spatial_resampling_filter_flag=%"PRIu8"; ", hdr->spatial_resampling_filter_flag); + write_info(ctx, "el_spatial_resampling_filter_flag=%"PRIu8"; ", hdr->el_spatial_resampling_filter_flag); + write_info(ctx, "disable_residual_flag=%"PRIu8"\n", hdr->disable_residual_flag); - av_log(ctx, AV_LOG_INFO, " data mapping: "); - av_log(ctx, AV_LOG_INFO, "vdr_rpu_id=%"PRIu8"; ", mapping->vdr_rpu_id); - av_log(ctx, AV_LOG_INFO, "mapping_color_space=%"PRIu8"; ", mapping->mapping_color_space); - av_log(ctx, AV_LOG_INFO, "mapping_chroma_format_idc=%"PRIu8"; ", mapping->mapping_chroma_format_idc); - av_log(ctx, AV_LOG_INFO, "nlq_method_idc=%d; ", (int) mapping->nlq_method_idc); - av_log(ctx, AV_LOG_INFO, "num_x_partitions=%"PRIu32"; ", mapping->num_x_partitions); - av_log(ctx, AV_LOG_INFO, "num_y_partitions=%"PRIu32"\n", mapping->num_y_partitions); + write_info(ctx, " data mapping: "); + write_info(ctx, "vdr_rpu_id=%"PRIu8"; ", mapping->vdr_rpu_id); + write_info(ctx, "mapping_color_space=%"PRIu8"; ", mapping->mapping_color_space); + write_info(ctx, "mapping_chroma_format_idc=%"PRIu8"; ", mapping->mapping_chroma_format_idc); + write_info(ctx, "nlq_method_idc=%d; ", (int) mapping->nlq_method_idc); + write_info(ctx, "num_x_partitions=%"PRIu32"; ", mapping->num_x_partitions); + write_info(ctx, "num_y_partitions=%"PRIu32"\n", mapping->num_y_partitions); for (int c = 0; c < 3; c++) { const AVDOVIReshapingCurve *curve = &mapping->curves[c]; const AVDOVINLQParams *nlq = &mapping->nlq[c]; - av_log(ctx, AV_LOG_INFO, " channel %d: ", c); - av_log(ctx, AV_LOG_INFO, "pivots={ "); + write_info(ctx, " channel %d: ", c); + write_info(ctx, "pivots={ "); for (int i = 0; i < curve->num_pivots; i++) - av_log(ctx, AV_LOG_INFO, "%"PRIu16" ", curve->pivots[i]); - av_log(ctx, AV_LOG_INFO, "}; mapping_idc={ "); + write_info(ctx, "%"PRIu16" ", curve->pivots[i]); + write_info(ctx, "}; mapping_idc={ "); for (int i = 0; i < curve->num_pivots - 1; i++) - av_log(ctx, AV_LOG_INFO, "%d ", (int) curve->mapping_idc[i]); - av_log(ctx, AV_LOG_INFO, "}; poly_order={ "); + write_info(ctx, "%d ", (int) curve->mapping_idc[i]); + write_info(ctx, "}; poly_order={ "); for (int i = 0; i < curve->num_pivots - 1; i++) - av_log(ctx, AV_LOG_INFO, "%"PRIu8" ", curve->poly_order[i]); - av_log(ctx, AV_LOG_INFO, "}; poly_coef={ "); + write_info(ctx, "%"PRIu8" ", curve->poly_order[i]); + write_info(ctx, "}; poly_coef={ "); for (int i = 0; i < curve->num_pivots - 1; i++) { - av_log(ctx, AV_LOG_INFO, "{%"PRIi64", %"PRIi64", %"PRIi64"} ", + write_info(ctx, "{%"PRIi64", %"PRIi64", %"PRIi64"} ", curve->poly_coef[i][0], curve->poly_coef[i][1], curve->poly_coef[i][2]); } - av_log(ctx, AV_LOG_INFO, "}; mmr_order={ "); + write_info(ctx, "}; mmr_order={ "); for (int i = 0; i < curve->num_pivots - 1; i++) - av_log(ctx, AV_LOG_INFO, "%"PRIu8" ", curve->mmr_order[i]); - av_log(ctx, AV_LOG_INFO, "}; mmr_constant={ "); + write_info(ctx, "%"PRIu8" ", curve->mmr_order[i]); + write_info(ctx, "}; mmr_constant={ "); for (int i = 0; i < curve->num_pivots - 1; i++) - av_log(ctx, AV_LOG_INFO, "%"PRIi64" ", curve->mmr_constant[i]); - av_log(ctx, AV_LOG_INFO, "}; mmr_coef={ "); + write_info(ctx, "%"PRIi64" ", curve->mmr_constant[i]); + write_info(ctx, "}; mmr_coef={ "); for (int i = 0; i < curve->num_pivots - 1; i++) { - av_log(ctx, AV_LOG_INFO, "{"); + write_info(ctx, "{"); for (int j = 0; j < curve->mmr_order[i]; j++) { for (int k = 0; k < 7; k++) - av_log(ctx, AV_LOG_INFO, "%"PRIi64" ", curve->mmr_coef[i][j][k]); + write_info(ctx, "%"PRIi64" ", curve->mmr_coef[i][j][k]); } - av_log(ctx, AV_LOG_INFO, "} "); + write_info(ctx, "} "); } - av_log(ctx, AV_LOG_INFO, "}; nlq_offset=%"PRIu16"; ", nlq->nlq_offset); - av_log(ctx, AV_LOG_INFO, "vdr_in_max=%"PRIu64"; ", nlq->vdr_in_max); + write_info(ctx, "}; nlq_offset=%"PRIu16"; ", nlq->nlq_offset); + write_info(ctx, "vdr_in_max=%"PRIu64"; ", nlq->vdr_in_max); switch (mapping->nlq_method_idc) { case AV_DOVI_NLQ_LINEAR_DZ: - av_log(ctx, AV_LOG_INFO, "linear_deadzone_slope=%"PRIu64"; ", nlq->linear_deadzone_slope); - av_log(ctx, AV_LOG_INFO, "linear_deadzone_threshold=%"PRIu64"\n", nlq->linear_deadzone_threshold); + write_info(ctx, "linear_deadzone_slope=%"PRIu64"; ", nlq->linear_deadzone_slope); + write_info(ctx, "linear_deadzone_threshold=%"PRIu64"\n", nlq->linear_deadzone_threshold); break; } } - av_log(ctx, AV_LOG_INFO, " color metadata: "); - av_log(ctx, AV_LOG_INFO, "dm_metadata_id=%"PRIu8"; ", color->dm_metadata_id); - av_log(ctx, AV_LOG_INFO, "scene_refresh_flag=%"PRIu8"; ", color->scene_refresh_flag); - av_log(ctx, AV_LOG_INFO, "ycc_to_rgb_matrix={ "); + write_info(ctx, " color metadata: "); + write_info(ctx, "dm_metadata_id=%"PRIu8"; ", color->dm_metadata_id); + write_info(ctx, "scene_refresh_flag=%"PRIu8"; ", color->scene_refresh_flag); + write_info(ctx, "ycc_to_rgb_matrix={ "); for (int i = 0; i < 9; i++) - av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->ycc_to_rgb_matrix[i])); - av_log(ctx, AV_LOG_INFO, "}; ycc_to_rgb_offset={ "); + write_info(ctx, "%f ", av_q2d(color->ycc_to_rgb_matrix[i])); + write_info(ctx, "}; ycc_to_rgb_offset={ "); for (int i = 0; i < 3; i++) - av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->ycc_to_rgb_offset[i])); - av_log(ctx, AV_LOG_INFO, "}; rgb_to_lms_matrix={ "); + write_info(ctx, "%f ", av_q2d(color->ycc_to_rgb_offset[i])); + write_info(ctx, "}; rgb_to_lms_matrix={ "); for (int i = 0; i < 9; i++) - av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->rgb_to_lms_matrix[i])); - av_log(ctx, AV_LOG_INFO, "}; signal_eotf=%"PRIu16"; ", color->signal_eotf); - av_log(ctx, AV_LOG_INFO, "signal_eotf_param0=%"PRIu16"; ", color->signal_eotf_param0); - av_log(ctx, AV_LOG_INFO, "signal_eotf_param1=%"PRIu16"; ", color->signal_eotf_param1); - av_log(ctx, AV_LOG_INFO, "signal_eotf_param2=%"PRIu32"; ", color->signal_eotf_param2); - av_log(ctx, AV_LOG_INFO, "signal_bit_depth=%"PRIu8"; ", color->signal_bit_depth); - av_log(ctx, AV_LOG_INFO, "signal_color_space=%"PRIu8"; ", color->signal_color_space); - av_log(ctx, AV_LOG_INFO, "signal_chroma_format=%"PRIu8"; ", color->signal_chroma_format); - av_log(ctx, AV_LOG_INFO, "signal_full_range_flag=%"PRIu8"; ", color->signal_full_range_flag); - av_log(ctx, AV_LOG_INFO, "source_min_pq=%"PRIu16"; ", color->source_min_pq); - av_log(ctx, AV_LOG_INFO, "source_max_pq=%"PRIu16"; ", color->source_max_pq); - av_log(ctx, AV_LOG_INFO, "source_diagonal=%"PRIu16"; ", color->source_diagonal); + write_info(ctx, "%f ", av_q2d(color->rgb_to_lms_matrix[i])); + write_info(ctx, "}; signal_eotf=%"PRIu16"; ", color->signal_eotf); + write_info(ctx, "signal_eotf_param0=%"PRIu16"; ", color->signal_eotf_param0); + write_info(ctx, "signal_eotf_param1=%"PRIu16"; ", color->signal_eotf_param1); + write_info(ctx, "signal_eotf_param2=%"PRIu32"; ", color->signal_eotf_param2); + write_info(ctx, "signal_bit_depth=%"PRIu8"; ", color->signal_bit_depth); + write_info(ctx, "signal_color_space=%"PRIu8"; ", color->signal_color_space); + write_info(ctx, "signal_chroma_format=%"PRIu8"; ", color->signal_chroma_format); + write_info(ctx, "signal_full_range_flag=%"PRIu8"; ", color->signal_full_range_flag); + write_info(ctx, "source_min_pq=%"PRIu16"; ", color->source_min_pq); + write_info(ctx, "source_max_pq=%"PRIu16"; ", color->source_max_pq); + write_info(ctx, "source_diagonal=%"PRIu16"; ", color->source_diagonal); } static void dump_ambient_viewing_environment(AVFilterContext *ctx, const AVFrameSideData *sd) @@ -660,7 +677,7 @@ static void dump_ambient_viewing_environment(AVFilterContext *ctx, const AVFrame const AVAmbientViewingEnvironment *ambient_viewing_environment = (const AVAmbientViewingEnvironment *)sd->data; - av_log(ctx, AV_LOG_INFO, "ambient_illuminance=%f, ambient_light_x=%f, ambient_light_y=%f", + write_info(ctx, "ambient_illuminance=%f, ambient_light_x=%f, ambient_light_y=%f", av_q2d(ambient_viewing_environment->ambient_illuminance), av_q2d(ambient_viewing_environment->ambient_light_x), av_q2d(ambient_viewing_environment->ambient_light_y)); @@ -674,29 +691,29 @@ static void dump_color_property(AVFilterContext *ctx, AVFrame *frame) const char *color_trc_str = av_color_transfer_name(frame->color_trc); if (!color_range_str || frame->color_range == AVCOL_RANGE_UNSPECIFIED) { - av_log(ctx, AV_LOG_INFO, "color_range:unknown"); + write_info(ctx, "color_range:unknown"); } else { - av_log(ctx, AV_LOG_INFO, "color_range:%s", color_range_str); + write_info(ctx, "color_range:%s", color_range_str); } if (!colorspace_str || frame->colorspace == AVCOL_SPC_UNSPECIFIED) { - av_log(ctx, AV_LOG_INFO, " color_space:unknown"); + write_info(ctx, " color_space:unknown"); } else { - av_log(ctx, AV_LOG_INFO, " color_space:%s", colorspace_str); + write_info(ctx, " color_space:%s", colorspace_str); } if (!color_primaries_str || frame->color_primaries == AVCOL_PRI_UNSPECIFIED) { - av_log(ctx, AV_LOG_INFO, " color_primaries:unknown"); + write_info(ctx, " color_primaries:unknown"); } else { - av_log(ctx, AV_LOG_INFO, " color_primaries:%s", color_primaries_str); + write_info(ctx, " color_primaries:%s", color_primaries_str); } if (!color_trc_str || frame->color_trc == AVCOL_TRC_UNSPECIFIED) { - av_log(ctx, AV_LOG_INFO, " color_trc:unknown"); + write_info(ctx, " color_trc:unknown"); } else { - av_log(ctx, AV_LOG_INFO, " color_trc:%s", color_trc_str); + write_info(ctx, " color_trc:%s", color_trc_str); } - av_log(ctx, AV_LOG_INFO, "\n"); + write_info(ctx, "\n"); } static void update_sample_stats_8(const uint8_t *src, int len, int64_t *sum, int64_t *sum2) @@ -733,6 +750,39 @@ static void update_sample_stats(int depth, int be, const uint8_t *src, int len, update_sample_stats_16(be, src, len, sum, sum2); } +static av_cold int init(AVFilterContext *ctx) { + int ret; + ShowInfoContext *s = ctx->priv; + + if (s->file_str != NULL) { + if (!strcmp("-", s->file_str)) { + ret = avio_open(&s->avio_context, "pipe:1", AVIO_FLAG_WRITE); + } else { + ret = avio_open(&s->avio_context, s->file_str, AVIO_FLAG_WRITE); + } + + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Could not open %s: %s\n", + s->file_str, av_err2str(ret)); + return ret; + } + } + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) { + int ret; + ShowInfoContext *s = ctx->priv; + + if (s->avio_context) { + ret = avio_close(s->avio_context); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to close file: %s\n", s->file_str); + } + } +} + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { FilterLink *inl = ff_filter_link(inlink); @@ -765,7 +815,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } } - av_log(ctx, AV_LOG_INFO, + write_info(ctx, "n:%4"PRId64" pts:%7s pts_time:%-7s duration:%7"PRId64 " duration_time:%-7s " "fmt:%s cl:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c ", @@ -781,33 +831,33 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) av_get_picture_type_char(frame->pict_type)); if (s->calculate_checksums) { - av_log(ctx, AV_LOG_INFO, + write_info(ctx, "checksum:%08"PRIX32" plane_checksum:[%08"PRIX32, checksum, plane_checksum[0]); for (plane = 1; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) - av_log(ctx, AV_LOG_INFO, " %08"PRIX32, plane_checksum[plane]); - av_log(ctx, AV_LOG_INFO, "] mean:["); + write_info(ctx, " %08"PRIX32, plane_checksum[plane]); + write_info(ctx, "] mean:["); for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) - av_log(ctx, AV_LOG_INFO, "%s%"PRId64, + write_info(ctx, "%s%"PRId64, plane ? " ":"", (sum[plane] + pixelcount[plane]/2) / pixelcount[plane]); - av_log(ctx, AV_LOG_INFO, "] stdev:["); + write_info(ctx, "] stdev:["); for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) - av_log(ctx, AV_LOG_INFO, "%s%3.1f", + write_info(ctx, "%s%3.1f", plane ? " ":"", sqrt((sum2[plane] - sum[plane]*(double)sum[plane]/pixelcount[plane])/pixelcount[plane])); - av_log(ctx, AV_LOG_INFO, "]"); + write_info(ctx, "]"); } - av_log(ctx, AV_LOG_INFO, "\n"); + write_info(ctx, "\n"); for (i = 0; i < frame->nb_side_data; i++) { AVFrameSideData *sd = frame->side_data[i]; const char *name = av_frame_side_data_name(sd->type); - av_log(ctx, AV_LOG_INFO, " side data - "); + write_info(ctx, " side data - "); if (name) - av_log(ctx, AV_LOG_INFO, "%s: ", name); + write_info(ctx, "%s: ", name); switch (sd->type) { case AV_FRAME_DATA_SPHERICAL: dump_spherical(ctx, frame, sd); @@ -820,11 +870,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) break; } case AV_FRAME_DATA_DISPLAYMATRIX: - av_log(ctx, AV_LOG_INFO, "rotation of %.2f degrees", + write_info(ctx, "rotation of %.2f degrees", av_display_rotation_get((int32_t *)sd->data)); break; case AV_FRAME_DATA_AFD: - av_log(ctx, AV_LOG_INFO, "value of %"PRIu8, sd->data[0]); + write_info(ctx, "value of %"PRIu8, sd->data[0]); break; case AV_FRAME_DATA_REGIONS_OF_INTEREST: dump_roi(ctx, sd); @@ -847,7 +897,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) case AV_FRAME_DATA_GOP_TIMECODE: { char tcbuf[AV_TIMECODE_STR_SIZE]; av_timecode_make_mpeg_tc_string(tcbuf, *(int64_t *)(sd->data)); - av_log(ctx, AV_LOG_INFO, "%s", tcbuf); + write_info(ctx, "%s", tcbuf); break; } case AV_FRAME_DATA_VIDEO_ENC_PARAMS: @@ -866,21 +916,21 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) dump_ambient_viewing_environment(ctx, sd); break; case AV_FRAME_DATA_VIEW_ID: - av_log(ctx, AV_LOG_INFO, "view id: %d\n", *(int*)sd->data); + write_info(ctx, "view id: %d\n", *(int*)sd->data); break; case AV_FRAME_DATA_3D_REFERENCE_DISPLAYS: dump_tdrdi(ctx, sd); break; default: if (name) - av_log(ctx, AV_LOG_INFO, "(%zu bytes)", sd->size); + write_info(ctx, "(%zu bytes)", sd->size); else - av_log(ctx, AV_LOG_WARNING, "unknown side data type %d " + write_info(ctx, "unknown side data type %d " "(%zu bytes)", sd->type, sd->size); break; } - av_log(ctx, AV_LOG_INFO, "\n"); + write_info(ctx, "\n"); } dump_color_property(ctx, frame); @@ -888,9 +938,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) if (desc->flags & AV_PIX_FMT_FLAG_ALPHA) { const char *alpha_mode_str = av_alpha_mode_name(frame->alpha_mode); if (!alpha_mode_str || frame->alpha_mode == AVALPHA_MODE_UNSPECIFIED) - av_log(ctx, AV_LOG_INFO, "alpha_mode:unspecified\n"); + write_info(ctx, "alpha_mode:unspecified\n"); else - av_log(ctx, AV_LOG_INFO, "alpha_mode:%s\n", alpha_mode_str); + write_info(ctx, "alpha_mode:%s\n", alpha_mode_str); + } + + if (s->avio_context) { + avio_flush(s->avio_context); + if (s->avio_context->error < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to write to %s: %s\n", + s->file_str, av_err2str(s->avio_context->error)); + } } return ff_filter_frame(inlink->dst->outputs[0], frame); @@ -900,7 +958,7 @@ static int config_props(AVFilterContext *ctx, AVFilterLink *link, int is_out) { FilterLink *l = ff_filter_link(link); - av_log(ctx, AV_LOG_INFO, "config %s time_base: %d/%d, frame_rate: %d/%d\n", + write_info(ctx, "config %s time_base: %d/%d, frame_rate: %d/%d\n", is_out ? "out" : "in", link->time_base.num, link->time_base.den, l->frame_rate.num, l->frame_rate.den); @@ -945,4 +1003,6 @@ const FFFilter ff_vf_showinfo = { FILTER_INPUTS(avfilter_vf_showinfo_inputs), FILTER_OUTPUTS(avfilter_vf_showinfo_outputs), .priv_size = sizeof(ShowInfoContext), + .init = init, + .uninit = uninit, }; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
