]> git.sesse.net Git - nageru/blobdiff - mixer.h
Release Nageru 1.6.0.
[nageru] / mixer.h
diff --git a/mixer.h b/mixer.h
index 8f5342afd4f7a5df0257a22ec119b67a6cb9dd24..73dfa3b53e5690a94557113a2d69fb8f9bfb1599 100644 (file)
--- a/mixer.h
+++ b/mixer.h
@@ -23,6 +23,8 @@
 #include <thread>
 #include <vector>
 
+#include <movit/image_format.h>
+
 #include "audio_mixer.h"
 #include "bmusb/bmusb.h"
 #include "defs.h"
@@ -35,6 +37,7 @@
 #include "theme.h"
 #include "timebase.h"
 #include "video_encoder.h"
+#include "ycbcr_interpretation.h"
 
 class ALSAOutput;
 class ChromaSubsampler;
@@ -47,8 +50,8 @@ class v210Converter;
 namespace movit {
 class Effect;
 class EffectChain;
-class FlatInput;
 class ResourcePool;
+class YCbCrInput;
 }  // namespace movit
 
 // For any card that's not the master (where we pick out the frames as they
@@ -139,10 +142,17 @@ public:
                return output_channel[output].get_display_frame(frame);
        }
 
+       // NOTE: Callbacks will be called with a mutex held, so you should probably
+       // not do real work in them.
        typedef std::function<void()> new_frame_ready_callback_t;
-       void set_frame_ready_callback(Output output, new_frame_ready_callback_t callback)
+       void add_frame_ready_callback(Output output, void *key, new_frame_ready_callback_t callback)
+       {
+               output_channel[output].add_frame_ready_callback(key, callback);
+       }
+
+       void remove_frame_ready_callback(Output output, void *key)
        {
-               output_channel[output].set_frame_ready_callback(callback);
+               output_channel[output].remove_frame_ready_callback(key);
        }
 
        // TODO: Should this really be per-channel? Shouldn't it just be called for e.g. the live output?
@@ -209,6 +219,9 @@ public:
                return theme->set_signal_mapping(signal, card);
        }
 
+       YCbCrInterpretation get_input_ycbcr_interpretation(unsigned card_index) const;
+       void set_input_ycbcr_interpretation(unsigned card_index, const YCbCrInterpretation &interpretation);
+
        bool get_supports_set_wb(unsigned channel) const
        {
                return theme->get_supports_set_wb(channel);
@@ -334,7 +347,12 @@ public:
 private:
        struct CaptureCard;
 
-       void configure_card(unsigned card_index, bmusb::CaptureInterface *capture, bool is_fake_capture, DeckLinkOutput *output);
+       enum class CardType {
+               LIVE_CARD,
+               FAKE_CAPTURE,
+               FFMPEG_INPUT
+       };
+       void configure_card(unsigned card_index, bmusb::CaptureInterface *capture, CardType card_type, DeckLinkOutput *output);
        void set_output_card_internal(int card_index);  // Should only be called from the mixer thread.
        void bm_frame(unsigned card_index, uint16_t timecode,
                bmusb::FrameAllocator::Frame video_frame, size_t video_offset, bmusb::VideoFormat video_format,
@@ -355,7 +373,7 @@ private:
        void trim_queue(CaptureCard *card, unsigned card_index);
 
        HTTPD httpd;
-       unsigned num_cards;
+       unsigned num_cards, num_video_inputs;
 
        QSurface *mixer_surface, *h264_encoder_surface, *decklink_output_surface;
        std::unique_ptr<movit::ResourcePool> resource_pool;
@@ -383,7 +401,7 @@ private:
        std::atomic<bool> display_timecode_on_stdout{false};
 
        // Effects part of <display_chain>. Owned by <display_chain>.
-       movit::FlatInput *display_input;
+       movit::YCbCrInput *display_input;
 
        int64_t pts_int = 0;  // In TIMEBASE units.
        unsigned frame_num = 0;
@@ -397,6 +415,7 @@ private:
        struct CaptureCard {
                std::unique_ptr<bmusb::CaptureInterface> capture;
                bool is_fake_capture;
+               CardType type;
                std::unique_ptr<DeckLinkOutput> output;
 
                // If this card is used for output (ie., output_card_index points to it),
@@ -429,6 +448,7 @@ private:
                int last_timecode = -1;  // Unwrapped.
        };
        CaptureCard cards[MAX_VIDEO_CARDS];  // Protected by <card_mutex>.
+       YCbCrInterpretation ycbcr_interpretation[MAX_VIDEO_CARDS];  // Protected by <card_mutex>.
        AudioMixer audio_mixer;  // Same as global_audio_mixer (see audio_mixer.h).
        bool input_card_is_master_clock(unsigned card_index, unsigned master_card_index) const;
        struct OutputFrameInfo {
@@ -452,7 +472,8 @@ private:
                ~OutputChannel();
                void output_frame(DisplayFrame frame);
                bool get_display_frame(DisplayFrame *frame);
-               void set_frame_ready_callback(new_frame_ready_callback_t callback);
+               void add_frame_ready_callback(void *key, new_frame_ready_callback_t callback);
+               void remove_frame_ready_callback(void *key);
                void set_transition_names_updated_callback(transition_names_updated_callback_t callback);
                void set_name_updated_callback(name_updated_callback_t callback);
                void set_color_updated_callback(color_updated_callback_t callback);
@@ -465,7 +486,7 @@ private:
                std::mutex frame_mutex;
                DisplayFrame current_frame, ready_frame;  // protected by <frame_mutex>
                bool has_current_frame = false, has_ready_frame = false;  // protected by <frame_mutex>
-               new_frame_ready_callback_t new_frame_ready_callback;
+               std::map<void *, new_frame_ready_callback_t> new_frame_ready_callbacks;  // protected by <frame_mutex>
                transition_names_updated_callback_t transition_names_updated_callback;
                name_updated_callback_t name_updated_callback;
                color_updated_callback_t color_updated_callback;