From 434377a7647f4beb2182ea9f27abb6a84347f42c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 24 Sep 2024 10:08:00 +0200 Subject: [PATCH] fftools/ffmpeg_enc: split Encoder into a private and public part 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, "; "); }