#include <atomic>
#include <chrono>
#include <condition_variable>
+#include <deque>
#include <memory>
#include <mutex>
#include <queue>
#include "DeckLinkAPITypes.h"
#include "LinuxCOM.h"
-#include "context.h"
+#include "shared/context.h"
#include "print_latency.h"
+#include "queue_length_policy.h"
#include "quittable_sleeper.h"
#include "ref_counted_frame.h"
-#include "ref_counted_gl_sync.h"
+#include "shared/ref_counted_gl_sync.h"
namespace movit {
DeckLinkOutput(movit::ResourcePool *resource_pool, QSurface *surface, unsigned width, unsigned height, unsigned card_index);
bool set_device(IDeckLink *output);
- void start_output(uint32_t mode, int64_t base_pts); // Mode comes from get_available_video_modes().
+ void start_output(uint32_t mode, int64_t base_pts, bool is_master_card); // Mode comes from get_available_video_modes().
void end_output();
void send_frame(GLuint y_tex, GLuint cbcr_tex, movit::YCbCrLumaCoefficients ycbcr_coefficients, const std::vector<RefCountedFrame> &input_frames, int64_t pts, int64_t duration);
void send_audio(int64_t pts, const std::vector<float> &samples);
+ // Only makes sense if is_master_card is true.
+ //
// NOTE: The returned timestamp is undefined for preroll.
// Otherwise, it is the timestamp of the output frame as it should have been,
// even if we're overshooting. E.g. at 50 fps (0.02 spf), assuming the
void create_uyvy(GLuint y_tex, GLuint cbcr_tex, GLuint dst_tex);
void present_thread_func();
+ double PTSToTime(int64_t pts);
std::atomic<int> refcount{1};
std::thread present_thread;
QuittableSleeper should_quit;
- 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::mutex frame_queue_mutex; // Protects all members in this block.
+ std::queue<std::unique_ptr<Frame>> pending_video_frames;
+ std::queue<std::unique_ptr<Frame>> frame_freelist;
+ std::deque<Frame *> scheduled_frames; // Owned by the driver, so no unique_ptr.
+ unsigned num_safe_frames = 1;
+ int64_t next_output_pts = 0;
+ JitterHistory input_jitter_history, output_jitter_history;
+ QueueLengthPolicy queue_length_policy;
+ // End of variables protected by frame_queue_mutex.
+
std::condition_variable frame_queues_changed;
bool playback_initiated = false, playback_started = false;
int64_t base_pts, frame_duration;
bool last_frame_had_mode_mismatch = false;
movit::ResourcePool *resource_pool;
+ IDeckLinkInput *input = nullptr;
IDeckLinkOutput *output = nullptr;
BMDVideoConnection video_connection;
QSurface *surface;