From patchwork Mon Apr 4 11:30:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 35169 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:c05:b0:7a:e998:b410 with SMTP id bw5csp1912660pzb; Mon, 4 Apr 2022 04:34:49 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxUhl1vT+g0IbTqcaWV7mAVSdzlfdN/qFJBycd/yF5zrZrdZVRoq8rX6+D7a5F5Kugidzjd X-Received: by 2002:a05:6402:4315:b0:419:2e38:ab8f with SMTP id m21-20020a056402431500b004192e38ab8fmr32713836edc.250.1649072088850; Mon, 04 Apr 2022 04:34:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649072088; cv=none; d=google.com; s=arc-20160816; b=lJAkGbVpjujsP5diG7Nqsea5jqHUi7OzRVDp82zcNeJ41ijlQjcLflF4/oTjkDPi3p e0paubXHTnNrCerBo3acoBoi9HpUTJuK01vg+CYpAn+FlIpkUepVR9A8sy4/iwDHmmYM VIIpivR82m9Ja00IkIBFIIhrvFDYf4kYAPDrndKw9gXRIySXim8GbiDZHse5L9ig3u0q xVDCBCwVaROh13LOu9qtCOBUoXWHpOMrmQYrntQOwKPIgMiXmgpLf55lojILzhtGYrsE fvTxrXAeTlvDJiSjVH1aBqoFO1LqUuHA0sA9drSg2uOX0h6PQELxehsvsRQxhyseiAgE K9jw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; 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:delivered-to; bh=H6PIoNMu1+P1ziOiUEvHYa8fXbZKuTebsF1Jp5t0DQ8=; b=p10oOmHGOpWE5UoYDNNMFDFWsn/alIBk/oGLLKIgP5/7IQ+W+5eb4AApTdXp0P1hz2 dqUfOKjjB1Dw+d4y6ZIW/CNdeauSZr7qpmZPGHH0r9gMm+R2brYmmjtrJd50P4ljMXqV T3ZiPCjrIf1vSa5whnZoW7kboVBQWyBFtHZPZ7h/pcFDu7Mktw3ih6LOvB5/hgqpA12G tnZRxTpyBhHks6AGfwlT/nW28uu/+HWMbS03FlTm7QsG7MLDHGjzvQIJy50dJmO/omtw kFtdv6M+o77JJrX8wu2bW2zQd7Iy+Ng+QoX5E5mTYQuVJfMiRF00wmPlFP99yTM/3F7I sqBw== ARC-Authentication-Results: i=1; mx.google.com; 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 n26-20020aa7c45a000000b00418fe90d5e1si6730911edr.431.2022.04.04.04.34.48; Mon, 04 Apr 2022 04:34:48 -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; 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 0854468B2D8; Mon, 4 Apr 2022 14:32:37 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9C16768B183 for ; Mon, 4 Apr 2022 14:32:24 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 24AF8240179 for ; Mon, 4 Apr 2022 13:32:24 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id NmM9ZFrA1Ler for ; Mon, 4 Apr 2022 13:32:23 +0200 (CEST) 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 mail0.khirnov.net (Postfix) with ESMTPS id 56095240685 for ; Mon, 4 Apr 2022 13:32:15 +0200 (CEST) Received: by libav.khirnov.net (Postfix, from userid 1000) id F01603A0C69; Mon, 4 Apr 2022 13:32:11 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Mon, 4 Apr 2022 13:30:12 +0200 Message-Id: <20220404113037.13070-25-anton@khirnov.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220404113037.13070-1-anton@khirnov.net> References: <20220404113037.13070-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 24/49] fftools/ffmpeg: move processing video stats to ffmpeg_mux 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: H6UwSwCCP0Ae Currently it is called from - do_video_out(), at the end of each encode loop iteration - from flush_encoders(), after muxing each packet Since this function processes the data from the last encoded packet, neither of the above is fully correct, because - an encoder can in principle produce multiple packets per one submitted frame - bitstream filters may modify the number of encoded packets or their properties. It thus makes most sense to call this function right before sending the packet to the muxer. --- fftools/ffmpeg.c | 61 +------------------------------------------- fftools/ffmpeg.h | 5 ++++ fftools/ffmpeg_mux.c | 47 ++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 60 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index ef0d5156eb..68e720d889 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -110,7 +110,7 @@ const char program_name[] = "ffmpeg"; const int program_birth_year = 2000; -static FILE *vstats_file; +FILE *vstats_file; const char *const forced_keyframes_const_names[] = { "n", @@ -127,7 +127,6 @@ typedef struct BenchmarkTimeStamps { int64_t sys_usec; } BenchmarkTimeStamps; -static void do_video_stats(OutputStream *ost, int frame_size); static BenchmarkTimeStamps get_benchmark_time_stamps(void); static int64_t getmaxrss(void); static int ifilter_has_all_input_formats(FilterGraph *fg); @@ -977,7 +976,6 @@ static void do_video_out(OutputFile *of, double delta, delta0; double duration = 0; double sync_ipts = AV_NOPTS_VALUE; - int frame_size = 0; InputStream *ist = NULL; AVFilterContext *filter = ost->filter->filter; @@ -1214,7 +1212,6 @@ static void do_video_out(OutputFile *of, av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->mux_timebase)); } - frame_size = pkt->size; output_packet(of, pkt, ost, 0); /* if two pass, output log */ @@ -1224,9 +1221,6 @@ static void do_video_out(OutputFile *of, } ost->sync_opts++; ost->frame_number++; - - if (vstats_filename && frame_size) - do_video_stats(ost, frame_size); } av_frame_unref(ost->last_frame); @@ -1239,54 +1233,6 @@ error: exit_program(1); } -static double psnr(double d) -{ - return -10.0 * log10(d); -} - -static void do_video_stats(OutputStream *ost, int frame_size) -{ - AVCodecContext *enc; - int frame_number; - double ti1, bitrate, avg_bitrate; - - /* this is executed just the first time do_video_stats is called */ - if (!vstats_file) { - vstats_file = fopen(vstats_filename, "w"); - if (!vstats_file) { - perror("fopen"); - exit_program(1); - } - } - - enc = ost->enc_ctx; - if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { - frame_number = ost->st->nb_frames; - if (vstats_version <= 1) { - fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, - ost->quality / (float)FF_QP2LAMBDA); - } else { - fprintf(vstats_file, "out= %2d st= %2d frame= %5d q= %2.1f ", ost->file_index, ost->index, frame_number, - ost->quality / (float)FF_QP2LAMBDA); - } - - if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR)) - fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0))); - - fprintf(vstats_file,"f_size= %6d ", frame_size); - /* compute pts value */ - ti1 = av_stream_get_end_pts(ost->st) * av_q2d(ost->st->time_base); - if (ti1 < 0.01) - ti1 = 0.01; - - bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0; - avg_bitrate = (double)(ost->data_size * 8) / ti1 / 1000.0; - fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", - (double)ost->data_size / 1024, ti1, bitrate, avg_bitrate); - fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type)); - } -} - static void finish_output_stream(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; @@ -1773,7 +1719,6 @@ static void flush_encoders(void) for (;;) { const char *desc = NULL; AVPacket *pkt = ost->pkt; - int pkt_size; switch (enc->codec_type) { case AVMEDIA_TYPE_AUDIO: @@ -1817,11 +1762,7 @@ static void flush_encoders(void) continue; } av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); - pkt_size = pkt->size; output_packet(of, pkt, ost, 0); - if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) { - do_video_stats(ost, pkt_size); - } } } } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c6bbc653b8..604f0145e3 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -627,6 +627,7 @@ extern int stdin_interaction; extern int frame_bits_per_raw_sample; extern AVIOContext *progress_avio; extern float max_error_rate; +extern FILE *vstats_file; extern char *filter_nbthreads; extern int filter_complex_nbthreads; @@ -644,6 +645,10 @@ extern HWDevice *filter_hw_device; extern unsigned nb_output_dumped; extern int main_return_code; +static inline double psnr(double d) +{ + return -10.0 * log10(d); +} void term_init(void); void term_exit(void); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index f301b8a66a..5facc9b1fc 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -56,6 +56,49 @@ struct Muxer { static int want_sdp = 1; +static void do_video_stats(OutputStream *ost, int frame_size) +{ + AVCodecContext *enc; + int frame_number; + double ti1, bitrate, avg_bitrate; + + /* this is executed just the first time do_video_stats is called */ + if (!vstats_file) { + vstats_file = fopen(vstats_filename, "w"); + if (!vstats_file) { + perror("fopen"); + exit_program(1); + } + } + + enc = ost->enc_ctx; + if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { + frame_number = ost->st->nb_frames; + if (vstats_version <= 1) { + fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, + ost->quality / (float)FF_QP2LAMBDA); + } else { + fprintf(vstats_file, "out= %2d st= %2d frame= %5d q= %2.1f ", ost->file_index, ost->index, frame_number, + ost->quality / (float)FF_QP2LAMBDA); + } + + if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR)) + fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0))); + + fprintf(vstats_file,"f_size= %6d ", frame_size); + /* compute pts value */ + ti1 = av_stream_get_end_pts(ost->st) * av_q2d(ost->st->time_base); + if (ti1 < 0.01) + ti1 = 0.01; + + bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0; + avg_bitrate = (double)(ost->data_size * 8) / ti1 / 1000.0; + fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", + (double)ost->data_size / 1024, ti1, bitrate, avg_bitrate); + fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type)); + } +} + static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, OSTFinished others) { int i; @@ -179,6 +222,10 @@ static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) ost->data_size += pkt->size; ost->packets_written++; + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + ost->encoding_needed && vstats_filename) + do_video_stats(ost, pkt->size); + pkt->stream_index = ost->index; if (debug_ts) {