]> git.sesse.net Git - nageru/commitdiff
Factor the basic metrics (memory, uptime, etc.) into a separate class, so that Kaeru...
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 10 Jul 2017 10:36:39 +0000 (12:36 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 10 Jul 2017 10:36:39 +0000 (12:36 +0200)
Makefile
basic_stats.cpp [new file with mode: 0644]
basic_stats.h [new file with mode: 0644]
kaeru.cpp
main.cpp
mixer.cpp
mixer.h

index ae66a3972d384c95d6ae5cb858fdb5154bbf9a2d..2c20001090581fcd0a436bdd5637bb846ea865dd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,7 @@ OBJS += midi_mapper.o midi_mapping.pb.o
 
 # Mixer objects
 AUDIO_MIXER_OBJS = audio_mixer.o alsa_input.o alsa_pool.o ebu_r128_proc.o stereocompressor.o resampling_queue.o flags.o correlation_measurer.o filter.o input_mapping.o state.pb.o
-OBJS += chroma_subsampler.o v210_converter.o mixer.o metrics.o pbo_frame_allocator.o context.o ref_counted_frame.o theme.o httpd.o flags.o image_input.o alsa_output.o disk_space_estimator.o print_latency.o timecode_renderer.o tweaked_inputs.o $(AUDIO_MIXER_OBJS)
+OBJS += chroma_subsampler.o v210_converter.o mixer.o basic_stats.o metrics.o pbo_frame_allocator.o context.o ref_counted_frame.o theme.o httpd.o flags.o image_input.o alsa_output.o disk_space_estimator.o print_latency.o timecode_renderer.o tweaked_inputs.o $(AUDIO_MIXER_OBJS)
 
 # Streaming and encoding objects
 OBJS += quicksync_encoder.o x264_encoder.o x264_dynamic.o x264_speed_control.o video_encoder.o metacube2.o mux.o audio_encoder.o ffmpeg_raii.o ffmpeg_util.o
@@ -30,7 +30,7 @@ OBJS += quicksync_encoder.o x264_encoder.o x264_dynamic.o x264_speed_control.o v
 # DeckLink
 OBJS += decklink_capture.o decklink_util.o decklink_output.o decklink/DeckLinkAPIDispatch.o
 
-KAERU_OBJS = kaeru.o x264_encoder.o mux.o metrics.o flags.o audio_encoder.o x264_speed_control.o print_latency.o x264_dynamic.o ffmpeg_raii.o ffmpeg_capture.o ffmpeg_util.o httpd.o metacube2.o
+KAERU_OBJS = kaeru.o x264_encoder.o mux.o basic_stats.o metrics.o flags.o audio_encoder.o x264_speed_control.o print_latency.o x264_dynamic.o ffmpeg_raii.o ffmpeg_capture.o ffmpeg_util.o httpd.o metacube2.o
 
 # bmusb
 ifeq ($(EMBEDDED_BMUSB),yes)
diff --git a/basic_stats.cpp b/basic_stats.cpp
new file mode 100644 (file)
index 0000000..63d5493
--- /dev/null
@@ -0,0 +1,84 @@
+#include "basic_stats.h"
+#include "metrics.h"
+
+#include <assert.h>
+#include <sys/resource.h>
+
+using namespace std;
+using namespace std::chrono;
+
+bool uses_mlock = false;
+
+BasicStats::BasicStats(bool verbose)
+       : verbose(verbose)
+{
+       start = steady_clock::now();
+
+       metric_start_time_seconds = get_timestamp_for_metrics();
+       global_metrics.add("frames_output_total", &metric_frames_output_total);
+       global_metrics.add("frames_output_dropped", &metric_frames_output_dropped);
+       global_metrics.add("start_time_seconds", &metric_start_time_seconds, Metrics::TYPE_GAUGE);
+       global_metrics.add("memory_used_bytes", &metrics_memory_used_bytes);
+       global_metrics.add("memory_locked_limit_bytes", &metrics_memory_locked_limit_bytes);
+}
+
+void BasicStats::update(int frame_num, int stats_dropped_frames)
+{
+       steady_clock::time_point now = steady_clock::now();
+       double elapsed = duration<double>(now - start).count();
+
+       metric_frames_output_total = frame_num;
+       metric_frames_output_dropped = stats_dropped_frames;
+
+       if (frame_num % 100 != 0) {
+               return;
+       }
+
+       if (verbose) {
+               printf("%d frames (%d dropped) in %.3f seconds = %.1f fps (%.1f ms/frame)",
+                       frame_num, stats_dropped_frames, elapsed, frame_num / elapsed,
+                       1e3 * elapsed / frame_num);
+       }
+
+       // Check our memory usage, to see if we are close to our mlockall()
+       // limit (if at all set).
+       rusage used;
+       if (getrusage(RUSAGE_SELF, &used) == -1) {
+               perror("getrusage(RUSAGE_SELF)");
+               assert(false);
+       }
+       metrics_memory_used_bytes = used.ru_maxrss * 1024;
+
+       if (uses_mlock) {
+               rlimit limit;
+               if (getrlimit(RLIMIT_MEMLOCK, &limit) == -1) {
+                       perror("getrlimit(RLIMIT_MEMLOCK)");
+                       assert(false);
+               }
+               metrics_memory_locked_limit_bytes = limit.rlim_cur;
+
+               if (verbose) {
+                       if (limit.rlim_cur == 0) {
+                               printf(", using %ld MB memory (locked)",
+                                               long(used.ru_maxrss / 1024));
+                       } else {
+                               printf(", using %ld / %ld MB lockable memory (%.1f%%)",
+                                               long(used.ru_maxrss / 1024),
+                                               long(limit.rlim_cur / 1048576),
+                                               float(100.0 * (used.ru_maxrss * 1024.0) / limit.rlim_cur));
+                       }
+               }
+       } else {
+               metrics_memory_locked_limit_bytes = 0.0 / 0.0;
+               if (verbose) {
+                       printf(", using %ld MB memory (not locked)",
+                                       long(used.ru_maxrss / 1024));
+               }
+       }
+
+       if (verbose) {
+               printf("\n");
+       }
+}
+
+
diff --git a/basic_stats.h b/basic_stats.h
new file mode 100644 (file)
index 0000000..800d6e6
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _BASIC_STATS_H
+#define _BASIC_STATS_H
+
+// Holds some metrics for basic statistics about uptime, memory usage and such.
+
+#include <stdint.h>
+
+#include <atomic>
+#include <chrono>
+
+extern bool uses_mlock;
+
+class BasicStats {
+public:
+       BasicStats(bool verbose);
+       void update(int frame_num, int stats_dropped_frames);
+
+private:
+       std::chrono::steady_clock::time_point start;
+       bool verbose;
+
+       // Metrics.
+       std::atomic<int64_t> metric_frames_output_total{0};
+       std::atomic<int64_t> metric_frames_output_dropped{0};
+       std::atomic<double> metric_start_time_seconds{0.0 / 0.0};
+       std::atomic<int64_t> metrics_memory_used_bytes{0};
+       std::atomic<double> metrics_memory_locked_limit_bytes{0.0 / 0.0};
+};
+
+#endif  // !defined(_BASIC_STATS_H)
index 7bf0ae953c2267d83ca5b006dca5900189c8faad..efbb4f11341360863f7bc8383c7cce299bb45bea 100644 (file)
--- a/kaeru.cpp
+++ b/kaeru.cpp
@@ -2,6 +2,7 @@
 // This is experimental code, not yet supported.
 
 #include "audio_encoder.h"
+#include "basic_stats.h"
 #include "defs.h"
 #include "flags.h"
 #include "ffmpeg_capture.h"
@@ -25,6 +26,8 @@ using namespace std::placeholders;
 
 Mixer *global_mixer = nullptr;
 X264Encoder *global_x264_encoder = nullptr;
+int frame_num = 0;
+BasicStats *global_basic_stats = nullptr;
 MuxMetrics stream_mux_metrics;
 
 int write_packet(void *opaque, uint8_t *buf, int buf_size, AVIODataMarkerType type, int64_t time)
@@ -84,6 +87,7 @@ void video_frame_callback(FFmpegCapture *video, X264Encoder *x264_encoder, Audio
                video_pts = av_rescale_q(video_pts, video_timebase, AVRational{ 1, TIMEBASE });
                int64_t frame_duration = TIMEBASE * video_format.frame_rate_den / video_format.frame_rate_nom;
                x264_encoder->add_frame(video_pts, frame_duration, video->get_current_frame_ycbcr_format().luma_coefficients, video_frame.data + video_offset, ts);
+               global_basic_stats->update(frame_num++, /*dropped_frames=*/0);
        }
        if (audio_frame.len > 0) {
                // FFmpegCapture takes care of this for us.
@@ -196,6 +200,8 @@ int main(int argc, char *argv[])
        video.start_bm_capture();
        video.change_rate(2.0);  // Be sure never to really fall behind, but also don't dump huge amounts of stuff onto x264.
 
+       BasicStats basic_stats(/*verbose=*/false);
+       global_basic_stats = &basic_stats;
        httpd.start(9095);
 
        signal(SIGUSR1, adjust_bitrate);
index fb67e0ea23ecb0e57456edfbb7dd8e55778bf0e4..d0427d1489a353ffb720462051d537d08f8822a4 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -13,6 +13,7 @@ extern "C" {
 #include <QSurfaceFormat>
 #include <string>
 
+#include "basic_stats.h"
 #include "context.h"
 #include "flags.h"
 #include "image_input.h"
index 7bfa009ca5ee49befa636859fcbbe3237767f886..f1d116fe497bdeb0e6f020aef2a7b468624ede2a 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
@@ -14,7 +14,6 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/resource.h>
 #include <algorithm>
 #include <chrono>
 #include <condition_variable>
@@ -31,6 +30,7 @@
 #include "DeckLinkAPI.h"
 #include "LinuxCOM.h"
 #include "alsa_output.h"
+#include "basic_stats.h"
 #include "bmusb/bmusb.h"
 #include "bmusb/fake_capture.h"
 #include "chroma_subsampler.h"
@@ -61,7 +61,6 @@ using namespace std::placeholders;
 using namespace bmusb;
 
 Mixer *global_mixer = nullptr;
-bool uses_mlock = false;
 
 namespace {
 
@@ -460,14 +459,7 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards)
                set_output_card_internal(global_flags.output_card);
        }
 
-       metric_start_time_seconds = get_timestamp_for_metrics();
-
        output_jitter_history.register_metrics({{ "card", "output" }});
-       global_metrics.add("frames_output_total", &metric_frames_output_total);
-       global_metrics.add("frames_output_dropped", &metric_frames_output_dropped);
-       global_metrics.add("start_time_seconds", &metric_start_time_seconds, Metrics::TYPE_GAUGE);
-       global_metrics.add("memory_used_bytes", &metrics_memory_used_bytes);
-       global_metrics.add("memory_locked_limit_bytes", &metrics_memory_locked_limit_bytes);
 }
 
 Mixer::~Mixer()
@@ -947,9 +939,7 @@ void Mixer::thread_func()
                }
        }
 
-       steady_clock::time_point start, now;
-       start = steady_clock::now();
-
+       BasicStats basic_stats(/*verbose=*/true);
        int stats_dropped_frames = 0;
 
        while (!should_quit) {
@@ -1026,54 +1016,8 @@ void Mixer::thread_func()
                ++frame_num;
                pts_int += frame_duration;
 
-               now = steady_clock::now();
-               double elapsed = duration<double>(now - start).count();
-
-               metric_frames_output_total = frame_num;
-               metric_frames_output_dropped = stats_dropped_frames;
-
-               if (frame_num % 100 == 0) {
-                       printf("%d frames (%d dropped) in %.3f seconds = %.1f fps (%.1f ms/frame)",
-                               frame_num, stats_dropped_frames, elapsed, frame_num / elapsed,
-                               1e3 * elapsed / frame_num);
-               //      chain->print_phase_timing();
-
-                       // Check our memory usage, to see if we are close to our mlockall()
-                       // limit (if at all set).
-                       rusage used;
-                       if (getrusage(RUSAGE_SELF, &used) == -1) {
-                               perror("getrusage(RUSAGE_SELF)");
-                               assert(false);
-                       }
-
-                       if (uses_mlock) {
-                               rlimit limit;
-                               if (getrlimit(RLIMIT_MEMLOCK, &limit) == -1) {
-                                       perror("getrlimit(RLIMIT_MEMLOCK)");
-                                       assert(false);
-                               }
-
-                               if (limit.rlim_cur == 0) {
-                                       printf(", using %ld MB memory (locked)",
-                                               long(used.ru_maxrss / 1024));
-                               } else {
-                                       printf(", using %ld / %ld MB lockable memory (%.1f%%)",
-                                               long(used.ru_maxrss / 1024),
-                                               long(limit.rlim_cur / 1048576),
-                                               float(100.0 * (used.ru_maxrss * 1024.0) / limit.rlim_cur));
-                               }
-                               metrics_memory_locked_limit_bytes = limit.rlim_cur;
-                       } else {
-                               printf(", using %ld MB memory (not locked)",
-                                       long(used.ru_maxrss / 1024));
-                               metrics_memory_locked_limit_bytes = 0.0 / 0.0;
-                       }
-
-                       printf("\n");
-
-                       metrics_memory_used_bytes = used.ru_maxrss * 1024;
-               }
-
+               basic_stats.update(frame_num, stats_dropped_frames);
+               // if (frame_num % 100 == 0) chain->print_phase_timing();
 
                if (should_cut.exchange(false)) {  // Test and clear.
                        video_encoder->do_cut(frame_num);
diff --git a/mixer.h b/mixer.h
index 572b26fcf97ef54179edddec6bcb8489ad3683bf..ff501b17635cd8830ba36e084754577cd75902b5 100644 (file)
--- a/mixer.h
+++ b/mixer.h
@@ -592,16 +592,8 @@ private:
        std::vector<uint32_t> mode_scanlist[MAX_VIDEO_CARDS];
        unsigned mode_scanlist_index[MAX_VIDEO_CARDS]{ 0 };
        std::chrono::steady_clock::time_point last_mode_scan_change[MAX_VIDEO_CARDS];
-
-       // Metrics.
-       std::atomic<int64_t> metric_frames_output_total{0};
-       std::atomic<int64_t> metric_frames_output_dropped{0};
-       std::atomic<double> metric_start_time_seconds{0.0 / 0.0};
-       std::atomic<int64_t> metrics_memory_used_bytes{0};
-       std::atomic<double> metrics_memory_locked_limit_bytes{0.0 / 0.0};
 };
 
 extern Mixer *global_mixer;
-extern bool uses_mlock;
 
 #endif  // !defined(_MIXER_H)