Przeglądaj źródła

(API Change) libobs: Make obs_service refcounted

Palana 10 lat temu
rodzic
commit
71abed387f
7 zmienionych plików z 138 dodań i 13 usunięć
  1. 9 0
      libobs/obs-internal.h
  2. 78 0
      libobs/obs-service.c
  3. 6 1
      libobs/obs.c
  4. 18 1
      libobs/obs.h
  5. 19 0
      libobs/obs.hpp
  6. 7 10
      obs/window-basic-main.cpp
  7. 1 1
      obs/window-basic-main.hpp

+ 9 - 0
libobs/obs-internal.h

@@ -586,9 +586,15 @@ void obs_encoder_destroy(obs_encoder_t *encoder);
 /* ------------------------------------------------------------------------- */
 /* services */
 
+struct obs_weak_service {
+	struct obs_weak_ref ref;
+	struct obs_service *service;
+};
+
 struct obs_service {
 	struct obs_context_data         context;
 	struct obs_service_info         info;
+	struct obs_weak_service         *control;
 
 	bool                            active;
 	bool                            destroy;
@@ -601,3 +607,6 @@ extern void obs_service_activate(struct obs_service *service);
 extern void obs_service_deactivate(struct obs_service *service, bool remove);
 extern bool obs_service_initialize(struct obs_service *service,
 		struct obs_output *output);
+
+void obs_service_destroy(obs_service_t *service);
+

+ 78 - 0
libobs/obs-service.c

@@ -60,6 +60,9 @@ obs_service_t *obs_service_create(const char *id, const char *name,
 		return NULL;
 	}
 
+	service->control = bzalloc(sizeof(obs_weak_service_t));
+	service->control->service = service;
+
 	obs_context_data_insert(&service->context,
 			&obs->data.services_mutex,
 			&obs->data.first_service);
@@ -247,3 +250,78 @@ void obs_service_apply_encoder_settings(obs_service_t *service,
 		service->info.apply_encoder_settings(service->context.data,
 				video_encoder_settings, audio_encoder_settings);
 }
+
+void obs_service_addref(obs_service_t *service)
+{
+	if (!service)
+		return;
+
+	obs_ref_addref(&service->control->ref);
+}
+
+void obs_service_release(obs_service_t *service)
+{
+	if (!service)
+		return;
+
+	obs_weak_service_t *control = service->control;
+	if (obs_ref_release(&control->ref)) {
+		// The order of operations is important here since
+		// get_context_by_name in obs.c relies on weak refs
+		// being alive while the context is listed
+		obs_service_destroy(service);
+		obs_weak_service_release(control);
+	}
+}
+
+void obs_weak_service_addref(obs_weak_service_t *weak)
+{
+	if (!weak)
+		return;
+
+	obs_weak_ref_addref(&weak->ref);
+}
+
+void obs_weak_service_release(obs_weak_service_t *weak)
+{
+	if (!weak)
+		return;
+
+	if (obs_weak_ref_release(&weak->ref))
+		bfree(weak);
+}
+
+obs_service_t *obs_service_get_ref(obs_service_t *service)
+{
+	if (!service)
+		return NULL;
+
+	return obs_weak_service_get_service(service->control);
+}
+
+obs_weak_service_t *obs_service_get_weak_service(obs_service_t *service)
+{
+	if (!service)
+		return NULL;
+
+	obs_weak_service_t *weak = service->control;
+	obs_weak_service_addref(weak);
+	return weak;
+}
+
+obs_service_t *obs_weak_service_get_service(obs_weak_service_t *weak)
+{
+	if (!weak)
+		return NULL;
+
+	if (obs_weak_ref_get_ref(&weak->ref))
+		return weak->service;
+
+	return NULL;
+}
+
+bool obs_weak_service_references_service(obs_weak_service_t *weak,
+		obs_service_t *service)
+{
+	return weak && service && weak->service == service;
+}

+ 6 - 1
libobs/obs.c

@@ -1194,6 +1194,11 @@ static inline void *obs_encoder_addref_safe_(void *ref)
 	return obs_encoder_get_ref(ref);
 }
 
+static inline void *obs_service_addref_safe_(void *ref)
+{
+	return obs_service_get_ref(ref);
+}
+
 static inline void *obs_id_(void *data)
 {
 	return data;
@@ -1217,7 +1222,7 @@ obs_service_t *obs_get_service_by_name(const char *name)
 {
 	if (!obs) return NULL;
 	return get_context_by_name(&obs->data.first_service, name,
-			&obs->data.services_mutex, obs_id_);
+			&obs->data.services_mutex, obs_service_addref_safe_);
 }
 
 gs_effect_t *obs_get_default_effect(void)

+ 18 - 1
libobs/obs.h

@@ -65,6 +65,7 @@ typedef struct obs_volmeter   obs_volmeter_t;
 typedef struct obs_weak_source  obs_weak_source_t;
 typedef struct obs_weak_output  obs_weak_output_t;
 typedef struct obs_weak_encoder obs_weak_encoder_t;
+typedef struct obs_weak_service obs_weak_service_t;
 
 #include "obs-source.h"
 #include "obs-encoder.h"
@@ -1433,7 +1434,23 @@ EXPORT const char *obs_service_get_display_name(const char *id);
 
 EXPORT obs_service_t *obs_service_create(const char *id, const char *name,
 		obs_data_t *settings);
-EXPORT void obs_service_destroy(obs_service_t *service);
+
+/**
+ * Adds/releases a reference to a service.  When the last reference is
+ * released, the service is destroyed.
+ */
+EXPORT void obs_service_addref(obs_service_t *service);
+EXPORT void obs_service_release(obs_service_t *service);
+
+EXPORT void obs_weak_service_addref(obs_weak_service_t *weak);
+EXPORT void obs_weak_service_release(obs_weak_service_t *weak);
+
+EXPORT obs_service_t *obs_service_get_ref(obs_service_t *service);
+EXPORT obs_weak_service_t *obs_service_get_weak_service(obs_service_t *service);
+EXPORT obs_service_t *obs_weak_service_get_service(obs_weak_service_t *weak);
+
+EXPORT bool obs_weak_service_references_service(obs_weak_service_t *weak,
+		obs_service_t *service);
 
 EXPORT const char *obs_service_get_name(const obs_service_t *service);
 

+ 19 - 0
libobs/obs.hpp

@@ -36,6 +36,8 @@ using OBSDataArray = OBSRef<obs_data_array_t*, obs_data_array_addref,
 using OBSOutput = OBSRef<obs_output_t*, obs_output_addref, obs_output_release>;
 using OBSEncoder = OBSRef<obs_encoder_t*, obs_encoder_addref,
 						obs_encoder_release>;
+using OBSService = OBSRef<obs_service_t*, obs_service_addref,
+						obs_service_release>;
 
 using OBSWeakSource = OBSRef<obs_weak_source_t*, obs_weak_source_addref,
 						obs_weak_source_release>;
@@ -43,6 +45,8 @@ using OBSWeakOutput = OBSRef<obs_weak_output_t*, obs_weak_output_addref,
 						obs_weak_output_release>;
 using OBSWeakEncoder = OBSRef<obs_weak_encoder_t*, obs_weak_encoder_addref,
 						obs_weak_encoder_release>;
+using OBSWeakService = OBSRef<obs_weak_service_t*, obs_weak_service_addref,
+						obs_weak_service_release>;
 
 template<typename T, void addref(T), void release(T)>
 class OBSRef {
@@ -94,6 +98,9 @@ public:
 
 	friend OBSEncoder OBSGetStrongRef(obs_weak_encoder_t *weak);
 	friend OBSWeakEncoder OBSGetWeakRef(obs_encoder_t *encoder);
+
+	friend OBSService OBSGetStrongRef(obs_weak_service_t *weak);
+	friend OBSWeakService OBSGetWeakRef(obs_service_t *service);
 };
 
 inline OBSSource OBSGetStrongRef(obs_weak_source_t *weak)
@@ -130,6 +137,18 @@ inline OBSWeakEncoder OBSGetWeakRef(obs_encoder_t *encoder)
 		OBSWeakEncoder::TakeOwnership()};
 }
 
+inline OBSService OBSGetStrongRef(obs_weak_service_t *weak)
+{
+	return {obs_weak_service_get_service(weak),
+		OBSService::TakeOwnership()};
+}
+
+inline OBSWeakService OBSGetWeakRef(obs_service_t *service)
+{
+	return {obs_service_get_weak_service(service),
+		OBSWeakService::TakeOwnership()};
+}
+
 /* objects that are not meant to be instanced */
 template<typename T, void destroy(T)> class OBSObj {
 	T obj;

+ 7 - 10
obs/window-basic-main.cpp

@@ -387,11 +387,6 @@ bool OBSBasic::LoadService()
 {
 	const char *type;
 
-	if (service) {
-		obs_service_destroy(service);
-		service = nullptr;
-	}
-
 	char serviceJsonPath[512];
 	int ret = os_get_config_path(serviceJsonPath, sizeof(serviceJsonPath),
 			SERVICE_PATH);
@@ -410,6 +405,7 @@ bool OBSBasic::LoadService()
 	obs_data_t *settings = obs_data_get_obj(data, "settings");
 
 	service = obs_service_create(type, "default_service", settings);
+	obs_service_release(service);
 
 	obs_data_release(settings);
 	obs_data_release(data);
@@ -425,6 +421,7 @@ bool OBSBasic::InitService()
 	service = obs_service_create("rtmp_common", "default_service", nullptr);
 	if (!service)
 		return false;
+	obs_service_release(service);
 
 	return true;
 }
@@ -690,6 +687,7 @@ OBSBasic::~OBSBasic()
 	delete cpuUsageTimer;
 	os_cpu_usage_info_destroy(cpuUsageInfo);
 
+	service = nullptr;
 	outputHandler.reset();
 
 	if (interaction)
@@ -1447,18 +1445,17 @@ void OBSBasic::RenderMain(void *data, uint32_t cx, uint32_t cy)
 
 obs_service_t *OBSBasic::GetService()
 {
-	if (!service)
+	if (!service) {
 		service = obs_service_create("rtmp_common", NULL, NULL);
+		obs_service_release(service);
+	}
 	return service;
 }
 
 void OBSBasic::SetService(obs_service_t *newService)
 {
-	if (newService) {
-		if (service)
-			obs_service_destroy(service);
+	if (newService)
 		service = newService;
-	}
 }
 
 bool OBSBasic::StreamingActive()

+ 1 - 1
obs/window-basic-main.hpp

@@ -82,7 +82,7 @@ private:
 	QPointer<QTimer>    cpuUsageTimer;
 	os_cpu_usage_info_t *cpuUsageInfo = nullptr;
 
-	obs_service_t *service = nullptr;
+	OBSService service;
 	std::unique_ptr<BasicOutputHandler> outputHandler;
 
 	gs_vertbuffer_t *box = nullptr;