#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"
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.
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)
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];
// 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.
{
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);
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;