浏览代码

libobs: Don't use source flags for async buffering

(This commit also modifies the decklink, linux-v4l2, mac-avcapture,
obs-ffmpeg, and win-dshow modules)

Originally, async buffering for sources was supposed to be a
user-controllable flag.  However, that turned out to be less than ideal
because sources (such as the win-dshow plugin) were programmed with
automatic control over their buffering (such as automatically detecting
USB 2.0 capture devices and then enabling in those cases).

The fact that it was a flag caused a design flaw to where buffering
values would be overwritten when a source is loaded from save data.

Because of that, this flag is being deprecated and replaced with a
specific function to enable unbuffered mode instead.
jp9000 8 年之前
父节点
当前提交
d13fa96851

+ 1 - 0
libobs/obs-internal.h

@@ -608,6 +608,7 @@ struct obs_source {
 	bool                            async_flip;
 	bool                            async_active;
 	bool                            async_update_texture;
+	bool                            async_unbuffered;
 	struct obs_source_frame         *async_preload_frame;
 	DARRAY(struct async_frame)      async_cache;
 	DARRAY(struct obs_source_frame*)async_frames;

+ 1 - 1
libobs/obs-source-deinterlace.c

@@ -27,7 +27,7 @@ static bool ready_deinterlace_frames(obs_source_t *source, uint64_t sys_time)
 	uint64_t frame_offset = 0;
 	size_t idx = 1;
 
-	if ((source->flags & OBS_SOURCE_FLAG_UNBUFFERED) != 0) {
+	if (source->async_unbuffered) {
 		while (source->async_frames.num > 2) {
 			da_erase(source->async_frames, 0);
 			remove_async_frame(source, next_frame);

+ 15 - 1
libobs/obs-source.c

@@ -2602,7 +2602,7 @@ static bool ready_async_frame(obs_source_t *source, uint64_t sys_time)
 	uint64_t frame_time = next_frame->timestamp;
 	uint64_t frame_offset = 0;
 
-	if ((source->flags & OBS_SOURCE_FLAG_UNBUFFERED) != 0) {
+	if (source->async_unbuffered) {
 		while (source->async_frames.num > 1) {
 			da_erase(source->async_frames, 0);
 			remove_async_frame(source, next_frame);
@@ -4020,3 +4020,17 @@ enum obs_monitoring_type obs_source_get_monitoring_type(
 	return obs_source_valid(source, "obs_source_get_monitoring_type") ?
 		source->monitoring_type : OBS_MONITORING_TYPE_NONE;
 }
+
+void obs_source_set_async_unbuffered(obs_source_t *source, bool unbuffered)
+{
+	if (!obs_source_valid(source, "obs_source_set_async_unbuffered"))
+		return;
+
+	source->async_unbuffered = unbuffered;
+}
+
+bool obs_source_async_unbuffered(const obs_source_t *source)
+{
+	return obs_source_valid(source, "obs_source_async_unbuffered") ?
+		source->async_unbuffered : false;
+}

+ 6 - 2
libobs/obs.h

@@ -834,8 +834,8 @@ EXPORT bool obs_source_active(const obs_source_t *source);
  */
 EXPORT bool obs_source_showing(const obs_source_t *source);
 
-/** Specifies that async video frames should be played as soon as possible */
-#define OBS_SOURCE_FLAG_UNBUFFERED             (1<<0)
+/** Unused flag */
+#define OBS_SOURCE_FLAG_UNUSED_1               (1<<0)
 /** Specifies to force audio to mono */
 #define OBS_SOURCE_FLAG_FORCE_MONO             (1<<1)
 
@@ -1100,6 +1100,10 @@ EXPORT uint64_t obs_source_get_audio_timestamp(const obs_source_t *source);
 EXPORT void obs_source_get_audio_mix(const obs_source_t *source,
 		struct obs_source_audio_mix *audio);
 
+EXPORT void obs_source_set_async_unbuffered(obs_source_t *source,
+		bool unbuffered);
+EXPORT bool obs_source_async_unbuffered(const obs_source_t *source);
+
 /* ------------------------------------------------------------------------- */
 /* Transition-specific functions */
 enum obs_transition_target {

+ 1 - 6
plugins/decklink/plugin-main.cpp

@@ -31,12 +31,7 @@ static DeckLinkDeviceDiscovery *deviceEnum = nullptr;
 static void decklink_enable_buffering(DeckLink *decklink, bool enabled)
 {
 	obs_source_t *source = decklink->GetSource();
-	uint32_t flags = obs_source_get_flags(source);
-	if (enabled)
-		flags &= ~OBS_SOURCE_FLAG_UNBUFFERED;
-	else
-		flags |= OBS_SOURCE_FLAG_UNBUFFERED;
-	obs_source_set_flags(source, flags);
+	obs_source_set_async_unbuffered(source, !enabled);
 }
 
 static void *decklink_create(obs_data_t *settings, obs_source_t *source)

+ 2 - 5
plugins/linux-v4l2/v4l2-input.c

@@ -912,11 +912,8 @@ fail:
 static void v4l2_update_source_flags(struct v4l2_data *data,
 		obs_data_t *settings)
 {
-	uint32_t flags = obs_source_get_flags(data->source);
-	flags = (obs_data_get_bool(settings, "buffering"))
-			? flags & ~OBS_SOURCE_FLAG_UNBUFFERED
-			: flags | OBS_SOURCE_FLAG_UNBUFFERED;
-	obs_source_set_flags(data->source, flags);
+	obs_source_set_async_unbuffered(data->source,
+			!obs_data_get_bool(settings, "buffering"));
 }
 
 /**

+ 1 - 7
plugins/mac-avcapture/av-capture.mm

@@ -645,13 +645,7 @@ static inline bool update_frame(av_capture *capture,
 
 static void av_capture_enable_buffering(av_capture *capture, bool enabled)
 {
-	obs_source_t *source = capture->source;
-	uint32_t flags = obs_source_get_flags(source);
-	if (enabled)
-		flags &= ~OBS_SOURCE_FLAG_UNBUFFERED;
-	else
-		flags |= OBS_SOURCE_FLAG_UNBUFFERED;
-	obs_source_set_flags(source, flags);
+	obs_source_set_async_unbuffered(capture->source, !enabled);
 }
 
 static const char *av_capture_getname(void*)

+ 2 - 2
plugins/obs-ffmpeg/obs-ffmpeg-source.c

@@ -273,14 +273,14 @@ static void ffmpeg_source_update(void *data, obs_data_t *settings)
 		input_format = NULL;
 		s->is_looping = obs_data_get_bool(settings, "looping");
 
-		obs_source_set_flags(s->source, OBS_SOURCE_FLAG_UNBUFFERED);
+		obs_source_set_async_unbuffered(s->source, true);
 	} else {
 		input = (char *)obs_data_get_string(settings, "input");
 		input_format = (char *)obs_data_get_string(settings,
 				"input_format");
 		s->is_looping = false;
 
-		obs_source_set_flags(s->source, 0);
+		obs_source_set_async_unbuffered(s->source, false);
 	}
 
 	s->input = input ? bstrdup(input) : NULL;

+ 1 - 6
plugins/win-dshow/win-dshow.cpp

@@ -753,12 +753,7 @@ inline void DShowInput::SetupBuffering(obs_data_t *settings)
 	else
 		useBuffering = bufType == BufferingType::On;
 
-	if (useBuffering)
-		flags &= ~OBS_SOURCE_FLAG_UNBUFFERED;
-	else
-		flags |= OBS_SOURCE_FLAG_UNBUFFERED;
-
-	obs_source_set_flags(source, flags);
+	obs_source_set_async_unbuffered(source, !useBuffering);
 }
 
 static DStr GetVideoFormatName(VideoFormat format);