DeckLinkSender green screen fix
This commit is contained in:
+12
-20
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
~DeckLinkSender() {
|
||||
if (decklink_output) {
|
||||
decklink_output->StopScheduledPlayback(0, nullptr, 1);
|
||||
if (playback_started_) decklink_output->StopScheduledPlayback(0, nullptr, 1);
|
||||
decklink_output->DisableVideoOutput();
|
||||
if (has_audio) decklink_output->DisableAudioOutput();
|
||||
decklink_output->SetScheduledFrameCompletionCallback(nullptr);
|
||||
@@ -107,33 +107,18 @@ public:
|
||||
r = decklink_output->RowBytesForPixelFormat(bmdFormat10BitYUV, width, &row_bytes);
|
||||
if (r != S_OK) throw std::runtime_error("Could not get row bytes for pixel format");
|
||||
|
||||
// Pre-fill 3 black frames and schedule them to prime the pipeline.
|
||||
// The card fires ScheduledFrameCompleted once each is done, at which point
|
||||
// submit_frame() can reclaim and reschedule them with live video.
|
||||
// Create frame pool. Frames start in free_frames; submit_frame() schedules
|
||||
// them as live content arrives. StartScheduledPlayback is deferred until
|
||||
// kPreroll frames have been scheduled so the card has a buffer to draw from.
|
||||
constexpr size_t kPreroll = 3;
|
||||
for (size_t i = 0; i < kPreroll; ++i) {
|
||||
IDeckLinkMutableVideoFrame* vf = nullptr;
|
||||
r = decklink_output->CreateVideoFrame(
|
||||
width, height, row_bytes, bmdFormat10BitYUV, bmdFrameFlagDefault, &vf);
|
||||
if (r != S_OK) throw std::runtime_error("Could not create video frame");
|
||||
|
||||
IDeckLinkVideoBuffer* buf = nullptr;
|
||||
vf->QueryInterface(IID_IDeckLinkVideoBuffer, (void**)&buf);
|
||||
buf->StartAccess(bmdBufferAccessWrite);
|
||||
void* ptr = nullptr;
|
||||
buf->GetBytes(&ptr);
|
||||
if (ptr) dmf::v210::fill_black(static_cast<uint8_t*>(ptr), width, height, row_bytes);
|
||||
buf->EndAccess(bmdBufferAccessWrite);
|
||||
buf->Release();
|
||||
|
||||
decklink_output->ScheduleVideoFrame(
|
||||
vf, static_cast<BMDTimeValue>(i * fps_den), fps_den, fps_num);
|
||||
all_frames.push_back(vf);
|
||||
free_frames.push_back(vf);
|
||||
}
|
||||
scheduled_time = static_cast<int64_t>(kPreroll) * fps_den;
|
||||
|
||||
r = decklink_output->StartScheduledPlayback(0, fps_num, 1.0);
|
||||
if (r != S_OK) throw std::runtime_error("Could not start scheduled playback");
|
||||
}
|
||||
|
||||
// Blocks until a frame slot is free (returned by the card via callback),
|
||||
@@ -169,6 +154,11 @@ public:
|
||||
const int64_t t = scheduled_time;
|
||||
scheduled_time += video_info.fps_den;
|
||||
decklink_output->ScheduleVideoFrame(vf, t, video_info.fps_den, video_info.fps_num);
|
||||
|
||||
if (!playback_started_ && ++frames_scheduled_ >= kPreroll) {
|
||||
playback_started_ = true;
|
||||
decklink_output->StartScheduledPlayback(0, video_info.fps_num, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
// Converts float32 planar → interleaved int32 and pushes to DeckLink audio buffer.
|
||||
@@ -232,6 +222,8 @@ private:
|
||||
std::vector<IDeckLinkMutableVideoFrame*> free_frames;
|
||||
|
||||
// Scheduling state — only written from submit_frame/submit_audio (single-threaded caller)
|
||||
bool playback_started_ = false;
|
||||
size_t frames_scheduled_ = 0;
|
||||
int64_t scheduled_time = 0; // next video frame position (fps_num units)
|
||||
int64_t audio_stream_time = 0; // next audio batch position (sample units)
|
||||
std::vector<int32_t> audio_convert_buf; // reused across submit_audio calls
|
||||
|
||||
Reference in New Issue
Block a user