libobs: Deactivate unnecessary GPU ops when not encoding

Reduces GPU usage when encoding is not active.  Does not perform color
conversion, frame staging, or frame downloading unless encoding is
explicitly active.
This commit is contained in:
jp9000 2018-01-31 18:54:36 -08:00
parent 47d920e9a2
commit 45b5291530
5 changed files with 71 additions and 23 deletions

View file

@ -189,8 +189,7 @@ static void add_connection(struct obs_encoder *encoder)
struct video_scale_info info = {0};
get_video_info(encoder, &info);
video_output_connect(encoder->media, &info, receive_video,
encoder);
start_raw_video(encoder->media, &info, receive_video, encoder);
}
set_encoder_active(encoder, true);
@ -202,8 +201,7 @@ static void remove_connection(struct obs_encoder *encoder)
audio_output_disconnect(encoder->media, encoder->mixer_idx,
receive_audio, encoder);
else
video_output_disconnect(encoder->media, receive_video,
encoder);
stop_raw_video(encoder->media, receive_video, encoder);
obs_encoder_shutdown(encoder);
set_encoder_active(encoder, false);

View file

@ -248,6 +248,7 @@ struct obs_core_video {
gs_samplerstate_t *point_sampler;
gs_stagesurf_t *mapped_surface;
int cur_texture;
long raw_active;
uint64_t video_time;
uint64_t video_avg_frame_time_ns;
@ -408,6 +409,13 @@ 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 void start_raw_video(video_t *video,
const struct video_scale_info *conversion,
void (*callback)(void *param, struct video_data *frame),
void *param);
extern void stop_raw_video(video_t *video,
void (*callback)(void *param, struct video_data *frame),
void *param);
/* ------------------------------------------------------------------------- */
/* obs shared context data */

View file

@ -1541,7 +1541,7 @@ static void hook_data_capture(struct obs_output *output, bool encoded,
encoded_callback, output);
} else {
if (has_video)
video_output_connect(output->video,
start_raw_video(output->video,
get_video_conversion(output),
default_raw_video_callback, output);
if (has_audio)
@ -1797,7 +1797,7 @@ static void *end_data_capture_thread(void *data)
stop_audio_encoders(output, encoded_callback);
} else {
if (has_video)
video_output_disconnect(output->video,
stop_raw_video(output->video,
default_raw_video_callback, output);
if (has_audio)
audio_output_disconnect(output->audio,

View file

@ -334,8 +334,8 @@ end:
profile_end(stage_output_texture_name);
}
static inline void render_video(struct obs_core_video *video, int cur_texture,
int prev_texture)
static inline void render_video(struct obs_core_video *video, bool raw_active,
int cur_texture, int prev_texture)
{
gs_begin_scene();
@ -343,11 +343,14 @@ static inline void render_video(struct obs_core_video *video, int cur_texture,
gs_set_cull_mode(GS_NEITHER);
render_main_texture(video, cur_texture);
render_output_texture(video, cur_texture, prev_texture);
if (video->gpu_conversion)
render_convert_texture(video, cur_texture, prev_texture);
stage_output_texture(video, cur_texture, prev_texture);
if (raw_active) {
render_output_texture(video, cur_texture, prev_texture);
if (video->gpu_conversion)
render_convert_texture(video, cur_texture, prev_texture);
stage_output_texture(video, cur_texture, prev_texture);
}
gs_set_render_target(NULL, NULL);
gs_enable_blending(true);
@ -522,7 +525,7 @@ static inline void output_video_data(struct obs_core_video *video,
}
}
static inline void video_sleep(struct obs_core_video *video,
static inline void video_sleep(struct obs_core_video *video, bool active,
uint64_t *p_time, uint64_t interval_ns)
{
struct obs_vframe_info vframe_info;
@ -543,8 +546,9 @@ static inline void video_sleep(struct obs_core_video *video,
vframe_info.timestamp = cur_time;
vframe_info.count = count;
circlebuf_push_back(&video->vframe_info_buffer, &vframe_info,
sizeof(vframe_info));
if (active)
circlebuf_push_back(&video->vframe_info_buffer, &vframe_info,
sizeof(vframe_info));
}
static const char *output_frame_gs_context_name = "gs_context(video->graphics)";
@ -552,7 +556,7 @@ static const char *output_frame_render_video_name = "render_video";
static const char *output_frame_download_frame_name = "download_frame";
static const char *output_frame_gs_flush_name = "gs_flush";
static const char *output_frame_output_video_data_name = "output_video_data";
static inline void output_frame(void)
static inline void output_frame(bool raw_active)
{
struct obs_core_video *video = &obs->video;
int cur_texture = video->cur_texture;
@ -566,12 +570,14 @@ static inline void output_frame(void)
gs_enter_context(video->graphics);
profile_start(output_frame_render_video_name);
render_video(video, cur_texture, prev_texture);
render_video(video, raw_active, cur_texture, prev_texture);
profile_end(output_frame_render_video_name);
profile_start(output_frame_download_frame_name);
frame_ready = download_frame(video, prev_texture, &frame);
profile_end(output_frame_download_frame_name);
if (raw_active) {
profile_start(output_frame_download_frame_name);
frame_ready = download_frame(video, prev_texture, &frame);
profile_end(output_frame_download_frame_name);
}
profile_start(output_frame_gs_flush_name);
gs_flush();
@ -580,7 +586,7 @@ static inline void output_frame(void)
gs_leave_context();
profile_end(output_frame_gs_context_name);
if (frame_ready) {
if (raw_active && frame_ready) {
struct obs_vframe_info vframe_info;
circlebuf_pop_front(&video->vframe_info_buffer, &vframe_info,
sizeof(vframe_info));
@ -597,6 +603,17 @@ static inline void output_frame(void)
#define NBSP "\xC2\xA0"
static void clear_frame_data(void)
{
struct obs_core_video *video = &obs->video;
memset(video->textures_rendered, 0, sizeof(video->textures_rendered));
memset(video->textures_output, 0, sizeof(video->textures_output));
memset(video->textures_copied, 0, sizeof(video->textures_copied));
memset(video->textures_converted, 0, sizeof(video->textures_converted));
circlebuf_free(&video->vframe_info_buffer);
video->cur_texture = 0;
}
static const char *tick_sources_name = "tick_sources";
static const char *render_displays_name = "render_displays";
static const char *output_frame_name = "output_frame";
@ -607,6 +624,7 @@ void *obs_graphics_thread(void *param)
uint64_t frame_time_total_ns = 0;
uint64_t fps_total_ns = 0;
uint32_t fps_total_frames = 0;
bool raw_was_active = false;
obs->video.video_time = os_gettime_ns();
@ -622,6 +640,11 @@ void *obs_graphics_thread(void *param)
while (!video_output_stopped(obs->video.video)) {
uint64_t frame_start = os_gettime_ns();
uint64_t frame_time_ns;
bool raw_active = obs->video.raw_active > 0;
if (!raw_was_active && raw_active)
clear_frame_data();
raw_was_active = raw_active;
profile_start(video_thread_name);
@ -630,7 +653,7 @@ void *obs_graphics_thread(void *param)
profile_end(tick_sources_name);
profile_start(output_frame_name);
output_frame();
output_frame(raw_active);
profile_end(output_frame_name);
profile_start(render_displays_name);
@ -643,7 +666,8 @@ void *obs_graphics_thread(void *param)
profile_reenable_thread();
video_sleep(&obs->video, &obs->video.video_time, interval);
video_sleep(&obs->video, raw_active, &obs->video.video_time,
interval);
frame_time_total_ns += frame_time_ns;
fps_total_ns += (obs->video.video_time - last_time);

View file

@ -2071,3 +2071,21 @@ uint32_t obs_get_lagged_frames(void)
{
return obs ? obs->video.lagged_frames : 0;
}
void start_raw_video(video_t *v, const struct video_scale_info *conversion,
void (*callback)(void *param, struct video_data *frame),
void *param)
{
struct obs_core_video *video = &obs->video;
os_atomic_inc_long(&video->raw_active);
video_output_connect(v, conversion, callback, param);
}
void stop_raw_video(video_t *v,
void (*callback)(void *param, struct video_data *frame),
void *param)
{
struct obs_core_video *video = &obs->video;
os_atomic_dec_long(&video->raw_active);
video_output_disconnect(v, callback, param);
}