mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-24 13:56:33 +02:00
fftools/ffmpeg: add an option for writing pre-muxing stats
Analogous to -enc_stats*, but happens right before muxing. Useful because bitstream filters and the sync queue can modify packets after encoding and before muxing. Also has access to the muxing timebase.
This commit is contained in:
parent
6d4f3ae116
commit
42a0dd6e7e
@ -32,7 +32,8 @@ version <next>:
|
|||||||
- WADY DPCM decoder and demuxer
|
- WADY DPCM decoder and demuxer
|
||||||
- CBD2 DPCM decoder
|
- CBD2 DPCM decoder
|
||||||
- ssim360 video filter
|
- ssim360 video filter
|
||||||
- ffmpeg CLI new options: -enc_stats_pre[_fmt], -enc_stats_post[_fmt]
|
- ffmpeg CLI new options: -enc_stats_pre[_fmt], -enc_stats_post[_fmt],
|
||||||
|
-stats_mux_pre[_fmt]
|
||||||
- hstack_vaapi, vstack_vaapi and xstack_vaapi filters
|
- hstack_vaapi, vstack_vaapi and xstack_vaapi filters
|
||||||
- XMD ADPCM decoder and demuxer
|
- XMD ADPCM decoder and demuxer
|
||||||
- media100 to mjpegb bsf
|
- media100 to mjpegb bsf
|
||||||
|
@ -2063,14 +2063,17 @@ or invalid output files.
|
|||||||
|
|
||||||
@item -enc_stats_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream})
|
@item -enc_stats_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream})
|
||||||
@item -enc_stats_post[:@var{stream_specifier}] @var{path} (@emph{output,per-stream})
|
@item -enc_stats_post[:@var{stream_specifier}] @var{path} (@emph{output,per-stream})
|
||||||
|
@item -stats_mux_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream})
|
||||||
Write per-frame encoding information about the matching streams into the file
|
Write per-frame encoding information about the matching streams into the file
|
||||||
given by @var{path}.
|
given by @var{path}.
|
||||||
|
|
||||||
@option{-enc_stats_pre} writes information about raw video or audio frames right
|
@option{-enc_stats_pre} writes information about raw video or audio frames right
|
||||||
before they are sent for encoding, while @option{-enc_stats_post} writes
|
before they are sent for encoding, while @option{-enc_stats_post} writes
|
||||||
information about encoded packets as they are received from the encoder. Every
|
information about encoded packets as they are received from the encoder.
|
||||||
frame or packet produces one line in the specified file. The format of this line
|
@option{-stats_mux_pre} writes information about packets just as they are about to
|
||||||
is controlled by @option{-enc_stats_pre_fmt} / @option{-enc_stats_post_fmt}.
|
be sent to the muxer. Every frame or packet produces one line in the specified
|
||||||
|
file. The format of this line is controlled by @option{-enc_stats_pre_fmt} /
|
||||||
|
@option{-enc_stats_post_fmt} / @option{-stats_mux_pre_fmt}.
|
||||||
|
|
||||||
When stats for multiple streams are written into a single file, the lines
|
When stats for multiple streams are written into a single file, the lines
|
||||||
corresponding to different streams will be interleaved. The precise order of
|
corresponding to different streams will be interleaved. The precise order of
|
||||||
@ -2079,8 +2082,9 @@ different invocations of the program, even with the same options.
|
|||||||
|
|
||||||
@item -enc_stats_pre_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream})
|
@item -enc_stats_pre_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream})
|
||||||
@item -enc_stats_post_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream})
|
@item -enc_stats_post_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream})
|
||||||
|
@item -stats_mux_pre_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream})
|
||||||
Specify the format for the lines written with @option{-enc_stats_pre} /
|
Specify the format for the lines written with @option{-enc_stats_pre} /
|
||||||
@option{-enc_stats_post}.
|
@option{-enc_stats_post} / @option{-stats_mux_pre}.
|
||||||
|
|
||||||
@var{format_spec} is a string that may contain directives of the form
|
@var{format_spec} is a string that may contain directives of the form
|
||||||
@var{@{fmt@}}. @var{format_spec} is backslash-escaped --- use \@{, \@}, and \\
|
@var{@{fmt@}}. @var{format_spec} is backslash-escaped --- use \@{, \@}, and \\
|
||||||
@ -2097,6 +2101,7 @@ Index of the output stream in the file.
|
|||||||
@item n
|
@item n
|
||||||
Frame number. Pre-encoding: number of frames sent to the encoder so far.
|
Frame number. Pre-encoding: number of frames sent to the encoder so far.
|
||||||
Post-encoding: number of packets received from the encoder so far.
|
Post-encoding: number of packets received from the encoder so far.
|
||||||
|
Muxing: number of packets submitted to the muxer for this stream so far.
|
||||||
|
|
||||||
@item ni
|
@item ni
|
||||||
Input frame number. Index of the input frame (i.e. output by a decoder) that
|
Input frame number. Index of the input frame (i.e. output by a decoder) that
|
||||||
|
@ -808,8 +808,9 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write
|
|||||||
fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type));
|
fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enc_stats_write(OutputStream *ost, EncStats *es,
|
void enc_stats_write(OutputStream *ost, EncStats *es,
|
||||||
const AVFrame *frame, const AVPacket *pkt)
|
const AVFrame *frame, const AVPacket *pkt,
|
||||||
|
uint64_t frame_num)
|
||||||
{
|
{
|
||||||
AVIOContext *io = es->io;
|
AVIOContext *io = es->io;
|
||||||
AVRational tb = frame ? frame->time_base : pkt->time_base;
|
AVRational tb = frame ? frame->time_base : pkt->time_base;
|
||||||
@ -840,12 +841,12 @@ static void enc_stats_write(OutputStream *ost, EncStats *es,
|
|||||||
case ENC_STATS_PTS_TIME: avio_printf(io, "%g", pts * av_q2d(tb)); continue;
|
case ENC_STATS_PTS_TIME: avio_printf(io, "%g", pts * av_q2d(tb)); continue;
|
||||||
case ENC_STATS_PTS_TIME_IN: avio_printf(io, "%g", ptsi == INT64_MAX ?
|
case ENC_STATS_PTS_TIME_IN: avio_printf(io, "%g", ptsi == INT64_MAX ?
|
||||||
INFINITY : ptsi * av_q2d(tbi)); continue;
|
INFINITY : ptsi * av_q2d(tbi)); continue;
|
||||||
|
case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, frame_num); continue;
|
||||||
case ENC_STATS_FRAME_NUM_IN: avio_printf(io, "%"PRIu64, fd ? fd->idx : -1); continue;
|
case ENC_STATS_FRAME_NUM_IN: avio_printf(io, "%"PRIu64, fd ? fd->idx : -1); continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame) {
|
if (frame) {
|
||||||
switch (c->type) {
|
switch (c->type) {
|
||||||
case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, ost->frames_encoded); continue;
|
|
||||||
case ENC_STATS_SAMPLE_NUM: avio_printf(io, "%"PRIu64, ost->samples_encoded); continue;
|
case ENC_STATS_SAMPLE_NUM: avio_printf(io, "%"PRIu64, ost->samples_encoded); continue;
|
||||||
case ENC_STATS_NB_SAMPLES: avio_printf(io, "%d", frame->nb_samples); continue;
|
case ENC_STATS_NB_SAMPLES: avio_printf(io, "%d", frame->nb_samples); continue;
|
||||||
default: av_assert0(0);
|
default: av_assert0(0);
|
||||||
@ -855,7 +856,6 @@ static void enc_stats_write(OutputStream *ost, EncStats *es,
|
|||||||
case ENC_STATS_DTS: avio_printf(io, "%"PRId64, pkt->dts); continue;
|
case ENC_STATS_DTS: avio_printf(io, "%"PRId64, pkt->dts); continue;
|
||||||
case ENC_STATS_DTS_TIME: avio_printf(io, "%g", pkt->dts * av_q2d(tb)); continue;
|
case ENC_STATS_DTS_TIME: avio_printf(io, "%g", pkt->dts * av_q2d(tb)); continue;
|
||||||
case ENC_STATS_PKT_SIZE: avio_printf(io, "%d", pkt->size); continue;
|
case ENC_STATS_PKT_SIZE: avio_printf(io, "%d", pkt->size); continue;
|
||||||
case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, ost->packets_encoded); continue;
|
|
||||||
case ENC_STATS_BITRATE: {
|
case ENC_STATS_BITRATE: {
|
||||||
double duration = FFMAX(pkt->duration, 1) * av_q2d(tb);
|
double duration = FFMAX(pkt->duration, 1) * av_q2d(tb);
|
||||||
avio_printf(io, "%g", 8.0 * pkt->size / duration);
|
avio_printf(io, "%g", 8.0 * pkt->size / duration);
|
||||||
@ -884,7 +884,8 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
|
|||||||
|
|
||||||
if (frame) {
|
if (frame) {
|
||||||
if (ost->enc_stats_pre.io)
|
if (ost->enc_stats_pre.io)
|
||||||
enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL);
|
enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL,
|
||||||
|
ost->frames_encoded);
|
||||||
|
|
||||||
ost->frames_encoded++;
|
ost->frames_encoded++;
|
||||||
ost->samples_encoded += frame->nb_samples;
|
ost->samples_encoded += frame->nb_samples;
|
||||||
@ -932,7 +933,8 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
|
|||||||
if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
|
if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||||
update_video_stats(ost, pkt, !!vstats_filename);
|
update_video_stats(ost, pkt, !!vstats_filename);
|
||||||
if (ost->enc_stats_post.io)
|
if (ost->enc_stats_post.io)
|
||||||
enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt);
|
enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt,
|
||||||
|
ost->packets_encoded);
|
||||||
|
|
||||||
if (debug_ts) {
|
if (debug_ts) {
|
||||||
av_log(ost, AV_LOG_INFO, "encoder -> type:%s "
|
av_log(ost, AV_LOG_INFO, "encoder -> type:%s "
|
||||||
|
@ -258,10 +258,14 @@ typedef struct OptionsContext {
|
|||||||
int nb_enc_stats_pre;
|
int nb_enc_stats_pre;
|
||||||
SpecifierOpt *enc_stats_post;
|
SpecifierOpt *enc_stats_post;
|
||||||
int nb_enc_stats_post;
|
int nb_enc_stats_post;
|
||||||
|
SpecifierOpt *mux_stats;
|
||||||
|
int nb_mux_stats;
|
||||||
SpecifierOpt *enc_stats_pre_fmt;
|
SpecifierOpt *enc_stats_pre_fmt;
|
||||||
int nb_enc_stats_pre_fmt;
|
int nb_enc_stats_pre_fmt;
|
||||||
SpecifierOpt *enc_stats_post_fmt;
|
SpecifierOpt *enc_stats_post_fmt;
|
||||||
int nb_enc_stats_post_fmt;
|
int nb_enc_stats_post_fmt;
|
||||||
|
SpecifierOpt *mux_stats_fmt;
|
||||||
|
int nb_mux_stats_fmt;
|
||||||
} OptionsContext;
|
} OptionsContext;
|
||||||
|
|
||||||
typedef struct InputFilter {
|
typedef struct InputFilter {
|
||||||
@ -789,6 +793,10 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
|
|||||||
|
|
||||||
int ffmpeg_parse_options(int argc, char **argv);
|
int ffmpeg_parse_options(int argc, char **argv);
|
||||||
|
|
||||||
|
void enc_stats_write(OutputStream *ost, EncStats *es,
|
||||||
|
const AVFrame *frame, const AVPacket *pkt,
|
||||||
|
uint64_t frame_num);
|
||||||
|
|
||||||
HWDevice *hw_device_get_by_name(const char *name);
|
HWDevice *hw_device_get_by_name(const char *name);
|
||||||
int hw_device_init_from_string(const char *arg, HWDevice **dev);
|
int hw_device_init_from_string(const char *arg, HWDevice **dev);
|
||||||
void hw_device_free_all(void);
|
void hw_device_free_all(void);
|
||||||
|
@ -64,6 +64,7 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
|
|||||||
AVFormatContext *s = mux->fc;
|
AVFormatContext *s = mux->fc;
|
||||||
AVStream *st = ost->st;
|
AVStream *st = ost->st;
|
||||||
int64_t fs;
|
int64_t fs;
|
||||||
|
uint64_t frame_num;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fs = filesize(s->pb);
|
fs = filesize(s->pb);
|
||||||
@ -128,7 +129,7 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
|
|||||||
ms->last_mux_dts = pkt->dts;
|
ms->last_mux_dts = pkt->dts;
|
||||||
|
|
||||||
ost->data_size_mux += pkt->size;
|
ost->data_size_mux += pkt->size;
|
||||||
atomic_fetch_add(&ost->packets_written, 1);
|
frame_num = atomic_fetch_add(&ost->packets_written, 1);
|
||||||
|
|
||||||
pkt->stream_index = ost->index;
|
pkt->stream_index = ost->index;
|
||||||
|
|
||||||
@ -143,6 +144,9 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ms->stats.io)
|
||||||
|
enc_stats_write(ost, &ms->stats, NULL, pkt, frame_num);
|
||||||
|
|
||||||
ret = av_interleaved_write_frame(s, pkt);
|
ret = av_interleaved_write_frame(s, pkt);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
print_error("av_interleaved_write_frame()", ret);
|
print_error("av_interleaved_write_frame()", ret);
|
||||||
@ -688,6 +692,10 @@ static void ost_free(OutputStream **post)
|
|||||||
av_freep(&ost->enc_stats_post.components[i].str);
|
av_freep(&ost->enc_stats_post.components[i].str);
|
||||||
av_freep(&ost->enc_stats_post.components);
|
av_freep(&ost->enc_stats_post.components);
|
||||||
|
|
||||||
|
for (int i = 0; i < ms->stats.nb_components; i++)
|
||||||
|
av_freep(&ms->stats.components[i].str);
|
||||||
|
av_freep(&ms->stats.components);
|
||||||
|
|
||||||
av_freep(post);
|
av_freep(post);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,8 @@ typedef struct MuxStream {
|
|||||||
|
|
||||||
AVBSFContext *bsf_ctx;
|
AVBSFContext *bsf_ctx;
|
||||||
|
|
||||||
|
EncStats stats;
|
||||||
|
|
||||||
int64_t max_frames;
|
int64_t max_frames;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -57,8 +57,10 @@ static const char *const opt_name_disposition[] = {"disposition",
|
|||||||
static const char *const opt_name_enc_time_bases[] = {"enc_time_base", NULL};
|
static const char *const opt_name_enc_time_bases[] = {"enc_time_base", NULL};
|
||||||
static const char *const opt_name_enc_stats_pre[] = {"enc_stats_pre", NULL};
|
static const char *const opt_name_enc_stats_pre[] = {"enc_stats_pre", NULL};
|
||||||
static const char *const opt_name_enc_stats_post[] = {"enc_stats_post", NULL};
|
static const char *const opt_name_enc_stats_post[] = {"enc_stats_post", NULL};
|
||||||
|
static const char *const opt_name_mux_stats[] = {"mux_stats", NULL};
|
||||||
static const char *const opt_name_enc_stats_pre_fmt[] = {"enc_stats_pre_fmt", NULL};
|
static const char *const opt_name_enc_stats_pre_fmt[] = {"enc_stats_pre_fmt", NULL};
|
||||||
static const char *const opt_name_enc_stats_post_fmt[] = {"enc_stats_post_fmt", NULL};
|
static const char *const opt_name_enc_stats_post_fmt[] = {"enc_stats_post_fmt", NULL};
|
||||||
|
static const char *const opt_name_mux_stats_fmt[] = {"mux_stats_fmt", NULL};
|
||||||
static const char *const opt_name_filters[] = {"filter", "af", "vf", NULL};
|
static const char *const opt_name_filters[] = {"filter", "af", "vf", NULL};
|
||||||
static const char *const opt_name_filter_scripts[] = {"filter_script", NULL};
|
static const char *const opt_name_filter_scripts[] = {"filter_script", NULL};
|
||||||
static const char *const opt_name_fix_sub_duration_heartbeat[] = {"fix_sub_duration_heartbeat", NULL};
|
static const char *const opt_name_fix_sub_duration_heartbeat[] = {"fix_sub_duration_heartbeat", NULL};
|
||||||
@ -262,7 +264,7 @@ static int unescape(char **pdst, size_t *dst_len,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int enc_stats_init(OutputStream *ost, int pre,
|
static int enc_stats_init(OutputStream *ost, EncStats *es, int pre,
|
||||||
const char *path, const char *fmt_spec)
|
const char *path, const char *fmt_spec)
|
||||||
{
|
{
|
||||||
static const struct {
|
static const struct {
|
||||||
@ -290,7 +292,6 @@ static int enc_stats_init(OutputStream *ost, int pre,
|
|||||||
{ ENC_STATS_BITRATE, "br", 0, 1 },
|
{ ENC_STATS_BITRATE, "br", 0, 1 },
|
||||||
{ ENC_STATS_AVG_BITRATE, "abr", 0, 1 },
|
{ ENC_STATS_AVG_BITRATE, "abr", 0, 1 },
|
||||||
};
|
};
|
||||||
EncStats *es = pre ? &ost->enc_stats_pre : &ost->enc_stats_post;
|
|
||||||
const char *next = fmt_spec;
|
const char *next = fmt_spec;
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
@ -479,7 +480,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o,
|
|||||||
AVCodecContext *enc = ost->enc_ctx;
|
AVCodecContext *enc = ost->enc_ctx;
|
||||||
AVIOContext *s = NULL;
|
AVIOContext *s = NULL;
|
||||||
char *buf = NULL, *arg = NULL, *preset = NULL;
|
char *buf = NULL, *arg = NULL, *preset = NULL;
|
||||||
const char *enc_stats_pre = NULL, *enc_stats_post = NULL;
|
const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL;
|
||||||
|
|
||||||
ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id,
|
ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id,
|
||||||
oc, st, enc->codec);
|
oc, st, enc->codec);
|
||||||
@ -518,7 +519,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o,
|
|||||||
|
|
||||||
MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st);
|
MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st);
|
||||||
|
|
||||||
ret = enc_stats_init(ost, 1, enc_stats_pre, format);
|
ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
exit_program(1);
|
exit_program(1);
|
||||||
}
|
}
|
||||||
@ -530,7 +531,19 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o,
|
|||||||
|
|
||||||
MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st);
|
MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st);
|
||||||
|
|
||||||
ret = enc_stats_init(ost, 0, enc_stats_post, format);
|
ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format);
|
||||||
|
if (ret < 0)
|
||||||
|
exit_program(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st);
|
||||||
|
if (mux_stats &&
|
||||||
|
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
|
||||||
|
const char *format = "{fidx} {sidx} {n} {t}";
|
||||||
|
|
||||||
|
MATCH_PER_STREAM_OPT(mux_stats_fmt, str, format, oc, st);
|
||||||
|
|
||||||
|
ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
exit_program(1);
|
exit_program(1);
|
||||||
}
|
}
|
||||||
|
@ -1548,10 +1548,14 @@ const OptionDef options[] = {
|
|||||||
"write encoding stats before encoding" },
|
"write encoding stats before encoding" },
|
||||||
{ "enc_stats_post", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post) },
|
{ "enc_stats_post", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post) },
|
||||||
"write encoding stats after encoding" },
|
"write encoding stats after encoding" },
|
||||||
|
{ "stats_mux_pre", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(mux_stats) },
|
||||||
|
"write packets stats before muxing" },
|
||||||
{ "enc_stats_pre_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_pre_fmt) },
|
{ "enc_stats_pre_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_pre_fmt) },
|
||||||
"format of the stats written with -enc_stats_pre" },
|
"format of the stats written with -enc_stats_pre" },
|
||||||
{ "enc_stats_post_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post_fmt) },
|
{ "enc_stats_post_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post_fmt) },
|
||||||
"format of the stats written with -enc_stats_post" },
|
"format of the stats written with -enc_stats_post" },
|
||||||
|
{ "stats_mux_pre_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(mux_stats_fmt) },
|
||||||
|
"format of the stats written with -stats_mux_pre" },
|
||||||
|
|
||||||
/* video options */
|
/* video options */
|
||||||
{ "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames },
|
{ "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user