]> git.sesse.net Git - nageru/commitdiff
Added some mux metrics.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 12 Jun 2017 18:06:00 +0000 (20:06 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 12 Jun 2017 18:06:00 +0000 (20:06 +0200)
mux.cpp
mux.h
quicksync_encoder.cpp
video_encoder.cpp
video_encoder.h

diff --git a/mux.cpp b/mux.cpp
index 1fd8e30ba3ff836a6b92521f96cda2b91a20f611..d01c18038a893cfec7152d35d8e3b0f1131ed0fb 100644 (file)
--- a/mux.cpp
+++ b/mux.cpp
@@ -23,6 +23,7 @@ extern "C" {
 
 #include "defs.h"
 #include "flags.h"
+#include "metrics.h"
 #include "timebase.h"
 
 using namespace std;
@@ -45,8 +46,8 @@ struct PacketBefore {
        const AVFormatContext * const ctx;
 };
 
-Mux::Mux(AVFormatContext *avctx, int width, int height, Codec video_codec, const string &video_extradata, const AVCodecParameters *audio_codecpar, int time_base, std::function<void(int64_t)> write_callback)
-       : avctx(avctx), write_callback(write_callback)
+Mux::Mux(AVFormatContext *avctx, int width, int height, Codec video_codec, const string &video_extradata, const AVCodecParameters *audio_codecpar, int time_base, std::function<void(int64_t)> write_callback, const vector<MuxMetrics *> &metrics)
+       : avctx(avctx), write_callback(write_callback), metrics(metrics)
 {
        avstream_video = avformat_new_stream(avctx, nullptr);
        if (avstream_video == nullptr) {
@@ -109,6 +110,9 @@ Mux::Mux(AVFormatContext *avctx, int width, int height, Codec video_codec, const
                fprintf(stderr, "avformat_write_header() failed\n");
                exit(1);
        }
+       for (MuxMetrics *metric : metrics) {
+               metric->metric_written_bytes += avctx->pb->pos;
+       }
 
        // Make sure the header is written before the constructor exits.
        avio_flush(avctx->pb);
@@ -116,7 +120,12 @@ Mux::Mux(AVFormatContext *avctx, int width, int height, Codec video_codec, const
 
 Mux::~Mux()
 {
+       int64_t old_pos = avctx->pb->pos;
        av_write_trailer(avctx);
+       for (MuxMetrics *metric : metrics) {
+               metric->metric_written_bytes += avctx->pb->pos - old_pos;
+       }
+
        if (!(avctx->oformat->flags & AVFMT_NOFILE) &&
            !(avctx->flags & AVFMT_FLAG_CUSTOM_IO)) {
                avio_closep(&avctx->pb);
@@ -165,11 +174,24 @@ void Mux::add_packet(const AVPacket &pkt, int64_t pts, int64_t dts)
 
 void Mux::write_packet_or_die(const AVPacket &pkt)
 {
+       for (MuxMetrics *metric : metrics) {
+               if (pkt.stream_index == 0) {
+                       metric->metric_video_bytes += pkt.size;
+               } else if (pkt.stream_index == 1) {
+                       metric->metric_audio_bytes += pkt.size;
+               } else {
+                       assert(false);
+               }
+       }
+       int64_t old_pos = avctx->pb->pos;
        if (av_interleaved_write_frame(avctx, const_cast<AVPacket *>(&pkt)) < 0) {
                fprintf(stderr, "av_interleaved_write_frame() failed\n");
                exit(1);
        }
        avio_flush(avctx->pb);
+       for (MuxMetrics *metric : metrics) {
+               metric->metric_written_bytes += avctx->pb->pos - old_pos;
+       }
 }
 
 void Mux::plug()
@@ -194,3 +216,16 @@ void Mux::unplug()
        }
        plugged_packets.clear();
 }
+
+void MuxMetrics::init(const vector<pair<string, string>> &labels)
+{
+       vector<pair<string, string>> labels_video = labels;
+       labels_video.emplace_back("stream", "video");
+       global_metrics.add("mux_stream_bytes", labels_video, &metric_video_bytes);
+
+       vector<pair<string, string>> labels_audio = labels;
+       labels_audio.emplace_back("stream", "audio");
+       global_metrics.add("mux_stream_bytes", labels_audio, &metric_audio_bytes);
+
+       global_metrics.add("mux_written_bytes", labels, &metric_written_bytes);
+}
diff --git a/mux.h b/mux.h
index ddf97fe92a591d86ec6dbebd9614cf32fa9a0846..c6c442100c58b18c481754747693b54c8571bcbc 100644 (file)
--- a/mux.h
+++ b/mux.h
@@ -9,11 +9,30 @@ extern "C" {
 }
 
 #include <sys/types.h>
+#include <atomic>
 #include <functional>
 #include <mutex>
 #include <string>
+#include <utility>
 #include <vector>
 
+struct MuxMetrics {
+       // “written” will usually be equal video + audio + mux overhead,
+       // except that there could be buffered packets that count in audio or video
+       // but not yet in written.
+       std::atomic<int64_t> metric_video_bytes{0}, metric_audio_bytes{0}, metric_written_bytes{0};
+
+       // Registers in global_metrics.
+       void init(const std::vector<std::pair<std::string, std::string>> &labels);
+
+       void reset()
+       {
+               metric_video_bytes = 0;
+               metric_audio_bytes = 0;
+               metric_written_bytes = 0;
+       }
+};
+
 class Mux {
 public:
        enum Codec {
@@ -24,7 +43,9 @@ public:
        // Takes ownership of avctx. <write_callback> will be called every time
        // a write has been made to the video stream (id 0), with the pts of
        // the just-written frame. (write_callback can be nullptr.)
-       Mux(AVFormatContext *avctx, int width, int height, Codec video_codec, const std::string &video_extradata, const AVCodecParameters *audio_codecpar, int time_base, std::function<void(int64_t)> write_callback);
+       // Does not take ownership of <metrics>; elements in there, if any,
+       // will be added to.
+       Mux(AVFormatContext *avctx, int width, int height, Codec video_codec, const std::string &video_extradata, const AVCodecParameters *audio_codecpar, int time_base, std::function<void(int64_t)> write_callback, const std::vector<MuxMetrics *> &metrics);
        ~Mux();
        void add_packet(const AVPacket &pkt, int64_t pts, int64_t dts);
 
@@ -50,6 +71,7 @@ private:
        AVStream *avstream_video, *avstream_audio;
 
        std::function<void(int64_t)> write_callback;
+       std::vector<MuxMetrics *> metrics;
 };
 
 #endif  // !defined(_MUX_H)
index 8eef63dd0d1338e69677e4e0c85ece83ea9fc3c2..d13cf87624069cc1319c3986df21fc89e42a26da 100644 (file)
@@ -70,6 +70,7 @@ namespace {
 // so they are outside.
 bool mux_metrics_inited = false;
 LatencyHistogram mixer_latency_histogram, qs_latency_histogram;
+MuxMetrics current_file_mux_metrics, total_mux_metrics;
 
 }  // namespace
 
@@ -1827,9 +1828,17 @@ void QuickSyncEncoderImpl::open_output_file(const std::string &filename)
                video_extradata = x264_encoder->get_global_headers();
        }
 
+       if (!mux_metrics_inited) {
+               current_file_mux_metrics.init({{ "destination", "current_file" }});
+               total_mux_metrics.init({{ "destination", "files_total" }});
+               mux_metrics_inited = true;
+       }
+       current_file_mux_metrics.reset();
+
        AVCodecParametersWithDeleter audio_codecpar = file_audio_encoder->get_codec_parameters();
        file_mux.reset(new Mux(avctx, frame_width, frame_height, Mux::CODEC_H264, video_extradata, audio_codecpar.get(), TIMEBASE,
-               std::bind(&DiskSpaceEstimator::report_write, disk_space_estimator, filename, _1)));
+               std::bind(&DiskSpaceEstimator::report_write, disk_space_estimator, filename, _1),
+               { &current_file_mux_metrics, &total_mux_metrics }));
 
        if (global_flags.x264_video_to_disk) {
                x264_encoder->add_mux(file_mux.get());
index 029652a6f576720f17f4ccfaec02d8503e4fc312..a622ba2af6640425d72dc5a72de44b4cc8f218e3 100644 (file)
@@ -186,7 +186,8 @@ void VideoEncoder::open_output_stream()
 
        int time_base = global_flags.stream_coarse_timebase ? COARSE_TIMEBASE : TIMEBASE;
        stream_mux.reset(new Mux(avctx, width, height, video_codec, video_extradata, stream_audio_encoder->get_codec_parameters().get(), time_base,
-               /*write_callback=*/nullptr));
+               /*write_callback=*/nullptr, { &stream_mux_metrics }));
+       stream_mux_metrics.init({{ "destination", "http" }});
 }
 
 int VideoEncoder::write_packet2_thunk(void *opaque, uint8_t *buf, int buf_size, AVIODataMarkerType type, int64_t time)
index d51399e17a82c71bcbf31fbe7ba28115fc768b85..31c0c5f05ff41cb5a97510a0a50e2d240442dcc2 100644 (file)
@@ -20,6 +20,7 @@ extern "C" {
 #include <libavformat/avio.h>
 }
 
+#include "mux.h"
 #include "ref_counted_gl_sync.h"
 
 class AudioEncoder;
@@ -94,6 +95,7 @@ private:
        std::unique_ptr<X264Encoder> x264_encoder;  // nullptr if not using x264.
 
        std::string stream_mux_header;
+       MuxMetrics stream_mux_metrics;
 
        std::atomic<int> quicksync_encoders_in_shutdown{0};
        std::atomic<int> overriding_bitrate{0};