[FFmpeg-devel] [PATCH 3/9] fftools/ffmpeg_enc: split Encoder into a private and public part

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


Similar to what was previously done for other components, e.g. decoders
(see 3b84140a1bb5a5b3044915888a40a7b619921633).

Start by moving {samples,frames}_encoded into the public struct.
---
 fftools/ffmpeg.h     | 11 +++---
 fftools/ffmpeg_enc.c | 86 +++++++++++++++++++++++++-------------------
 fftools/ffmpeg_mux.c |  4 +--
 3 files changed, 58 insertions(+), 43 deletions(-)

diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index d12b0e0d88..9aeb217e73 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -569,7 +569,13 @@ typedef struct KeyframeForceCtx {
     int          dropped_keyframe;
 } KeyframeForceCtx;
 
-typedef struct Encoder Encoder;
+typedef struct Encoder {
+    const AVClass          *class;
+
+    // number of frames/samples sent to the encoder
+    uint64_t                frames_encoded;
+    uint64_t                samples_encoded;
+} Encoder;
 
 enum CroppingType {
     CROP_DISABLED = 0,
@@ -621,9 +627,6 @@ typedef struct OutputStream {
     /* stats */
     // number of packets send to the muxer
     atomic_uint_least64_t packets_written;
-    // number of frames/samples sent to the encoder
-    uint64_t frames_encoded;
-    uint64_t samples_encoded;
 
     /* packet quality factor */
     atomic_int quality;
diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c
index 4b3efb8db1..c8623ed343 100644
--- a/fftools/ffmpeg_enc.c
+++ b/fftools/ffmpeg_enc.c
@@ -38,8 +38,9 @@
 
 #include "libavcodec/avcodec.h"
 
-struct Encoder {
-    const AVClass *class;
+typedef struct EncoderPriv {
+    Encoder        e;
+
     void          *log_parent;
     char           log_name[32];
 
@@ -54,7 +55,12 @@ struct Encoder {
 
     Scheduler      *sch;
     unsigned        sch_idx;
-};
+} EncoderPriv;
+
+static EncoderPriv *ep_from_enc(Encoder *enc)
+{
+    return (EncoderPriv*)enc;
+}
 
 // data that is local to the decoder thread and not visible outside of it
 typedef struct EncoderThread {
@@ -74,38 +80,38 @@ void enc_free(Encoder **penc)
 
 static const char *enc_item_name(void *obj)
 {
-    const Encoder *e = obj;
+    const EncoderPriv *ep = obj;
 
-    return e->log_name;
+    return ep->log_name;
 }
 
 static const AVClass enc_class = {
     .class_name                = "Encoder",
     .version                   = LIBAVUTIL_VERSION_INT,
-    .parent_log_context_offset = offsetof(Encoder, log_parent),
+    .parent_log_context_offset = offsetof(EncoderPriv, log_parent),
     .item_name                 = enc_item_name,
 };
 
 int enc_alloc(Encoder **penc, const AVCodec *codec,
               Scheduler *sch, unsigned sch_idx, void *log_parent)
 {
-    Encoder *enc;
+    EncoderPriv *ep;
 
     *penc = NULL;
 
-    enc = av_mallocz(sizeof(*enc));
-    if (!enc)
+    ep = av_mallocz(sizeof(*ep));
+    if (!ep)
         return AVERROR(ENOMEM);
 
-    enc->class      = &enc_class;
-    enc->log_parent = log_parent;
+    ep->e.class    = &enc_class;
+    ep->log_parent = log_parent;
 
-    enc->sch     = sch;
-    enc->sch_idx = sch_idx;
+    ep->sch     = sch;
+    ep->sch_idx = sch_idx;
 
-    snprintf(enc->log_name, sizeof(enc->log_name), "enc:%s", codec->name);
+    snprintf(ep->log_name, sizeof(ep->log_name), "enc:%s", codec->name);
 
-    *penc = enc;
+    *penc = &ep->e;
 
     return 0;
 }
@@ -166,6 +172,7 @@ int enc_open(void *opaque, const AVFrame *frame)
     OutputStream *ost = opaque;
     InputStream *ist = ost->ist;
     Encoder              *e = ost->enc;
+    EncoderPriv         *ep = ep_from_enc(e);
     AVCodecContext *enc_ctx = ost->enc_ctx;
     Decoder            *dec = NULL;
     const AVCodec      *enc = enc_ctx->codec;
@@ -174,7 +181,7 @@ int enc_open(void *opaque, const AVFrame *frame)
     int frame_samples = 0;
     int ret;
 
-    if (e->opened)
+    if (ep->opened)
         return 0;
 
     // frame is always non-NULL for audio and video
@@ -320,7 +327,7 @@ int enc_open(void *opaque, const AVFrame *frame)
         return ret;
     }
 
-    e->opened = 1;
+    ep->opened = 1;
 
     if (enc_ctx->frame_size)
         frame_samples = enc_ctx->frame_size;
@@ -352,6 +359,7 @@ static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *
                            AVPacket *pkt)
 {
     Encoder *e = ost->enc;
+    EncoderPriv *ep = ep_from_enc(e);
     int subtitle_out_max_size = 1024 * 1024;
     int subtitle_out_size, nb, i, ret;
     AVCodecContext *enc;
@@ -403,7 +411,7 @@ static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *
             local_sub.rects += i;
         }
 
-        ost->frames_encoded++;
+        e->frames_encoded++;
 
         subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, &local_sub);
         if (subtitle_out_size < 0) {
@@ -425,7 +433,7 @@ static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *
         }
         pkt->dts = pkt->pts;
 
-        ret = sch_enc_send(e->sch, e->sch_idx, pkt);
+        ret = sch_enc_send(ep->sch, ep->sch_idx, pkt);
         if (ret < 0) {
             av_packet_unref(pkt);
             return ret;
@@ -440,6 +448,7 @@ void enc_stats_write(OutputStream *ost, EncStats *es,
                      uint64_t frame_num)
 {
     Encoder      *e = ost->enc;
+    EncoderPriv *ep = ep_from_enc(e);
     AVIOContext *io = es->io;
     AVRational   tb = frame ? frame->time_base : pkt->time_base;
     int64_t     pts = frame ? frame->pts : pkt->pts;
@@ -477,7 +486,7 @@ void enc_stats_write(OutputStream *ost, EncStats *es,
 
         if (frame) {
             switch (c->type) {
-            case ENC_STATS_SAMPLE_NUM:  avio_printf(io, "%"PRIu64,  ost->samples_encoded);          continue;
+            case ENC_STATS_SAMPLE_NUM:  avio_printf(io, "%"PRIu64,  e->samples_encoded);            continue;
             case ENC_STATS_NB_SAMPLES:  avio_printf(io, "%d",       frame->nb_samples);             continue;
             default: av_assert0(0);
             }
@@ -495,7 +504,7 @@ void enc_stats_write(OutputStream *ost, EncStats *es,
             }
             case ENC_STATS_AVG_BITRATE: {
                 double duration = pkt->dts * av_q2d(tb);
-                avio_printf(io, "%g",  duration > 0 ? 8.0 * e->data_size / duration : -1.);
+                avio_printf(io, "%g",  duration > 0 ? 8.0 * ep->data_size / duration : -1.);
                 continue;
             }
             default: av_assert0(0);
@@ -515,7 +524,7 @@ static inline double psnr(double d)
 
 static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats)
 {
-    Encoder        *e = ost->enc;
+    EncoderPriv   *ep = ep_from_enc(ost->enc);
     const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
                                                 NULL);
     AVCodecContext *enc = ost->enc_ctx;
@@ -549,7 +558,7 @@ static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_
         }
     }
 
-    frame_number = e->packets_encoded;
+    frame_number = ep->packets_encoded;
     if (vstats_version <= 1) {
         fprintf(vstats_file, "frame= %5"PRId64" q= %2.1f ", frame_number,
                 quality / (float)FF_QP2LAMBDA);
@@ -569,9 +578,9 @@ static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_
         ti1 = 0.01;
 
     bitrate     = (pkt->size * 8) / av_q2d(enc->time_base) / 1000.0;
-    avg_bitrate = (double)(e->data_size * 8) / ti1 / 1000.0;
+    avg_bitrate = (double)(ep->data_size * 8) / ti1 / 1000.0;
     fprintf(vstats_file, "s_size= %8.0fKiB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
-           (double)e->data_size / 1024, ti1, bitrate, avg_bitrate);
+           (double)ep->data_size / 1024, ti1, bitrate, avg_bitrate);
     fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(pict_type));
 
     return 0;
@@ -581,6 +590,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
                         AVPacket *pkt)
 {
     Encoder            *e = ost->enc;
+    EncoderPriv       *ep = ep_from_enc(e);
     AVCodecContext   *enc = ost->enc_ctx;
     const char *type_desc = av_get_media_type_string(enc->codec_type);
     const char    *action = frame ? "encode" : "flush";
@@ -596,10 +606,10 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
 
         if (ost->enc_stats_pre.io)
             enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL,
-                            ost->frames_encoded);
+                            e->frames_encoded);
 
-        ost->frames_encoded++;
-        ost->samples_encoded += frame->nb_samples;
+        e->frames_encoded++;
+        e->samples_encoded += frame->nb_samples;
 
         if (debug_ts) {
             av_log(e, AV_LOG_INFO, "encoder <- type:%s "
@@ -653,7 +663,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
 
         // attach stream parameters to first packet if requested
         avcodec_parameters_free(&fd->par_enc);
-        if (e->attach_par && !e->packets_encoded) {
+        if (ep->attach_par && !ep->packets_encoded) {
             fd->par_enc = avcodec_parameters_alloc();
             if (!fd->par_enc)
                 return AVERROR(ENOMEM);
@@ -673,7 +683,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
 
         if (ost->enc_stats_post.io)
             enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt,
-                            e->packets_encoded);
+                            ep->packets_encoded);
 
         if (debug_ts) {
             av_log(e, AV_LOG_INFO, "encoder -> type:%s "
@@ -685,11 +695,11 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
                    av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
         }
 
-        e->data_size += pkt->size;
+        ep->data_size += pkt->size;
 
-        e->packets_encoded++;
+        ep->packets_encoded++;
 
-        ret = sch_enc_send(e->sch, e->sch_idx, pkt);
+        ret = sch_enc_send(ep->sch, ep->sch_idx, pkt);
         if (ret < 0) {
             av_packet_unref(pkt);
             return ret;
@@ -826,6 +836,7 @@ int encoder_thread(void *arg)
 {
     OutputStream *ost = arg;
     Encoder        *e = ost->enc;
+    EncoderPriv   *ep = ep_from_enc(e);
     EncoderThread et;
     int ret = 0, input_status = 0;
     int name_set = 0;
@@ -848,11 +859,11 @@ int encoder_thread(void *arg)
     }
 
     while (!input_status) {
-        input_status = sch_enc_receive(e->sch, e->sch_idx, et.frame);
+        input_status = sch_enc_receive(ep->sch, ep->sch_idx, et.frame);
         if (input_status < 0) {
             if (input_status == AVERROR_EOF) {
                 av_log(e, AV_LOG_VERBOSE, "Encoder thread received EOF\n");
-                if (e->opened)
+                if (ep->opened)
                     break;
 
                 av_log(e, AV_LOG_ERROR, "Could not open encoder before EOF\n");
@@ -905,6 +916,7 @@ finish:
 
 int enc_loopback(Encoder *enc)
 {
-    enc->attach_par = 1;
-    return enc->sch_idx;
+    EncoderPriv *ep = ep_from_enc(enc);
+    ep->attach_par = 1;
+    return ep->sch_idx;
 }
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index d38f1ec317..1980e3287c 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -723,9 +723,9 @@ static void mux_final_stats(Muxer *mux)
                of->index, j, av_get_media_type_string(type));
         if (ost->enc) {
             av_log(of, AV_LOG_VERBOSE, "%"PRIu64" frames encoded",
-                   ost->frames_encoded);
+                   ost->enc->frames_encoded);
             if (type == AVMEDIA_TYPE_AUDIO)
-                av_log(of, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->samples_encoded);
+                av_log(of, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->enc->samples_encoded);
             av_log(of, AV_LOG_VERBOSE, "; ");
         }
 
-- 
2.43.0



More information about the ffmpeg-devel mailing list