Przeglądaj źródła

libobs: Allow object creation if id not found

Allows objects to be created regardless of whether the actual id exists
or not.  This is a precaution that preserves objects/settings if for
some reason the id was removed for whatever reason (plugin removed, or
hardware encoder that disappeared).  This was already added for sources,
but really needs to be added for other libobs objects as well: outputs,
encoders, services.
jp9000 10 lat temu
rodzic
commit
af310fb556
4 zmienionych plików z 62 dodań i 21 usunięć
  1. 16 4
      libobs/obs-encoder.c
  2. 9 0
      libobs/obs-internal.h
  3. 23 11
      libobs/obs-output.c
  4. 14 6
      libobs/obs-service.c

+ 16 - 4
libobs/obs-encoder.c

@@ -70,13 +70,22 @@ static struct obs_encoder *create_encoder(const char *id,
 	struct obs_encoder_info *ei = find_encoder(id);
 	bool success;
 
-	if (!ei || ei->type != type)
+	if (ei && ei->type != type)
 		return NULL;
 
 	encoder = bzalloc(sizeof(struct obs_encoder));
-	encoder->info = *ei;
 	encoder->mixer_idx = mixer_idx;
 
+	if (!ei) {
+		blog(LOG_ERROR, "Encoder ID '%s' not found", id);
+
+		encoder->info.id      = bstrdup(id);
+		encoder->info.type    = type;
+		encoder->owns_info_id = true;
+	} else {
+		encoder->info = *ei;
+	}
+
 	success = init_encoder(encoder, name, settings, hotkey_data);
 	if (!success) {
 		blog(LOG_ERROR, "creating encoder '%s' (%s) failed", name, id);
@@ -221,6 +230,8 @@ static void obs_encoder_actually_destroy(obs_encoder_t *encoder)
 		pthread_mutex_destroy(&encoder->callbacks_mutex);
 		pthread_mutex_destroy(&encoder->outputs_mutex);
 		obs_context_data_free(&encoder->context);
+		if (encoder->owns_info_id)
+			bfree((void*)encoder->info.id);
 		bfree(encoder);
 	}
 }
@@ -361,8 +372,9 @@ bool obs_encoder_initialize(obs_encoder_t *encoder)
 	if (encoder->context.data)
 		encoder->info.destroy(encoder->context.data);
 
-	encoder->context.data = encoder->info.create(encoder->context.settings,
-			encoder);
+	if (encoder->info.create)
+		encoder->context.data = encoder->info.create(
+				encoder->context.settings, encoder);
 	if (!encoder->context.data)
 		return false;
 

+ 9 - 0
libobs/obs-internal.h

@@ -620,6 +620,9 @@ struct obs_output {
 	struct obs_output_info          info;
 	struct obs_weak_output          *control;
 
+	/* indicates ownership of the info.id buffer */
+	bool                            owns_info_id;
+
 	bool                            received_video;
 	bool                            received_audio;
 	int64_t                         video_offset;
@@ -731,6 +734,9 @@ struct obs_encoder {
 
 	bool                            active;
 
+	/* indicates ownership of the info.id buffer */
+	bool                            owns_info_id;
+
 	uint32_t                        timebase_num;
 	uint32_t                        timebase_den;
 
@@ -792,6 +798,9 @@ struct obs_service {
 	struct obs_service_info         info;
 	struct obs_weak_service         *control;
 
+	/* indicates ownership of the info.id buffer */
+	bool                            owns_info_id;
+
 	bool                            active;
 	bool                            destroy;
 	struct obs_output               *output;

+ 23 - 11
libobs/obs-output.c

@@ -68,11 +68,6 @@ obs_output_t *obs_output_create(const char *id, const char *name,
 	struct obs_output *output;
 	int ret;
 
-	if (!info) {
-		blog(LOG_ERROR, "Output '%s' not found", id);
-		return NULL;
-	}
-
 	output = bzalloc(sizeof(struct obs_output));
 	pthread_mutex_init_value(&output->interleaved_mutex);
 	pthread_mutex_init_value(&output->delay_mutex);
@@ -84,7 +79,14 @@ obs_output_t *obs_output_create(const char *id, const char *name,
 	if (!init_output_handlers(output, name, settings, hotkey_data))
 		goto fail;
 
-	output->info     = *info;
+	if (!info) {
+		blog(LOG_ERROR, "Output ID '%s' not found", id);
+
+		output->info.id      = bstrdup(id);
+		output->owns_info_id = true;
+	} else {
+		output->info = *info;
+	}
 	output->video    = obs_get_video();
 	output->audio    = obs_get_audio();
 	if (output->info.get_defaults)
@@ -95,9 +97,11 @@ obs_output_t *obs_output_create(const char *id, const char *name,
 	if (ret < 0)
 		goto fail;
 
-	output->context.data = info->create(output->context.settings, output);
+	if (info)
+		output->context.data = info->create(output->context.settings,
+				output);
 	if (!output->context.data)
-		goto fail;
+		blog(LOG_ERROR, "Failed to create output '%s'!", name);
 
 	output->reconnect_retry_sec = 2;
 	output->reconnect_retry_max = 20;
@@ -160,6 +164,8 @@ void obs_output_destroy(obs_output_t *output)
 		os_event_destroy(output->reconnect_stop_event);
 		obs_context_data_free(&output->context);
 		circlebuf_free(&output->delay_data);
+		if (output->owns_info_id)
+			bfree((void*)output->info.id);
 		bfree(output);
 	}
 }
@@ -171,11 +177,12 @@ const char *obs_output_get_name(const obs_output_t *output)
 
 bool obs_output_actual_start(obs_output_t *output)
 {
-	bool success;
+	bool success = false;
 
 	output->stopped = false;
 
-	success = output->info.start(output->context.data);
+	if (output->context.data)
+		success = output->info.start(output->context.data);
 
 	if (success && output->video) {
 		output->starting_frame_count =
@@ -195,6 +202,8 @@ bool obs_output_start(obs_output_t *output)
 	bool encoded;
 	if (!obs_output_valid(output, "obs_output_start"))
 		return false;
+	if (!output->context.data)
+		return false;
 
 	encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0;
 
@@ -251,7 +260,8 @@ void obs_output_actual_stop(obs_output_t *output, bool force)
 	if (output->reconnect_thread_active)
 		pthread_join(output->reconnect_thread, NULL);
 
-	output->info.stop(output->context.data);
+	if (output->context.data)
+		output->info.stop(output->context.data);
 
 	if (output->video)
 		log_frame_info(output);
@@ -270,6 +280,8 @@ void obs_output_stop(obs_output_t *output)
 	bool encoded;
 	if (!obs_output_valid(output, "obs_output_stop"))
 		return;
+	if (!output->context.data)
+		return;
 
 	encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0;
 

+ 14 - 6
libobs/obs-service.c

@@ -52,15 +52,21 @@ obs_service_t *obs_service_create(const char *id, const char *name,
 		return NULL;
 	}
 
-	service->info = *info;
+	if (!info) {
+		blog(LOG_ERROR, "Service ID '%s' not found", id);
 
-	service->context.data = service->info.create(service->context.settings,
-			service);
-	if (!service->context.data) {
-		obs_service_destroy(service);
-		return NULL;
+		service->info.id      = bstrdup(id);
+		service->owns_info_id = true;
+	} else {
+		service->info = *info;
 	}
 
+	if (info)
+		service->context.data = service->info.create(
+				service->context.settings, service);
+	if (!service->context.data)
+		blog(LOG_ERROR, "Failed to create service '%s'!", name);
+
 	service->control = bzalloc(sizeof(obs_weak_service_t));
 	service->control->service = service;
 
@@ -83,6 +89,8 @@ static void actually_destroy_service(struct obs_service *service)
 	blog(LOG_INFO, "service '%s' destroyed", service->context.name);
 
 	obs_context_data_free(&service->context);
+	if (service->owns_info_id)
+		bfree((void*)service->info.id);
 	bfree(service);
 }