mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-19 09:39:15 +00:00
libobs: Allow overriding video resolution per view
This commit is contained in:
parent
0c4e7c4142
commit
c7f4c78a69
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
18
libobs/obs.c
18
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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue