]> git.sesse.net Git - nageru/commitdiff
Prepare get_one_frame_from_each_card() interface for different clocks.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 24 Dec 2016 10:50:00 +0000 (11:50 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 24 Dec 2016 11:02:25 +0000 (12:02 +0100)
This interface is more flexible, and less bound to the idea of having
the master clock locked to an input card.

mixer.cpp
mixer.h

index 85f974b401d08c054ecf4e3ad4b3a0870f622dd1..db7a060ce392aae209b38d94cfc95ec60d73cf09 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
@@ -330,7 +330,6 @@ void Mixer::configure_card(unsigned card_index, CaptureInterface *capture, bool
                card->surface = create_surface_with_same_format(mixer_surface);
        }
        while (!card->new_frames.empty()) card->new_frames.pop();
-       card->fractional_samples = 0;
        card->last_timecode = -1;
        card->capture->configure_card();
 
@@ -606,14 +605,13 @@ void Mixer::thread_func()
        while (!should_quit) {
                CaptureCard::NewFrame new_frames[MAX_VIDEO_CARDS];
                bool has_new_frame[MAX_VIDEO_CARDS] = { false };
-               int num_samples[MAX_VIDEO_CARDS] = { 0 };
 
                unsigned master_card_index = theme->map_signal(master_clock_channel);
                assert(master_card_index < num_cards);
 
-               get_one_frame_from_each_card(master_card_index, new_frames, has_new_frame, num_samples);
-               schedule_audio_resampling_tasks(new_frames[master_card_index].dropped_frames, num_samples[master_card_index], new_frames[master_card_index].length);
-               stats_dropped_frames += new_frames[master_card_index].dropped_frames;
+               OutputFrameInfo output_frame_info = get_one_frame_from_each_card(master_card_index, new_frames, has_new_frame);
+               schedule_audio_resampling_tasks(output_frame_info.dropped_frames, output_frame_info.num_samples, output_frame_info.frame_duration);
+               stats_dropped_frames += output_frame_info.dropped_frames;
 
                handle_hotplugged_cards();
 
@@ -654,7 +652,7 @@ void Mixer::thread_func()
                        }
                }
 
-               int64_t frame_duration = new_frames[master_card_index].length;
+               int64_t frame_duration = output_frame_info.frame_duration;
                render_one_frame(frame_duration);
                ++frame;
                pts_int += frame_duration;
@@ -715,8 +713,10 @@ void Mixer::thread_func()
        resource_pool->clean_context();
 }
 
-void Mixer::get_one_frame_from_each_card(unsigned master_card_index, CaptureCard::NewFrame new_frames[MAX_VIDEO_CARDS], bool has_new_frame[MAX_VIDEO_CARDS], int num_samples[MAX_VIDEO_CARDS])
+Mixer::OutputFrameInfo Mixer::get_one_frame_from_each_card(unsigned master_card_index, CaptureCard::NewFrame new_frames[MAX_VIDEO_CARDS], bool has_new_frame[MAX_VIDEO_CARDS])
 {
+       OutputFrameInfo output_frame_info;
+
 start:
        // The first card is the master timer, so wait for it to have a new frame.
        // TODO: Add a timeout.
@@ -743,11 +743,6 @@ start:
                card->new_frames.pop();
                card->new_frames_changed.notify_all();
 
-               int num_samples_times_timebase = OUTPUT_FREQUENCY * new_frames[card_index].length + card->fractional_samples;
-               num_samples[card_index] = num_samples_times_timebase / TIMEBASE;
-               card->fractional_samples = num_samples_times_timebase % TIMEBASE;
-               assert(num_samples[card_index] >= 0);
-
                if (card_index == master_card_index) {
                        // We don't use the queue length policy for the master card,
                        // but we will if it stops being the master. Thus, clear out
@@ -762,6 +757,18 @@ start:
                        }
                }
        }
+
+       output_frame_info.dropped_frames = new_frames[master_card_index].dropped_frames;
+       output_frame_info.frame_duration = new_frames[master_card_index].length;
+
+       // This might get off by a fractional sample when changing master card
+       // between ones with different frame rates, but that's fine.
+       int num_samples_times_timebase = OUTPUT_FREQUENCY * output_frame_info.frame_duration + fractional_samples;
+       output_frame_info.num_samples = num_samples_times_timebase / TIMEBASE;
+       fractional_samples = num_samples_times_timebase % TIMEBASE;
+       assert(output_frame_info.num_samples >= 0);
+
+       return output_frame_info;
 }
 
 void Mixer::handle_hotplugged_cards()
diff --git a/mixer.h b/mixer.h
index 0de651915f6fe9aa0a3c268fd993121b9e3c3dbf..28b190b531a1c86a6c617ffd274d16f2d024f3a0 100644 (file)
--- a/mixer.h
+++ b/mixer.h
@@ -320,6 +320,10 @@ private:
 
        int64_t pts_int = 0;  // In TIMEBASE units.
 
+       // Accumulated errors in number of 1/TIMEBASE audio samples. If OUTPUT_FREQUENCY divided by
+       // frame rate is integer, will always stay zero.
+       unsigned fractional_samples = 0;
+
        std::mutex bmusb_mutex;
        bool has_bmusb_thread = false;
        struct CaptureCard {
@@ -345,15 +349,16 @@ private:
 
                QueueLengthPolicy queue_length_policy;  // Refers to the "new_frames" queue.
 
-               // Accumulated errors in number of 1/TIMEBASE samples. If OUTPUT_FREQUENCY divided by
-               // frame rate is integer, will always stay zero.
-               unsigned fractional_samples = 0;
-
                int last_timecode = -1;  // Unwrapped.
        };
        CaptureCard cards[MAX_VIDEO_CARDS];  // protected by <bmusb_mutex>
        AudioMixer audio_mixer;  // Same as global_audio_mixer (see audio_mixer.h).
-       void get_one_frame_from_each_card(unsigned master_card_index, CaptureCard::NewFrame new_frames[MAX_VIDEO_CARDS], bool has_new_frame[MAX_VIDEO_CARDS], int num_samples[MAX_VIDEO_CARDS]);
+       struct OutputFrameInfo {
+               int dropped_frames;  // Since last frame.
+               int num_samples;  // Audio samples needed for this output frame.
+               int64_t frame_duration;  // In TIMEBASE units.
+       };
+       OutputFrameInfo get_one_frame_from_each_card(unsigned master_card_index, CaptureCard::NewFrame new_frames[MAX_VIDEO_CARDS], bool has_new_frame[MAX_VIDEO_CARDS]);
 
        InputState input_state;