[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