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:
parent
7e39ee291c
commit
0a87797a21
@ -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;
|
||||
|
@ -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);
|
||||
|
205
libobs/obs.c
205
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)
|
||||
|
Loading…
Reference in New Issue
Block a user