]> git.sesse.net Git - nageru/commitdiff
Move all mixer stuff into a class.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 4 Oct 2015 21:52:56 +0000 (23:52 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 4 Oct 2015 21:52:56 +0000 (23:52 +0200)
glwidget.cpp
main.cpp
mainwindow.cpp
mixer.cpp
mixer.h

index 319592e5e89a99a98c7f6f27da7758866a4cc0b6..7f7e0082a1baee969ed98c4de1d42c60763dcd66 100644 (file)
@@ -39,7 +39,7 @@ void GLWidget::initializeGL()
        //printf("threads: %p %p\n", QThread::currentThread(), qGuiApp->thread());
 
        GLWidget *t = this;
-       set_frame_ready_fallback([t]{
+       global_mixer->set_frame_ready_fallback([t]{
                QMetaObject::invokeMethod(t, "update", Qt::AutoConnection);
        });
 
@@ -48,7 +48,8 @@ void GLWidget::initializeGL()
        QSurface *surface2 = create_surface(fmt);
        QSurface *surface3 = create_surface(fmt);
        QSurface *surface4 = create_surface(fmt);
-       start_mixer(surface, surface2, surface3, surface4);
+       global_mixer = new Mixer;
+       global_mixer->start(surface, surface2, surface3, surface4);
 
        // Prepare the shaders to actually get the texture shown (ick).
        glDisable(GL_BLEND);
@@ -103,8 +104,8 @@ void GLWidget::resizeGL(int width, int height)
 
 void GLWidget::paintGL()
 {
-       DisplayFrame frame;
-       if (!mixer_get_display_frame(&frame)) {
+       Mixer::DisplayFrame frame;
+       if (!global_mixer->get_display_frame(&frame)) {
                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                return;
index f92b12e37735890b28110680d56b04d46d3de7d2..d3206f7ff86786032b55a978105cf7e0874c70e4 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -35,6 +35,6 @@ int main(int argc, char *argv[])
        mainWindow.show();
 
        int rc = app.exec();
-       mixer_quit();
+       global_mixer->quit();
        return rc;
 }
index b8d9e67a9461cb81394645088e30fa95737abcb5..badc2368c1900769e210032608f1866a8a64a9d0 100644 (file)
@@ -19,5 +19,5 @@ MainWindow::MainWindow()
 void MainWindow::cut()
 {
        static int i = 0;
-       mixer_cut(Source((++i) % 3));
+       global_mixer->cut(Mixer::Source((++i) % 3));
 }
index fec83ff1d90c05c8f5e908e2640a018dfec4fdef..057efb93fb20a3ba87a408498ee6f40cf51bebdf 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
@@ -1,7 +1,3 @@
-#define GL_GLEXT_PROTOTYPES 1
-#define NO_SDL_GLEXT 1
-#define NUM_CARDS 2
-
 #define WIDTH 1280
 #define HEIGHT 720
 
@@ -52,36 +48,11 @@ using namespace movit;
 using namespace std;
 using namespace std::placeholders;
 
-Source current_source = SOURCE_INPUT1;
-
-ResourcePool *resource_pool;
-
-std::mutex display_frame_mutex;
-DisplayFrame current_display_frame, ready_display_frame;  // protected by <frame_mutex>
-bool has_current_display_frame = false, has_ready_display_frame = false;  // protected by <frame_mutex>
-
-std::mutex bmusb_mutex;
-struct CaptureCard {
-       BMUSBCapture *usb;
-
-       // Threading stuff
-       bool thread_initialized;
-       QSurface *surface;
-       QOpenGLContext *context;
+Mixer *global_mixer = nullptr;
 
-       bool new_data_ready;  // Whether new_frame contains anything.
-       PBOFrameAllocator::Frame new_frame;
-       GLsync new_data_ready_fence;  // Whether new_frame is ready for rendering.
-       std::condition_variable new_data_ready_changed;  // Set whenever new_data_ready is changed.
-};
-CaptureCard cards[NUM_CARDS];  // protected by <bmusb_mutex>
-
-new_frame_ready_callback_t new_frame_ready_callback;
-bool has_new_frame_ready_callback = false;
-
-void bm_frame(int card_index, uint16_t timecode,
-              FrameAllocator::Frame video_frame, size_t video_offset, uint16_t video_format,
-             FrameAllocator::Frame audio_frame, size_t audio_offset, uint16_t audio_format)
+void Mixer::bm_frame(int card_index, uint16_t timecode,
+                     FrameAllocator::Frame video_frame, size_t video_offset, uint16_t video_format,
+                    FrameAllocator::Frame audio_frame, size_t audio_offset, uint16_t audio_format)
 {
        CaptureCard *card = &cards[card_index];
        if (!card->thread_initialized) {
@@ -133,7 +104,7 @@ void bm_frame(int card_index, uint16_t timecode,
         card->usb->get_audio_frame_allocator()->release_frame(audio_frame);
 }
        
-void place_rectangle(Effect *resample_effect, Effect *padding_effect, float x0, float y0, float x1, float y1)
+void Mixer::place_rectangle(Effect *resample_effect, Effect *padding_effect, float x0, float y0, float x1, float y1)
 {
        float srcx0 = 0.0f;
        float srcx1 = 1.0f;
@@ -195,9 +166,7 @@ void place_rectangle(Effect *resample_effect, Effect *padding_effect, float x0,
        CHECK(padding_effect->set_float("border_offset_bottom", y1 - (floor(y0) + height)));
 }
        
-static bool quit = false;
-       
-void mixer_thread_func(QSurface *surface, QSurface *surface2, QSurface *surface3, QSurface *surface4)
+void Mixer::thread_func(QSurface *surface, QSurface *surface2, QSurface *surface3, QSurface *surface4)
 {
        cards[0].surface = surface3;
 #if NUM_CARDS == 2
@@ -264,7 +233,7 @@ void mixer_thread_func(QSurface *surface, QSurface *surface2, QSurface *surface3
        printf("Configuring first card...\n");
        cards[0].usb = new BMUSBCapture(0x1edb, 0xbd3b);  // 0xbd4f
        //cards[0].usb = new BMUSBCapture(0x1edb, 0xbd4f);
-       cards[0].usb->set_frame_callback(std::bind(bm_frame, 0, _1, _2, _3, _4, _5, _6, _7));
+       cards[0].usb->set_frame_callback(std::bind(&Mixer::bm_frame, this, 0, _1, _2, _3, _4, _5, _6, _7));
        std::unique_ptr<PBOFrameAllocator> pbo_allocator1(new PBOFrameAllocator(1280 * 750 * 2 + 44));
        cards[0].usb->set_video_frame_allocator(pbo_allocator1.get());
        cards[0].usb->configure_card();
@@ -273,7 +242,7 @@ void mixer_thread_func(QSurface *surface, QSurface *surface2, QSurface *surface3
        if (NUM_CARDS == 2) {
                printf("Configuring second card...\n");
                cards[1].usb = new BMUSBCapture(0x1edb, 0xbd4f);
-               cards[1].usb->set_frame_callback(std::bind(bm_frame, 1, _1, _2, _3, _4, _5, _6, _7));
+               cards[1].usb->set_frame_callback(std::bind(&Mixer::bm_frame, this, 1, _1, _2, _3, _4, _5, _6, _7));
                cards[1].usb->set_video_frame_allocator(pbo_allocator2.get());
                cards[1].usb->configure_card();
        }
@@ -323,7 +292,7 @@ void mixer_thread_func(QSurface *surface, QSurface *surface2, QSurface *surface3
        glGenVertexArrays(1, &vao);
        check_error();
 
-       while (!quit) {
+       while (!should_quit) {
                ++frame;
 
                //int width0 = lrintf(848 * (1.0 + 0.2 * sin(frame * 0.02)));
@@ -392,7 +361,7 @@ void mixer_thread_func(QSurface *surface, QSurface *surface2, QSurface *surface3
 
                        // The first card is the master timer, so wait for it to have a new frame.
                        // TODO: Make configurable, and with a timeout.
-                       cards[0].new_data_ready_changed.wait(lock, []{ return cards[0].new_data_ready; });
+                       cards[0].new_data_ready_changed.wait(lock, [this]{ return cards[0].new_data_ready; });
 
                        for (int card_index = 0; card_index < NUM_CARDS; ++card_index) {
                                CaptureCard *card = &cards[card_index];
@@ -551,7 +520,7 @@ void mixer_thread_func(QSurface *surface, QSurface *surface2, QSurface *surface3
        BMUSBCapture::stop_bm_thread();
 }
 
-bool mixer_get_display_frame(DisplayFrame *frame)
+bool Mixer::get_display_frame(DisplayFrame *frame)
 {
        std::unique_lock<std::mutex> lock(display_frame_mutex);
        if (!has_current_display_frame && !has_ready_display_frame) {
@@ -576,28 +545,26 @@ bool mixer_get_display_frame(DisplayFrame *frame)
        return true;
 }
 
-void set_frame_ready_fallback(new_frame_ready_callback_t callback)
+void Mixer::set_frame_ready_fallback(new_frame_ready_callback_t callback)
 {
        new_frame_ready_callback = callback;
        has_new_frame_ready_callback = true;
 }
 
-std::thread mixer_thread;
-
-void start_mixer(QSurface *surface, QSurface *surface2, QSurface *surface3, QSurface *surface4)
+void Mixer::start(QSurface *surface, QSurface *surface2, QSurface *surface3, QSurface *surface4)
 {
-       mixer_thread = std::thread([surface, surface2, surface3, surface4]{
-               mixer_thread_func(surface, surface2, surface3, surface4);
+       mixer_thread = std::thread([this, surface, surface2, surface3, surface4]{
+               thread_func(surface, surface2, surface3, surface4);
        });
 }
 
-void mixer_quit()
+void Mixer::quit()
 {
-       quit = true;
+       should_quit = true;
        mixer_thread.join();
 }
 
-void mixer_cut(Source source)
+void Mixer::cut(Source source)
 {
        current_source = source;
 }
diff --git a/mixer.h b/mixer.h
index 70953bdd06124eb4819da26f6cf1b9e40e90c6f6..2dffe6dc3ceced01116581ed834e401884ac0614 100644 (file)
--- a/mixer.h
+++ b/mixer.h
@@ -1,30 +1,83 @@
 #ifndef _MIXER_H
 #define _MIXER_H 1
 
+// The actual video mixer, running in its own separate background thread.
+
 #include <epoxy/gl.h>
 #include <functional>
 
+#include "bmusb.h"
 #include "ref_counted_gl_sync.h"
 
+#define NUM_CARDS 2
+
+namespace movit {
+class Effect;
+class ResourcePool;
+}
+class QOpenGLContext;
 class QSurface;
 
-void start_mixer(QSurface *surface, QSurface *surface2, QSurface *surface3, QSurface *surface4);
-void mixer_quit();
+class Mixer {
+public:
+       void start(QSurface *surface, QSurface *surface2, QSurface *surface3, QSurface *surface4);
+       void quit();
 
-enum Source {
-       SOURCE_INPUT1,
-       SOURCE_INPUT2,
-       SOURCE_SBS,
-};
-void mixer_cut(Source source);
+       enum Source {
+               SOURCE_INPUT1,
+               SOURCE_INPUT2,
+               SOURCE_SBS,
+       };
+       void cut(Source source);
+
+       struct DisplayFrame {
+               GLuint texnum;
+               RefCountedGLsync ready_fence;  // Asserted when the texture is done rendering.
+       };
+       // Implicitly frees the previous one if there's a new frame available.
+       bool get_display_frame(DisplayFrame *frame);
+
+       typedef std::function<void()> new_frame_ready_callback_t;
+       void set_frame_ready_fallback(new_frame_ready_callback_t callback);
+
+private:
+       void bm_frame(int card_index, uint16_t timecode,
+               FrameAllocator::Frame video_frame, size_t video_offset, uint16_t video_format,
+               FrameAllocator::Frame audio_frame, size_t audio_offset, uint16_t audio_format);
+       void place_rectangle(movit::Effect *resample_effect, movit::Effect *padding_effect, float x0, float y0, float x1, float y1);
+       void thread_func(QSurface *surface, QSurface *surface2, QSurface *surface3, QSurface *surface4);
+
+       Source current_source = SOURCE_INPUT1;
+
+       movit::ResourcePool *resource_pool;
+
+       std::mutex display_frame_mutex;
+       DisplayFrame current_display_frame, ready_display_frame;  // protected by <frame_mutex>
+       bool has_current_display_frame = false, has_ready_display_frame = false;  // protected by <frame_mutex>
+
+       std::mutex bmusb_mutex;
+       struct CaptureCard {
+               BMUSBCapture *usb;
+
+               // Threading stuff
+               bool thread_initialized;
+               QSurface *surface;
+               QOpenGLContext *context;
+
+               bool new_data_ready;  // Whether new_frame contains anything.
+               FrameAllocator::Frame new_frame;
+               GLsync new_data_ready_fence;  // Whether new_frame is ready for rendering.
+               std::condition_variable new_data_ready_changed;  // Set whenever new_data_ready is changed.
+       };
+       CaptureCard cards[NUM_CARDS];  // protected by <bmusb_mutex>
+
+       new_frame_ready_callback_t new_frame_ready_callback;
+       bool has_new_frame_ready_callback = false;
 
-struct DisplayFrame {
-       GLuint texnum;
-       RefCountedGLsync ready_fence;  // Asserted when the texture is done rendering.
+       std::thread mixer_thread;
+       bool should_quit;
 };
-bool mixer_get_display_frame(DisplayFrame *frame);  // Implicitly frees the previous one if there's a new frame available.
 
-typedef std::function<void()> new_frame_ready_callback_t;
-void set_frame_ready_fallback(new_frame_ready_callback_t callback);
+extern Mixer *global_mixer;
 
 #endif  // !defined(_MIXER_H)