Browse Source

libobs: Allow overriding video resolution per view

Antti Tapaninen 2 years ago
parent
commit
c7f4c78a69
7 changed files with 51 additions and 37 deletions
  1. 3 1
      libobs/obs-encoder.c
  2. 3 5
      libobs/obs-internal.h
  3. 10 2
      libobs/obs-scene.c
  4. 15 15
      libobs/obs-video.c
  5. 9 2
      libobs/obs-view.c
  6. 7 11
      libobs/obs.c
  7. 4 1
      libobs/obs.h

+ 3 - 1
libobs/obs-encoder.c

@@ -187,7 +187,9 @@ static inline bool has_scaling(const struct obs_encoder *encoder)
 
 static inline bool gpu_encode_available(const struct obs_encoder *encoder)
 {
-	struct obs_core_video_mix *video = obs->video.main_mix;
+	struct obs_core_video_mix *video = get_mix_for_video(encoder->media);
+	if (!video)
+		return false;
 	return (encoder->info.caps & OBS_ENCODER_CAP_PASS_TEXTURE) != 0 &&
 	       (video->using_p010_tex || video->using_nv12_tex);
 }

+ 3 - 5
libobs/obs-internal.h

@@ -284,6 +284,7 @@ struct obs_core_video_mix {
 	volatile bool gpu_encode_stop;
 
 	video_t *video;
+	struct obs_video_info ovi;
 
 	bool gpu_conversion;
 	const char *conversion_techs[NUM_CHANNELS];
@@ -292,7 +293,6 @@ struct obs_core_video_mix {
 	float conversion_height_i;
 
 	float color_matrix[16];
-	enum obs_scale_type scale_type;
 };
 
 extern struct obs_core_video_mix *
@@ -324,9 +324,6 @@ struct obs_core_video {
 	uint32_t lagged_frames;
 	bool thread_initialized;
 
-	uint32_t base_width;
-	uint32_t base_height;
-
 	gs_texture_t *transparent_texture;
 
 	gs_effect_t *deinterlace_discard_effect;
@@ -338,7 +335,6 @@ struct obs_core_video {
 	gs_effect_t *deinterlace_yadif_effect;
 	gs_effect_t *deinterlace_yadif_2x_effect;
 
-	struct obs_video_info ovi;
 	float sdr_white_level;
 	float hdr_nominal_peak_level;
 
@@ -498,6 +494,8 @@ extern bool audio_callback(void *param, uint64_t start_ts_in,
 			   uint64_t end_ts_in, uint64_t *out_ts,
 			   uint32_t mixers, struct audio_output_data *mixes);
 
+extern struct obs_core_video_mix *get_mix_for_video(video_t *video);
+
 extern void
 start_raw_video(video_t *video, const struct video_scale_info *conversion,
 		void (*callback)(void *param, struct video_data *frame),

+ 10 - 2
libobs/obs-scene.c

@@ -1265,13 +1265,21 @@ static void scene_save(void *data, obs_data_t *settings)
 static uint32_t scene_getwidth(void *data)
 {
 	obs_scene_t *scene = data;
-	return scene->custom_size ? scene->cx : obs->video.base_width;
+	if (scene->custom_size)
+		return scene->cx;
+	if (obs->video.main_mix)
+		return obs->video.main_mix->ovi.base_width;
+	return 0;
 }
 
 static uint32_t scene_getheight(void *data)
 {
 	obs_scene_t *scene = data;
-	return scene->custom_size ? scene->cy : obs->video.base_height;
+	if (scene->custom_size)
+		return scene->cy;
+	if (obs->video.main_mix)
+		return obs->video.main_mix->ovi.base_height;
+	return 0;
 }
 
 static void apply_scene_item_audio_actions(struct obs_scene_item *item,

+ 15 - 15
libobs/obs-video.c

@@ -125,8 +125,8 @@ static inline void unmap_last_surface(struct obs_core_video_mix *video)
 static const char *render_main_texture_name = "render_main_texture";
 static inline void render_main_texture(struct obs_core_video_mix *video)
 {
-	uint32_t base_width = obs->video.base_width;
-	uint32_t base_height = obs->video.base_height;
+	uint32_t base_width = video->ovi.base_width;
+	uint32_t base_height = video->ovi.base_height;
 
 	profile_start(render_main_texture_name);
 	GS_DEBUG_MARKER_BEGIN(GS_DEBUG_COLOR_MAIN_TEXTURE,
@@ -170,12 +170,12 @@ get_scale_effect_internal(struct obs_core_video_mix *mix)
 	/* if the dimension is under half the size of the original image,
 	 * bicubic/lanczos can't sample enough pixels to create an accurate
 	 * image, so use the bilinear low resolution effect instead */
-	if (info->width < (video->base_width / 2) &&
-	    info->height < (video->base_height / 2)) {
+	if (info->width < (mix->ovi.base_width / 2) &&
+	    info->height < (mix->ovi.base_height / 2)) {
 		return video->bilinear_lowres_effect;
 	}
 
-	switch (mix->scale_type) {
+	switch (mix->ovi.scale_type) {
 	case OBS_SCALE_BILINEAR:
 		return video->default_effect;
 	case OBS_SCALE_LANCZOS:
@@ -189,11 +189,11 @@ get_scale_effect_internal(struct obs_core_video_mix *mix)
 	return video->bicubic_effect;
 }
 
-static inline bool resolution_close(struct obs_core_video *video,
+static inline bool resolution_close(struct obs_core_video_mix *mix,
 				    uint32_t width, uint32_t height)
 {
-	long width_cmp = (long)video->base_width - (long)width;
-	long height_cmp = (long)video->base_height - (long)height;
+	long width_cmp = (long)mix->ovi.base_width - (long)width;
+	long height_cmp = (long)mix->ovi.base_height - (long)height;
 
 	return labs(width_cmp) <= 16 && labs(height_cmp) <= 16;
 }
@@ -203,7 +203,7 @@ static inline gs_effect_t *get_scale_effect(struct obs_core_video_mix *mix,
 {
 	struct obs_core_video *video = &obs->video;
 
-	if (resolution_close(video, width, height)) {
+	if (resolution_close(mix, width, height)) {
 		return video->default_effect;
 	} else {
 		/* if the scale method couldn't be loaded, use either bicubic
@@ -233,8 +233,8 @@ render_output_texture(struct obs_core_video_mix *mix)
 	if (video_output_get_format(mix->video) == VIDEO_FORMAT_BGRA) {
 		tech = gs_effect_get_technique(effect, "DrawAlphaDivide");
 	} else {
-		if ((width == video->base_width) &&
-		    (height == video->base_height))
+		if ((width == mix->ovi.base_width) &&
+		    (height == mix->ovi.base_height))
 			return texture;
 
 		tech = gs_effect_get_technique(effect, "Draw");
@@ -254,15 +254,15 @@ render_output_texture(struct obs_core_video_mix *mix)
 
 	if (bres) {
 		struct vec2 base;
-		vec2_set(&base, (float)video->base_width,
-			 (float)video->base_height);
+		vec2_set(&base, (float)mix->ovi.base_width,
+			 (float)mix->ovi.base_height);
 		gs_effect_set_vec2(bres, &base);
 	}
 
 	if (bres_i) {
 		struct vec2 base_i;
-		vec2_set(&base_i, 1.0f / (float)video->base_width,
-			 1.0f / (float)video->base_height);
+		vec2_set(&base_i, 1.0f / (float)mix->ovi.base_width,
+			 1.0f / (float)mix->ovi.base_height);
 		gs_effect_set_vec2(bres_i, &base_i);
 	}
 

+ 9 - 2
libobs/obs-view.c

@@ -162,10 +162,17 @@ static inline void set_main_mix()
 
 video_t *obs_view_add(obs_view_t *view)
 {
-	if (!view)
+	if (!obs->video.main_mix)
+		return NULL;
+	return obs_view_add2(view, &obs->video.main_mix->ovi);
+}
+
+video_t *obs_view_add2(obs_view_t *view, struct obs_video_info *ovi)
+{
+	if (!view || !ovi)
 		return NULL;
 
-	struct obs_core_video_mix *mix = obs_create_video_mix(&obs->video.ovi);
+	struct obs_core_video_mix *mix = obs_create_video_mix(ovi);
 	if (!mix) {
 		return NULL;
 	}

+ 7 - 11
libobs/obs.c

@@ -398,7 +398,7 @@ static bool obs_init_textures(struct obs_core_video_mix *video)
 	}
 
 	video->render_texture =
-		gs_texture_create(obs->video.base_width, obs->video.base_height,
+		gs_texture_create(video->ovi.base_width, video->ovi.base_height,
 				  format, 1, NULL, GS_RENDER_TARGET);
 	if (!video->render_texture)
 		success = false;
@@ -586,8 +586,8 @@ static int obs_init_video_mix(struct obs_video_info *ovi,
 	pthread_mutex_init_value(&video->gpu_encoder_mutex);
 
 	make_video_info(&vi, ovi);
+	video->ovi = *ovi;
 	video->gpu_conversion = ovi->gpu_conversion;
-	video->scale_type = ovi->scale_type;
 	video->gpu_was_active = false;
 	video->raw_was_active = false;
 	video->was_active = false;
@@ -634,8 +634,6 @@ struct obs_core_video_mix *obs_create_video_mix(struct obs_video_info *ovi)
 static int obs_init_video(struct obs_video_info *ovi)
 {
 	struct obs_core_video *video = &obs->video;
-	video->base_width = ovi->base_width;
-	video->base_height = ovi->base_height;
 	video->video_frame_interval_ns =
 		util_mul_div64(1000000000ULL, ovi->fps_den, ovi->fps_num);
 	video->video_half_frame_interval_ns =
@@ -646,9 +644,7 @@ static int obs_init_video(struct obs_video_info *ovi)
 	if (pthread_mutex_init(&video->mixes_mutex, NULL) < 0)
 		return OBS_VIDEO_FAIL;
 
-	video->ovi = *ovi;
-
-	if (!obs_view_add(&obs->data.main_view))
+	if (!obs_view_add2(&obs->data.main_view, ovi))
 		return OBS_VIDEO_FAIL;
 
 	int errorcode;
@@ -1510,10 +1506,10 @@ bool obs_reset_audio(const struct obs_audio_info *oai)
 
 bool obs_get_video_info(struct obs_video_info *ovi)
 {
-	if (!obs->video.graphics)
+	if (!obs->video.graphics || !obs->video.main_mix)
 		return false;
 
-	*ovi = obs->video.ovi;
+	*ovi = obs->video.main_mix->ovi;
 	return true;
 }
 
@@ -2825,7 +2821,7 @@ extern void free_gpu_encoding(struct obs_core_video_mix *video);
 
 bool start_gpu_encode(obs_encoder_t *encoder)
 {
-	struct obs_core_video_mix *video = obs->video.main_mix;
+	struct obs_core_video_mix *video = get_mix_for_video(encoder->media);
 	bool success = true;
 
 	obs_enter_graphics();
@@ -2851,7 +2847,7 @@ bool start_gpu_encode(obs_encoder_t *encoder)
 
 void stop_gpu_encode(obs_encoder_t *encoder)
 {
-	struct obs_core_video_mix *video = obs->video.main_mix;
+	struct obs_core_video_mix *video = get_mix_for_video(encoder->media);
 	bool call_free = false;
 
 	os_atomic_dec_long(&video->gpu_encoder_active);

+ 4 - 1
libobs/obs.h

@@ -909,9 +909,12 @@ EXPORT obs_source_t *obs_view_get_source(obs_view_t *view, uint32_t channel);
 /** Renders the sources of this view context */
 EXPORT void obs_view_render(obs_view_t *view);
 
-/** Adds a view to the main render loop */
+/** Adds a view to the main render loop, with current obs_get_video_info state */
 EXPORT video_t *obs_view_add(obs_view_t *view);
 
+/** Adds a view to the main render loop, with custom video settings */
+EXPORT video_t *obs_view_add2(obs_view_t *view, struct obs_video_info *ovi);
+
 /** Removes a view from the main render loop */
 EXPORT void obs_view_remove(obs_view_t *view);