From patchwork Sat Sep 28 09:53:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 51905 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a59:d8ca:0:b0:48e:c0f8:d0de with SMTP id dy10csp897811vqb; Sat, 28 Sep 2024 03:01:16 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCUjvQ3CIXanpF4UVa9VUe9XuGWVYx43Jm1Y6rbK8II3uPFeKAP9xOyLDjeLVUtHPB2AKx93toZMaHHnx/A4jlDt@gmail.com X-Google-Smtp-Source: AGHT+IF1zv9jjJ2M4wLgb+N5NJYSV//J5wgA92j9ST/7fIZoVQIgCQFxFyM/590EIoZfmUNercMZ X-Received: by 2002:a17:907:748:b0:a7a:b73f:7584 with SMTP id a640c23a62f3a-a93c492a391mr597909866b.34.1727517675875; Sat, 28 Sep 2024 03:01:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1727517675; cv=none; d=google.com; s=arc-20240605; b=Bst3vfjUijbMW0BdodyiTxsmuzMjyHfTjDjfNQXCalPEM6mXf1BTmnZMpFX7zAmfml A81ZRkufO3Ye1DAUEB3whgUd04lWo2bgREISW8EFPuRI8htfWI/kSoftHV3t5rO0hjs+ Tw4czQ3g1R80vkj54KJppzmqFsSPRyHX6MUUF8i+TpuHoapz7mxdlPuZNsVEZXCzZiv5 k03Cc2Rc3wd3MAlzjXTVuVV7hR6SP0LDMBCgqxCcNJqjprL7zOAMQ4TwtCDur5FvAYss oWiIghyeg1pBkKa0ZcS2tDs+00wGndAOVpBD8zDWB7aKkpNaxRtb3KKYL9/fWye6tUcA z/OQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to; bh=IZ1CBzPZBlNVkY7AOPYg0DN35fYo8kenhr8EOMdcFzQ=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=BI1v760w7zXV8lndwJ8i7K91laY1apmSvlyN5AnIMl/7MOHslxajOBnlGd1I699pSk TenYhM3sXSKpoMPH/ic/ED4OILZBMi6UtRbsTFjEt0xfkwVOEI/MHunXUyFry7DPbOjv rHNCt6U/+Ty70eKMSnTtNIJtGINUqIeA5rLQkvwo4CX3RGRW1OS60n0fM0jXmPm7ANU8 zcHIzGjTOmdIBqFsQNVswqASx5MB3a7kgTXDBEpaf9GxYygEzgQxSHbWCWe+voBkMyoo tgshw55eVDqRNJktrN+5z4QYwXr6H6mwfrkj0ElObs/wDOZ9ndm0spPaSAEt8rhbdMhQ bZLQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@khirnov.net header.s=mail header.b=WCIxa6zm; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id 4fb4d7f45d1cf-5c8824b0874si2710066a12.659.2024.09.28.03.01.15; Sat, 28 Sep 2024 03:01:15 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@khirnov.net header.s=mail header.b=WCIxa6zm; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5860F68DCA9; Sat, 28 Sep 2024 12:54:11 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail1.khirnov.net (quelana.khirnov.net [94.230.150.81]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5AA9B68DA92 for ; Sat, 28 Sep 2024 12:54:02 +0300 (EEST) Authentication-Results: mail1.khirnov.net; dkim=pass (2048-bit key; unprotected) header.d=khirnov.net header.i=@khirnov.net header.a=rsa-sha256 header.s=mail header.b=WCIxa6zm; dkim-atps=neutral Received: from localhost (mail1.khirnov.net [IPv6:::1]) by mail1.khirnov.net (Postfix) with ESMTP id D2FFC4DE2 for ; Sat, 28 Sep 2024 11:53:56 +0200 (CEST) Received: from mail1.khirnov.net ([IPv6:::1]) by localhost (mail1.khirnov.net [IPv6:::1]) (amavis, port 10024) with ESMTP id 269mIvLFrwZc for ; Sat, 28 Sep 2024 11:53:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=khirnov.net; s=mail; t=1727517234; bh=ImHPlb5RzOEwt+Emwl1+cdgpNuT5MrpuEqtXQWoqDu4=; h=From:To:Subject:Date:In-Reply-To:References:From; b=WCIxa6zmKYibVEmo40ODiJPE2VYrb0KSWezzpjsYagrTjHiZjpbTZIVKaPPWO5eEV ljIDJFDqh67MdikkVpM4zgRkGLO4+7oZYOMCwkcD2A8dpkV+kmYt/9ULk7sfsVHaG+ XvaMKRFHauUBt1Dau/ruYvlRs0GCWlQtrqKp9HyXBzlBdyGo8ZT5YRbONBESP7jtOq pnSbPvs4lbAYTqxgyCaR0nW7Z8hBUYrUTE5HfGlfosmW1K+172llEZ1b3LipTZyVZo B4zp2IuoYbJ7bnIXMmqbvppAHsvchjt7XfnAhxf4XQQAMfZiOk/FV68WyntdupogsN Oke4qLokhGdeA== Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail1.khirnov.net (Postfix) with ESMTPS id BA4A44DE6 for ; Sat, 28 Sep 2024 11:53:54 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 6B1453A0998 for ; Sat, 28 Sep 2024 11:53:48 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Sat, 28 Sep 2024 11:53:35 +0200 Message-ID: <20240928095341.15552-3-anton@khirnov.net> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240928095341.15552-1-anton@khirnov.net> References: <20240928095341.15552-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/9] fftools/ffmpeg_enc: split Encoder into a private and public part X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: yoRnAj7b7TAN 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, "; "); }