[FFmpeg-devel] [PATCH 4/9] fftools/ffmpeg_mux: move OutputStream.enc_ctx to Encoder

Anton Khirnov anton at khirnov.net
Sat Sep 28 12:53:36 EEST 2024


The encoding AVCodecContext is a part of the encoder, and so should live
there.
---
 fftools/ffmpeg.c          |  6 ++--
 fftools/ffmpeg.h          |  3 +-
 fftools/ffmpeg_enc.c      | 33 ++++++++++++++------
 fftools/ffmpeg_mux.c      |  8 ++---
 fftools/ffmpeg_mux_init.c | 66 ++++++++++++++++++---------------------
 5 files changed, 62 insertions(+), 54 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 420ba3c6e4..dc321fb4a2 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -728,7 +728,7 @@ static void print_stream_maps(void)
                 av_log(NULL, AV_LOG_INFO, " (graph %d)", ost->filter->graph->index);
 
             av_log(NULL, AV_LOG_INFO, " -> Stream #%d:%d (%s)\n", ost->file->index,
-                   ost->index, ost->enc_ctx->codec->name);
+                   ost->index, ost->enc->enc_ctx->codec->name);
             continue;
         }
 
@@ -737,9 +737,9 @@ static void print_stream_maps(void)
                ost->ist->index,
                ost->file->index,
                ost->index);
-        if (ost->enc_ctx) {
+        if (ost->enc) {
             const AVCodec *in_codec    = ost->ist->dec;
-            const AVCodec *out_codec   = ost->enc_ctx->codec;
+            const AVCodec *out_codec   = ost->enc->enc_ctx->codec;
             const char *decoder_name   = "?";
             const char *in_codec_name  = "?";
             const char *encoder_name   = "?";
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 9aeb217e73..c796de19f5 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -572,6 +572,8 @@ typedef struct KeyframeForceCtx {
 typedef struct Encoder {
     const AVClass          *class;
 
+    AVCodecContext         *enc_ctx;
+
     // number of frames/samples sent to the encoder
     uint64_t                frames_encoded;
     uint64_t                samples_encoded;
@@ -602,7 +604,6 @@ typedef struct OutputStream {
     AVStream *st;            /* stream in the output file */
 
     Encoder *enc;
-    AVCodecContext *enc_ctx;
 
     /* video only */
 #if FFMPEG_OPT_TOP
diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c
index c8623ed343..a46af4dce1 100644
--- a/fftools/ffmpeg_enc.c
+++ b/fftools/ffmpeg_enc.c
@@ -75,6 +75,10 @@ void enc_free(Encoder **penc)
     if (!enc)
         return;
 
+    if (enc->enc_ctx)
+        av_freep(&enc->enc_ctx->stats_in);
+    avcodec_free_context(&enc->enc_ctx);
+
     av_freep(penc);
 }
 
@@ -96,6 +100,7 @@ int enc_alloc(Encoder **penc, const AVCodec *codec,
               Scheduler *sch, unsigned sch_idx, void *log_parent)
 {
     EncoderPriv *ep;
+    int ret = 0;
 
     *penc = NULL;
 
@@ -111,9 +116,18 @@ int enc_alloc(Encoder **penc, const AVCodec *codec,
 
     snprintf(ep->log_name, sizeof(ep->log_name), "enc:%s", codec->name);
 
+    ep->e.enc_ctx = avcodec_alloc_context3(codec);
+    if (!ep->e.enc_ctx) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
     *penc = &ep->e;
 
     return 0;
+fail:
+    enc_free((Encoder**)&ep);
+    return ret;
 }
 
 static int hw_device_setup_for_encode(Encoder *e, AVCodecContext *enc_ctx,
@@ -173,7 +187,7 @@ int enc_open(void *opaque, const AVFrame *frame)
     InputStream *ist = ost->ist;
     Encoder              *e = ost->enc;
     EncoderPriv         *ep = ep_from_enc(e);
-    AVCodecContext *enc_ctx = ost->enc_ctx;
+    AVCodecContext *enc_ctx = e->enc_ctx;
     Decoder            *dec = NULL;
     const AVCodec      *enc = enc_ctx->codec;
     OutputFile          *of = ost->file;
@@ -372,7 +386,7 @@ static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *
     if ((of->start_time != AV_NOPTS_VALUE && sub->pts < of->start_time))
         return 0;
 
-    enc = ost->enc_ctx;
+    enc = e->enc_ctx;
 
     /* Note: DVB subtitle need one packet to draw them and one other
        packet to clear them */
@@ -524,10 +538,11 @@ static inline double psnr(double d)
 
 static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats)
 {
-    EncoderPriv   *ep = ep_from_enc(ost->enc);
+    Encoder        *e = ost->enc;
+    EncoderPriv   *ep = ep_from_enc(e);
     const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
                                                 NULL);
-    AVCodecContext *enc = ost->enc_ctx;
+    AVCodecContext *enc = e->enc_ctx;
     enum AVPictureType pict_type;
     int64_t frame_number;
     double ti1, bitrate, avg_bitrate;
@@ -591,7 +606,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
 {
     Encoder            *e = ost->enc;
     EncoderPriv       *ep = ep_from_enc(e);
-    AVCodecContext   *enc = ost->enc_ctx;
+    AVCodecContext   *enc = e->enc_ctx;
     const char *type_desc = av_get_media_type_string(enc->codec_type);
     const char    *action = frame ? "encode" : "flush";
     int ret;
@@ -775,7 +790,7 @@ static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt)
             return AVERROR_EOF;
 
         if (type == AVMEDIA_TYPE_VIDEO) {
-            frame->quality   = ost->enc_ctx->global_quality;
+            frame->quality   = e->enc_ctx->global_quality;
             frame->pict_type = forced_kf_apply(e, &ost->kf, frame);
 
 #if FFMPEG_OPT_TOP
@@ -785,8 +800,8 @@ static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt)
             }
 #endif
         } else {
-            if (!(ost->enc_ctx->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) &&
-                ost->enc_ctx->ch_layout.nb_channels != frame->ch_layout.nb_channels) {
+            if (!(e->enc_ctx->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) &&
+                e->enc_ctx->ch_layout.nb_channels != frame->ch_layout.nb_channels) {
                 av_log(e, AV_LOG_ERROR,
                        "Audio channel count changed and encoder does not support parameter changes\n");
                 return 0;
@@ -801,7 +816,7 @@ static void enc_thread_set_name(const OutputStream *ost)
 {
     char name[16];
     snprintf(name, sizeof(name), "enc%d:%d:%s", ost->file->index, ost->index,
-             ost->enc_ctx->codec->name);
+             ost->enc->enc_ctx->codec->name);
     ff_thread_setname(name);
 }
 
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 1980e3287c..25f66dd185 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -661,8 +661,8 @@ static int check_written(OutputFile *of)
 
         total_packets_written += packets_written;
 
-        if (ost->enc_ctx &&
-            (ost->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2))
+        if (ost->enc &&
+            (ost->enc->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2))
              != AV_CODEC_FLAG_PASS1)
             pass1_used = 0;
 
@@ -837,10 +837,6 @@ static void ost_free(OutputStream **post)
 
     av_freep(&ost->attachment_filename);
 
-    if (ost->enc_ctx)
-        av_freep(&ost->enc_ctx->stats_in);
-    avcodec_free_context(&ost->enc_ctx);
-
     enc_stats_uninit(&ost->enc_stats_pre);
     enc_stats_uninit(&ost->enc_stats_post);
     enc_stats_uninit(&ms->stats);
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 2541be59da..033fa6aba8 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -555,7 +555,7 @@ static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name)
         return AV_PIX_FMT_NONE;
     }
 
-    ret = avcodec_get_supported_config(ost->enc_ctx, NULL, AV_CODEC_CONFIG_PIX_FORMAT,
+    ret = avcodec_get_supported_config(ost->enc->enc_ctx, NULL, AV_CODEC_CONFIG_PIX_FORMAT,
                                        0, (const void **) &fmts, NULL);
     if (ret < 0)
         return AV_PIX_FMT_NONE;
@@ -587,7 +587,7 @@ static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name)
     }
 
     if (fmts && !fmt_in_list(fmts, fmt))
-        fmt = choose_pixel_fmt(ost->enc_ctx, fmt);
+        fmt = choose_pixel_fmt(ost->enc->enc_ctx, fmt);
 
     return fmt;
 }
@@ -632,8 +632,8 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
         ost->frame_aspect_ratio = q;
     }
 
-    if (ost->enc_ctx) {
-        AVCodecContext *video_enc = ost->enc_ctx;
+    if (ost->enc) {
+        AVCodecContext *video_enc = ost->enc->enc_ctx;
         const char *p = NULL, *fps_mode = NULL;
         const char *frame_size = NULL;
         const char *frame_pix_fmt = NULL;
@@ -746,10 +746,10 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
                      ost->logfile_prefix ? ost->logfile_prefix :
                                            DEFAULT_PASS_LOGFILENAME_PREFIX,
                      ost_idx);
-            if (!strcmp(ost->enc_ctx->codec->name, "libx264") || !strcmp(ost->enc_ctx->codec->name, "libvvenc")) {
-                if (av_opt_is_set_to_default_by_name(ost->enc_ctx, "stats",
+            if (!strcmp(video_enc->codec->name, "libx264") || !strcmp(video_enc->codec->name, "libvvenc")) {
+                if (av_opt_is_set_to_default_by_name(video_enc, "stats",
                                                      AV_OPT_SEARCH_CHILDREN) > 0)
-                    av_opt_set(ost->enc_ctx, "stats", logfilename,
+                    av_opt_set(video_enc, "stats", logfilename,
                                AV_OPT_SEARCH_CHILDREN);
             } else {
                 if (video_enc->flags & AV_CODEC_FLAG_PASS2) {
@@ -842,8 +842,8 @@ static int new_stream_audio(Muxer *mux, const OptionsContext *o,
     AVFormatContext *oc = mux->fc;
     AVStream *st = ost->st;
 
-    if (ost->enc_ctx) {
-        AVCodecContext *audio_enc = ost->enc_ctx;
+    if (ost->enc) {
+        AVCodecContext *audio_enc = ost->enc->enc_ctx;
         int channels = 0;
         const char *layout = NULL;
         const char *sample_fmt = NULL;
@@ -881,8 +881,8 @@ static int new_stream_subtitle(Muxer *mux, const OptionsContext *o,
 
     st  = ost->st;
 
-    if (ost->enc_ctx) {
-        AVCodecContext *subtitle_enc = ost->enc_ctx;
+    if (ost->enc) {
+        AVCodecContext *subtitle_enc = ost->enc->enc_ctx;
 
         AVCodecDescriptor const *input_descriptor =
             avcodec_descriptor_get(ost->ist->par->codec_id);
@@ -923,7 +923,7 @@ ost_bind_filter(const Muxer *mux, MuxStream *ms, OutputFilter *ofilter,
                 const ViewSpecifier *vs)
 {
     OutputStream       *ost = &ms->ost;
-    AVCodecContext *enc_ctx = ost->enc_ctx;
+    AVCodecContext *enc_ctx = ost->enc->enc_ctx;
     char name[16];
     int ret;
 
@@ -1245,10 +1245,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
     }
 
     if (enc) {
-        ost->enc_ctx = avcodec_alloc_context3(enc);
-        if (!ost->enc_ctx)
-            return AVERROR(ENOMEM);
-
         ret = sch_add_enc(mux->sch, encoder_thread, ost,
                           ost->type == AVMEDIA_TYPE_SUBTITLE ? NULL : enc_open);
         if (ret < 0)
@@ -1290,21 +1286,21 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
     if (!ms->pkt)
         return AVERROR(ENOMEM);
 
-    if (ost->enc_ctx) {
+    if (ost->enc) {
         AVIOContext *s = NULL;
         char *buf = NULL, *arg = NULL;
         const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL;
         const char *enc_time_base = NULL, *preset = NULL;
 
-        ret = filter_codec_opts(o->g->codec_opts, ost->enc_ctx->codec_id,
-                                oc, st, ost->enc_ctx->codec, &encoder_opts,
+        ret = filter_codec_opts(o->g->codec_opts, enc->id,
+                                oc, st, enc, &encoder_opts,
                                 &mux->enc_opts_used);
         if (ret < 0)
             goto fail;
 
         opt_match_per_stream_str(ost, &o->presets, oc, st, &preset);
         opt_match_per_stream_int(ost, &o->autoscale, oc, st, &autoscale);
-        if (preset && (!(ret = get_preset_file_2(preset, ost->enc_ctx->codec->name, &s)))) {
+        if (preset && (!(ret = get_preset_file_2(preset, enc->name, &s)))) {
             AVBPrint bprint;
             av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
             do  {
@@ -1404,7 +1400,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
 
         threads_manual = !!av_dict_get(encoder_opts, "threads", NULL, 0);
 
-        ret = av_opt_set_dict2(ost->enc_ctx, &encoder_opts, AV_OPT_SEARCH_CHILDREN);
+        ret = av_opt_set_dict2(ost->enc->enc_ctx, &encoder_opts, AV_OPT_SEARCH_CHILDREN);
         if (ret < 0) {
             av_log(ost, AV_LOG_ERROR, "Error applying encoder options: %s\n",
                    av_err2str(ret));
@@ -1417,7 +1413,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
 
         // default to automatic thread count
         if (!threads_manual)
-            ost->enc_ctx->thread_count = 0;
+            ost->enc->enc_ctx->thread_count = 0;
     } else {
         ret = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st,
                                 NULL, &encoder_opts,
@@ -1429,8 +1425,8 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
 
     if (o->bitexact) {
         ost->bitexact        = 1;
-    } else if (ost->enc_ctx) {
-        ost->bitexact        = !!(ost->enc_ctx->flags & AV_CODEC_FLAG_BITEXACT);
+    } else if (ost->enc) {
+        ost->bitexact        = !!(ost->enc->enc_ctx->flags & AV_CODEC_FLAG_BITEXACT);
     }
 
     if (enc) {
@@ -1482,14 +1478,14 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
         }
         ost->st->codecpar->codec_tag = tag;
         ms->par_in->codec_tag = tag;
-        if (ost->enc_ctx)
-            ost->enc_ctx->codec_tag = tag;
+        if (ost->enc)
+            ost->enc->enc_ctx->codec_tag = tag;
     }
 
     opt_match_per_stream_dbl(ost, &o->qscale, oc, st, &qscale);
-    if (ost->enc_ctx && qscale >= 0) {
-        ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE;
-        ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale;
+    if (ost->enc && qscale >= 0) {
+        ost->enc->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE;
+        ost->enc->enc_ctx->global_quality = FF_QP2LAMBDA * qscale;
     }
 
     if (ms->sch_idx >= 0) {
@@ -1511,8 +1507,8 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
     opt_match_per_stream_int(ost, &o->fix_sub_duration_heartbeat,
                              oc, st, &ost->fix_sub_duration_heartbeat);
 
-    if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx)
-        ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
+    if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc)
+        ost->enc->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
 
     opt_match_per_stream_int(ost, &o->copy_initial_nonkeyframes,
                              oc, st, &ms->copy_initial_nonkeyframes);
@@ -2047,7 +2043,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc,
     int limit_frames = 0, limit_frames_av_enc = 0;
 
 #define IS_AV_ENC(ost, type)  \
-    (ost->enc_ctx && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))
+    (ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))
 #define IS_INTERLEAVED(type) (type != AVMEDIA_TYPE_ATTACHMENT)
 
     for (int i = 0; i < oc->nb_streams; i++) {
@@ -2059,8 +2055,8 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc,
 
         nb_interleaved += IS_INTERLEAVED(type);
         nb_av_enc      += IS_AV_ENC(ost, type);
-        nb_audio_fs    += (ost->enc_ctx && type == AVMEDIA_TYPE_AUDIO &&
-                           !(ost->enc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE));
+        nb_audio_fs    += (ost->enc && type == AVMEDIA_TYPE_AUDIO &&
+                           !(ost->enc->enc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE));
 
         limit_frames        |=  ms->max_frames < INT64_MAX;
         limit_frames_av_enc |= (ms->max_frames < INT64_MAX) && IS_AV_ENC(ost, type);
@@ -3193,7 +3189,7 @@ static int process_forced_keyframes(Muxer *mux, const OptionsContext *o)
                                  mux->fc, ost->st, &forced_keyframes);
 
         if (!(ost->type == AVMEDIA_TYPE_VIDEO &&
-              ost->enc_ctx && forced_keyframes))
+              ost->enc && forced_keyframes))
             continue;
 
         if (!strncmp(forced_keyframes, "expr:", 5)) {
-- 
2.43.0



More information about the ffmpeg-devel mailing list