From 0a87797a219e60432616816641fe7bd97e06207b Mon Sep 17 00:00:00 2001 From: Chip Bradford Date: Wed, 15 Jun 2022 10:07:50 -0700 Subject: [PATCH] libobs: Format changes for multiple video mixes --- libobs/obs-video-gpu-encode.c | 17 ++- libobs/obs-video.c | 41 +++---- libobs/obs.c | 205 +++++++++++++++++----------------- 3 files changed, 131 insertions(+), 132 deletions(-) diff --git a/libobs/obs-video-gpu-encode.c b/libobs/obs-video-gpu-encode.c index 7317e4519..0dfb11df0 100644 --- a/libobs/obs-video-gpu-encode.c +++ b/libobs/obs-video-gpu-encode.c @@ -150,7 +150,8 @@ static void *gpu_encode_thread(struct obs_core_video_mix *video) bool init_gpu_encoding(struct obs_core_video_mix *video) { #ifdef _WIN32 - const struct video_output_info *info = video_output_get_info(video->video); + const struct video_output_info *info = + video_output_get_info(video->video); video->gpu_encode_stop = false; @@ -160,15 +161,13 @@ bool init_gpu_encoding(struct obs_core_video_mix *video) gs_texture_t *tex_uv; if (info->format == VIDEO_FORMAT_P010) { - gs_texture_create_p010(&tex, &tex_uv, info->width, - info->height, - GS_RENDER_TARGET | - GS_SHARED_KM_TEX); + gs_texture_create_p010( + &tex, &tex_uv, info->width, info->height, + GS_RENDER_TARGET | GS_SHARED_KM_TEX); } else { - gs_texture_create_nv12(&tex, &tex_uv, info->width, - info->height, - GS_RENDER_TARGET | - GS_SHARED_KM_TEX); + gs_texture_create_nv12( + &tex, &tex_uv, info->width, info->height, + GS_RENDER_TARGET | GS_SHARED_KM_TEX); } if (!tex) { return false; diff --git a/libobs/obs-video.c b/libobs/obs-video.c index d464aed85..2584ed9be 100644 --- a/libobs/obs-video.c +++ b/libobs/obs-video.c @@ -37,8 +37,7 @@ static uint64_t tick_sources(uint64_t cur_time, uint64_t last_time) float seconds; if (!last_time) - last_time = cur_time - - obs->video.video_frame_interval_ns; + last_time = cur_time - obs->video.video_frame_interval_ns; delta_time = cur_time - last_time; seconds = (float)((double)delta_time / 1000000000.0); @@ -148,8 +147,7 @@ static inline void render_main_texture(struct obs_core_video_mix *video) struct draw_callback *callback; callback = obs->data.draw_callbacks.array + (i - 1); - callback->draw(callback->param, base_width, - base_height); + callback->draw(callback->param, base_width, base_height); } pthread_mutex_unlock(&obs->data.draw_callbacks_mutex); @@ -166,7 +164,8 @@ static inline gs_effect_t * get_scale_effect_internal(struct obs_core_video_mix *mix) { struct obs_core_video *video = &obs->video; - const struct video_output_info *info = video_output_get_info(mix->video); + const struct video_output_info *info = + video_output_get_info(mix->video); /* if the dimension is under half the size of the original image, * bicubic/lanczos can't sample enough pixels to create an accurate @@ -219,7 +218,8 @@ static inline gs_effect_t *get_scale_effect(struct obs_core_video_mix *mix, } static const char *render_output_texture_name = "render_output_texture"; -static inline gs_texture_t *render_output_texture(struct obs_core_video_mix *mix) +static inline gs_texture_t * +render_output_texture(struct obs_core_video_mix *mix) { struct obs_core_video *video = &obs->video; gs_texture_t *texture = mix->render_texture; @@ -427,7 +427,8 @@ stage_output_texture(struct obs_core_video_mix *video, int cur_texture, } #ifdef _WIN32 -static inline bool queue_frame(struct obs_core_video_mix *video, bool raw_active, +static inline bool queue_frame(struct obs_core_video_mix *video, + bool raw_active, struct obs_vframe_info *vframe_info) { bool duplicate = @@ -497,7 +498,8 @@ static inline void encode_gpu(struct obs_core_video_mix *video, bool raw_active, } static const char *output_gpu_encoders_name = "output_gpu_encoders"; -static void output_gpu_encoders(struct obs_core_video_mix *video, bool raw_active) +static void output_gpu_encoders(struct obs_core_video_mix *video, + bool raw_active) { profile_start(output_gpu_encoders_name); @@ -519,8 +521,9 @@ end: } #endif -static inline void render_video(struct obs_core_video_mix *video, bool raw_active, - const bool gpu_active, int cur_texture) +static inline void render_video(struct obs_core_video_mix *video, + bool raw_active, const bool gpu_active, + int cur_texture) { gs_begin_scene(); @@ -795,8 +798,7 @@ static inline void output_video_data(struct obs_core_video_mix *video, } } -static inline void video_sleep(struct obs_core_video *video, - uint64_t *p_time, +static inline void video_sleep(struct obs_core_video *video, uint64_t *p_time, uint64_t interval_ns) { struct obs_vframe_info vframe_info; @@ -830,12 +832,12 @@ static inline void video_sleep(struct obs_core_video *video, bool raw_active = video->raw_was_active; bool gpu_active = video->gpu_was_active; - if (raw_active) - circlebuf_push_back(&video->vframe_info_buffer, &vframe_info, - sizeof(vframe_info)); - if (gpu_active) - circlebuf_push_back(&video->vframe_info_buffer_gpu, - &vframe_info, sizeof(vframe_info)); + if (raw_active) + circlebuf_push_back(&video->vframe_info_buffer, + &vframe_info, sizeof(vframe_info)); + if (gpu_active) + circlebuf_push_back(&video->vframe_info_buffer_gpu, + &vframe_info, sizeof(vframe_info)); } pthread_mutex_unlock(&obs->video.mixes_mutex); } @@ -1132,8 +1134,7 @@ bool obs_graphics_thread_loop(struct obs_graphics_context *context) profile_reenable_thread(); - video_sleep(&obs->video, &obs->video.video_time, - context->interval); + video_sleep(&obs->video, &obs->video.video_time, context->interval); context->frame_time_total_ns += frame_time_ns; context->fps_total_ns += (obs->video.video_time - context->last_time); diff --git a/libobs/obs.c b/libobs/obs.c index 680c05e65..95223f464 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -46,7 +46,8 @@ static inline void make_video_info(struct video_output_info *vi, static inline void calc_gpu_conversion_sizes(struct obs_core_video_mix *video) { - const struct video_output_info *info = video_output_get_info(video->video); + const struct video_output_info *info = + video_output_get_info(video->video); video->conversion_needed = false; video->conversion_techs[0] = NULL; @@ -117,12 +118,10 @@ static bool obs_init_gpu_conversion(struct obs_core_video_mix *video) calc_gpu_conversion_sizes(video); - video->using_nv12_tex = info->format == VIDEO_FORMAT_NV12 - ? gs_nv12_available() - : false; - video->using_p010_tex = info->format == VIDEO_FORMAT_P010 - ? gs_p010_available() - : false; + video->using_nv12_tex = + info->format == VIDEO_FORMAT_NV12 ? gs_nv12_available() : false; + video->using_p010_tex = + info->format == VIDEO_FORMAT_P010 ? gs_p010_available() : false; if (!video->conversion_needed) { blog(LOG_INFO, "GPU conversion not available for format: %u", @@ -152,19 +151,19 @@ static bool obs_init_gpu_conversion(struct obs_core_video_mix *video) video->convert_textures_encode[1] = NULL; video->convert_textures_encode[2] = NULL; if (video->using_nv12_tex) { - if (!gs_texture_create_nv12( - &video->convert_textures_encode[0], - &video->convert_textures_encode[1], - info->width, info->height, - GS_RENDER_TARGET | GS_SHARED_KM_TEX)) { + if (!gs_texture_create_nv12(&video->convert_textures_encode[0], + &video->convert_textures_encode[1], + info->width, info->height, + GS_RENDER_TARGET | + GS_SHARED_KM_TEX)) { return false; } } else if (video->using_p010_tex) { - if (!gs_texture_create_p010( - &video->convert_textures_encode[0], - &video->convert_textures_encode[1], - info->width, info->height, - GS_RENDER_TARGET | GS_SHARED_KM_TEX)) { + if (!gs_texture_create_p010(&video->convert_textures_encode[0], + &video->convert_textures_encode[1], + info->width, info->height, + GS_RENDER_TARGET | + GS_SHARED_KM_TEX)) { return false; } } @@ -175,63 +174,63 @@ static bool obs_init_gpu_conversion(struct obs_core_video_mix *video) switch (info->format) { case VIDEO_FORMAT_I420: video->convert_textures[0] = - gs_texture_create(info->width, info->height, + gs_texture_create(info->width, info->height, GS_R8, 1, + NULL, GS_RENDER_TARGET); + video->convert_textures[1] = + gs_texture_create(info->width / 2, info->height / 2, + GS_R8, 1, NULL, GS_RENDER_TARGET); + video->convert_textures[2] = + gs_texture_create(info->width / 2, info->height / 2, GS_R8, 1, NULL, GS_RENDER_TARGET); - video->convert_textures[1] = gs_texture_create( - info->width / 2, info->height / 2, GS_R8, 1, - NULL, GS_RENDER_TARGET); - video->convert_textures[2] = gs_texture_create( - info->width / 2, info->height / 2, GS_R8, 1, - NULL, GS_RENDER_TARGET); if (!video->convert_textures[0] || !video->convert_textures[1] || !video->convert_textures[2]) success = false; break; case VIDEO_FORMAT_NV12: video->convert_textures[0] = - gs_texture_create(info->width, info->height, - GS_R8, 1, NULL, GS_RENDER_TARGET); - video->convert_textures[1] = gs_texture_create( - info->width / 2, info->height / 2, GS_R8G8, - 1, NULL, GS_RENDER_TARGET); + gs_texture_create(info->width, info->height, GS_R8, 1, + NULL, GS_RENDER_TARGET); + video->convert_textures[1] = + gs_texture_create(info->width / 2, info->height / 2, + GS_R8G8, 1, NULL, GS_RENDER_TARGET); if (!video->convert_textures[0] || !video->convert_textures[1]) success = false; break; case VIDEO_FORMAT_I444: video->convert_textures[0] = - gs_texture_create(info->width, info->height, - GS_R8, 1, NULL, GS_RENDER_TARGET); + gs_texture_create(info->width, info->height, GS_R8, 1, + NULL, GS_RENDER_TARGET); video->convert_textures[1] = - gs_texture_create(info->width, info->height, - GS_R8, 1, NULL, GS_RENDER_TARGET); + gs_texture_create(info->width, info->height, GS_R8, 1, + NULL, GS_RENDER_TARGET); video->convert_textures[2] = - gs_texture_create(info->width, info->height, - GS_R8, 1, NULL, GS_RENDER_TARGET); + gs_texture_create(info->width, info->height, GS_R8, 1, + NULL, GS_RENDER_TARGET); if (!video->convert_textures[0] || !video->convert_textures[1] || !video->convert_textures[2]) success = false; break; case VIDEO_FORMAT_I010: video->convert_textures[0] = - gs_texture_create(info->width, info->height, + gs_texture_create(info->width, info->height, GS_R16, 1, + NULL, GS_RENDER_TARGET); + video->convert_textures[1] = + gs_texture_create(info->width / 2, info->height / 2, + GS_R16, 1, NULL, GS_RENDER_TARGET); + video->convert_textures[2] = + gs_texture_create(info->width / 2, info->height / 2, GS_R16, 1, NULL, GS_RENDER_TARGET); - video->convert_textures[1] = gs_texture_create( - info->width / 2, info->height / 2, GS_R16, - 1, NULL, GS_RENDER_TARGET); - video->convert_textures[2] = gs_texture_create( - info->width / 2, info->height / 2, GS_R16, - 1, NULL, GS_RENDER_TARGET); if (!video->convert_textures[0] || !video->convert_textures[1] || !video->convert_textures[2]) success = false; break; case VIDEO_FORMAT_P010: video->convert_textures[0] = - gs_texture_create(info->width, info->height, - GS_R16, 1, NULL, GS_RENDER_TARGET); - video->convert_textures[1] = gs_texture_create( - info->width / 2, info->height / 2, GS_RG16, - 1, NULL, GS_RENDER_TARGET); + gs_texture_create(info->width, info->height, GS_R16, 1, + NULL, GS_RENDER_TARGET); + video->convert_textures[1] = + gs_texture_create(info->width / 2, info->height / 2, + GS_RG16, 1, NULL, GS_RENDER_TARGET); if (!video->convert_textures[0] || !video->convert_textures[1]) success = false; break; @@ -256,7 +255,8 @@ static bool obs_init_gpu_conversion(struct obs_core_video_mix *video) return success; } -static bool obs_init_gpu_copy_surfaces(struct obs_core_video_mix *video, size_t i) +static bool obs_init_gpu_copy_surfaces(struct obs_core_video_mix *video, + size_t i) { const struct video_output_info *info = video_output_get_info(video->video); @@ -332,7 +332,8 @@ static bool obs_init_gpu_copy_surfaces(struct obs_core_video_mix *video, size_t static bool obs_init_textures(struct obs_core_video_mix *video) { - const struct video_output_info *info = video_output_get_info(video->video); + const struct video_output_info *info = + video_output_get_info(video->video); bool success = true; @@ -396,15 +397,14 @@ 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, format, 1, - NULL, GS_RENDER_TARGET); + video->render_texture = + gs_texture_create(obs->video.base_width, obs->video.base_height, + format, 1, NULL, GS_RENDER_TARGET); if (!video->render_texture) success = false; - video->output_texture = gs_texture_create(info->width, - info->height, format, 1, - NULL, GS_RENDER_TARGET); + video->output_texture = gs_texture_create( + info->width, info->height, format, 1, NULL, GS_RENDER_TARGET); if (!video->output_texture) success = false; @@ -625,8 +625,10 @@ 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 = util_mul_div64(500000000ULL, ovi->fps_den, ovi->fps_num); + video->video_frame_interval_ns = + util_mul_div64(1000000000ULL, ovi->fps_den, ovi->fps_num); + video->video_half_frame_interval_ns = + util_mul_div64(500000000ULL, ovi->fps_den, ovi->fps_num); if (pthread_mutex_init(&video->task_mutex, NULL) < 0) return OBS_VIDEO_FAIL; @@ -663,67 +665,64 @@ static void stop_video(void) struct obs_core_video *video = &obs->video; void *thread_retval; - if (video->thread_initialized) { - pthread_join(video->video_thread, &thread_retval); - video->thread_initialized = false; - } + if (video->thread_initialized) { + pthread_join(video->video_thread, &thread_retval); + video->thread_initialized = false; + } } static void obs_free_render_textures(struct obs_core_video_mix *video) { - if (!obs->video.graphics) - return; + if (!obs->video.graphics) + return; - gs_enter_context(obs->video.graphics); + gs_enter_context(obs->video.graphics); - for (size_t c = 0; c < NUM_CHANNELS; c++) { - if (video->mapped_surfaces[c]) { - gs_stagesurface_unmap( - video->mapped_surfaces[c]); - video->mapped_surfaces[c] = NULL; - } + for (size_t c = 0; c < NUM_CHANNELS; c++) { + if (video->mapped_surfaces[c]) { + gs_stagesurface_unmap(video->mapped_surfaces[c]); + video->mapped_surfaces[c] = NULL; } + } - for (size_t i = 0; i < NUM_TEXTURES; i++) { - for (size_t c = 0; c < NUM_CHANNELS; c++) { - if (video->copy_surfaces[i][c]) { - gs_stagesurface_destroy( - video->copy_surfaces[i][c]); - video->copy_surfaces[i][c] = NULL; - } - - video->active_copy_surfaces[i][c] = NULL; - } -#ifdef _WIN32 - if (video->copy_surfaces_encode[i]) { + for (size_t i = 0; i < NUM_TEXTURES; i++) { + for (size_t c = 0; c < NUM_CHANNELS; c++) { + if (video->copy_surfaces[i][c]) { gs_stagesurface_destroy( - video->copy_surfaces_encode[i]); - video->copy_surfaces_encode[i] = NULL; + video->copy_surfaces[i][c]); + video->copy_surfaces[i][c] = NULL; } -#endif + + video->active_copy_surfaces[i][c] = NULL; } - - gs_texture_destroy(video->render_texture); - - for (size_t c = 0; c < NUM_CHANNELS; c++) { - if (video->convert_textures[c]) { - gs_texture_destroy(video->convert_textures[c]); - video->convert_textures[c] = NULL; - } #ifdef _WIN32 - if (video->convert_textures_encode[c]) { - gs_texture_destroy( - video->convert_textures_encode[c]); - video->convert_textures_encode[c] = NULL; - } -#endif + if (video->copy_surfaces_encode[i]) { + gs_stagesurface_destroy(video->copy_surfaces_encode[i]); + video->copy_surfaces_encode[i] = NULL; } +#endif + } - gs_texture_destroy(video->output_texture); - video->render_texture = NULL; - video->output_texture = NULL; + gs_texture_destroy(video->render_texture); - gs_leave_context(); + for (size_t c = 0; c < NUM_CHANNELS; c++) { + if (video->convert_textures[c]) { + gs_texture_destroy(video->convert_textures[c]); + video->convert_textures[c] = NULL; + } +#ifdef _WIN32 + if (video->convert_textures_encode[c]) { + gs_texture_destroy(video->convert_textures_encode[c]); + video->convert_textures_encode[c] = NULL; + } +#endif + } + + gs_texture_destroy(video->output_texture); + video->render_texture = NULL; + video->output_texture = NULL; + + gs_leave_context(); } void obs_free_video_mix(struct obs_core_video_mix *video)