[FFmpeg-cvslog] fftools/ffmpeg: use a separate counter for encoded packet data size

Anton Khirnov git at videolan.org
Mon Aug 29 16:42:43 EEST 2022


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Thu Aug 25 10:44:55 2022 +0200| [4fce3bab64699092100a65e957be4d1394c0b4d3] | committer: Anton Khirnov

fftools/ffmpeg: use a separate counter for encoded packet data size

update_video_stats() currently uses OutputStream.data_size to print the
total size of the encoded stream so far and the average bitrate.
However, that field is updated in the muxer thread, right before the
packet is sent to the muxer. Not only is this racy, but the numbers may
not match even if muxing was in the main thread due to bitstream
filters, filesize limiting, etc.

Introduce a new counter, data_size_enc, for total size of the packets
received from the encoder and use that in update_video_stats(). Rename
data_size to data_size_mux to indicate its semantics more clearly.

No synchronization is needed for data_size_mux, because it is only read
in the main thread in print_final_stats(), which runs after the muxer
threads are terminated.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=4fce3bab64699092100a65e957be4d1394c0b4d3
---

 fftools/ffmpeg.c     | 22 +++++++++++++---------
 fftools/ffmpeg.h     |  6 ++++--
 fftools/ffmpeg_mux.c |  2 +-
 3 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 0ca07873b2..fbabbe6ea2 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -901,9 +901,9 @@ static void 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)(ost->data_size * 8) / ti1 / 1000.0;
+    avg_bitrate = (double)(ost->data_size_enc * 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);
+           (double)ost->data_size_enc / 1024, ti1, bitrate, avg_bitrate);
     fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type));
 }
 
@@ -979,6 +979,8 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
                    av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
         }
 
+        ost->data_size_enc += pkt->size;
+
         if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
             update_video_stats(ost, pkt, !!vstats_filename);
 
@@ -1454,14 +1456,16 @@ static void print_final_stats(int64_t total_size)
     for (i = 0; i < nb_output_streams; i++) {
         OutputStream *ost = output_streams[i];
         AVCodecParameters *par = ost->st->codecpar;
+        const uint64_t s = ost->data_size_mux;
+
         switch (par->codec_type) {
-            case AVMEDIA_TYPE_VIDEO: video_size += ost->data_size; break;
-            case AVMEDIA_TYPE_AUDIO: audio_size += ost->data_size; break;
-            case AVMEDIA_TYPE_SUBTITLE: subtitle_size += ost->data_size; break;
-            default:                 other_size += ost->data_size; break;
+            case AVMEDIA_TYPE_VIDEO:    video_size    += s; break;
+            case AVMEDIA_TYPE_AUDIO:    audio_size    += s; break;
+            case AVMEDIA_TYPE_SUBTITLE: subtitle_size += s; break;
+            default:                    other_size    += s; break;
         }
         extra_size += par->extradata_size;
-        data_size  += ost->data_size;
+        data_size  += s;
         if (ost->enc_ctx &&
             (ost->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2))
             != AV_CODEC_FLAG_PASS1)
@@ -1529,7 +1533,7 @@ static void print_final_stats(int64_t total_size)
             OutputStream *ost = output_streams[of->ost_index + j];
             enum AVMediaType type = ost->st->codecpar->codec_type;
 
-            total_size    += ost->data_size;
+            total_size    += ost->data_size_mux;
             total_packets += atomic_load(&ost->packets_written);
 
             av_log(NULL, AV_LOG_VERBOSE, "  Output stream #%d:%d (%s): ",
@@ -1543,7 +1547,7 @@ static void print_final_stats(int64_t total_size)
             }
 
             av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ",
-                   atomic_load(&ost->packets_written), ost->data_size);
+                   atomic_load(&ost->packets_written), ost->data_size_mux);
 
             av_log(NULL, AV_LOG_VERBOSE, "\n");
         }
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 74bc9220fc..ede0b2bd96 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -585,8 +585,10 @@ typedef struct OutputStream {
     int keep_pix_fmt;
 
     /* stats */
-    // combined size of all the packets written
-    uint64_t data_size;
+    // combined size of all the packets sent to the muxer
+    uint64_t data_size_mux;
+    // combined size of all the packets received from the encoder
+    uint64_t data_size_enc;
     // number of packets send to the muxer
     atomic_uint_least64_t packets_written;
     // number of frames/samples sent to the encoder
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index b424ef0021..b781e1f5a6 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -156,7 +156,7 @@ static int write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
     }
     ms->last_mux_dts = pkt->dts;
 
-    ost->data_size += pkt->size;
+    ost->data_size_mux += pkt->size;
     atomic_fetch_add(&ost->packets_written, 1);
 
     pkt->stream_index = ost->index;



More information about the ffmpeg-cvslog mailing list