]> git.sesse.net Git - nageru/commitdiff
Add some input metrics.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 9 Jun 2017 18:18:33 +0000 (20:18 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 9 Jun 2017 18:18:33 +0000 (20:18 +0200)
mixer.cpp
mixer.h

index ccbbf1a089b27b8a2f9694d63f2d8e8fc31eea7a..03caeb3cc63208660c64c983f42f334084bbb3e9 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
@@ -198,8 +198,17 @@ void upload_texture(GLuint tex, GLuint width, GLuint height, GLuint stride, bool
 
 }  // namespace
 
+void QueueLengthPolicy::register_metrics(const string &card_name)
+{
+       global_metrics.register_int_metric("input_queue_length_frames{" + card_name + "}", &metric_input_queue_length_frames, Metrics::TYPE_GAUGE);
+       global_metrics.register_int_metric("input_queue_safe_length_frames{" + card_name + "}", &metric_input_queue_safe_length_frames, Metrics::TYPE_GAUGE);
+       global_metrics.register_int_metric("input_queue_duped_frames{" + card_name + "}", &metric_input_duped_frames);
+}
+
 void QueueLengthPolicy::update_policy(unsigned queue_length)
 {
+       metric_input_queue_length_frames = queue_length;
+
        if (queue_length == 0) {  // Starvation.
                if (been_at_safe_point_since_last_starvation && safe_queue_length < unsigned(global_flags.max_input_queue_frames)) {
                        ++safe_queue_length;
@@ -208,6 +217,8 @@ void QueueLengthPolicy::update_policy(unsigned queue_length)
                }
                frames_with_at_least_one = 0;
                been_at_safe_point_since_last_starvation = false;
+               ++metric_input_duped_frames;
+               metric_input_queue_safe_length_frames = safe_queue_length;
                return;
        }
        if (queue_length >= safe_queue_length) {
@@ -215,6 +226,7 @@ void QueueLengthPolicy::update_policy(unsigned queue_length)
        }
        if (++frames_with_at_least_one >= 1000 && safe_queue_length > 1) {
                --safe_queue_length;
+               metric_input_queue_safe_length_frames = safe_queue_length;
                fprintf(stderr, "Card %u: Spare frames for more than 1000 frames, reducing safe limit to %u frame(s)\n",
                        card_index, safe_queue_length);
                frames_with_at_least_one = 0;
@@ -458,6 +470,35 @@ void Mixer::configure_card(unsigned card_index, CaptureInterface *capture, CardT
        audio_mixer.reset_resampler(device);
        audio_mixer.set_display_name(device, card->capture->get_description());
        audio_mixer.trigger_state_changed_callback();
+
+       // Register metrics.
+       char card_name[64];
+       switch (card_type) {
+       case CardType::LIVE_CARD:
+               snprintf(card_name, sizeof(card_name), "card=\"%d\",cardtype=\"live\"", card_index);
+               break;
+       case CardType::FAKE_CAPTURE:
+               snprintf(card_name, sizeof(card_name), "card=\"%d\",cardtype=\"fake\"", card_index);
+               break;
+       case CardType::FFMPEG_INPUT:
+               snprintf(card_name, sizeof(card_name), "card=\"%d\",cardtype=\"ffmpeg\"", card_index);
+               break;
+       default:
+               assert(false);
+       }
+       card->queue_length_policy.register_metrics(card_name);
+       global_metrics.register_int_metric(string("input_dropped_frames_jitter{") + card_name + "}", &card->metric_input_dropped_frames_jitter);
+       global_metrics.register_int_metric(string("input_dropped_frames_error{") + card_name + "}", &card->metric_input_dropped_frames_error);
+       global_metrics.register_int_metric(string("input_dropped_frames_resets{") + card_name + "}", &card->metric_input_resets);
+
+       global_metrics.register_int_metric(string("input_has_signal_bool{") + card_name + "}", &card->metric_input_has_signal_bool, Metrics::TYPE_GAUGE);
+       global_metrics.register_int_metric(string("input_is_connected_bool{") + card_name + "}", &card->metric_input_is_connected_bool, Metrics::TYPE_GAUGE);
+       global_metrics.register_int_metric(string("input_interlaced_bool{") + card_name + "}", &card->metric_input_interlaced_bool, Metrics::TYPE_GAUGE);
+       global_metrics.register_int_metric(string("input_width_pixels{") + card_name + "}", &card->metric_input_width_pixels, Metrics::TYPE_GAUGE);
+       global_metrics.register_int_metric(string("input_height_pixels{") + card_name + "}", &card->metric_input_height_pixels, Metrics::TYPE_GAUGE);
+       global_metrics.register_int_metric(string("input_frame_rate_nom{") + card_name + "}", &card->metric_input_frame_rate_nom, Metrics::TYPE_GAUGE);
+       global_metrics.register_int_metric(string("input_frame_rate_den{") + card_name + "}", &card->metric_input_frame_rate_den, Metrics::TYPE_GAUGE);
+       global_metrics.register_int_metric(string("input_sample_rate_hz{") + card_name + "}", &card->metric_input_sample_rate_hz, Metrics::TYPE_GAUGE);
 }
 
 void Mixer::set_output_card_internal(int card_index)
@@ -523,6 +564,15 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
        DeviceSpec device{InputSourceType::CAPTURE_CARD, card_index};
        CaptureCard *card = &cards[card_index];
 
+       card->metric_input_has_signal_bool = video_format.has_signal;
+       card->metric_input_is_connected_bool = video_format.is_connected;
+       card->metric_input_interlaced_bool = video_format.interlaced;
+       card->metric_input_width_pixels = video_format.width;
+       card->metric_input_height_pixels = video_format.height;
+       card->metric_input_frame_rate_nom = video_format.frame_rate_nom;
+       card->metric_input_frame_rate_den = video_format.frame_rate_den;
+       card->metric_input_sample_rate_hz = audio_format.sample_rate;
+
        if (is_mode_scanning[card_index]) {
                if (video_format.has_signal) {
                        // Found a stable signal, so stop scanning.
@@ -572,10 +622,12 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
                        card_index, card->last_timecode, timecode);
                audio_mixer.reset_resampler(device);
                dropped_frames = 0;
+               ++card->metric_input_resets;
        } else if (dropped_frames > 0) {
                // Insert silence as needed.
                fprintf(stderr, "Card %d dropped %d frame(s) (before timecode 0x%04x), inserting silence.\n",
                        card_index, dropped_frames, timecode);
+               card->metric_input_dropped_frames_error += dropped_frames;
 
                bool success;
                do {
@@ -984,6 +1036,8 @@ void Mixer::trim_queue(CaptureCard *card, unsigned card_index)
                ++dropped_frames;
        }
 
+       card->metric_input_dropped_frames_jitter += dropped_frames;
+
 #if 0
        if (dropped_frames > 0) {
                fprintf(stderr, "Card %u dropped %u frame(s) to keep latency down.\n",
diff --git a/mixer.h b/mixer.h
index 3a9868d8ea8ffdbe260d97a2b861b3e1ac188ac5..dd44f74bd74906b88c622dd8ff5e819d703daf87 100644 (file)
--- a/mixer.h
+++ b/mixer.h
@@ -88,6 +88,8 @@ public:
                been_at_safe_point_since_last_starvation = false;
        }
 
+       void register_metrics(const std::string &card_name);
+
        void update_policy(unsigned queue_length);  // Call before picking out a frame, so 0 means starvation.
        unsigned get_safe_queue_length() const { return safe_queue_length; }
 
@@ -96,6 +98,11 @@ private:
        unsigned safe_queue_length = 1;  // Called N in the comments. Can never go below 1.
        unsigned frames_with_at_least_one = 0;
        bool been_at_safe_point_since_last_starvation = false;
+
+       // Metrics.
+       std::atomic<int64_t> metric_input_queue_length_frames{0};
+       std::atomic<int64_t> metric_input_queue_safe_length_frames{1};
+       std::atomic<int64_t> metric_input_duped_frames{0};
 };
 
 class Mixer {
@@ -446,6 +453,20 @@ private:
                QueueLengthPolicy queue_length_policy;  // Refers to the "new_frames" queue.
 
                int last_timecode = -1;  // Unwrapped.
+
+               // Metrics.
+               std::atomic<int64_t> metric_input_dropped_frames_jitter{0};
+               std::atomic<int64_t> metric_input_dropped_frames_error{0};
+               std::atomic<int64_t> metric_input_resets{0};
+
+               std::atomic<int64_t> metric_input_has_signal_bool{-1};
+               std::atomic<int64_t> metric_input_is_connected_bool{-1};
+               std::atomic<int64_t> metric_input_interlaced_bool{-1};
+               std::atomic<int64_t> metric_input_width_pixels{-1};
+               std::atomic<int64_t> metric_input_height_pixels{-1};
+               std::atomic<int64_t> metric_input_frame_rate_nom{-1};
+               std::atomic<int64_t> metric_input_frame_rate_den{-1};
+               std::atomic<int64_t> metric_input_sample_rate_hz{-1};
        };
        CaptureCard cards[MAX_VIDEO_CARDS];  // Protected by <card_mutex>.
        YCbCrInterpretation ycbcr_interpretation[MAX_VIDEO_CARDS];  // Protected by <card_mutex>.