瀏覽代碼

libobs: Add weak reference type for obs_source

Palana 10 年之前
父節點
當前提交
a563fbc05b
共有 5 個文件被更改,包括 116 次插入16 次删除
  1. 6 1
      libobs/obs-internal.h
  2. 63 4
      libobs/obs-source.c
  3. 2 4
      libobs/obs-video.c
  4. 15 0
      libobs/obs.h
  5. 30 7
      libobs/obs.hpp

+ 6 - 1
libobs/obs-internal.h

@@ -326,10 +326,15 @@ struct async_frame {
 	bool used;
 };
 
+struct obs_weak_source {
+	struct obs_weak_ref ref;
+	struct obs_source *source;
+};
+
 struct obs_source {
 	struct obs_context_data         context;
 	struct obs_source_info          info;
-	volatile long                   refs;
+	struct obs_weak_source          *control;
 
 	/* general exposed flags that can be set for the source */
 	uint32_t                        flags;

+ 63 - 4
libobs/obs-source.c

@@ -116,7 +116,6 @@ bool obs_source_init(struct obs_source *source,
 {
 	pthread_mutexattr_t attr;
 
-	source->refs = 1;
 	source->user_volume = 1.0f;
 	source->present_volume = 1.0f;
 	source->base_volume = 0.0f;
@@ -146,6 +145,9 @@ bool obs_source_init(struct obs_source *source,
 		}
 	}
 
+	source->control = bzalloc(sizeof(obs_weak_source_t));
+	source->control->source = source;
+
 	obs_context_data_insert(&source->context,
 			&obs->data.sources_mutex,
 			&obs->data.first_source);
@@ -302,8 +304,10 @@ void obs_source_destroy(struct obs_source *source)
 
 void obs_source_addref(obs_source_t *source)
 {
-	if (source)
-		os_atomic_inc_long(&source->refs);
+	if (!source)
+		return;
+
+	obs_ref_addref(&source->control->ref);
 }
 
 void obs_source_release(obs_source_t *source)
@@ -317,8 +321,63 @@ void obs_source_release(obs_source_t *source)
 	if (!source)
 		return;
 
-	if (os_atomic_dec_long(&source->refs) == 0)
+	obs_weak_source_t *control = source->control;
+	if (obs_ref_release(&control->ref)) {
 		obs_source_destroy(source);
+		obs_weak_source_release(control);
+	}
+}
+
+void obs_weak_source_addref(obs_weak_source_t *weak)
+{
+	if (!weak)
+		return;
+
+	obs_weak_ref_addref(&weak->ref);
+}
+
+void obs_weak_source_release(obs_weak_source_t *weak)
+{
+	if (!weak)
+		return;
+
+	if (obs_weak_ref_release(&weak->ref))
+		bfree(weak);
+}
+
+obs_source_t *obs_source_get_ref(obs_source_t *source)
+{
+	if (!source)
+		return NULL;
+
+	return obs_weak_source_get_source(source->control);
+}
+
+obs_weak_source_t *obs_source_get_weak_source(obs_source_t *source)
+{
+	if (!source)
+		return NULL;
+
+	obs_weak_source_t *weak = source->control;
+	obs_weak_source_addref(weak);
+	return weak;
+}
+
+obs_source_t *obs_weak_source_get_source(obs_weak_source_t *weak)
+{
+	if (!weak)
+		return NULL;
+
+	if (obs_weak_ref_get_ref(&weak->ref))
+		return weak->source;
+
+	return NULL;
+}
+
+bool obs_weak_source_references_source(obs_weak_source_t *weak,
+		obs_source_t *source)
+{
+	return weak && source && weak->source == source;
 }
 
 void obs_source_remove(obs_source_t *source)

+ 2 - 4
libobs/obs-video.c

@@ -70,8 +70,7 @@ static uint64_t tick_sources(uint64_t cur_time, uint64_t last_time)
 	/* call the tick function of each source */
 	source = data->first_source;
 	while (source) {
-		if (source->refs)
-			obs_source_video_tick(source, seconds);
+		obs_source_video_tick(source, seconds);
 		source = (struct obs_source*)source->context.next;
 	}
 
@@ -80,8 +79,7 @@ static uint64_t tick_sources(uint64_t cur_time, uint64_t last_time)
 
 	source = data->first_source;
 	while (source) {
-		if (source->refs)
-			calculate_base_volume(data, view, source);
+		calculate_base_volume(data, view, source);
 		source = (struct obs_source*)source->context.next;
 	}
 

+ 15 - 0
libobs/obs.h

@@ -62,6 +62,8 @@ typedef struct obs_module     obs_module_t;
 typedef struct obs_fader      obs_fader_t;
 typedef struct obs_volmeter   obs_volmeter_t;
 
+typedef struct obs_weak_source  obs_weak_source_t;
+
 #include "obs-source.h"
 #include "obs-encoder.h"
 #include "obs-output.h"
@@ -458,6 +460,9 @@ EXPORT obs_source_t *obs_get_output_source(uint32_t channel);
  *
  *   Callback function returns true to continue enumeration, or false to end
  * enumeration.
+ *
+ *   Use obs_source_get_ref or obs_source_get_weak_source if you want to retain
+ * a reference after obs_enum_sources finishes
  */
 EXPORT void obs_enum_sources(bool (*enum_proc)(void*, obs_source_t*),
 		void *param);
@@ -655,6 +660,16 @@ EXPORT obs_source_t *obs_source_create(enum obs_source_type type,
 EXPORT void obs_source_addref(obs_source_t *source);
 EXPORT void obs_source_release(obs_source_t *source);
 
+EXPORT void obs_weak_source_addref(obs_weak_source_t *weak);
+EXPORT void obs_weak_source_release(obs_weak_source_t *weak);
+
+EXPORT obs_source_t *obs_source_get_ref(obs_source_t *source);
+EXPORT obs_weak_source_t *obs_source_get_weak_source(obs_source_t *source);
+EXPORT obs_source_t *obs_weak_source_get_source(obs_weak_source_t *weak);
+
+EXPORT bool obs_weak_source_references_source(obs_weak_source_t *weak,
+		obs_source_t *source);
+
 /** Notifies all references that the source should be released */
 EXPORT void obs_source_remove(obs_source_t *source);
 

+ 30 - 7
libobs/obs.hpp

@@ -23,6 +23,20 @@
 
 /* RAII wrappers */
 
+template<typename T, void addref(T), void release(T)>
+class OBSRef;
+
+using OBSSource = OBSRef<obs_source_t*, obs_source_addref, obs_source_release>;
+using OBSScene = OBSRef<obs_scene_t*,  obs_scene_addref,  obs_scene_release>;
+using OBSSceneItem = OBSRef<obs_sceneitem_t*, obs_sceneitem_addref,
+						obs_sceneitem_release>;
+using OBSData = OBSRef<obs_data_t*, obs_data_addref, obs_data_release>;
+using OBSDataArray = OBSRef<obs_data_array_t*, obs_data_array_addref,
+						obs_data_array_release>;
+
+using OBSWeakSource = OBSRef<obs_weak_source_t*, obs_weak_source_addref,
+						obs_weak_source_release>;
+
 template<typename T, void addref(T), void release(T)>
 class OBSRef {
 	T val;
@@ -35,6 +49,9 @@ class OBSRef {
 		return *this;
 	}
 
+	struct TakeOwnership {};
+	inline OBSRef(T val, TakeOwnership) : val(val)           {}
+
 public:
 	inline OBSRef() : val(nullptr)                  {}
 	inline OBSRef(T val_) : val(val_)               {addref(val);}
@@ -61,15 +78,21 @@ public:
 
 	inline bool operator==(T p) const {return val == p;}
 	inline bool operator!=(T p) const {return val != p;}
+
+	friend OBSSource OBSGetStrongRef(obs_weak_source_t *weak);
+	friend OBSWeakSource OBSGetWeakRef(obs_source_t *source);
 };
 
-using OBSSource = OBSRef<obs_source_t*, obs_source_addref, obs_source_release>;
-using OBSScene = OBSRef<obs_scene_t*,  obs_scene_addref,  obs_scene_release>;
-using OBSSceneItem = OBSRef<obs_sceneitem_t*, obs_sceneitem_addref,
-						obs_sceneitem_release>;
-using OBSData = OBSRef<obs_data_t*, obs_data_addref, obs_data_release>;
-using OBSDataArray = OBSRef<obs_data_array_t*, obs_data_array_addref,
-						obs_data_array_release>;
+inline OBSSource OBSGetStrongRef(obs_weak_source_t *weak)
+{
+	return {obs_weak_source_get_source(weak), OBSSource::TakeOwnership()};
+}
+
+inline OBSWeakSource OBSGetWeakRef(obs_source_t *source)
+{
+	return {obs_source_get_weak_source(source),
+		OBSWeakSource::TakeOwnership()};
+}
 
 /* objects that are not meant to be instanced */
 template<typename T, void destroy(T)> class OBSObj {