Skip to content

Commit

Permalink
libobs: Deactivate unnecessary GPU ops when not encoding
Browse files Browse the repository at this point in the history
Reduces GPU usage when encoding is not active.  Does not perform color
conversion, frame staging, or frame downloading unless encoding is
explicitly active.
  • Loading branch information
jp9000 committed Apr 23, 2018
1 parent 47d920e commit 45b5291
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 23 deletions.
6 changes: 2 additions & 4 deletions libobs/obs-encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions libobs/obs-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down
4 changes: 2 additions & 2 deletions libobs/obs-output.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down
58 changes: 41 additions & 17 deletions libobs/obs-video.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,20 +334,23 @@ static inline void stage_output_texture(struct obs_core_video *video,
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();

gs_enable_depth_test(false);
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);
Expand Down Expand Up @@ -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;
Expand All @@ -543,16 +546,17 @@ 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)";
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;
Expand All @@ -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();
Expand All @@ -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));
Expand All @@ -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";
Expand All @@ -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();

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

Expand All @@ -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);
Expand All @@ -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);
Expand Down
18 changes: 18 additions & 0 deletions libobs/obs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

0 comments on commit 45b5291

Please sign in to comment.