0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-19 20:32:15 +02:00

libobs: Format changes for multiple video mixes

This commit is contained in:
Chip Bradford 2022-06-15 10:07:50 -07:00
parent 7e39ee291c
commit 0a87797a21
3 changed files with 131 additions and 132 deletions

View File

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

View File

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

View File

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