New upstream version 23.2.1+dfsg1
This commit is contained in:
parent
cdc9a9fc87
commit
b14f9eae6d
1017 changed files with 37232 additions and 11111 deletions
265
libobs/obs.c
265
libobs/obs.c
|
|
@ -164,17 +164,42 @@ static bool obs_init_gpu_conversion(struct obs_video_info *ovi)
|
|||
|
||||
calc_gpu_conversion_sizes(ovi);
|
||||
|
||||
video->using_nv12_tex = ovi->output_format == VIDEO_FORMAT_NV12
|
||||
? gs_nv12_available() : false;
|
||||
|
||||
if (!video->conversion_height) {
|
||||
blog(LOG_INFO, "GPU conversion not available for format: %u",
|
||||
(unsigned int)ovi->output_format);
|
||||
video->gpu_conversion = false;
|
||||
video->using_nv12_tex = false;
|
||||
blog(LOG_INFO, "NV12 texture support not available");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (video->using_nv12_tex)
|
||||
blog(LOG_INFO, "NV12 texture support enabled");
|
||||
else
|
||||
blog(LOG_INFO, "NV12 texture support not available");
|
||||
|
||||
for (size_t i = 0; i < NUM_TEXTURES; i++) {
|
||||
video->convert_textures[i] = gs_texture_create(
|
||||
ovi->output_width, video->conversion_height,
|
||||
GS_RGBA, 1, NULL, GS_RENDER_TARGET);
|
||||
#ifdef _WIN32
|
||||
if (video->using_nv12_tex) {
|
||||
gs_texture_create_nv12(
|
||||
&video->convert_textures[i],
|
||||
&video->convert_uv_textures[i],
|
||||
ovi->output_width, ovi->output_height,
|
||||
GS_RENDER_TARGET | GS_SHARED_KM_TEX);
|
||||
if (!video->convert_uv_textures[i])
|
||||
return false;
|
||||
} else {
|
||||
#endif
|
||||
video->convert_textures[i] = gs_texture_create(
|
||||
ovi->output_width,
|
||||
video->conversion_height,
|
||||
GS_RGBA, 1, NULL, GS_RENDER_TARGET);
|
||||
#ifdef _WIN32
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!video->convert_textures[i])
|
||||
return false;
|
||||
|
|
@ -191,11 +216,23 @@ static bool obs_init_textures(struct obs_video_info *ovi)
|
|||
size_t i;
|
||||
|
||||
for (i = 0; i < NUM_TEXTURES; i++) {
|
||||
video->copy_surfaces[i] = gs_stagesurface_create(
|
||||
ovi->output_width, output_height, GS_RGBA);
|
||||
#ifdef _WIN32
|
||||
if (video->using_nv12_tex) {
|
||||
video->copy_surfaces[i] = gs_stagesurface_create_nv12(
|
||||
ovi->output_width, ovi->output_height);
|
||||
if (!video->copy_surfaces[i])
|
||||
return false;
|
||||
|
||||
if (!video->copy_surfaces[i])
|
||||
return false;
|
||||
} else {
|
||||
#endif
|
||||
video->copy_surfaces[i] = gs_stagesurface_create(
|
||||
ovi->output_width, output_height,
|
||||
GS_RGBA);
|
||||
if (!video->copy_surfaces[i])
|
||||
return false;
|
||||
#ifdef _WIN32
|
||||
}
|
||||
#endif
|
||||
|
||||
video->render_textures[i] = gs_texture_create(
|
||||
ovi->base_width, ovi->base_height,
|
||||
|
|
@ -272,6 +309,11 @@ static int obs_init_graphics(struct obs_video_info *ovi)
|
|||
NULL);
|
||||
bfree(filename);
|
||||
|
||||
filename = obs_find_data_file("repeat.effect");
|
||||
video->repeat_effect = gs_effect_create_from_file(filename,
|
||||
NULL);
|
||||
bfree(filename);
|
||||
|
||||
filename = obs_find_data_file("format_conversion.effect");
|
||||
video->conversion_effect = gs_effect_create_from_file(filename,
|
||||
NULL);
|
||||
|
|
@ -287,6 +329,11 @@ static int obs_init_graphics(struct obs_video_info *ovi)
|
|||
NULL);
|
||||
bfree(filename);
|
||||
|
||||
filename = obs_find_data_file("area.effect");
|
||||
video->area_effect = gs_effect_create_from_file(filename,
|
||||
NULL);
|
||||
bfree(filename);
|
||||
|
||||
filename = obs_find_data_file("bilinear_lowres_scale.effect");
|
||||
video->bilinear_lowres_effect = gs_effect_create_from_file(filename,
|
||||
NULL);
|
||||
|
|
@ -297,6 +344,7 @@ static int obs_init_graphics(struct obs_video_info *ovi)
|
|||
NULL);
|
||||
bfree(filename);
|
||||
|
||||
point_sampler.max_anisotropy = 1;
|
||||
video->point_sampler = gs_samplerstate_create(&point_sampler);
|
||||
|
||||
obs->video.transparent_texture = gs_texture_create(2, 2, GS_RGBA, 1,
|
||||
|
|
@ -351,6 +399,7 @@ static int obs_init_video(struct obs_video_info *ovi)
|
|||
{
|
||||
struct obs_core_video *video = &obs->video;
|
||||
struct video_output_info vi;
|
||||
pthread_mutexattr_t attr;
|
||||
int errorcode;
|
||||
|
||||
make_video_info(&vi, ovi);
|
||||
|
|
@ -384,6 +433,13 @@ static int obs_init_video(struct obs_video_info *ovi)
|
|||
|
||||
gs_leave_context();
|
||||
|
||||
if (pthread_mutexattr_init(&attr) != 0)
|
||||
return OBS_VIDEO_FAIL;
|
||||
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0)
|
||||
return OBS_VIDEO_FAIL;
|
||||
if (pthread_mutex_init(&video->gpu_encoder_mutex, NULL) < 0)
|
||||
return OBS_VIDEO_FAIL;
|
||||
|
||||
errorcode = pthread_create(&video->video_thread, NULL,
|
||||
obs_graphics_thread, obs);
|
||||
if (errorcode != 0)
|
||||
|
|
@ -431,17 +487,20 @@ static void obs_free_video(void)
|
|||
gs_stagesurface_destroy(video->copy_surfaces[i]);
|
||||
gs_texture_destroy(video->render_textures[i]);
|
||||
gs_texture_destroy(video->convert_textures[i]);
|
||||
gs_texture_destroy(video->convert_uv_textures[i]);
|
||||
gs_texture_destroy(video->output_textures[i]);
|
||||
|
||||
video->copy_surfaces[i] = NULL;
|
||||
video->render_textures[i] = NULL;
|
||||
video->convert_textures[i] = NULL;
|
||||
video->output_textures[i] = NULL;
|
||||
video->copy_surfaces[i] = NULL;
|
||||
video->render_textures[i] = NULL;
|
||||
video->convert_textures[i] = NULL;
|
||||
video->convert_uv_textures[i] = NULL;
|
||||
video->output_textures[i] = NULL;
|
||||
}
|
||||
|
||||
gs_leave_context();
|
||||
|
||||
circlebuf_free(&video->vframe_info_buffer);
|
||||
circlebuf_free(&video->vframe_info_buffer_gpu);
|
||||
|
||||
memset(&video->textures_rendered, 0,
|
||||
sizeof(video->textures_rendered));
|
||||
|
|
@ -452,6 +511,11 @@ static void obs_free_video(void)
|
|||
memset(&video->textures_converted, 0,
|
||||
sizeof(video->textures_converted));
|
||||
|
||||
pthread_mutex_destroy(&video->gpu_encoder_mutex);
|
||||
pthread_mutex_init_value(&video->gpu_encoder_mutex);
|
||||
da_free(video->gpu_encoders);
|
||||
|
||||
video->gpu_encoder_active = 0;
|
||||
video->cur_texture = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -473,7 +537,9 @@ static void obs_free_graphics(void)
|
|||
gs_effect_destroy(video->solid_effect);
|
||||
gs_effect_destroy(video->conversion_effect);
|
||||
gs_effect_destroy(video->bicubic_effect);
|
||||
gs_effect_destroy(video->repeat_effect);
|
||||
gs_effect_destroy(video->lanczos_effect);
|
||||
gs_effect_destroy(video->area_effect);
|
||||
gs_effect_destroy(video->bilinear_lowres_effect);
|
||||
video->default_effect = NULL;
|
||||
|
||||
|
|
@ -753,6 +819,7 @@ static bool obs_init(const char *locale, const char *module_config_path,
|
|||
obs = bzalloc(sizeof(struct obs_core));
|
||||
|
||||
pthread_mutex_init_value(&obs->audio.monitoring_mutex);
|
||||
pthread_mutex_init_value(&obs->video.gpu_encoder_mutex);
|
||||
|
||||
obs->name_store_owned = !store;
|
||||
obs->name_store = store ? store : profiler_name_store_create();
|
||||
|
|
@ -853,6 +920,42 @@ bool obs_startup(const char *locale, const char *module_config_path,
|
|||
return success;
|
||||
}
|
||||
|
||||
static struct obs_cmdline_args cmdline_args = {0, NULL};
|
||||
void obs_set_cmdline_args(int argc, const char * const *argv)
|
||||
{
|
||||
char *data;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
/* Once argc is set (non-zero) we shouldn't call again */
|
||||
if (cmdline_args.argc)
|
||||
return;
|
||||
|
||||
cmdline_args.argc = argc;
|
||||
|
||||
/* Safely copy over argv */
|
||||
len = 0;
|
||||
for (i = 0; i < argc; i++)
|
||||
len += strlen(argv[i]) + 1;
|
||||
|
||||
cmdline_args.argv = bmalloc(sizeof(char *) * (argc + 1) + len);
|
||||
data = (char *) cmdline_args.argv + sizeof(char *) * (argc + 1);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
cmdline_args.argv[i] = data;
|
||||
len = strlen(argv[i]) + 1;
|
||||
memcpy(data, argv[i], len);
|
||||
data += len;
|
||||
}
|
||||
|
||||
cmdline_args.argv[argc] = NULL;
|
||||
}
|
||||
|
||||
struct obs_cmdline_args obs_get_cmdline_args(void)
|
||||
{
|
||||
return cmdline_args;
|
||||
}
|
||||
|
||||
void obs_shutdown(void)
|
||||
{
|
||||
struct obs_module *module;
|
||||
|
|
@ -918,6 +1021,7 @@ void obs_shutdown(void)
|
|||
bfree(core->module_config_path);
|
||||
bfree(core->locale);
|
||||
bfree(core);
|
||||
bfree(cmdline_args.argv);
|
||||
|
||||
#ifdef _WIN32
|
||||
uninitialize_com();
|
||||
|
|
@ -977,7 +1081,7 @@ int obs_reset_video(struct obs_video_info *ovi)
|
|||
if (!obs) return OBS_VIDEO_FAIL;
|
||||
|
||||
/* don't allow changing of video settings if active. */
|
||||
if (obs->video.video && video_output_active(obs->video.video))
|
||||
if (obs->video.video && obs_video_active())
|
||||
return OBS_VIDEO_CURRENTLY_ACTIVE;
|
||||
|
||||
if (!size_valid(ovi->output_width, ovi->output_height) ||
|
||||
|
|
@ -1018,11 +1122,15 @@ int obs_reset_video(struct obs_video_info *ovi)
|
|||
case OBS_SCALE_LANCZOS:
|
||||
scale_type_name = "Lanczos";
|
||||
break;
|
||||
case OBS_SCALE_AREA:
|
||||
scale_type_name = "Area";
|
||||
break;
|
||||
}
|
||||
|
||||
bool yuv = format_is_yuv(ovi->output_format);
|
||||
const char *yuv_format = get_video_colorspace_name(ovi->colorspace);
|
||||
const char *yuv_range = get_video_range_name(ovi->range);
|
||||
const char *yuv_range = get_video_range_name(ovi->output_format,
|
||||
ovi->range);
|
||||
|
||||
blog(LOG_INFO, "---------------------------------");
|
||||
blog(LOG_INFO, "video settings reset:\n"
|
||||
|
|
@ -1323,6 +1431,31 @@ void obs_enum_sources(bool (*enum_proc)(void*, obs_source_t*), void *param)
|
|||
pthread_mutex_unlock(&obs->data.sources_mutex);
|
||||
}
|
||||
|
||||
void obs_enum_scenes(bool (*enum_proc)(void*, obs_source_t*), void *param)
|
||||
{
|
||||
obs_source_t *source;
|
||||
|
||||
if (!obs) return;
|
||||
|
||||
pthread_mutex_lock(&obs->data.sources_mutex);
|
||||
source = obs->data.first_source;
|
||||
|
||||
while (source) {
|
||||
obs_source_t *next_source =
|
||||
(obs_source_t*)source->context.next;
|
||||
|
||||
if (source->info.type == OBS_SOURCE_TYPE_SCENE &&
|
||||
!source->context.private &&
|
||||
!enum_proc(param, source)) {
|
||||
break;
|
||||
}
|
||||
|
||||
source = next_source;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&obs->data.sources_mutex);
|
||||
}
|
||||
|
||||
static inline void obs_enum(void *pstart, pthread_mutex_t *mutex, void *proc,
|
||||
void *param)
|
||||
{
|
||||
|
|
@ -1454,10 +1587,14 @@ gs_effect_t *obs_get_base_effect(enum obs_base_effect effect)
|
|||
return obs->video.opaque_effect;
|
||||
case OBS_EFFECT_SOLID:
|
||||
return obs->video.solid_effect;
|
||||
case OBS_EFFECT_REPEAT:
|
||||
return obs->video.repeat_effect;
|
||||
case OBS_EFFECT_BICUBIC:
|
||||
return obs->video.bicubic_effect;
|
||||
case OBS_EFFECT_LANCZOS:
|
||||
return obs->video.lanczos_effect;
|
||||
case OBS_EFFECT_AREA:
|
||||
return obs->video.area_effect;
|
||||
case OBS_EFFECT_BILINEAR_LOWRES:
|
||||
return obs->video.bilinear_lowres_effect;
|
||||
case OBS_EFFECT_PREMULTIPLIED_ALPHA:
|
||||
|
|
@ -1514,8 +1651,13 @@ void obs_render_main_texture(void)
|
|||
param = gs_effect_get_param_by_name(effect, "image");
|
||||
gs_effect_set_texture(param, tex);
|
||||
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
|
||||
while (gs_effect_loop(effect, "Draw"))
|
||||
gs_draw_sprite(tex, 0, 0, 0);
|
||||
|
||||
gs_blend_state_pop();
|
||||
}
|
||||
|
||||
gs_texture_t *obs_get_main_texture(void)
|
||||
|
|
@ -1563,6 +1705,7 @@ static obs_source_t *obs_load_source_type(obs_data_t *source_data)
|
|||
obs_data_t *settings = obs_data_get_obj(source_data, "settings");
|
||||
obs_data_t *hotkeys = obs_data_get_obj(source_data, "hotkeys");
|
||||
double volume;
|
||||
double balance;
|
||||
int64_t sync;
|
||||
uint32_t flags;
|
||||
uint32_t mixers;
|
||||
|
|
@ -1578,6 +1721,10 @@ static obs_source_t *obs_load_source_type(obs_data_t *source_data)
|
|||
volume = obs_data_get_double(source_data, "volume");
|
||||
obs_source_set_volume(source, (float)volume);
|
||||
|
||||
obs_data_set_default_double(source_data, "balance", 0.5);
|
||||
balance = obs_data_get_double(source_data, "balance");
|
||||
obs_source_set_balance_value(source, (float)balance);
|
||||
|
||||
sync = obs_data_get_int(source_data, "sync");
|
||||
obs_source_set_sync_offset(source, sync);
|
||||
|
||||
|
|
@ -1694,6 +1841,11 @@ void obs_load_sources(obs_data_array_t *array, obs_load_source_cb cb,
|
|||
if (source->info.type == OBS_SOURCE_TYPE_TRANSITION)
|
||||
obs_transition_load(source, source_data);
|
||||
obs_source_load(source);
|
||||
for (size_t i = source->filters.num; i > 0; i--) {
|
||||
obs_source_t *filter =
|
||||
source->filters.array[i - 1];
|
||||
obs_source_load(filter);
|
||||
}
|
||||
if (cb)
|
||||
cb(private_data, source);
|
||||
}
|
||||
|
|
@ -1716,6 +1868,7 @@ obs_data_t *obs_save_source(obs_source_t *source)
|
|||
obs_data_t *hotkey_data = source->context.hotkey_data;
|
||||
obs_data_t *hotkeys;
|
||||
float volume = obs_source_get_volume(source);
|
||||
float balance = obs_source_get_balance_value(source);
|
||||
uint32_t mixers = obs_source_get_audio_mixers(source);
|
||||
int64_t sync = obs_source_get_sync_offset(source);
|
||||
uint32_t flags = obs_source_get_flags(source);
|
||||
|
|
@ -1748,6 +1901,7 @@ obs_data_t *obs_save_source(obs_source_t *source)
|
|||
obs_data_set_int (source_data, "sync", sync);
|
||||
obs_data_set_int (source_data, "flags", flags);
|
||||
obs_data_set_double(source_data, "volume", volume);
|
||||
obs_data_set_double(source_data, "balance", balance);
|
||||
obs_data_set_bool (source_data, "enabled", enabled);
|
||||
obs_data_set_bool (source_data, "muted", muted);
|
||||
obs_data_set_bool (source_data, "push-to-mute", push_to_mute);
|
||||
|
|
@ -2013,6 +2167,15 @@ bool obs_obj_invalid(void *obj)
|
|||
return !context->data;
|
||||
}
|
||||
|
||||
void *obs_obj_get_data(void *obj)
|
||||
{
|
||||
struct obs_context_data *context = obj;
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
||||
return context->data;
|
||||
}
|
||||
|
||||
bool obs_set_audio_monitoring_device(const char *name, const char *id)
|
||||
{
|
||||
if (!obs || !name || !id || !*name || !*id)
|
||||
|
|
@ -2189,3 +2352,79 @@ obs_data_t *obs_get_private_data(void)
|
|||
obs_data_addref(private_data);
|
||||
return private_data;
|
||||
}
|
||||
|
||||
extern bool init_gpu_encoding(struct obs_core_video *video);
|
||||
extern void stop_gpu_encoding_thread(struct obs_core_video *video);
|
||||
extern void free_gpu_encoding(struct obs_core_video *video);
|
||||
|
||||
bool start_gpu_encode(obs_encoder_t *encoder)
|
||||
{
|
||||
struct obs_core_video *video = &obs->video;
|
||||
bool success = true;
|
||||
|
||||
obs_enter_graphics();
|
||||
pthread_mutex_lock(&video->gpu_encoder_mutex);
|
||||
|
||||
if (!video->gpu_encoders.num)
|
||||
success = init_gpu_encoding(video);
|
||||
if (success)
|
||||
da_push_back(video->gpu_encoders, &encoder);
|
||||
else
|
||||
free_gpu_encoding(video);
|
||||
|
||||
pthread_mutex_unlock(&video->gpu_encoder_mutex);
|
||||
obs_leave_graphics();
|
||||
|
||||
if (success) {
|
||||
os_atomic_inc_long(&video->gpu_encoder_active);
|
||||
video_output_inc_texture_encoders(video->video);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void stop_gpu_encode(obs_encoder_t *encoder)
|
||||
{
|
||||
struct obs_core_video *video = &obs->video;
|
||||
bool call_free = false;
|
||||
|
||||
os_atomic_dec_long(&video->gpu_encoder_active);
|
||||
video_output_dec_texture_encoders(video->video);
|
||||
|
||||
pthread_mutex_lock(&video->gpu_encoder_mutex);
|
||||
da_erase_item(video->gpu_encoders, &encoder);
|
||||
if (!video->gpu_encoders.num)
|
||||
call_free = true;
|
||||
pthread_mutex_unlock(&video->gpu_encoder_mutex);
|
||||
|
||||
os_event_wait(video->gpu_encode_inactive);
|
||||
|
||||
if (call_free) {
|
||||
stop_gpu_encoding_thread(video);
|
||||
|
||||
obs_enter_graphics();
|
||||
pthread_mutex_lock(&video->gpu_encoder_mutex);
|
||||
free_gpu_encoding(video);
|
||||
pthread_mutex_unlock(&video->gpu_encoder_mutex);
|
||||
obs_leave_graphics();
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_video_active(void)
|
||||
{
|
||||
struct obs_core_video *video = &obs->video;
|
||||
if (!obs)
|
||||
return false;
|
||||
|
||||
return os_atomic_load_long(&video->raw_active) > 0 ||
|
||||
os_atomic_load_long(&video->gpu_encoder_active) > 0;
|
||||
}
|
||||
|
||||
bool obs_nv12_tex_active(void)
|
||||
{
|
||||
struct obs_core_video *video = &obs->video;
|
||||
if (!obs)
|
||||
return false;
|
||||
|
||||
return video->using_nv12_tex;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue