- // Video frame will be released later.
- 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)
-{
- 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)));
+ BMUSBCapture::start_bm_thread();
+
+ for (unsigned card_index = 0; card_index < num_cards; ++card_index) {
+ cards[card_index].usb->start_bm_capture();
+ }
+
+ //chain->enable_phase_timing(true);
+
+ // Set up stuff for NV12 conversion.
+
+ // Cb/Cr shader.
+ string cbcr_vert_shader = read_file("vs-cbcr.130.vert");
+ string cbcr_frag_shader =
+ "#version 130 \n"
+ "in vec2 tc0; \n"
+ "uniform sampler2D cbcr_tex; \n"
+ "void main() { \n"
+ " gl_FragColor = texture2D(cbcr_tex, tc0); \n"
+ "} \n";
+ cbcr_program_num = resource_pool->compile_glsl_program(cbcr_vert_shader, cbcr_frag_shader);
+
+ r128.init(2, OUTPUT_FREQUENCY);
+ r128.integr_start();
+
+ locut.init(FILTER_HPF, 2);
+
+ // hlen=16 is pretty low quality, but we use quite a bit of CPU otherwise,
+ // and there's a limit to how important the peak meter is.
+ peak_resampler.setup(OUTPUT_FREQUENCY, OUTPUT_FREQUENCY * 4, /*num_channels=*/2, /*hlen=*/16);
+
+ alsa.reset(new ALSAOutput(OUTPUT_FREQUENCY, /*num_channels=*/2));