]> git.sesse.net Git - nageru/blobdiff - mixer.cpp
Flesh out the zooming logic in the theme.
[nageru] / mixer.cpp
index 99aa33cbecd33f06e08a9a5ee8cc2f3dd8b2b9b6..fd3cbae4a058f9506a3b3d46aebb61dee8c6d96e 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
@@ -79,24 +79,28 @@ Mixer::Mixer(const QSurfaceFormat &format)
 
        h264_encoder.reset(new H264Encoder(h264_encoder_surface, WIDTH, HEIGHT, "test.mp4"));
 
-       printf("Configuring first card...\n");
-       cards[0].usb = new BMUSBCapture(0x1edb, 0xbd3b);  // 0xbd4f
-       cards[0].usb->set_frame_callback(std::bind(&Mixer::bm_frame, this, 0, _1, _2, _3, _4, _5, _6, _7));
-       cards[0].frame_allocator.reset(new PBOFrameAllocator(1280 * 750 * 2 + 44, 1280, 720));
-       cards[0].usb->set_video_frame_allocator(cards[0].frame_allocator.get());
-       cards[0].usb->configure_card();
-       cards[0].surface = create_surface(format);
-#if NUM_CARDS == 2
-       cards[1].surface = create_surface(format);
-#endif
-
-       if (NUM_CARDS == 2) {
-               printf("Configuring second card...\n");
-               cards[1].usb = new BMUSBCapture(0x1edb, 0xbd4f);
-               cards[1].usb->set_frame_callback(std::bind(&Mixer::bm_frame, this, 1, _1, _2, _3, _4, _5, _6, _7));
-               cards[1].frame_allocator.reset(new PBOFrameAllocator(1280 * 750 * 2 + 44, 1280, 720));
-               cards[1].usb->set_video_frame_allocator(cards[1].frame_allocator.get());
-               cards[1].usb->configure_card();
+       for (int card_index = 0; card_index < NUM_CARDS; ++card_index) {
+               printf("Configuring card %d...\n", card_index);
+               CaptureCard *card = &cards[card_index];
+               card->usb = new BMUSBCapture(0x1edb, card_index == 0 ? 0xbd3b : 0xbd4f);
+               card->usb->set_frame_callback(std::bind(&Mixer::bm_frame, this, card_index, _1, _2, _3, _4, _5, _6, _7));
+               card->frame_allocator.reset(new PBOFrameAllocator(1280 * 750 * 2 + 44, 1280, 720));
+               card->usb->set_video_frame_allocator(card->frame_allocator.get());
+               card->surface = create_surface(format);
+               card->usb->set_dequeue_thread_callbacks(
+                       [card]{
+                               eglBindAPI(EGL_OPENGL_API);
+                               card->context = create_context();
+                               if (!make_current(card->context, card->surface)) {
+                                       printf("failed to create bmusb context\n");
+                                       exit(1);
+                               }
+                               printf("inited!\n");
+                       },
+                       [this]{
+                               resource_pool->clean_context();
+                       });
+               card->usb->configure_card();
        }
 
        BMUSBCapture::start_bm_thread();
@@ -125,6 +129,12 @@ Mixer::~Mixer()
 {
        resource_pool->release_glsl_program(cbcr_program_num);
        BMUSBCapture::stop_bm_thread();
+
+       for (int card_index = 0; card_index < NUM_CARDS; ++card_index) {
+               cards[card_index].new_data_ready = false;  // Unblock thread.
+               cards[card_index].new_data_ready_changed.notify_all();
+               cards[card_index].usb->stop_dequeue_thread();
+       }
 }
 
 void Mixer::bm_frame(int card_index, uint16_t timecode,
@@ -132,16 +142,6 @@ void Mixer::bm_frame(int card_index, uint16_t timecode,
                     FrameAllocator::Frame audio_frame, size_t audio_offset, uint16_t audio_format)
 {
        CaptureCard *card = &cards[card_index];
-       if (!card->thread_initialized) {
-               printf("initializing context for bmusb thread %d\n", card_index);
-               eglBindAPI(EGL_OPENGL_API);
-               card->context = create_context();
-               if (!make_current(card->context, card->surface)) {
-                       printf("failed to create bmusb context\n");
-                       exit(1);
-               }
-               card->thread_initialized = true;
-       }       
 
        if (video_frame.len - video_offset != 1280 * 750 * 2) {
                printf("dropping frame with wrong length (%ld)\n", video_frame.len - video_offset);
@@ -193,69 +193,7 @@ void Mixer::bm_frame(int card_index, uint16_t timecode,
        // Video frame will be released when last user of card->new_frame goes out of scope.
         card->usb->get_audio_frame_allocator()->release_frame(audio_frame);
 }
-       
-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;
-       float srcy0 = 0.0f;
-       float srcy1 = 1.0f;
-
-       // Cull.
-       if (x0 > 1280.0 || x1 < 0.0 || y0 > 720.0 || y1 < 0.0) {
-               CHECK(resample_effect->set_int("width", 1));
-               CHECK(resample_effect->set_int("height", 1));
-               CHECK(resample_effect->set_float("zoom_x", 1280.0));
-               CHECK(resample_effect->set_float("zoom_y", 720.0));
-               CHECK(padding_effect->set_int("left", 2000));
-               CHECK(padding_effect->set_int("top", 2000));
-               return; 
-       }
 
-       // Clip. (TODO: Clip on upper/left sides, too.)
-       if (x1 > 1280.0) {
-               srcx1 = (1280.0 - x0) / (x1 - x0);
-               x1 = 1280.0;
-       }
-       if (y1 > 720.0) {
-               srcy1 = (720.0 - y0) / (y1 - y0);
-               y1 = 720.0;
-       }
-
-       float x_subpixel_offset = x0 - floor(x0);
-       float y_subpixel_offset = y0 - floor(y0);
-
-       // Resampling must be to an integral number of pixels. Round up,
-       // and then add an extra pixel so we have some leeway for the border.
-       int width = int(ceil(x1 - x0)) + 1;
-       int height = int(ceil(y1 - y0)) + 1;
-       CHECK(resample_effect->set_int("width", width));
-       CHECK(resample_effect->set_int("height", height));
-
-       // Correct the discrepancy with zoom. (This will leave a small
-       // excess edge of pixels and subpixels, which we'll correct for soon.)
-       float zoom_x = (x1 - x0) / (width * (srcx1 - srcx0));
-       float zoom_y = (y1 - y0) / (height * (srcy1 - srcy0));
-       CHECK(resample_effect->set_float("zoom_x", zoom_x));
-       CHECK(resample_effect->set_float("zoom_y", zoom_y));
-       CHECK(resample_effect->set_float("zoom_center_x", 0.0f));
-       CHECK(resample_effect->set_float("zoom_center_y", 0.0f));
-
-       // Padding must also be to a whole-pixel offset.
-       CHECK(padding_effect->set_int("left", floor(x0)));
-       CHECK(padding_effect->set_int("top", floor(y0)));
-
-       // Correct _that_ discrepancy by subpixel offset in the resampling.
-       CHECK(resample_effect->set_float("left", -x_subpixel_offset / zoom_x));
-       CHECK(resample_effect->set_float("top", -y_subpixel_offset / zoom_y));
-
-       // Finally, adjust the border so it is exactly where we want it.
-       CHECK(padding_effect->set_float("border_offset_left", x_subpixel_offset));
-       CHECK(padding_effect->set_float("border_offset_right", x1 - (floor(x0) + width)));
-       CHECK(padding_effect->set_float("border_offset_top", y_subpixel_offset));
-       CHECK(padding_effect->set_float("border_offset_bottom", y1 - (floor(y0) + height)));
-}
-       
 void Mixer::thread_func()
 {
        eglBindAPI(EGL_OPENGL_API);
@@ -271,67 +209,6 @@ void Mixer::thread_func()
        while (!should_quit) {
                ++frame;
 
-#if 0
-               //int width0 = lrintf(848 * (1.0 + 0.2 * sin(frame * 0.02)));
-               int width0 = 848;
-               int height0 = lrintf(width0 * 9.0 / 16.0);
-
-               //float top0 = 96 + 48 * sin(frame * 0.005);
-               //float left0 = 96 + 48 * cos(frame * 0.006);
-               float top0 = 48;
-               float left0 = 16;
-               float bottom0 = top0 + height0;
-               float right0 = left0 + width0;
-
-               int width1 = 384;
-               int height1 = 216;
-       
-               float bottom1 = 720 - 48;
-               float right1 = 1280 - 16;
-               float top1 = bottom1 - height1;
-               float left1 = right1 - width1;
-       
-               if (current_source == SOURCE_INPUT1) {
-                       top0 = 0.0;
-                       bottom0 = HEIGHT;
-                       left0 = 0.0;
-                       right0 = WIDTH;
-
-                       top1 = HEIGHT + 10;
-                       bottom1 = HEIGHT + 20;
-                       left1 = WIDTH + 10;
-                       right1 = WIDTH + 20;
-               } else if (current_source == SOURCE_INPUT2) {
-                       top1 = 0.0;
-                       bottom1 = HEIGHT;
-                       left1 = 0.0;
-                       right1 = WIDTH;
-
-                       top0 = HEIGHT + 10;
-                       bottom0 = HEIGHT + 20;
-                       left0 = WIDTH + 10;
-                       right0 = WIDTH + 20;
-               } else {
-                       float t = 0.5 + 0.5 * cos(frame * 0.006);
-                       float scale0 = 1.0 + t * (1280.0 / 848.0 - 1.0);
-                       float tx0 = 0.0 + t * (-16.0 * scale0);
-                       float ty0 = 0.0 + t * (-48.0 * scale0);
-
-                       top0 = top0 * scale0 + ty0;
-                       bottom0 = bottom0 * scale0 + ty0;
-                       left0 = left0 * scale0 + tx0;
-                       right0 = right0 * scale0 + tx0;
-
-                       top1 = top1 * scale0 + ty0;
-                       bottom1 = bottom1 * scale0 + ty0;
-                       left1 = left1 * scale0 + tx0;
-                       right1 = right1 * scale0 + tx0;
-               }
-
-               place_rectangle(resample_effect, padding_effect, left0, top0, right0, bottom0);
-               place_rectangle(resample2_effect, padding2_effect, left1, top1, right1, bottom1);
-#endif
-
                CaptureCard card_copy[NUM_CARDS];
 
                {
@@ -422,8 +299,8 @@ void Mixer::thread_func()
                live_frame.temp_textures = { rgba_tex };
                output_channel[OUTPUT_LIVE].output_frame(live_frame);
 
-               // Set up non-live inputs.
-               for (unsigned i = 1; i < 4; ++i) {  // FIXME: Don't lock to 4, ask Lua.
+               // Set up preview and any additional channels.
+               for (unsigned i = 1; i < theme->get_num_channels() + 2; ++i) {
                        DisplayFrame display_frame;
                        pair<EffectChain *, function<void()>> chain = theme->get_chain(i, frame / 60.0f, WIDTH, HEIGHT);  // FIXME: dimensions
                        display_frame.chain = chain.first;
@@ -454,6 +331,8 @@ void Mixer::thread_func()
                }
                check_error();
        }
+
+       resource_pool->clean_context();
 }
 
 void Mixer::subsample_chroma(GLuint src_tex, GLuint dst_tex)
@@ -531,9 +410,24 @@ void Mixer::quit()
        mixer_thread.join();
 }
 
-void Mixer::transition_clicked(int transition_num, float t)
+void Mixer::transition_clicked(int transition_num)
+{
+       theme->transition_clicked(transition_num, frame / 60.0);
+}
+
+void Mixer::channel_clicked(int preview_num)
+{
+       theme->channel_clicked(preview_num);
+}
+
+Mixer::OutputChannel::~OutputChannel()
 {
-       theme->transition_clicked(transition_num, t);
+       if (has_current_frame) {
+               parent->release_display_frame(&current_frame);
+       }
+       if (has_ready_frame) {
+               parent->release_display_frame(&ready_frame);
+       }
 }
 
 void Mixer::OutputChannel::output_frame(DisplayFrame frame)