libobs: Allow overriding video resolution per view

This commit is contained in:
Antti Tapaninen 2022-11-09 21:05:32 -08:00 committed by Jim
parent 0c4e7c4142
commit c7f4c78a69
7 changed files with 51 additions and 37 deletions

View file

@ -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);
}

View file

@ -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),

View file

@ -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,

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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);