From: Steinar H. Gunderson Date: Sat, 27 Feb 2016 15:22:20 +0000 (+0100) Subject: Add audio support for the DeckLink inputs. X-Git-Tag: 1.2.0~57 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=4a0a27cb0512737b3025804d52237fadc6afcc26;p=nageru Add audio support for the DeckLink inputs. --- diff --git a/bmusb b/bmusb index 30a75fd..29a8343 160000 --- a/bmusb +++ b/bmusb @@ -1 +1 @@ -Subproject commit 30a75fd8110601c89ecc7c1a0832a96878917cd4 +Subproject commit 29a8343d5cbbfdfc913b18fca7da0e14f0472f32 diff --git a/decklink_capture.cpp b/decklink_capture.cpp index 6680de1..c1b228d 100644 --- a/decklink_capture.cpp +++ b/decklink_capture.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -12,6 +13,8 @@ #include #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) { diff --git a/decklink_capture.h b/decklink_capture.h index c591cdc..695f9d3 100644 --- a/decklink_capture.h +++ b/decklink_capture.h @@ -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; diff --git a/mixer.cpp b/mixer.cpp index e8c9a75..d725ad3 100644 --- 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);