Переглянути джерело

libobs: Split scene mutex to improve performance

Splits the scene mutex in to an audio/video mutex to allow video/audio
thread to use the same data at the same time without locking on each
other.
jp9000 9 роки тому
батько
коміт
40d6f986e6
2 змінених файлів з 60 додано та 35 видалено
  1. 58 34
      libobs/obs-scene.c
  2. 2 1
      libobs/obs-scene.h

+ 58 - 34
libobs/obs-scene.c

@@ -62,8 +62,14 @@ static void *scene_create(obs_data_t *settings, struct obs_source *source)
 		goto fail;
 	if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0)
 		goto fail;
-	if (pthread_mutex_init(&scene->mutex, &attr) != 0) {
-		blog(LOG_ERROR, "scene_create: Couldn't initialize mutex");
+	if (pthread_mutex_init(&scene->audio_mutex, &attr) != 0) {
+		blog(LOG_ERROR, "scene_create: Couldn't initialize audio "
+				"mutex");
+		goto fail;
+	}
+	if (pthread_mutex_init(&scene->video_mutex, &attr) != 0) {
+		blog(LOG_ERROR, "scene_create: Couldn't initialize video "
+				"mutex");
 		goto fail;
 	}
 
@@ -76,11 +82,28 @@ fail:
 	return NULL;
 }
 
+#define audio_lock(scene) pthread_mutex_lock(&scene->audio_mutex)
+#define video_lock(scene) pthread_mutex_lock(&scene->video_mutex)
+#define audio_unlock(scene) pthread_mutex_unlock(&scene->audio_mutex)
+#define video_unlock(scene) pthread_mutex_unlock(&scene->video_mutex)
+
+static inline void full_lock(struct obs_scene *scene)
+{
+	video_lock(scene);
+	audio_lock(scene);
+}
+
+static inline void full_unlock(struct obs_scene *scene)
+{
+	audio_unlock(scene);
+	video_unlock(scene);
+}
+
 static void remove_all_items(struct obs_scene *scene)
 {
 	struct obs_scene_item *item;
 
-	pthread_mutex_lock(&scene->mutex);
+	full_lock(scene);
 
 	item = scene->first_item;
 
@@ -91,7 +114,7 @@ static void remove_all_items(struct obs_scene *scene)
 		obs_sceneitem_remove(del_item);
 	}
 
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 }
 
 static void scene_destroy(void *data)
@@ -99,7 +122,8 @@ static void scene_destroy(void *data)
 	struct obs_scene *scene = data;
 
 	remove_all_items(scene);
-	pthread_mutex_destroy(&scene->mutex);
+	pthread_mutex_destroy(&scene->video_mutex);
+	pthread_mutex_destroy(&scene->audio_mutex);
 	bfree(scene);
 }
 
@@ -109,12 +133,13 @@ static void scene_enum_sources(void *data,
 {
 	struct obs_scene *scene = data;
 	struct obs_scene_item *item;
+	struct obs_scene_item *next;
 
-	pthread_mutex_lock(&scene->mutex);
-
+	full_lock(scene);
 	item = scene->first_item;
+
 	while (item) {
-		struct obs_scene_item *next = item->next;
+		next = item->next;
 
 		obs_sceneitem_addref(item);
 		if (item->visible)
@@ -124,7 +149,7 @@ static void scene_enum_sources(void *data,
 		item = next;
 	}
 
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 }
 
 static inline void detach_sceneitem(struct obs_scene_item *item)
@@ -304,8 +329,7 @@ static void scene_video_render(void *data, gs_effect_t *effect)
 	struct obs_scene *scene = data;
 	struct obs_scene_item *item;
 
-	pthread_mutex_lock(&scene->mutex);
-
+	video_lock(scene);
 	item = scene->first_item;
 
 	gs_blend_state_push();
@@ -335,7 +359,7 @@ static void scene_video_render(void *data, gs_effect_t *effect)
 
 	gs_blend_state_pop();
 
-	pthread_mutex_unlock(&scene->mutex);
+	video_unlock(scene);
 
 	UNUSED_PARAMETER(effect);
 }
@@ -432,7 +456,7 @@ static void scene_save(void *data, obs_data_t *settings)
 	obs_data_array_t      *array  = obs_data_array_create();
 	struct obs_scene_item *item;
 
-	pthread_mutex_lock(&scene->mutex);
+	full_lock(scene);
 
 	item = scene->first_item;
 	while (item) {
@@ -440,7 +464,7 @@ static void scene_save(void *data, obs_data_t *settings)
 		item = item->next;
 	}
 
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 
 	obs_data_set_array(settings, "items", array);
 	obs_data_array_release(array);
@@ -487,7 +511,7 @@ obs_scene_t *obs_scene_duplicate(obs_scene_t *scene, const char *name)
 	struct obs_scene *new_scene = obs_scene_create(name);
 	struct obs_scene_item *item = scene->first_item;
 
-	pthread_mutex_lock(&scene->mutex);
+	full_lock(scene);
 
 	while (item) {
 		struct obs_source *source = item->source;
@@ -517,7 +541,7 @@ obs_scene_t *obs_scene_duplicate(obs_scene_t *scene, const char *name)
 		item = item->next;
 	}
 
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 
 	return new_scene;
 }
@@ -554,7 +578,7 @@ obs_sceneitem_t *obs_scene_find_source(obs_scene_t *scene, const char *name)
 	if (!scene)
 		return NULL;
 
-	pthread_mutex_lock(&scene->mutex);
+	full_lock(scene);
 
 	item = scene->first_item;
 	while (item) {
@@ -564,7 +588,7 @@ obs_sceneitem_t *obs_scene_find_source(obs_scene_t *scene, const char *name)
 		item = item->next;
 	}
 
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 
 	return item;
 }
@@ -578,7 +602,7 @@ void obs_scene_enum_items(obs_scene_t *scene,
 	if (!scene || !callback)
 		return;
 
-	pthread_mutex_lock(&scene->mutex);
+	full_lock(scene);
 
 	item = scene->first_item;
 	while (item) {
@@ -596,7 +620,7 @@ void obs_scene_enum_items(obs_scene_t *scene,
 		item = next;
 	}
 
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 }
 
 static obs_sceneitem_t *sceneitem_get_ref(obs_sceneitem_t *si)
@@ -707,7 +731,7 @@ obs_sceneitem_t *obs_scene_add(obs_scene_t *scene, obs_source_t *source)
 
 	obs_source_addref(source);
 
-	pthread_mutex_lock(&scene->mutex);
+	full_lock(scene);
 
 	last = scene->first_item;
 	if (!last) {
@@ -720,7 +744,7 @@ obs_sceneitem_t *obs_scene_add(obs_scene_t *scene, obs_source_t *source)
 		item->prev = last;
 	}
 
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 
 	init_hotkeys(scene, item, obs_source_get_name(source));
 
@@ -768,11 +792,11 @@ void obs_sceneitem_remove(obs_sceneitem_t *item)
 	scene = item->parent;
 
 	if (scene)
-		pthread_mutex_lock(&scene->mutex);
+		full_lock(scene);
 
 	if (item->removed) {
 		if (scene)
-			pthread_mutex_unlock(&scene->mutex);
+			full_unlock(scene);
 		return;
 	}
 
@@ -786,7 +810,7 @@ void obs_sceneitem_remove(obs_sceneitem_t *item)
 	signal_item_remove(item);
 	detach_sceneitem(item);
 
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 
 	obs_sceneitem_release(item);
 }
@@ -880,7 +904,7 @@ void obs_sceneitem_set_order(obs_sceneitem_t *item,
 	struct obs_scene *scene = item->parent;
 
 	obs_scene_addref(scene);
-	pthread_mutex_lock(&scene->mutex);
+	full_lock(scene);
 
 	next = item->next;
 	prev = item->prev;
@@ -910,7 +934,7 @@ void obs_sceneitem_set_order(obs_sceneitem_t *item,
 
 	signal_reorder(item);
 
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 	obs_scene_release(scene);
 }
 
@@ -923,7 +947,7 @@ void obs_sceneitem_set_order_position(obs_sceneitem_t *item,
 	struct obs_scene_item *next;
 
 	obs_scene_addref(scene);
-	pthread_mutex_lock(&scene->mutex);
+	full_lock(scene);
 
 	detach_sceneitem(item);
 	next = scene->first_item;
@@ -942,7 +966,7 @@ void obs_sceneitem_set_order_position(obs_sceneitem_t *item,
 
 	signal_reorder(item);
 
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 	obs_scene_release(scene);
 }
 
@@ -1129,12 +1153,12 @@ bool obs_scene_reorder_items(obs_scene_t *scene,
 		return false;
 
 	obs_scene_addref(scene);
-	pthread_mutex_lock(&scene->mutex);
+	full_lock(scene);
 
 	bool order_matches = true;
 	if (!sceneitems_match(scene, item_order, item_order_size,
 				&order_matches) || order_matches) {
-		pthread_mutex_unlock(&scene->mutex);
+		full_unlock(scene);
 		obs_scene_release(scene);
 		return false;
 	}
@@ -1154,7 +1178,7 @@ bool obs_scene_reorder_items(obs_scene_t *scene,
 
 	signal_reorder(scene->first_item);
 
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 	obs_scene_release(scene);
 	return true;
 }
@@ -1166,8 +1190,8 @@ void obs_scene_atomic_update(obs_scene_t *scene,
 		return;
 
 	obs_scene_addref(scene);
-	pthread_mutex_lock(&scene->mutex);
+	full_lock(scene);
 	func(data, scene);
-	pthread_mutex_unlock(&scene->mutex);
+	full_unlock(scene);
 	obs_scene_release(scene);
 }

+ 2 - 1
libobs/obs-scene.h

@@ -59,6 +59,7 @@ struct obs_scene_item {
 struct obs_scene {
 	struct obs_source     *source;
 
-	pthread_mutex_t       mutex;
+	pthread_mutex_t       video_mutex;
+	pthread_mutex_t       audio_mutex;
 	struct obs_scene_item *first_item;
 };