]> git.sesse.net Git - nageru/blobdiff - mixer.cpp
Send the audio format explicitly down, not just the ID.
[nageru] / mixer.cpp
index 878204e4219a1ac6539f2dd7fb3e9d539cf940ca..e8c9a758ad4f6c25bd6fb144cc565c1234ff7999 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
 #include <thread>
 #include <utility>
 #include <vector>
+#include <arpa/inet.h>
 
 #include "bmusb/bmusb.h"
 #include "context.h"
+#include "decklink_capture.h"
 #include "defs.h"
 #include "flags.h"
 #include "h264encode.h"
@@ -135,34 +137,37 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards)
 
        h264_encoder.reset(new H264Encoder(h264_encoder_surface, global_flags.va_display, WIDTH, HEIGHT, &httpd));
 
-       for (unsigned 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(card_index);
-               card->usb->set_frame_callback(bind(&Mixer::bm_frame, this, card_index, _1, _2, _3, _4, _5, _6, _7));
-               card->frame_allocator.reset(new PBOFrameAllocator(8 << 20, WIDTH, HEIGHT));  // 8 MB.
-               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(card->surface);
-                               if (!make_current(card->context, card->surface)) {
-                                       printf("failed to create bmusb context\n");
-                                       exit(1);
-                               }
-                       },
-                       [this]{
-                               resource_pool->clean_context();
-                       });
-               card->resampling_queue.reset(new ResamplingQueue(OUTPUT_FREQUENCY, OUTPUT_FREQUENCY, 2));
-               card->usb->configure_card();
+       // First try initializing the PCI devices, then USB, until we have the desired number of cards.
+       unsigned num_pci_devices = 0, num_usb_devices = 0;
+       unsigned card_index = 0;
+
+       IDeckLinkIterator *decklink_iterator = CreateDeckLinkIteratorInstance();
+       if (decklink_iterator != nullptr) {
+               for ( ; card_index < num_cards; ++card_index) {
+                       IDeckLink *decklink;
+                       if (decklink_iterator->Next(&decklink) != S_OK) {
+                               break;
+                       }
+
+                       configure_card(card_index, format, new DeckLinkCapture(decklink, card_index));
+                       ++num_pci_devices;
+               }
+               decklink_iterator->Release();
+               fprintf(stderr, "Found %d DeckLink PCI card(s).\n", num_pci_devices);
+       } else {
+               fprintf(stderr, "DeckLink drivers not found. Probing for USB cards only.\n");
+       }
+       for ( ; card_index < num_cards; ++card_index) {
+               configure_card(card_index, format, new BMUSBCapture(card_index - num_pci_devices));
+               ++num_usb_devices;
        }
 
-       BMUSBCapture::start_bm_thread();
+       if (num_usb_devices > 0) {
+               BMUSBCapture::start_bm_thread();
+       }
 
-       for (unsigned card_index = 0; card_index < num_cards; ++card_index) {
-               cards[card_index].usb->start_bm_capture();
+       for (card_index = 0; card_index < num_cards; ++card_index) {
+               cards[card_index].capture->start_bm_capture();
        }
 
        // Set up stuff for NV12 conversion.
@@ -232,12 +237,39 @@ Mixer::~Mixer()
                        cards[card_index].should_quit = true;  // Unblock thread.
                        cards[card_index].new_data_ready_changed.notify_all();
                }
-               cards[card_index].usb->stop_dequeue_thread();
+               cards[card_index].capture->stop_dequeue_thread();
        }
 
        h264_encoder.reset(nullptr);
 }
 
+void Mixer::configure_card(unsigned card_index, const QSurfaceFormat &format, CaptureInterface *capture)
+{
+       printf("Configuring card %d...\n", card_index);
+
+       CaptureCard *card = &cards[card_index];
+       card->capture = capture;
+       card->capture->set_frame_callback(bind(&Mixer::bm_frame, this, card_index, _1, _2, _3, _4, _5, _6, _7));
+       card->frame_allocator.reset(new PBOFrameAllocator(8 << 20, WIDTH, HEIGHT));  // 8 MB.
+       card->capture->set_video_frame_allocator(card->frame_allocator.get());
+       card->surface = create_surface(format);
+       card->capture->set_dequeue_thread_callbacks(
+               [card]{
+                       eglBindAPI(EGL_OPENGL_API);
+                       card->context = create_context(card->surface);
+                       if (!make_current(card->context, card->surface)) {
+                               printf("failed to create bmusb context\n");
+                               exit(1);
+                       }
+               },
+               [this]{
+                       resource_pool->clean_context();
+               });
+       card->resampling_queue.reset(new ResamplingQueue(OUTPUT_FREQUENCY, OUTPUT_FREQUENCY, 2));
+       card->capture->configure_card();
+}
+
+
 namespace {
 
 int unwrap_timecode(uint16_t current_wrapped, int last)
@@ -278,7 +310,7 @@ void deinterleave_samples(const vector<float> &in, vector<float> *out_l, vector<
 
 void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
                      FrameAllocator::Frame video_frame, size_t video_offset, VideoFormat video_format,
-                    FrameAllocator::Frame audio_frame, size_t audio_offset, uint16_t audio_format)
+                    FrameAllocator::Frame audio_frame, size_t audio_offset, AudioFormat audio_format)
 {
        CaptureCard *card = &cards[card_index];
 
@@ -307,7 +339,14 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
        // Convert the audio to stereo fp32 and add it.
        vector<float> audio;
        audio.resize(num_samples * 2);
-       convert_fixed24_to_fp32(&audio[0], 2, audio_frame.data + audio_offset, 8, num_samples);
+       switch (audio_format.bits_per_sample) {
+       case 24:
+               convert_fixed24_to_fp32(&audio[0], 2, audio_frame.data + audio_offset, audio_format.num_channels, num_samples);
+               break;
+       default:
+               fprintf(stderr, "Cannot handle audio with %u bits per sample\n", audio_format.bits_per_sample);
+               assert(false);
+       }
 
        // Add the audio.
        {
@@ -398,6 +437,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
                clock_gettime(CLOCK_MONOTONIC, &frame_upload_start);
        }
        userdata->last_interlaced = video_format.interlaced;
+       userdata->last_has_signal = video_format.has_signal;
        userdata->last_frame_rate_nom = video_format.frame_rate_nom;
        userdata->last_frame_rate_den = video_format.frame_rate_den;
        RefCountedFrame new_frame(video_frame);
@@ -519,7 +559,6 @@ void Mixer::thread_func()
 
                        for (unsigned card_index = 0; card_index < num_cards; ++card_index) {
                                CaptureCard *card = &cards[card_index];
-                               card_copy[card_index].usb = card->usb;
                                card_copy[card_index].new_data_ready = card->new_data_ready;
                                card_copy[card_index].new_frame = card->new_frame;
                                card_copy[card_index].new_frame_length = card->new_frame_length;