From 4330021617a8828edb88d01804c5b4ad5e554c30 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Fri, 29 Sep 2017 00:40:03 -0700 Subject: [PATCH] decklink: Use unbuffered by default, and decouple Use unbuffered async mode by default, and when in unbuffered mode, decouple audio/video so that audio plays as soon as it's received. This is a workaround for decklink device drivers having unreliable video/audio timestamps (audio/video sync drifting over time). From testing, it seems that the handling of video and audio is completely separate in the driver; along with the timestamp calculations. For example, when the thread of the decklink audio callback is stalled, it would cause the timestamps of the audio alone to go out of sync, which indicates timestamps are calculated more or less on the spot independent of what video is doing (which is how we replicated the issue fixed by b63e4b055e68a). Because decklink drivers treats the audio and video as essentially decoupled, we must also treat it as decoupled. This is what was causing video/audio to drift out of sync over time. --- plugins/decklink/decklink-device-instance.cpp | 7 +++++++ plugins/decklink/decklink.hpp | 2 ++ plugins/decklink/plugin-main.cpp | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/plugins/decklink/decklink-device-instance.cpp b/plugins/decklink/decklink-device-instance.cpp index 9e95e68d0..debc21b27 100644 --- a/plugins/decklink/decklink-device-instance.cpp +++ b/plugins/decklink/decklink-device-instance.cpp @@ -83,6 +83,13 @@ void DeckLinkDeviceInstance::HandleAudioPacket( currentPacket.frames = frameCount; currentPacket.timestamp = timestamp; + if (decklink && !decklink->buffering) { + currentPacket.timestamp = os_gettime_ns(); + currentPacket.timestamp -= + (uint64_t)frameCount * 1000000000ULL / + (uint64_t)currentPacket.samples_per_sec; + } + if (!ISSTEREO(channelFormat)) { if (audioRepacker->repack((uint8_t *)bytes, frameCount) < 0) { LOG(LOG_ERROR, "Failed to convert audio packet data"); diff --git a/plugins/decklink/decklink.hpp b/plugins/decklink/decklink.hpp index 10d3b11f9..23f8b59b7 100644 --- a/plugins/decklink/decklink.hpp +++ b/plugins/decklink/decklink.hpp @@ -62,4 +62,6 @@ public: bool Activate(DeckLinkDevice *device, long long modeId); void Deactivate(); + + bool buffering = false; }; diff --git a/plugins/decklink/plugin-main.cpp b/plugins/decklink/plugin-main.cpp index 0cefc1979..7438f7ee3 100644 --- a/plugins/decklink/plugin-main.cpp +++ b/plugins/decklink/plugin-main.cpp @@ -40,12 +40,14 @@ static void decklink_enable_buffering(DeckLink *decklink, bool enabled) { obs_source_t *source = decklink->GetSource(); obs_source_set_async_unbuffered(source, !enabled); + decklink->buffering = enabled; } static void *decklink_create(obs_data_t *settings, obs_source_t *source) { DeckLink *decklink = new DeckLink(source, deviceEnum); + obs_source_set_async_decoupled(source, true); decklink_enable_buffering(decklink, obs_data_get_bool(settings, BUFFERING)); @@ -88,7 +90,7 @@ static void decklink_update(void *data, obs_data_t *settings) static void decklink_get_defaults(obs_data_t *settings) { - obs_data_set_default_bool(settings, BUFFERING, true); + obs_data_set_default_bool(settings, BUFFERING, false); obs_data_set_default_int(settings, PIXEL_FORMAT, bmdFormat8BitYUV); obs_data_set_default_int(settings, COLOR_SPACE, VIDEO_CS_DEFAULT); obs_data_set_default_int(settings, COLOR_RANGE, VIDEO_RANGE_DEFAULT);