]> git.sesse.net Git - nageru/blobdiff - ffmpeg_capture.cpp
Add the GPU memory metrics to the Grafana dashboard.
[nageru] / ffmpeg_capture.cpp
index 6a235f5e4305a134a43b19918782f8befc7e4198..235393a5058b0a2215a8ea021becc6c1fc75ab9a 100644 (file)
@@ -208,7 +208,6 @@ YCbCrFormat decode_ycbcr_format(const AVPixFmtDescriptor *desc, const AVFrame *f
 FFmpegCapture::FFmpegCapture(const string &filename, unsigned width, unsigned height)
        : filename(filename), width(width), height(height), video_timebase{1, 1}
 {
-       // Not really used for anything.
        description = "Video: " + filename;
 
        last_frame = steady_clock::now();
@@ -283,9 +282,15 @@ void FFmpegCapture::producer_thread_func()
        pthread_setname_np(pthread_self(), thread_name);
 
        while (!producer_thread_should_quit.should_quit()) {
-               string pathname = search_for_file(filename);
-               if (filename.empty()) {
-                       fprintf(stderr, "%s not found, sleeping one second and trying again...\n", filename.c_str());
+               string filename_copy;
+               {
+                       lock_guard<mutex> lock(filename_mu);
+                       filename_copy = filename;
+               }
+
+               string pathname = search_for_file(filename_copy);
+               if (pathname.empty()) {
+                       fprintf(stderr, "%s not found, sleeping one second and trying again...\n", filename_copy.c_str());
                        send_disconnected_frame();
                        producer_thread_should_quit.sleep_for(seconds(1));
                        continue;
@@ -322,6 +327,7 @@ void FFmpegCapture::send_disconnected_frame()
                if (pixel_format == bmusb::PixelFormat_8BitBGRA) {
                        video_format.stride = width * 4;
                        video_frame.len = width * height * 4;
+                       memset(video_frame.data, 0, video_frame.len);
                } else {
                        video_format.stride = width;
                        current_frame_ycbcr_format.luma_coefficients = YCBCR_REC_709;
@@ -334,8 +340,9 @@ void FFmpegCapture::send_disconnected_frame()
                        current_frame_ycbcr_format.cr_x_position = 0.0f;
                        current_frame_ycbcr_format.cr_y_position = 0.0f;
                        video_frame.len = width * height * 2;
+                       memset(video_frame.data, 0, width * height);
+                       memset(video_frame.data + width * height, 128, width * height);  // Valid for both NV12 and planar.
                }
-               memset(video_frame.data, 0, video_frame.len);
 
                frame_callback(-1, AVRational{1, TIMEBASE}, -1, AVRational{1, TIMEBASE}, timecode++,
                        video_frame, /*video_offset=*/0, video_format,
@@ -510,6 +517,19 @@ bool FFmpegCapture::play_video(const string &pathname)
                                audio_frame->received_timestamp += duration_cast<steady_clock::duration>(duration<double>(offset));
                        }
 
+                       steady_clock::time_point now = steady_clock::now();
+                       if (duration<double>(now - next_frame_start).count() >= 0.1) {
+                               // If we don't have enough CPU to keep up, or if we have a live stream
+                               // where the initial origin was somehow wrong, we could be behind indefinitely.
+                               // In particular, this will give the audio resampler problems as it tries
+                               // to speed up to reduce the delay, hitting the low end of the buffer every time.
+                               fprintf(stderr, "%s: Playback %.0f ms behind, resetting time scale\n",
+                                       pathname.c_str(),
+                                       1e3 * duration<double>(now - next_frame_start).count());
+                               pts_origin = frame->pts;
+                               start = next_frame_start = now;
+                               timecode += MAX_FPS * 2 + 1;
+                       }
                        bool finished_wakeup = producer_thread_should_quit.sleep_until(next_frame_start);
                        if (finished_wakeup) {
                                if (audio_frame->len > 0) {