Skip to content

Commit cf8902f

Browse files
authored
Handle missing Decklink hardware when drivers are installed (#238)
Signed-off-by: xShirae <xshiraayuki@gmail.com>
1 parent 347d90a commit cf8902f

4 files changed

Lines changed: 40 additions & 6 deletions

File tree

src/plugin/video_output/bmd_decklink/src/decklink_audio_device.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,16 @@ long DecklinkAudioOutputDevice::desired_samples() {
2929
}
3030

3131
long DecklinkAudioOutputDevice::latency_microseconds() {
32+
if (!bmd_output_) {
33+
return 0;
34+
}
3235
return (bmd_output_->num_samples_in_buffer() * 1000000) / sample_rate_;
3336
}
3437

3538
bool DecklinkAudioOutputDevice::push_samples(const void *sample_data, const long num_samples) {
39+
if (!bmd_output_) {
40+
return false;
41+
}
3642
bmd_output_->receive_samples_from_xstudio((int16_t *)sample_data, num_samples);
3743
return true;
38-
}
44+
}

src/plugin/video_output/bmd_decklink/src/decklink_output.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ DecklinkOutput::DecklinkOutput(BMDecklinkPlugin *decklink_xstudio_plugin)
113113
decklink_output_interface_(NULL),
114114
decklink_xstudio_plugin_(decklink_xstudio_plugin) {
115115

116-
init_decklink();
116+
is_available_ = init_decklink();
117117
}
118118

119119
DecklinkOutput::~DecklinkOutput() {
@@ -436,6 +436,10 @@ bool DecklinkOutput::start_sdi_output() {
436436

437437
try {
438438

439+
if (!decklink_output_interface_) {
440+
throw std::runtime_error("No DeckLink device is available.");
441+
}
442+
439443
bool mode_matched = false;
440444
// Get first avaliable video mode for Output
441445
if (decklink_output_interface_->GetDisplayModeIterator(&display_mode_iterator) ==
@@ -532,9 +536,11 @@ bool DecklinkOutput::stop_sdi_output(const std::string &error_message) {
532536

533537
spdlog::info("Stopping Decklink output loop. {}", error_message);
534538

535-
decklink_output_interface_->StopScheduledPlayback(0, NULL, 0);
536-
decklink_output_interface_->DisableVideoOutput();
537-
decklink_output_interface_->DisableAudioOutput();
539+
if (decklink_output_interface_) {
540+
decklink_output_interface_->StopScheduledPlayback(0, NULL, 0);
541+
decklink_output_interface_->DisableVideoOutput();
542+
decklink_output_interface_->DisableAudioOutput();
543+
}
538544

539545
mutex_.lock();
540546

@@ -908,6 +914,9 @@ long DecklinkOutput::num_samples_in_buffer() {
908914
// note this method is called by the xstudio audio output thread
909915
// Have to assume that GetBufferedAudioSampleFrameCount is not thread safe. BMD SDK
910916
// does not tell us otherwise
917+
if (!decklink_output_interface_) {
918+
return 0;
919+
}
911920
std::unique_lock lk0(bmd_mutex_);
912921
uint32_t prerollAudioSampleCount;
913922
if (decklink_output_interface_->GetBufferedAudioSampleFrameCount(
@@ -920,6 +929,12 @@ long DecklinkOutput::num_samples_in_buffer() {
920929
// Note, I have not yet understood the significance of the preroll flag
921930
void DecklinkOutput::copy_audio_samples_to_decklink_buffer(const bool /*preroll*/) {
922931

932+
if (!decklink_output_interface_) {
933+
fetch_more_samples_from_xstudio_ = true;
934+
audio_samples_cv_.notify_one();
935+
return;
936+
}
937+
923938
std::unique_lock lk0(bmd_mutex_);
924939

925940
// How many samples are sitting on the SDI card ready to be played?

src/plugin/video_output/bmd_decklink/src/decklink_output.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ namespace bm_decklink_plugin_1_0 {
142142
hdr_metadata_mutex_.unlock();
143143
}
144144

145+
[[nodiscard]] bool is_available() const { return is_available_; }
146+
145147
private:
146148
AVOutputCallback *output_callback_;
147149
std::mutex mutex_;
@@ -195,6 +197,7 @@ namespace bm_decklink_plugin_1_0 {
195197

196198
HDRMetadata hdr_metadata_;
197199
std::mutex hdr_metadata_mutex_;
200+
bool is_available_ = {false};
198201
};
199202

200203
class AVOutputCallback : public IDeckLinkVideoOutputCallback,
@@ -234,4 +237,4 @@ namespace bm_decklink_plugin_1_0 {
234237
};
235238

236239
} // namespace bm_decklink_plugin_1_0
237-
} // namespace xstudio
240+
} // namespace xstudio

src/plugin/video_output/bmd_decklink/src/decklink_plugin.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ void BMDecklinkPlugin::attribute_changed(const utility::Uuid &attribute_uuid, co
284284

285285
audio::AudioOutputDevice *
286286
BMDecklinkPlugin::make_audio_output_device(const utility::JsonStore &prefs) {
287+
if (!dcl_output_ || !dcl_output_->is_available()) {
288+
return nullptr;
289+
}
287290
return static_cast<audio::AudioOutputDevice *>(
288291
new DecklinkAudioOutputDevice(prefs, dcl_output_));
289292
}
@@ -295,6 +298,13 @@ void BMDecklinkPlugin::initialise() {
295298
dcl_output_ = new DecklinkOutput(this);
296299
set_hdr_mode_and_metadata();
297300

301+
if (!dcl_output_->is_available()) {
302+
status_message_->set_value("No DeckLink device detected.");
303+
is_in_error_->set_value(true);
304+
spdlog::warn("Decklink drivers found, but no DeckLink device is available.");
305+
return;
306+
}
307+
298308
resolutions_->set_role_data(
299309
module::Attribute::StringChoices, dcl_output_->output_resolution_names());
300310

0 commit comments

Comments
 (0)