From c7dab6c92ba7380b0d91f4a34b1f507a512d581b Mon Sep 17 00:00:00 2001 From: pkviet Date: Thu, 28 Jun 2018 02:11:15 +0200 Subject: [PATCH] decklink: Remove inactive audio channels (linux, macOs) Decklink cards accept 2, 8 or 16 audio channels. If obs audio output is setup to n channels ( 8 >= n > 2), and the decklink card captures n channels, one needs to squash the silent channels (n+1, .., 8) or sampling issues occur. This had been done on windows but is required also on macOs and linux. The commit adds the fix for macOS and linux. Some code factoring has also been done. Closes obsproject/obs-studio#1350 --- plugins/decklink/audio-repack.c | 93 +++---------------- plugins/decklink/audio-repack.h | 9 +- plugins/decklink/decklink-device-instance.cpp | 25 ++--- 3 files changed, 26 insertions(+), 101 deletions(-) diff --git a/plugins/decklink/audio-repack.c b/plugins/decklink/audio-repack.c index 02d0879fb..5fd4293b5 100644 --- a/plugins/decklink/audio-repack.c +++ b/plugins/decklink/audio-repack.c @@ -21,38 +21,16 @@ int check_buffer(struct audio_repack *repack, } /* - * Swap channel 3 & 4, 5 & 7, 6 & 8 and squash arrays + * Squash arrays. + * For instance: * 2.1: * * | FL | FR | LFE | emp | emp | emp |emp |emp | * | | | * | FL | FR | LFE | - * 4.0 (quad): - * - * | FL | FR | BR | BL | emp | emp |emp |emp | - * | | x | - * | FL | FR | BL | BC | - * - * 4.1: - * - * | FL | FR |LFE | FC | BC | emp |emp |emp | - * | | x | | - * | FL | FR | FC |LFE | BC | - * - * 5.1: - * - * | FL | FR |LFE | FC |(emp|emp)|(BL|BR)| - * | | x x - * | FL | FR | FC |LFE | BL | BR | - * - * 7.1: - * - * | FL | FR |LFE | FC |( SL | SR )|(BL |BR )| - * | | x X - * | FL | FR | FC |LFE |( BL | BR )|(SL |SR )| - */ +*/ -int repack_squash_swap(struct audio_repack *repack, +int repack_squash(struct audio_repack *repack, const uint8_t *bsrc, uint32_t frame_count) { if (check_buffer(repack, frame_count) < 0) @@ -62,23 +40,13 @@ int repack_squash_swap(struct audio_repack *repack, const __m128i *src = (__m128i *)bsrc; const __m128i *esrc = src + frame_count; uint16_t *dst = (uint16_t *)repack->packet_buffer; - /* 2.1 audio does not require re-ordering but still needs squashing - * in order to avoid sampling issues. + + /* Audio needs squashing in order to avoid resampling issues. */ - if (squash == 5) { - while (src != esrc) { - __m128i target = _mm_load_si128(src++); - _mm_storeu_si128((__m128i *)dst, target); - dst += 8 - squash; - } - } else { - while (src != esrc) { - __m128i target = _mm_load_si128(src++); - __m128i buf = _mm_shufflelo_epi16(target, _MM_SHUFFLE(2, 3, 1, 0)); - __m128i buf2 = _mm_shufflehi_epi16(buf, _MM_SHUFFLE(1, 0, 3, 2)); - _mm_storeu_si128((__m128i *)dst, buf2); - dst += 8 - squash; - } + while (src != esrc) { + __m128i target = _mm_load_si128(src++); + _mm_storeu_si128((__m128i *)dst, target); + dst += 8 - squash; } return 0; @@ -92,43 +60,10 @@ int audio_repack_init(struct audio_repack *repack, if (sample_bit != 16) return -1; - switch (repack_mode) { - case repack_mode_8to3ch_swap23: - repack->base_src_size = 8 * (16 / 8); - repack->base_dst_size = 3 * (16 / 8); - repack->extra_dst_size = 5; - repack->repack_func = &repack_squash_swap; - break; - case repack_mode_8to4ch_swap23: - repack->base_src_size = 8 * (16 / 8); - repack->base_dst_size = 4 * (16 / 8); - repack->extra_dst_size = 4; - repack->repack_func = &repack_squash_swap; - break; - - case repack_mode_8to5ch_swap23: - repack->base_src_size = 8 * (16 / 8); - repack->base_dst_size = 5 * (16 / 8); - repack->extra_dst_size = 3; - repack->repack_func = &repack_squash_swap; - break; - - case repack_mode_8to6ch_swap23: - repack->base_src_size = 8 * (16 / 8); - repack->base_dst_size = 6 * (16 / 8); - repack->extra_dst_size = 2; - repack->repack_func = &repack_squash_swap; - break; - - case repack_mode_8ch_swap23_swap46_swap57: - repack->base_src_size = 8 * (16 / 8); - repack->base_dst_size = 8 * (16 / 8); - repack->extra_dst_size = 0; - repack->repack_func = &repack_squash_swap; - break; - - default: return -1; - } + repack->base_src_size = 8 * (16 / 8); + repack->base_dst_size = (int)repack_mode * (16 / 8); + repack->extra_dst_size = 8 - (int)repack_mode; + repack->repack_func = &repack_squash; return 0; } diff --git a/plugins/decklink/audio-repack.h b/plugins/decklink/audio-repack.h index e063e13dc..22a1df81b 100644 --- a/plugins/decklink/audio-repack.h +++ b/plugins/decklink/audio-repack.h @@ -26,11 +26,10 @@ struct audio_repack { }; enum _audio_repack_mode { - repack_mode_8to3ch_swap23, - repack_mode_8to4ch_swap23, - repack_mode_8to5ch_swap23, - repack_mode_8to6ch_swap23, - repack_mode_8ch_swap23_swap46_swap57, + repack_mode_8to3ch=3, + repack_mode_8to4ch, + repack_mode_8to5ch, + repack_mode_8to6ch, }; typedef enum _audio_repack_mode audio_repack_mode_t; diff --git a/plugins/decklink/decklink-device-instance.cpp b/plugins/decklink/decklink-device-instance.cpp index 5dc674e5e..cc666392d 100644 --- a/plugins/decklink/decklink-device-instance.cpp +++ b/plugins/decklink/decklink-device-instance.cpp @@ -9,12 +9,6 @@ #define LOG(level, message, ...) blog(level, "%s: " message, \ obs_source_get_name(this->decklink->GetSource()), ##__VA_ARGS__) -#ifdef _WIN32 -#define IS_WIN 1 -#else -#define IS_WIN 0 -#endif - static inline enum video_format ConvertPixelFormat(BMDPixelFormat format) { switch (format) { @@ -47,15 +41,14 @@ static inline audio_repack_mode_t ConvertRepackFormat(speaker_layout format) { switch (format) { case SPEAKERS_2POINT1: - return repack_mode_8to3ch_swap23; + return repack_mode_8to3ch; case SPEAKERS_4POINT0: - return repack_mode_8to4ch_swap23; + return repack_mode_8to4ch; case SPEAKERS_4POINT1: - return repack_mode_8to5ch_swap23; + return repack_mode_8to5ch; case SPEAKERS_5POINT1: - return repack_mode_8to6ch_swap23; + return repack_mode_8to6ch; case SPEAKERS_7POINT1: - return repack_mode_8ch_swap23_swap46_swap57; default: assert(false && "No repack requested"); return (audio_repack_mode_t)-1; @@ -100,13 +93,12 @@ void DeckLinkDeviceInstance::HandleAudioPacket( } int maxdevicechannel = device->GetMaxChannel(); - bool isWin = IS_WIN; if (channelFormat != SPEAKERS_UNKNOWN && channelFormat != SPEAKERS_MONO && channelFormat != SPEAKERS_STEREO && - maxdevicechannel >= 8 && - isWin) { + channelFormat != SPEAKERS_7POINT1 && + maxdevicechannel >= 8) { if (audioRepacker->repack((uint8_t *)bytes, frameCount) < 0) { LOG(LOG_ERROR, "Failed to convert audio packet data"); @@ -235,7 +227,6 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_) currentPacket.speakers = channelFormat; int maxdevicechannel = device->GetMaxChannel(); - bool isWin = IS_WIN; if (channelFormat != SPEAKERS_UNKNOWN) { const int channel = ConvertChannelFormat(channelFormat); @@ -248,8 +239,8 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_) if (channelFormat != SPEAKERS_UNKNOWN && channelFormat != SPEAKERS_MONO && channelFormat != SPEAKERS_STEREO && - maxdevicechannel >= 8 && - isWin) { + channelFormat != SPEAKERS_7POINT1 && + maxdevicechannel >= 8) { const audio_repack_mode_t repack_mode = ConvertRepackFormat (channelFormat);