mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-09-20 13:08:50 +02:00
decklink: Fix FC<->LFE channel swap for some devices
Fixes mantis issue https://obsproject.com/mantis/view.php?id=1379 For some devices with hdmi input, the Front Center channel and the LFE channel are swapped. For some others they are not. To solve the issue a new swap setting is added so that the user can swap the two channels if needed.
This commit is contained in:
parent
748067c930
commit
05508ac895
@ -1,4 +1,4 @@
|
||||
#include "DecklinkInput.hpp"
|
||||
#include "DecklinkInput.hpp"
|
||||
|
||||
#include <util/threading.h>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -47,4 +47,5 @@ public:
|
||||
bool dwns = false;
|
||||
std::string hash;
|
||||
long long id;
|
||||
bool swap = false;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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")
|
||||
|
@ -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"
|
@ -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<DeckLinkInput*>(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<DeckLinkInput*>(decklink)->GetChannelFormat();
|
||||
currentPacket.speakers = channelFormat;
|
||||
swap = static_cast<DeckLinkInput*>(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);
|
||||
}
|
||||
}
|
||||
|
@ -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;}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user