X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Fmixer.cpp;h=22867422858e0913eb6dcd52fcb2ddac5767b09f;hb=896b8bb8e44409738aef56ba7d7b7f300c22d2ce;hp=ce8a73237fd4a838ee85ca0c307663d6e3c9edda;hpb=0f5b8fd8420a450f5994d5f535fdce84dbb10093;p=nageru diff --git a/nageru/mixer.cpp b/nageru/mixer.cpp index ce8a732..2286742 100644 --- a/nageru/mixer.cpp +++ b/nageru/mixer.cpp @@ -232,7 +232,7 @@ void JitterHistory::unregister_metrics(const vector> &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(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(expected_timestamp.time_since_epoch()).count(), + 1e3 * dropped_frames * duration(nanoseconds(frame_duration * 1000000000 / TIMEBASE)).count(), + dropped_frames, + frame_duration, + duration(now.time_since_epoch()).count(), + 1e3 * duration(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(now.time_since_epoch()).count(), + duration((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(expected_next_input_frame - now).count(), + 1e3 * max_input_card_jitter_seconds, + 1e3 * max_master_card_jitter_seconds, + frames_allowed); + } safe_queue_length = max(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;