[FFmpeg-devel] [PATCH 19/23] fftools/ffmpeg: add encoder private data

Anton Khirnov anton at khirnov.net
Sat Mar 25 21:15:25 EET 2023


Start by moving OutputStream.last_frame to it. In the future it will
hold other encoder-internal state.
---
 fftools/ffmpeg.h          |  7 +++++-
 fftools/ffmpeg_enc.c      | 51 +++++++++++++++++++++++++++++++++++----
 fftools/ffmpeg_mux.c      |  3 ++-
 fftools/ffmpeg_mux_init.c |  8 +++---
 4 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index c30659176e..8193dabb57 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -557,6 +557,8 @@ typedef struct KeyframeForceCtx {
     int          dropped_keyframe;
 } KeyframeForceCtx;
 
+typedef struct Encoder Encoder;
+
 typedef struct OutputStream {
     const AVClass *class;
 
@@ -588,9 +590,9 @@ typedef struct OutputStream {
     AVRational mux_timebase;
     AVRational enc_timebase;
 
+    Encoder *enc;
     AVCodecContext *enc_ctx;
     AVFrame *filtered_frame;
-    AVFrame *last_frame;
     AVFrame *sq_frame;
     AVPacket *pkt;
     int64_t last_dropped;
@@ -824,6 +826,9 @@ AVBufferRef *hw_device_for_filter(void);
 
 int hwaccel_decode_init(AVCodecContext *avctx);
 
+int enc_alloc(Encoder **penc, const AVCodec *codec);
+void enc_free(Encoder **penc);
+
 int enc_open(OutputStream *ost, AVFrame *frame);
 void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub);
 void enc_frame(OutputStream *ost, AVFrame *frame);
diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c
index c0e3eaa1e8..1387e05cf6 100644
--- a/fftools/ffmpeg_enc.c
+++ b/fftools/ffmpeg_enc.c
@@ -43,8 +43,48 @@
 
 #include "libavformat/avformat.h"
 
+struct Encoder {
+    AVFrame *last_frame;
+};
+
 static uint64_t dup_warning = 1000;
 
+void enc_free(Encoder **penc)
+{
+    Encoder *enc = *penc;
+
+    if (!enc)
+        return;
+
+    av_frame_free(&enc->last_frame);
+
+    av_freep(penc);
+}
+
+int enc_alloc(Encoder **penc, const AVCodec *codec)
+{
+    Encoder *enc;
+
+    *penc = NULL;
+
+    enc = av_mallocz(sizeof(*enc));
+    if (!enc)
+        return AVERROR(ENOMEM);
+
+    if (codec->type == AVMEDIA_TYPE_VIDEO) {
+        enc->last_frame = av_frame_alloc();
+        if (!enc->last_frame)
+            goto fail;
+    }
+
+    *penc = enc;
+
+    return 0;
+fail:
+    enc_free(&enc);
+    return AVERROR(ENOMEM);
+}
+
 static void set_encoder_id(OutputFile *of, OutputStream *ost)
 {
     const char *cname = ost->enc_ctx->codec->name;
@@ -919,6 +959,7 @@ static void do_video_out(OutputFile *of,
                          AVFrame *next_picture)
 {
     int ret;
+    Encoder *e = ost->enc;
     AVCodecContext *enc = ost->enc_ctx;
     AVRational frame_rate;
     int64_t nb_frames, nb_frames_prev, i;
@@ -965,7 +1006,7 @@ static void do_video_out(OutputFile *of,
         nb_frames_drop++;
         av_log(ost, AV_LOG_VERBOSE,
                "*** dropping frame %"PRId64" at ts %"PRId64"\n",
-               ost->vsync_frame_number, ost->last_frame->pts);
+               ost->vsync_frame_number, e->last_frame->pts);
     }
     if (nb_frames > (nb_frames_prev && ost->last_dropped) + (nb_frames > nb_frames_prev)) {
         if (nb_frames > dts_error_threshold * 30) {
@@ -987,8 +1028,8 @@ static void do_video_out(OutputFile *of,
     for (i = 0; i < nb_frames; i++) {
         AVFrame *in_picture;
 
-        if (i < nb_frames_prev && ost->last_frame->buf[0]) {
-            in_picture = ost->last_frame;
+        if (i < nb_frames_prev && e->last_frame->buf[0]) {
+            in_picture = e->last_frame;
         } else
             in_picture = next_picture;
 
@@ -1013,9 +1054,9 @@ static void do_video_out(OutputFile *of,
         ost->vsync_frame_number++;
     }
 
-    av_frame_unref(ost->last_frame);
+    av_frame_unref(e->last_frame);
     if (next_picture)
-        av_frame_move_ref(ost->last_frame, next_picture);
+        av_frame_move_ref(e->last_frame, next_picture);
 }
 
 void enc_frame(OutputStream *ost, AVFrame *frame)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 1937bc2aa7..527567831f 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -643,6 +643,8 @@ static void ost_free(OutputStream **post)
         return;
     ms = ms_from_ost(ost);
 
+    enc_free(&ost->enc);
+
     if (ost->logfile) {
         if (fclose(ost->logfile))
             av_log(ms, AV_LOG_ERROR,
@@ -662,7 +664,6 @@ static void ost_free(OutputStream **post)
 
     av_frame_free(&ost->filtered_frame);
     av_frame_free(&ost->sq_frame);
-    av_frame_free(&ost->last_frame);
     av_packet_free(&ost->pkt);
     av_dict_free(&ost->encoder_opts);
 
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 385312d4fe..ff95ea9e02 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -462,6 +462,10 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o,
         if (!ost->enc_ctx)
             report_and_exit(AVERROR(ENOMEM));
 
+        ret = enc_alloc(&ost->enc, enc);
+        if (ret < 0)
+            report_and_exit(ret);
+
         av_strlcat(ms->log_name, "/",       sizeof(ms->log_name));
         av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name));
     } else {
@@ -933,10 +937,6 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input
         ost->avfilter = get_ost_filters(o, oc, ost);
         if (!ost->avfilter)
             exit_program(1);
-
-        ost->last_frame = av_frame_alloc();
-        if (!ost->last_frame)
-            report_and_exit(AVERROR(ENOMEM));
     } else
         check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_VIDEO);
 
-- 
2.39.1



More information about the ffmpeg-devel mailing list