瀏覽代碼

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.
jp9000 11 年之前
父節點
當前提交
c7bb73fe07
共有 2 個文件被更改,包括 30 次插入6 次删除
  1. 28 6
      libobs/media-io/video-io.c
  2. 2 0
      libobs/media-io/video-io.h

+ 28 - 6
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;
+}

+ 2 - 0
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
 }