summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2022-11-25 14:00:48 +0100
committerAnton Khirnov <anton@khirnov.net>2022-12-10 10:21:53 +0100
commitfae4903e392c22ae509ae5bb6f74fae4de66293f (patch)
tree720e9e63e02194bdc14051997a8cfcbccc60f7d7
parentbbc069133344bfa7c4b6f8b38fb9b9caa3a76a6a (diff)
ffmpeg: write frame map WIP
-rw-r--r--doc/ffmpeg.texi3
-rw-r--r--fftools/ffmpeg.c40
-rw-r--r--fftools/ffmpeg.h4
-rw-r--r--fftools/ffmpeg_mux_init.c7
-rw-r--r--fftools/ffmpeg_opt.c1
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 },