});
}
-bool DeckLinkOutput::set_device(IDeckLink *decklink)
+bool DeckLinkOutput::set_device(IDeckLink *decklink, IDeckLinkInput *input_arg)
{
+ input_arg = input;
if (decklink->QueryInterface(IID_IDeckLinkOutput, (void**)&output) != S_OK) {
fprintf(stderr, "Warning: Card %u has no outputs\n", card_index);
return false;
fprintf(stderr, "Failed to set video output connection for card %u\n", card_index);
abort();
}
- if (config->SetFlag(bmdDeckLinkConfigUse1080pNotPsF, true) != S_OK) {
+ if (config->SetFlag(bmdDeckLinkConfigOutput1080pAsPsF, true) != S_OK) {
fprintf(stderr, "Failed to set PsF flag for card\n");
abort();
}
display_mode->Release();
+ if (input != nullptr) {
+ if (input->DisableVideoInput() != S_OK) {
+ fprintf(stderr, "Warning: Failed to disable video input for card %d\n", card_index);
+ }
+ if (input->DisableAudioInput() != S_OK) {
+ fprintf(stderr, "Warning: Failed to disable audio input for card %d\n", card_index);
+ }
+ }
+
HRESULT result = output->EnableVideoOutput(mode, bmdVideoOutputFlagDefault);
if (result != S_OK) {
fprintf(stderr, "Couldn't enable output with error 0x%x\n", result);
// 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();
}
}
+ if (input != nullptr) {
+ input->Release();
+ input = nullptr;
+ }
if (output != nullptr) {
output->Release();
output = nullptr;
}
// Prioritize 59.94 > 60 > 29.97. If none of those are found, then pick the highest one.
- for (const pair<int, int> &desired : vector<pair<int, int>>{ { 60000, 1001 }, { 60, 0 }, { 30000, 1001 } }) {
+ for (const pair<int, int> &desired : vector<pair<int, int>>{ { 60000, 1001 }, { 60, 1 }, { 30000, 1001 } }) {
for (const auto &it : video_modes) {
if (it.second.frame_rate_num * desired.second == desired.first * it.second.frame_rate_den) {
return it.first;
{
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;
}
for ( ;; ) {
unique_ptr<Frame> frame;
{
- unique_lock<mutex> lock(frame_queue_mutex);
- frame_queues_changed.wait(lock, [this]{
- return should_quit.should_quit() || !pending_video_frames.empty();
- });
- if (should_quit.should_quit()) {
+ unique_lock<mutex> lock(frame_queue_mutex);
+ frame_queues_changed.wait(lock, [this]{
+ return should_quit.should_quit() || !pending_video_frames.empty();
+ });
+ if (should_quit.should_quit()) {
return;
}
frame = move(pending_video_frames.front());
pending_video_frames.pop();
- ++num_frames_in_flight;
- ++metric_decklink_output_inflight_frames;
}
for ( ;; ) {
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;
}
}
}