]> git.sesse.net Git - nageru/blobdiff - ffmpeg_capture.cpp
Fix a problem where we could wait for a very long time for the first frame on FFmpeg...
[nageru] / ffmpeg_capture.cpp
index 97363a7a82a3ab686717ed3542eaa9a021537dc3..be27e6fb129a24c840837c0b85418bccc2c2f672 100644 (file)
@@ -411,6 +411,9 @@ bool FFmpegCapture::play_video(const string &pathname)
                 audio_format.num_channels = 8;
 
                for ( ;; ) {
+                       if (last_pts == 0 && pts_origin == 0) {
+                               pts_origin = frame->pts;        
+                       }
                        next_frame_start = compute_frame_start(frame->pts, pts_origin, video_timebase, start, rate);
                        video_frame.received_timestamp = next_frame_start;
                        bool finished_wakeup = producer_thread_should_quit.sleep_until(next_frame_start);
@@ -420,6 +423,8 @@ bool FFmpegCapture::play_video(const string &pathname)
                                        audio_frame, 0, audio_format);
                                break;
                        } else {
+                               if (producer_thread_should_quit.should_quit()) break;
+
                                bool rewound = false;
                                if (process_queued_commands(format_ctx.get(), pathname, last_modified, &rewound)) {
                                        return true;
@@ -429,8 +434,15 @@ bool FFmpegCapture::play_video(const string &pathname)
                                        video_frame_allocator->release_frame(video_frame);
                                        break;
                                }
-                               // OK, we didn't, so probably a rate change. We'll recalculate next_frame_start
-                               // in the next run.
+                               // OK, we didn't, so probably a rate change. Recalculate next_frame_start,
+                               // but if it's now in the past, we'll reset the origin, so that we don't
+                               // generate a huge backlog of frames that we need to run through quickly.
+                               next_frame_start = compute_frame_start(frame->pts, pts_origin, video_timebase, start, rate);
+                               steady_clock::time_point now = steady_clock::now();
+                               if (next_frame_start < now) {
+                                       pts_origin = frame->pts;
+                                       start = next_frame_start = now;
+                               }
                        }
                }
                last_pts = frame->pts;