浏览代码

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.
jp9000 8 年之前
父节点
当前提交
4330021617
共有 3 个文件被更改,包括 12 次插入1 次删除
  1. 7 0
      plugins/decklink/decklink-device-instance.cpp
  2. 2 0
      plugins/decklink/decklink.hpp
  3. 3 1
      plugins/decklink/plugin-main.cpp

+ 7 - 0
plugins/decklink/decklink-device-instance.cpp

@@ -83,6 +83,13 @@ void DeckLinkDeviceInstance::HandleAudioPacket(
 	currentPacket.frames      = frameCount;
 	currentPacket.frames      = frameCount;
 	currentPacket.timestamp   = timestamp;
 	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 (!ISSTEREO(channelFormat)) {
 		if (audioRepacker->repack((uint8_t *)bytes, frameCount) < 0) {
 		if (audioRepacker->repack((uint8_t *)bytes, frameCount) < 0) {
 			LOG(LOG_ERROR, "Failed to convert audio packet data");
 			LOG(LOG_ERROR, "Failed to convert audio packet data");

+ 2 - 0
plugins/decklink/decklink.hpp

@@ -62,4 +62,6 @@ public:
 
 
 	bool Activate(DeckLinkDevice *device, long long modeId);
 	bool Activate(DeckLinkDevice *device, long long modeId);
 	void Deactivate();
 	void Deactivate();
+
+	bool buffering = false;
 };
 };

+ 3 - 1
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_t *source = decklink->GetSource();
 	obs_source_set_async_unbuffered(source, !enabled);
 	obs_source_set_async_unbuffered(source, !enabled);
+	decklink->buffering = enabled;
 }
 }
 
 
 static void *decklink_create(obs_data_t *settings, obs_source_t *source)
 static void *decklink_create(obs_data_t *settings, obs_source_t *source)
 {
 {
 	DeckLink *decklink = new DeckLink(source, deviceEnum);
 	DeckLink *decklink = new DeckLink(source, deviceEnum);
 
 
+	obs_source_set_async_decoupled(source, true);
 	decklink_enable_buffering(decklink,
 	decklink_enable_buffering(decklink,
 			obs_data_get_bool(settings, BUFFERING));
 			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)
 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, PIXEL_FORMAT, bmdFormat8BitYUV);
 	obs_data_set_default_int(settings, COLOR_SPACE, VIDEO_CS_DEFAULT);
 	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, COLOR_RANGE, VIDEO_RANGE_DEFAULT);