ソースを参照

make data access in the threads a bit more safe (note: probably will need some more safety measures later on)

jp9000 12 年 前
コミット
ae3cecf09f
6 ファイル変更50 行追加42 行削除
  1. 1 2
      libobs/graphics/graphics.c
  2. 5 4
      libobs/obs-data.h
  3. 6 1
      libobs/obs-source.c
  4. 24 30
      libobs/obs-video.c
  5. 7 5
      libobs/obs.c
  6. 7 0
      libobs/util/threading.h

+ 1 - 2
libobs/graphics/graphics.c

@@ -110,11 +110,10 @@ int gs_create(graphics_t *pgraphics, const char *module,
 		struct gs_init_data *data)
 {
 	int errcode = GS_ERROR_FAIL;
-	pthread_mutex_t mutex_init = PTHREAD_MUTEX_INITIALIZER;
 
 	graphics_t graphics = bmalloc(sizeof(struct graphics_subsystem));
 	memset(graphics, 0, sizeof(struct graphics_subsystem));
-	graphics->mutex = mutex_init;
+	pthread_mutex_init_value(&graphics->mutex);
 
 	graphics->module = os_dlopen(module);
 	if (!graphics->module) {

+ 5 - 4
libobs/obs-data.h

@@ -62,17 +62,18 @@ struct obs_data {
 	/* TODO: sound output stuff */
 
 	/* media */
-	media_t    media;
-	video_t    video;
-	audio_t    audio;
+	media_t  media;
+	video_t  video;
+	audio_t  audio;
 
 	uint32_t output_width;
 	uint32_t output_height;
 
 	/* threading */
 	pthread_t       video_thread;
-	pthread_mutex_t source_mutex;
 	bool            thread_initialized;
+	pthread_mutex_t source_list_mutex;
+	pthread_mutex_t display_list_mutex;
 
 	obs_source_t primary_source;
 };

+ 6 - 1
libobs/obs-source.c

@@ -84,7 +84,10 @@ void obs_source_init(struct obs_source *source)
 
 	dstr_init(&source->settings);
 	da_init(source->filters);
+
+	pthread_mutex_lock(&obs->source_list_mutex);
 	da_push_back(obs->sources, &source);
+	pthread_mutex_unlock(&obs->source_list_mutex);
 }
 
 obs_source_t obs_source_create(enum obs_source_type type, const char *name,
@@ -125,9 +128,11 @@ obs_source_t obs_source_create(enum obs_source_type type, const char *name,
 void obs_source_destroy(obs_source_t source)
 {
 	if (source) {
-		da_free(source->filters);
+		pthread_mutex_lock(&obs->source_list_mutex);
 		da_erase_item(obs->sources, &source);
+		pthread_mutex_unlock(&obs->source_list_mutex);
 
+		da_free(source->filters);
 		source->callbacks.destroy(source->data);
 		dstr_free(&source->settings);
 		bfree(source);

+ 24 - 30
libobs/obs-video.c

@@ -36,38 +36,17 @@ static void tick_sources(uint64_t cur_time, uint64_t *last_time)
 	*last_time = cur_time;
 }
 
-static inline void render_displays(void)
+static inline void render_display(struct obs_display *display)
 {
-	size_t i;
 	struct vec4 clear_color;
-	vec4_set(&clear_color, 0.3f, 0.0f, 0.0f, 1.0f);
-
-
-	for (i = 0; i < obs->displays.num; i++) {
-		uint32_t cx, cy;
-		obs_display_t display = obs->displays.array[i];
-
-		gs_load_swapchain(display->swap);
+	uint32_t width, height;
 
-		cx = gs_getwidth();
-		cy = gs_getheight();
+	gs_load_swapchain(display ? display->swap : NULL);
 
-
-		gs_beginscene();
-		gs_setviewport(0, 0, (int)cx, (int)cy);
-		gs_ortho(0.0f, (float)cx, 0.0f, (float)cy, -100.0f, 100.0f);
-		gs_setviewport(0, 0, obs->output_width, obs->output_height);
-
-		if (display->source)
-			obs_source_video_render(display->source);
-
-		gs_endscene();
-		gs_present();
-	}
-
-	gs_load_swapchain(NULL);
+	gs_getsize(&width, &height);
 
 	gs_beginscene();
+	vec4_set(&clear_color, 0.3f, 0.0f, 0.0f, 1.0f);
 	gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH | GS_CLEAR_STENCIL,
 			&clear_color, 1.0f, 0);
 
@@ -75,10 +54,8 @@ static inline void render_displays(void)
 	gs_enable_blending(false);
 	gs_setcullmode(GS_NEITHER);
 
-	gs_ortho(0.0f, (float)obs->output_width,
-	         0.0f, (float)obs->output_height,
-	         -100.0f, 100.0f);
-	gs_setviewport(0, 0, obs->output_width, obs->output_height);
+	gs_ortho(0.0f, (float)width, 0.0f, (float)height, -100.0f, 100.0f);
+	gs_setviewport(0, 0, width, height);
 
 	if (obs->primary_source)
 		obs_source_video_render(obs->primary_source);
@@ -87,6 +64,23 @@ static inline void render_displays(void)
 	gs_present();
 }
 
+static inline void render_displays(void)
+{
+	size_t i;
+
+	pthread_mutex_lock(&obs->display_list_mutex);
+
+	for (i = 0; i < obs->displays.num; i++) {
+		struct obs_display *display = obs->displays.array[i];
+
+		render_display(display);
+	}
+
+	pthread_mutex_unlock(&obs->display_list_mutex);
+
+	render_display(NULL);
+}
+
 static bool swap_frame(uint64_t timestamp)
 {
 	stagesurf_t last_surface = obs->copy_surfaces[obs->cur_texture];

+ 7 - 5
libobs/obs.c

@@ -64,7 +64,9 @@ static bool obs_init_media(struct video_info *vi, struct audio_info *ai)
 
 static bool obs_init_threading(void)
 {
-	if (pthread_mutex_init(&obs->source_mutex, NULL) != 0)
+	if (pthread_mutex_init(&obs->source_list_mutex, NULL) != 0)
+		return false;
+	if (pthread_mutex_init(&obs->display_list_mutex, NULL) != 0)
 		return false;
 	if (pthread_create(&obs->video_thread, NULL, obs_video_thread,
 				obs) != 0)
@@ -78,12 +80,11 @@ static bool obs_init(const char *graphics_module,
 		struct gs_init_data *graphics_data,
 		struct video_info *vi, struct audio_info *ai)
 {
-	pthread_mutex_t pthread_init_val = PTHREAD_MUTEX_INITIALIZER;
-
 	obs = bmalloc(sizeof(struct obs_data));
 
 	memset(obs, 0, sizeof(struct obs_data));
-	obs->source_mutex = pthread_init_val;
+	pthread_mutex_init_value(&obs->source_list_mutex);
+	pthread_mutex_init_value(&obs->display_list_mutex);
 
 	if (!obs_init_graphics(graphics_module, graphics_data, vi))
 		return false;
@@ -127,7 +128,8 @@ static inline void obs_free_threading(void)
 	video_output_stop(obs->video);
 	if (obs->thread_initialized)
 		pthread_join(obs->video_thread, &thread_ret);
-	pthread_mutex_destroy(&obs->source_mutex);
+	pthread_mutex_destroy(&obs->source_list_mutex);
+	pthread_mutex_destroy(&obs->display_list_mutex);
 }
 
 static void obs_destroy(void)

+ 7 - 0
libobs/util/threading.h

@@ -46,6 +46,13 @@
 extern "C" {
 #endif
 
+/* this may seem strange, but you can't use it unless it's an initializer */
+static inline void pthread_mutex_init_value(pthread_mutex_t *mutex)
+{
+	pthread_mutex_t init_val = PTHREAD_MUTEX_INITIALIZER;
+	*mutex = init_val;
+}
+
 struct event_data {
 	pthread_mutex_t mutex;
 	pthread_cond_t  cond;