]> git.sesse.net Git - nageru/commitdiff
In DeckLinkOutput, keep a list of all the scheduled frames instead of just a count.
authorSteinar H. Gunderson <steinar+nageru@gunderson.no>
Sun, 30 Aug 2020 17:23:43 +0000 (19:23 +0200)
committerSteinar H. Gunderson <steinar+nageru@gunderson.no>
Sat, 12 Dec 2020 13:55:41 +0000 (14:55 +0100)
This will be important when we want to track frames the driver inserts
on our behalf; we'll need to be able to adjust their estimated pts then.

nageru/decklink_output.cpp
nageru/decklink_output.h

index 00d80432564c569f437a0817e3dafc22a9a3c37d..da172af686acbc3ff7acf489a7befd01a2efb2f7 100644 (file)
@@ -255,7 +255,7 @@ void DeckLinkOutput::end_output()
        // Wait until all frames are accounted for, and free them.
        {
                unique_lock<mutex> lock(frame_queue_mutex);
-               while (!(frame_freelist.empty() && num_frames_in_flight == 0)) {
+               while (!(frame_freelist.empty() && scheduled_frames.empty())) {
                        frame_queues_changed.wait(lock, [this]{ return !frame_freelist.empty(); });
                        frame_freelist.pop();
                }
@@ -503,7 +503,8 @@ HRESULT DeckLinkOutput::ScheduledFrameCompleted(/* in */ IDeckLinkVideoFrame *co
        {
                lock_guard<mutex> lock(frame_queue_mutex);
                frame_freelist.push(unique_ptr<Frame>(frame));
-               --num_frames_in_flight;
+               assert(scheduled_frames.front() == frame);
+               scheduled_frames.pop_front();
                --metric_decklink_output_inflight_frames;
        }
 
@@ -573,8 +574,6 @@ void DeckLinkOutput::present_thread_func()
                        }
                        frame = move(pending_video_frames.front());
                        pending_video_frames.pop();
-                       ++num_frames_in_flight;
-                       ++metric_decklink_output_inflight_frames;
                }
 
                for ( ;; ) {
@@ -601,15 +600,14 @@ void DeckLinkOutput::present_thread_func()
                BMDTimeValue pts = frame->pts;
                BMDTimeValue duration = frame->duration;
                HRESULT res = output->ScheduleVideoFrame(frame.get(), pts, duration, TIMEBASE);
+               lock_guard<mutex> lock(frame_queue_mutex);
                if (res == S_OK) {
-                       frame.release();  // Owned by the driver now.
+                       scheduled_frames.push_back(frame.release());  // Owned by the driver now.
+                       ++metric_decklink_output_inflight_frames;
                } else {
                        fprintf(stderr, "Could not schedule video frame! (error=0x%08x)\n", res);
 
-                       lock_guard<mutex> lock(frame_queue_mutex);
                        frame_freelist.push(move(frame));
-                       --num_frames_in_flight;
-                       --metric_decklink_output_inflight_frames;
                }
        }
 }
index 2c07bc72ccae0c32c8300081d473eebaf6bc7af9..f1b40f468abdd703eb8df9c1e0410d3a78696d29 100644 (file)
@@ -7,6 +7,7 @@
 #include <atomic>
 #include <chrono>
 #include <condition_variable>
+#include <deque>
 #include <memory>
 #include <mutex>
 #include <queue>
@@ -133,7 +134,8 @@ private:
        std::mutex frame_queue_mutex;
        std::queue<std::unique_ptr<Frame>> pending_video_frames;  // Under <frame_queue_mutex>.
        std::queue<std::unique_ptr<Frame>> frame_freelist;  // Under <frame_queue_mutex>.
-       int num_frames_in_flight = 0;  // Number of frames allocated but not on the freelist. Under <frame_queue_mutex>.
+       std::deque<Frame *> scheduled_frames;  // Owned by the driver, so no unique_ptr. Under <frame_queue_mutex>.
+
        std::condition_variable frame_queues_changed;
        bool playback_initiated = false, playback_started = false;
        int64_t base_pts, frame_duration;