diff options
author | Anton Khirnov <anton@khirnov.net> | 2022-11-25 14:00:48 +0100 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2022-12-10 10:21:53 +0100 |
commit | fae4903e392c22ae509ae5bb6f74fae4de66293f (patch) | |
tree | 720e9e63e02194bdc14051997a8cfcbccc60f7d7 | |
parent | bbc069133344bfa7c4b6f8b38fb9b9caa3a76a6a (diff) |
ffmpeg: write frame map WIP
-rw-r--r-- | doc/ffmpeg.texi | 3 | ||||
-rw-r--r-- | fftools/ffmpeg.c | 40 | ||||
-rw-r--r-- | fftools/ffmpeg.h | 4 | ||||
-rw-r--r-- | fftools/ffmpeg_mux_init.c | 7 | ||||
-rw-r--r-- | fftools/ffmpeg_opt.c | 1 |
5 files changed, 54 insertions, 1 deletions
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 67b3294256..bf2cc67a03 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -2047,6 +2047,9 @@ encoder/muxer, it does not change the stream to conform to this value. Setting values that do not match the stream properties may result in encoding failures or invalid output files. +@item -enc_stats (@emph{output,per-stream}) +TODO + @end table @section Preset files diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 4aba4f0b26..9079b44b9f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -111,6 +111,12 @@ const char program_name[] = "ffmpeg"; const int program_birth_year = 2000; +typedef struct FrameData { + uint64_t frame_idx; + int64_t pts_in; + AVRational tb_in; +} FrameData; + static FILE *vstats_file; typedef struct BenchmarkTimeStamps { @@ -798,6 +804,18 @@ 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)); } +static void write_enc_stats(OutputStream *ost, const AVFrame *frame) +{ + FrameData *fd; + + if (!frame->opaque_ref) + return; + + fd = (FrameData*)frame->opaque_ref->data; + fprintf(ost->enc_stats_pre, "%"PRIu64" %"PRIu64"\n", + ost->frames_encoded - 1, fd->frame_idx); +} + static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) { AVCodecContext *enc = ost->enc_ctx; @@ -817,6 +835,9 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base), enc->time_base.num, enc->time_base.den); } + + if (ost->enc_stats_pre) + write_enc_stats(ost, frame); } update_benchmark(NULL); @@ -1994,8 +2015,22 @@ static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacke ret = avcodec_receive_frame(avctx, frame); if (ret < 0 && ret != AVERROR(EAGAIN)) return ret; - if (ret >= 0) + if (ret >= 0) { + FrameData *fd; + + av_assert0(!frame->opaque_ref); + frame->opaque_ref = av_buffer_allocz(sizeof(FrameData)); + if (!frame->opaque_ref) { + av_frame_unref(frame); + return AVERROR(ENOMEM); + } + fd = (FrameData*)frame->opaque_ref->data; + fd->pts_in = frame->pts; + fd->tb_in = avctx->pkt_timebase; + fd->frame_idx = avctx->frame_number - 1; + *got_frame = 1; + } return 0; } @@ -2970,6 +3005,9 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame, return ret; } + if (codec->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) + ost->enc_ctx->flags |= AV_CODEC_FLAG_COPY_OPAQUE; + if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) { if (ret == AVERROR_EXPERIMENTAL) abort_codec_experimental(codec, 1); diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 5527dbe49b..7403930b1a 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -252,6 +252,8 @@ typedef struct OptionsContext { int nb_autoscale; SpecifierOpt *bits_per_raw_sample; int nb_bits_per_raw_sample; + SpecifierOpt *enc_stats_pre; + int nb_enc_stats_pre; } OptionsContext; typedef struct InputFilter { @@ -625,6 +627,8 @@ typedef struct OutputStream { int sq_idx_encode; int sq_idx_mux; + + FILE *enc_stats_pre; } OutputStream; typedef struct OutputFile { diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 9eea8639dc..a249942853 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -55,6 +55,7 @@ static const char *const opt_name_copy_initial_nonkeyframes[] = {"copyinkf", NUL static const char *const opt_name_copy_prior_start[] = {"copypriorss", NULL}; static const char *const opt_name_disposition[] = {"disposition", 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_filters[] = {"filter", "af", "vf", NULL}; static const char *const opt_name_filter_scripts[] = {"filter_script", NULL}; static const char *const opt_name_fps_mode[] = {"fps_mode", NULL}; @@ -230,6 +231,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, AVCodecContext *enc = ost->enc_ctx; AVIOContext *s = NULL; char *buf = NULL, *arg = NULL, *preset = NULL; + const char *enc_stats_pre = NULL; ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id, oc, st, enc->codec); @@ -261,6 +263,11 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, preset, ost->file_index, ost->index); exit_program(1); } + + MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st); + if (enc_stats_pre) { + ost->enc_stats_pre = fopen(enc_stats_pre, "w"); + } } else { ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); } diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index a9dcf0e088..356d64ccc4 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1542,6 +1542,7 @@ const OptionDef options[] = { { "bits_per_raw_sample", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(bits_per_raw_sample) }, "set the number of bits per raw sample", "number" }, + { "enc_stats_pre", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_pre) }, "" }, /* video options */ { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames }, |