fftools/ffmpeg_enc: split Encoder into a private and public part

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

Start by moving {samples,frames}_encoded into the public struct.
This commit is contained in:
Anton Khirnov 2024-09-24 10:08:00 +02:00
parent f295b4d8a0
commit 434377a764
3 changed files with 58 additions and 43 deletions

View File

@ -569,7 +569,13 @@ typedef struct KeyframeForceCtx {
int dropped_keyframe; int dropped_keyframe;
} KeyframeForceCtx; } 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 { enum CroppingType {
CROP_DISABLED = 0, CROP_DISABLED = 0,
@ -621,9 +627,6 @@ typedef struct OutputStream {
/* stats */ /* stats */
// number of packets send to the muxer // number of packets send to the muxer
atomic_uint_least64_t packets_written; 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 */ /* packet quality factor */
atomic_int quality; atomic_int quality;

View File

@ -38,8 +38,9 @@
#include "libavcodec/avcodec.h" #include "libavcodec/avcodec.h"
struct Encoder { typedef struct EncoderPriv {
const AVClass *class; Encoder e;
void *log_parent; void *log_parent;
char log_name[32]; char log_name[32];
@ -54,7 +55,12 @@ struct Encoder {
Scheduler *sch; Scheduler *sch;
unsigned sch_idx; 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 // data that is local to the decoder thread and not visible outside of it
typedef struct EncoderThread { typedef struct EncoderThread {
@ -74,38 +80,38 @@ void enc_free(Encoder **penc)
static const char *enc_item_name(void *obj) 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 = { static const AVClass enc_class = {
.class_name = "Encoder", .class_name = "Encoder",
.version = LIBAVUTIL_VERSION_INT, .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, .item_name = enc_item_name,
}; };
int enc_alloc(Encoder **penc, const AVCodec *codec, int enc_alloc(Encoder **penc, const AVCodec *codec,
Scheduler *sch, unsigned sch_idx, void *log_parent) Scheduler *sch, unsigned sch_idx, void *log_parent)
{ {
Encoder *enc; EncoderPriv *ep;
*penc = NULL; *penc = NULL;
enc = av_mallocz(sizeof(*enc)); ep = av_mallocz(sizeof(*ep));
if (!enc) if (!ep)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
enc->class = &enc_class; ep->e.class = &enc_class;
enc->log_parent = log_parent; ep->log_parent = log_parent;
enc->sch = sch; ep->sch = sch;
enc->sch_idx = sch_idx; 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; return 0;
} }
@ -166,6 +172,7 @@ int enc_open(void *opaque, const AVFrame *frame)
OutputStream *ost = opaque; OutputStream *ost = opaque;
InputStream *ist = ost->ist; InputStream *ist = ost->ist;
Encoder *e = ost->enc; Encoder *e = ost->enc;
EncoderPriv *ep = ep_from_enc(e);
AVCodecContext *enc_ctx = ost->enc_ctx; AVCodecContext *enc_ctx = ost->enc_ctx;
Decoder *dec = NULL; Decoder *dec = NULL;
const AVCodec *enc = enc_ctx->codec; const AVCodec *enc = enc_ctx->codec;
@ -174,7 +181,7 @@ int enc_open(void *opaque, const AVFrame *frame)
int frame_samples = 0; int frame_samples = 0;
int ret; int ret;
if (e->opened) if (ep->opened)
return 0; return 0;
// frame is always non-NULL for audio and video // frame is always non-NULL for audio and video
@ -320,7 +327,7 @@ int enc_open(void *opaque, const AVFrame *frame)
return ret; return ret;
} }
e->opened = 1; ep->opened = 1;
if (enc_ctx->frame_size) if (enc_ctx->frame_size)
frame_samples = 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) AVPacket *pkt)
{ {
Encoder *e = ost->enc; Encoder *e = ost->enc;
EncoderPriv *ep = ep_from_enc(e);
int subtitle_out_max_size = 1024 * 1024; int subtitle_out_max_size = 1024 * 1024;
int subtitle_out_size, nb, i, ret; int subtitle_out_size, nb, i, ret;
AVCodecContext *enc; AVCodecContext *enc;
@ -403,7 +411,7 @@ static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *
local_sub.rects += i; local_sub.rects += i;
} }
ost->frames_encoded++; e->frames_encoded++;
subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, &local_sub); subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, &local_sub);
if (subtitle_out_size < 0) { if (subtitle_out_size < 0) {
@ -425,7 +433,7 @@ static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *
} }
pkt->dts = pkt->pts; 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) { if (ret < 0) {
av_packet_unref(pkt); av_packet_unref(pkt);
return ret; return ret;
@ -440,6 +448,7 @@ void enc_stats_write(OutputStream *ost, EncStats *es,
uint64_t frame_num) uint64_t frame_num)
{ {
Encoder *e = ost->enc; Encoder *e = ost->enc;
EncoderPriv *ep = ep_from_enc(e);
AVIOContext *io = es->io; AVIOContext *io = es->io;
AVRational tb = frame ? frame->time_base : pkt->time_base; AVRational tb = frame ? frame->time_base : pkt->time_base;
int64_t pts = frame ? frame->pts : pkt->pts; int64_t pts = frame ? frame->pts : pkt->pts;
@ -477,7 +486,7 @@ void enc_stats_write(OutputStream *ost, EncStats *es,
if (frame) { if (frame) {
switch (c->type) { 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; case ENC_STATS_NB_SAMPLES: avio_printf(io, "%d", frame->nb_samples); continue;
default: av_assert0(0); default: av_assert0(0);
} }
@ -495,7 +504,7 @@ void enc_stats_write(OutputStream *ost, EncStats *es,
} }
case ENC_STATS_AVG_BITRATE: { case ENC_STATS_AVG_BITRATE: {
double duration = pkt->dts * av_q2d(tb); 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; continue;
} }
default: av_assert0(0); 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) 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, const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
NULL); NULL);
AVCodecContext *enc = ost->enc_ctx; 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) { if (vstats_version <= 1) {
fprintf(vstats_file, "frame= %5"PRId64" q= %2.1f ", frame_number, fprintf(vstats_file, "frame= %5"PRId64" q= %2.1f ", frame_number,
quality / (float)FF_QP2LAMBDA); quality / (float)FF_QP2LAMBDA);
@ -569,9 +578,9 @@ static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_
ti1 = 0.01; ti1 = 0.01;
bitrate = (pkt->size * 8) / av_q2d(enc->time_base) / 1000.0; 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 ", 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)); fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(pict_type));
return 0; return 0;
@ -581,6 +590,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
AVPacket *pkt) AVPacket *pkt)
{ {
Encoder *e = ost->enc; Encoder *e = ost->enc;
EncoderPriv *ep = ep_from_enc(e);
AVCodecContext *enc = ost->enc_ctx; AVCodecContext *enc = ost->enc_ctx;
const char *type_desc = av_get_media_type_string(enc->codec_type); const char *type_desc = av_get_media_type_string(enc->codec_type);
const char *action = frame ? "encode" : "flush"; 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) if (ost->enc_stats_pre.io)
enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL, enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL,
ost->frames_encoded); e->frames_encoded);
ost->frames_encoded++; e->frames_encoded++;
ost->samples_encoded += frame->nb_samples; e->samples_encoded += frame->nb_samples;
if (debug_ts) { if (debug_ts) {
av_log(e, AV_LOG_INFO, "encoder <- type:%s " 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 // attach stream parameters to first packet if requested
avcodec_parameters_free(&fd->par_enc); 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(); fd->par_enc = avcodec_parameters_alloc();
if (!fd->par_enc) if (!fd->par_enc)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
@ -673,7 +683,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
if (ost->enc_stats_post.io) if (ost->enc_stats_post.io)
enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt, enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt,
e->packets_encoded); ep->packets_encoded);
if (debug_ts) { if (debug_ts) {
av_log(e, AV_LOG_INFO, "encoder -> type:%s " 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)); 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) { if (ret < 0) {
av_packet_unref(pkt); av_packet_unref(pkt);
return ret; return ret;
@ -826,6 +836,7 @@ int encoder_thread(void *arg)
{ {
OutputStream *ost = arg; OutputStream *ost = arg;
Encoder *e = ost->enc; Encoder *e = ost->enc;
EncoderPriv *ep = ep_from_enc(e);
EncoderThread et; EncoderThread et;
int ret = 0, input_status = 0; int ret = 0, input_status = 0;
int name_set = 0; int name_set = 0;
@ -848,11 +859,11 @@ int encoder_thread(void *arg)
} }
while (!input_status) { 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 < 0) {
if (input_status == AVERROR_EOF) { if (input_status == AVERROR_EOF) {
av_log(e, AV_LOG_VERBOSE, "Encoder thread received EOF\n"); av_log(e, AV_LOG_VERBOSE, "Encoder thread received EOF\n");
if (e->opened) if (ep->opened)
break; break;
av_log(e, AV_LOG_ERROR, "Could not open encoder before EOF\n"); av_log(e, AV_LOG_ERROR, "Could not open encoder before EOF\n");
@ -905,6 +916,7 @@ finish:
int enc_loopback(Encoder *enc) int enc_loopback(Encoder *enc)
{ {
enc->attach_par = 1; EncoderPriv *ep = ep_from_enc(enc);
return enc->sch_idx; ep->attach_par = 1;
return ep->sch_idx;
} }

View File

@ -723,9 +723,9 @@ static void mux_final_stats(Muxer *mux)
of->index, j, av_get_media_type_string(type)); of->index, j, av_get_media_type_string(type));
if (ost->enc) { if (ost->enc) {
av_log(of, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", av_log(of, AV_LOG_VERBOSE, "%"PRIu64" frames encoded",
ost->frames_encoded); ost->enc->frames_encoded);
if (type == AVMEDIA_TYPE_AUDIO) 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, "; "); av_log(of, AV_LOG_VERBOSE, "; ");
} }