diff --git a/plugins/decklink/DecklinkInput.cpp b/plugins/decklink/DecklinkInput.cpp index 58687a5c6..b79a617cf 100644 --- a/plugins/decklink/DecklinkInput.cpp +++ b/plugins/decklink/DecklinkInput.cpp @@ -1,4 +1,4 @@ -#include "DecklinkInput.hpp" +#include "DecklinkInput.hpp" #include @@ -61,7 +61,8 @@ bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId) instance->GetActivePixelFormat() == pixelFormat && instance->GetActiveColorSpace() == colorSpace && instance->GetActiveColorRange() == colorRange && - instance->GetActiveChannelFormat() == channelFormat) + instance->GetActiveChannelFormat() == channelFormat && + instance->GetActiveSwapState() == swap) return false; } diff --git a/plugins/decklink/DecklinkInput.hpp b/plugins/decklink/DecklinkInput.hpp index 4111fa9f9..5ec79bf6d 100644 --- a/plugins/decklink/DecklinkInput.hpp +++ b/plugins/decklink/DecklinkInput.hpp @@ -47,4 +47,5 @@ public: bool dwns = false; std::string hash; long long id; + bool swap = false; }; diff --git a/plugins/decklink/audio-repack.c b/plugins/decklink/audio-repack.c index 5fd4293b5..ec92f7673 100644 --- a/plugins/decklink/audio-repack.c +++ b/plugins/decklink/audio-repack.c @@ -42,16 +42,37 @@ int repack_squash(struct audio_repack *repack, uint16_t *dst = (uint16_t *)repack->packet_buffer; /* Audio needs squashing in order to avoid resampling issues. + * The condition checks for 7.1 audio for which no squash is needed. */ - while (src != esrc) { - __m128i target = _mm_load_si128(src++); - _mm_storeu_si128((__m128i *)dst, target); - dst += 8 - squash; + if (squash > 0) { + while (src != esrc) { + __m128i target = _mm_load_si128(src++); + _mm_storeu_si128((__m128i *)dst, target); + dst += 8 - squash; + } } return 0; } +int repack_squash_swap(struct audio_repack *repack, + const uint8_t *bsrc, uint32_t frame_count) +{ + if (check_buffer(repack, frame_count) < 0) + return -1; + int squash = repack->extra_dst_size; + const __m128i *src = (__m128i *)bsrc; + const __m128i *esrc = src + frame_count; + uint16_t *dst = (uint16_t *)repack->packet_buffer; + while (src != esrc) { + __m128i target = _mm_load_si128(src++); + __m128i buf = _mm_shufflelo_epi16(target, _MM_SHUFFLE(2, 3, 1, 0)); + _mm_storeu_si128((__m128i *)dst, buf); + dst += 8 - squash; + } + return 0; +} + int audio_repack_init(struct audio_repack *repack, audio_repack_mode_t repack_mode, uint8_t sample_bit) { @@ -59,11 +80,15 @@ int audio_repack_init(struct audio_repack *repack, if (sample_bit != 16) return -1; - + int _audio_repack_ch[8] = { 3, 4, 5, 6, 5, 6, 8, 8 }; 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->base_dst_size = _audio_repack_ch[repack_mode] * (16 / 8); + repack->extra_dst_size = 8 - _audio_repack_ch[repack_mode]; repack->repack_func = &repack_squash; + if (repack_mode == repack_mode_8to5ch_swap || + repack_mode == repack_mode_8to6ch_swap || + repack_mode == repack_mode_8ch_swap) + repack->repack_func = &repack_squash_swap; return 0; } diff --git a/plugins/decklink/audio-repack.h b/plugins/decklink/audio-repack.h index 22a1df81b..448cd992b 100644 --- a/plugins/decklink/audio-repack.h +++ b/plugins/decklink/audio-repack.h @@ -26,10 +26,14 @@ struct audio_repack { }; enum _audio_repack_mode { - repack_mode_8to3ch=3, + repack_mode_8to3ch=0, repack_mode_8to4ch, repack_mode_8to5ch, repack_mode_8to6ch, + repack_mode_8to5ch_swap, + repack_mode_8to6ch_swap, + repack_mode_8ch_swap, + repack_mode_8ch, }; typedef enum _audio_repack_mode audio_repack_mode_t; diff --git a/plugins/decklink/const.h b/plugins/decklink/const.h index 872d04499..595fbb1a0 100644 --- a/plugins/decklink/const.h +++ b/plugins/decklink/const.h @@ -10,6 +10,7 @@ #define DEACTIVATE_WNS "deactivate_when_not_showing" #define AUTO_START "auto_start" #define KEYER "keyer" +#define SWAP "swap" #define TEXT_DEVICE obs_module_text("Device") #define TEXT_MODE obs_module_text("Mode") @@ -32,3 +33,5 @@ #define TEXT_DWNS obs_module_text("DeactivateWhenNotShowing") #define TEXT_AUTO_START obs_module_text("AutoStart") #define TEXT_ENABLE_KEYER obs_module_text("Keyer") +#define TEXT_SWAP obs_module_text("SwapFC-LFE") +#define TEXT_SWAP_TOOLTIP obs_module_text("SwapFC-LFE.Tooltip") diff --git a/plugins/decklink/data/locale/en-US.ini b/plugins/decklink/data/locale/en-US.ini index 7fc9453a4..e3123fcc9 100644 --- a/plugins/decklink/data/locale/en-US.ini +++ b/plugins/decklink/data/locale/en-US.ini @@ -19,3 +19,5 @@ ChannelFormat.5_1ch="5.1ch" ChannelFormat.7_1ch="7.1ch" DeactivateWhenNotShowing="Deactivate when not showing" AutoStart="Auto start on launch" +SwapFC-LFE="Swap FC <-> LFE" +SwapFC-LFE.Tooltip="Swap Front Channel and LFE Channel" \ No newline at end of file diff --git a/plugins/decklink/decklink-device-instance.cpp b/plugins/decklink/decklink-device-instance.cpp index 10b70dad3..6dbfd7616 100644 --- a/plugins/decklink/decklink-device-instance.cpp +++ b/plugins/decklink/decklink-device-instance.cpp @@ -38,7 +38,7 @@ static inline int ConvertChannelFormat(speaker_layout format) } } -static inline audio_repack_mode_t ConvertRepackFormat(speaker_layout format) +static inline audio_repack_mode_t ConvertRepackFormat(speaker_layout format, bool swap) { switch (format) { case SPEAKERS_2POINT1: @@ -46,10 +46,11 @@ static inline audio_repack_mode_t ConvertRepackFormat(speaker_layout format) case SPEAKERS_4POINT0: return repack_mode_8to4ch; case SPEAKERS_4POINT1: - return repack_mode_8to5ch; + return swap? repack_mode_8to5ch_swap:repack_mode_8to5ch; case SPEAKERS_5POINT1: - return repack_mode_8to6ch; + return swap ? repack_mode_8to6ch_swap : repack_mode_8to6ch; case SPEAKERS_7POINT1: + return swap ? repack_mode_8ch_swap: repack_mode_8ch; default: assert(false && "No repack requested"); return (audio_repack_mode_t)-1; @@ -98,8 +99,8 @@ void DeckLinkDeviceInstance::HandleAudioPacket( if (channelFormat != SPEAKERS_UNKNOWN && channelFormat != SPEAKERS_MONO && channelFormat != SPEAKERS_STEREO && - channelFormat != SPEAKERS_7POINT1 && - maxdevicechannel >= 8) { + (channelFormat != SPEAKERS_7POINT1 || static_cast(decklink)->swap) + && maxdevicechannel >= 8) { if (audioRepacker->repack((uint8_t *)bytes, frameCount) < 0) { LOG(LOG_ERROR, "Failed to convert audio packet data"); @@ -226,6 +227,7 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_) channelFormat = static_cast(decklink)->GetChannelFormat(); currentPacket.speakers = channelFormat; + swap = static_cast(decklink)->swap; int maxdevicechannel = device->GetMaxChannel(); @@ -240,11 +242,11 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_) if (channelFormat != SPEAKERS_UNKNOWN && channelFormat != SPEAKERS_MONO && channelFormat != SPEAKERS_STEREO && - channelFormat != SPEAKERS_7POINT1 && - maxdevicechannel >= 8) { + (channelFormat != SPEAKERS_7POINT1 || swap) + && maxdevicechannel >= 8) { const audio_repack_mode_t repack_mode = ConvertRepackFormat - (channelFormat); + (channelFormat, swap); audioRepacker = new AudioRepacker(repack_mode); } } diff --git a/plugins/decklink/decklink-device-instance.hpp b/plugins/decklink/decklink-device-instance.hpp index 354d5052e..2b1c78180 100644 --- a/plugins/decklink/decklink-device-instance.hpp +++ b/plugins/decklink/decklink-device-instance.hpp @@ -29,6 +29,7 @@ protected: uint64_t lastVideoTS = 0; AudioRepacker *audioRepacker = nullptr; speaker_layout channelFormat = SPEAKERS_STEREO; + bool swap; IDeckLinkMutableVideoFrame *decklinkOutputFrame = nullptr; @@ -54,6 +55,7 @@ public: inline video_colorspace GetActiveColorSpace() const {return colorSpace;} inline video_range_type GetActiveColorRange() const {return colorRange;} inline speaker_layout GetActiveChannelFormat() const {return channelFormat;} + inline bool GetActiveSwapState() const {return swap;} inline DeckLinkDeviceMode *GetMode() const {return mode;} diff --git a/plugins/decklink/decklink-source.cpp b/plugins/decklink/decklink-source.cpp index 9e448c8f1..a9a68d840 100644 --- a/plugins/decklink/decklink-source.cpp +++ b/plugins/decklink/decklink-source.cpp @@ -70,8 +70,9 @@ static void decklink_update(void *data, obs_data_t *settings) decklink->SetColorSpace(colorSpace); decklink->SetColorRange(colorRange); decklink->SetChannelFormat(channelFormat); - decklink->Activate(device, id); decklink->hash = std::string(hash); + decklink->swap = obs_data_get_bool(settings, SWAP); + decklink->Activate(device, id); } static void decklink_show(void *data) @@ -101,6 +102,7 @@ static void decklink_get_defaults(obs_data_t *settings) obs_data_set_default_int(settings, COLOR_SPACE, VIDEO_CS_DEFAULT); obs_data_set_default_int(settings, COLOR_RANGE, VIDEO_RANGE_DEFAULT); obs_data_set_default_int(settings, CHANNEL_FORMAT, SPEAKERS_STEREO); + obs_data_set_default_bool(settings, SWAP, false); } static const char *decklink_get_name(void*) @@ -260,6 +262,9 @@ static obs_properties_t *decklink_get_properties(void *data) obs_property_list_add_int(list, TEXT_CHANNEL_FORMAT_7_1CH, SPEAKERS_7POINT1); + obs_property_t *swap = obs_properties_add_bool(props, SWAP, TEXT_SWAP); + obs_property_set_long_description(swap, TEXT_SWAP_TOOLTIP); + obs_properties_add_bool(props, BUFFERING, TEXT_BUFFERING); obs_properties_add_bool(props, DEACTIVATE_WNS, TEXT_DWNS);