]> git.sesse.net Git - nageru/commitdiff
Add audio support for the DeckLink inputs.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 27 Feb 2016 15:22:20 +0000 (16:22 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 27 Feb 2016 15:22:20 +0000 (16:22 +0100)
bmusb
decklink_capture.cpp
decklink_capture.h
mixer.cpp

diff --git a/bmusb b/bmusb
index 30a75fd8110601c89ecc7c1a0832a96878917cd4..29a8343d5cbbfdfc913b18fca7da0e14f0472f32 160000 (submodule)
--- a/bmusb
+++ b/bmusb
@@ -1 +1 @@
-Subproject commit 30a75fd8110601c89ecc7c1a0832a96878917cd4
+Subproject commit 29a8343d5cbbfdfc913b18fca7da0e14f0472f32
index 6680de1c57be8467b42077939eab1ba5535c8ce5..c1b228dd43ead8afbe9d52cef3d3a1721489075f 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <cstddef>
 
 #include <DeckLinkAPI.h>
@@ -12,6 +13,8 @@
 #include <DeckLinkAPIModes.h>
 #include "bmusb/bmusb.h"
 
+#define FRAME_SIZE (8 << 20)  // 8 MB.
+
 using namespace std;
 using namespace std::placeholders;
 
@@ -91,7 +94,7 @@ DeckLinkCapture::DeckLinkCapture(IDeckLink *card, int card_index)
                exit(1);
        }
 
-       if (input->EnableAudioInput(48000, bmdAudioSampleType16bitInteger, 2) != S_OK) {
+       if (input->EnableAudioInput(48000, bmdAudioSampleType32bitInteger, 2) != S_OK) {
                fprintf(stderr, "Failed to enable audio input for card %d\n", card_index);
                exit(1);
        }
@@ -182,8 +185,9 @@ HRESULT STDMETHODCALLTYPE DeckLinkCapture::VideoInputFrameArrived(
                if (current_audio_frame.data != nullptr) {
                        const uint8_t *frame_bytes;
                        audio_frame->GetBytes((void **)&frame_bytes);
+                       current_audio_frame.len = sizeof(int32_t) * 2 * num_samples;
 
-                       memcpy(current_audio_frame.data, frame_bytes, sizeof(int32_t) * 2 * num_samples);
+                       memcpy(current_audio_frame.data, frame_bytes, current_audio_frame.len);
 
                        audio_format.bits_per_sample = 32;
                        audio_format.num_channels = 2;
@@ -202,6 +206,16 @@ HRESULT STDMETHODCALLTYPE DeckLinkCapture::VideoInputFrameArrived(
        return S_OK;
 }
 
+void DeckLinkCapture::configure_card()
+{
+       if (video_frame_allocator == nullptr) {
+               set_video_frame_allocator(new MallocFrameAllocator(FRAME_SIZE, NUM_QUEUED_VIDEO_FRAMES));  // FIXME: leak.
+       }
+       if (audio_frame_allocator == nullptr) {
+               set_audio_frame_allocator(new MallocFrameAllocator(65536, NUM_QUEUED_AUDIO_FRAMES));  // FIXME: leak.
+       }
+}
+
 void DeckLinkCapture::start_bm_capture()
 {
        if (input->StartStreams() != S_OK) {
index c591cdc9867424fb84e58271f26afa4402e18679..695f9d376325c9729f64956109d784072f52dea8 100644 (file)
@@ -71,7 +71,7 @@ public:
                return description;
        }
 
-       void configure_card() override {}
+       void configure_card() override;
        void start_bm_capture() override;
        void stop_dequeue_thread() override;
 
index e8c9a758ad4f6c25bd6fb144cc565c1234ff7999..d725ad36b8fe84415d1b92f6201510b978029f2d 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
@@ -50,6 +50,7 @@ namespace {
 
 void convert_fixed24_to_fp32(float *dst, size_t out_channels, const uint8_t *src, size_t in_channels, size_t num_samples)
 {
+       assert(in_channels >= out_channels);
        for (size_t i = 0; i < num_samples; ++i) {
                for (size_t j = 0; j < out_channels; ++j) {
                        uint32_t s1 = *src++;
@@ -62,6 +63,20 @@ void convert_fixed24_to_fp32(float *dst, size_t out_channels, const uint8_t *src
        }
 }
 
+void convert_fixed32_to_fp32(float *dst, size_t out_channels, const uint8_t *src, size_t in_channels, size_t num_samples)
+{
+       assert(in_channels >= out_channels);
+       for (size_t i = 0; i < num_samples; ++i) {
+               for (size_t j = 0; j < out_channels; ++j) {
+                       // Note: Assumes little-endian.
+                       int32_t s = *(int32_t *)src;
+                       dst[i * out_channels + j] = s * (1.0f / 4294967296.0f);
+                       src += 4;
+               }
+               src += 4 * (in_channels - out_channels);
+       }
+}
+
 void insert_new_frame(RefCountedFrame frame, unsigned field_num, bool interlaced, unsigned card_index, InputState *input_state)
 {
        if (interlaced) {
@@ -316,7 +331,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
 
        int64_t frame_length = int64_t(TIMEBASE * video_format.frame_rate_den) / video_format.frame_rate_nom;
 
-       size_t num_samples = (audio_frame.len >= audio_offset) ? (audio_frame.len - audio_offset) / 8 / 3 : 0;
+       size_t num_samples = (audio_frame.len >= audio_offset) ? (audio_frame.len - audio_offset) / audio_format.num_channels / (audio_format.bits_per_sample / 8) : 0;
        if (num_samples > OUTPUT_FREQUENCY / 10) {
                printf("Card %d: Dropping frame with implausible audio length (len=%d, offset=%d) [timecode=0x%04x video_len=%d video_offset=%d video_format=%x)\n",
                        card_index, int(audio_frame.len), int(audio_offset),
@@ -343,6 +358,9 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
        case 24:
                convert_fixed24_to_fp32(&audio[0], 2, audio_frame.data + audio_offset, audio_format.num_channels, num_samples);
                break;
+       case 32:
+               convert_fixed32_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);