]> git.sesse.net Git - nageru/blobdiff - nageru/mixer.cpp
WIP patch for async output.
[nageru] / nageru / mixer.cpp
index ce8a73237fd4a838ee85ca0c307663d6e3c9edda..22867422858e0913eb6dcd52fcb2ddac5767b09f 100644 (file)
@@ -232,7 +232,7 @@ void JitterHistory::unregister_metrics(const vector<pair<string, string>> &label
        global_metrics.remove("input_estimated_max_jitter_seconds", labels);
 }
 
-void JitterHistory::frame_arrived(steady_clock::time_point now, int64_t frame_duration, size_t dropped_frames)
+void JitterHistory::frame_arrived(steady_clock::time_point now, int64_t frame_duration, size_t dropped_frames, bool verbose)
 {
        if (frame_duration != last_duration) {
                // If the frame rate changed, the input clock is also going to change,
@@ -243,10 +243,23 @@ void JitterHistory::frame_arrived(steady_clock::time_point now, int64_t frame_du
                // rather keep the history so that we take jitter they may introduce into account.)
                clear();
                last_duration = frame_duration;
+               if (verbose) {
+                       fprintf(stderr, "JITTER %p: clearing due to format change\n", this);
+               }
        }
        if (expected_timestamp > steady_clock::time_point::min()) {
                expected_timestamp += dropped_frames * nanoseconds(frame_duration * 1000000000 / TIMEBASE);
                double jitter_seconds = fabs(duration<double>(expected_timestamp - now).count());
+               if (verbose) {
+                       fprintf(stderr, "JITTER %p: expected_ts=%.6f (after adding %.1f ms for %zu dropped frames, duration=%ld), now=%.6f => %.1f ms late\n",
+                               this,
+                               duration<double>(expected_timestamp.time_since_epoch()).count(),
+                               1e3 * dropped_frames * duration<double>(nanoseconds(frame_duration * 1000000000 / TIMEBASE)).count(),
+                               dropped_frames,
+                               frame_duration,
+                               duration<double>(now.time_since_epoch()).count(),
+                               1e3 * duration<double>(now - expected_timestamp).count());
+               }
                history.push_back(orders.insert(jitter_seconds));
                if (jitter_seconds > estimate_max_jitter()) {
                        ++metric_input_underestimated_jitter_frames;
@@ -259,6 +272,12 @@ void JitterHistory::frame_arrived(steady_clock::time_point now, int64_t frame_du
                        history.pop_front();
                }
                assert(history.size() <= history_length);
+       } else if (verbose) {
+               fprintf(stderr, "JITTER %p: now=%.6f, expected=%.6f duration=%ld [initial]\n",
+                       this,
+                       duration<double>(now.time_since_epoch()).count(),
+                       duration<double>((now + nanoseconds(frame_duration * 1000000000 / TIMEBASE)).time_since_epoch()).count(),
+                       frame_duration);
        }
        expected_timestamp = now + nanoseconds(frame_duration * 1000000000 / TIMEBASE);
 }
@@ -291,7 +310,7 @@ void QueueLengthPolicy::update_policy(steady_clock::time_point now,
                                       int64_t input_frame_duration,
                                       int64_t master_frame_duration,
                                       double max_input_card_jitter_seconds,
-                                      double max_master_card_jitter_seconds)
+                                      double max_master_card_jitter_seconds, bool verbose)
 {
        double input_frame_duration_seconds = input_frame_duration / double(TIMEBASE);
        double master_frame_duration_seconds = master_frame_duration / double(TIMEBASE);
@@ -318,6 +337,13 @@ void QueueLengthPolicy::update_policy(steady_clock::time_point now,
        } else {
                frames_allowed = frames_needed;
        }
+       if (verbose) {
+               fprintf(stderr, "secs_until_next_frame = %.1f ms, input jitter = %.1f ms, master jitter = %.1f ms, frames_allowed = %.3f\n",
+                       1e3 * duration<double>(expected_next_input_frame - now).count(),
+                       1e3 * max_input_card_jitter_seconds,
+                       1e3 * max_master_card_jitter_seconds,
+                       frames_allowed);
+       }
 
        safe_queue_length = max<int>(floor(frames_allowed), 0);
        metric_input_queue_safe_length_frames = safe_queue_length;
@@ -899,7 +925,7 @@ void Mixer::set_output_card_internal(int card_index)
                card->jitter_history.clear();
                card->capture->start_bm_capture();
                desired_output_video_mode = output_video_mode = card->output->pick_video_mode(desired_output_video_mode);
-               card->output->start_output(desired_output_video_mode, pts_int);
+               card->output->start_output(desired_output_video_mode, pts_int, /*is_master_card=*/slave_to_output);
        }
        output_card_index = card_index;
        output_jitter_history.clear();
@@ -1286,7 +1312,7 @@ void Mixer::thread_func()
                        DeckLinkOutput *output = cards[output_card_index].output.get();
                        output->end_output();
                        desired_output_video_mode = output_video_mode = output->pick_video_mode(desired_output_video_mode);
-                       output->start_output(desired_output_video_mode, pts_int);
+                       output->start_output(desired_output_video_mode, pts_int, /*is_master_card=*/slave_to_output);
                }
 
                {
@@ -1299,7 +1325,7 @@ void Mixer::thread_func()
 
                bool master_card_is_output;
                unsigned master_card_index;
-               if (output_card_index != -1) {
+               if (output_card_index != -1 && slave_to_output) {
                        master_card_is_output = true;
                        master_card_index = output_card_index;
                } else {
@@ -1406,7 +1432,7 @@ void Mixer::thread_func()
 
 bool Mixer::input_card_is_master_clock(unsigned card_index, unsigned master_card_index) const
 {
-       if (output_card_index != -1) {
+       if (output_card_index != -1 && slave_to_output) {
                // The output card (ie., cards[output_card_index].output) is the master clock,
                // so no input card (ie., cards[card_index].capture) is.
                return false;