#define _DECKLINK_OUTPUT_H 1
#include <epoxy/gl.h>
+#include <movit/image_format.h>
#include <stdint.h>
#include <atomic>
#include <chrono>
#include "context.h"
#include "print_latency.h"
+#include "quittable_sleeper.h"
#include "ref_counted_frame.h"
#include "ref_counted_gl_sync.h"
public:
DeckLinkOutput(movit::ResourcePool *resource_pool, QSurface *surface, unsigned width, unsigned height, unsigned card_index);
- void set_device(IDeckLink *output);
+ bool set_device(IDeckLink *output);
void start_output(uint32_t mode, int64_t base_pts); // Mode comes from get_available_video_modes().
void end_output();
- void send_frame(GLuint y_tex, GLuint cbcr_tex, const std::vector<RefCountedFrame> &input_frames, int64_t pts, int64_t duration);
+ 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);
// NOTE: The returned timestamp is undefined for preroll.
// Analogous to CaptureInterface. Will only return modes that have the right width/height.
std::map<uint32_t, bmusb::VideoMode> get_available_video_modes() const { return video_modes; }
+ // If the given mode is supported, return it. If not, pick some “best” valid mode.
+ uint32_t pick_video_mode(uint32_t mode) const;
+
+ // Desired Y'CbCr coefficients for the current mode. Undefined before start_output().
+ movit::YCbCrLumaCoefficients preferred_ycbcr_coefficients() const;
+
// IUnknown.
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) override;
ULONG STDMETHODCALLTYPE AddRef() override;
movit::ResourcePool *resource_pool;
// These members are persistently allocated, and reused when the frame object is.
- GLuint uyvy_tex; // Owned by <resource_pool>.
+ GLuint uyvy_tex; // Owned by <resource_pool>. Can also hold v210 data.
GLuint pbo;
uint8_t *uyvy_ptr; // Persistent mapping into the PBO.
std::map<uint32_t, bmusb::VideoMode> video_modes;
std::thread present_thread;
- std::atomic<bool> should_quit{false};
+ QuittableSleeper should_quit;
std::mutex frame_queue_mutex;
std::queue<std::unique_ptr<Frame>> pending_video_frames; // Under <frame_queue_mutex>.
std::condition_variable frame_queues_changed;
bool playback_initiated = false, playback_started = false;
int64_t base_pts, frame_duration;
+ BMDDisplayModeFlags current_mode_flags = 0;
+ bool last_frame_had_mode_mismatch = false;
movit::ResourcePool *resource_pool;
IDeckLinkOutput *output = nullptr;