0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-20 13:08:50 +02:00

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
This commit is contained in:
pkviet 2018-06-28 02:11:15 +02:00 committed by jp9000
parent 8c4b496ea0
commit c7dab6c92b
3 changed files with 26 additions and 101 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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);