From c7bb73fe079d08344a31d4928beb22644d65a2af Mon Sep 17 00:00:00 2001 From: jp9000 Date: Tue, 1 Jul 2014 11:01:22 -0700 Subject: [PATCH] Implement high encoder CPU usage handling This implements the 'frame skipping' mechanism to forcibly cause frames to be duplicated in order to reduce encoder complexity so the encoder can catch up to the video, otherwise it will continue to be progressively behind and will cause a desync of the video. Typically, if a user gets this issue, they should turn down their settings. For the love of god do not tell them that 'frames are skipping', just tell them that CPU usage is high, and that they should consider turning down their settings. --- libobs/media-io/video-io.c | 34 ++++++++++++++++++++++++++++------ libobs/media-io/video-io.h | 2 ++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/libobs/media-io/video-io.c b/libobs/media-io/video-io.c index 7ee371e80..bcd80f6df 100644 --- a/libobs/media-io/video-io.c +++ b/libobs/media-io/video-io.c @@ -59,6 +59,7 @@ struct video_output { os_event_t update_event; uint64_t frame_time; volatile uint64_t cur_video_time; + uint32_t skipped_frames; bool initialized; @@ -121,22 +122,38 @@ static inline void video_output_cur_frame(struct video_output *video) pthread_mutex_unlock(&video->input_mutex); } +#define MAX_MISSED_TIMINGS 8 + +static inline bool safe_sleepto(uint64_t t, uint32_t *missed_timings) +{ + if (!os_sleepto_ns(t)) + (*missed_timings)++; + else + *missed_timings = 0; + + return *missed_timings <= MAX_MISSED_TIMINGS; +} + static void *video_thread(void *param) { - struct video_output *video = param; - uint64_t cur_time = os_gettime_ns(); + struct video_output *video = param; + uint64_t cur_time = os_gettime_ns(); + uint32_t missed_timings = 0; while (os_event_try(video->stop_event) == EAGAIN) { /* wait half a frame, update frame */ cur_time += (video->frame_time/2); - os_sleepto_ns(cur_time); - video->cur_video_time = cur_time; - os_event_signal(video->update_event); + if (safe_sleepto(cur_time, &missed_timings)) { + video->cur_video_time = cur_time; + os_event_signal(video->update_event); + } else { + video->skipped_frames++; + } /* wait another half a frame, swap and output frames */ cur_time += (video->frame_time/2); - os_sleepto_ns(cur_time); + safe_sleepto(cur_time, &missed_timings); pthread_mutex_lock(&video->data_mutex); @@ -391,3 +408,8 @@ double video_output_framerate(video_t video) return (double)video->info.fps_num / (double)video->info.fps_den; } + +uint32_t video_output_num_skipped_frames(video_t video) +{ + return video->skipped_frames; +} diff --git a/libobs/media-io/video-io.h b/libobs/media-io/video-io.h index c7075dbff..e871345db 100644 --- a/libobs/media-io/video-io.h +++ b/libobs/media-io/video-io.h @@ -143,6 +143,8 @@ EXPORT uint32_t video_output_width(video_t video); EXPORT uint32_t video_output_height(video_t video); EXPORT double video_output_framerate(video_t video); +EXPORT uint32_t video_output_num_skipped_frames(video_t video); + #ifdef __cplusplus }