Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ if (USE_VCPKG)
message(FATAL_ERROR "Failed to ensurepip.")
else()
execute_process(
COMMAND "${Python_EXECUTABLE}" -m pip install setuptools sphinx breathe sphinx-rtd-theme OpenTimelineIO-Plugins importlib_metadata zipp
COMMAND "${Python_EXECUTABLE}" -m pip install setuptools sphinx breathe sphinx-rtd-theme OpenTimelineIO-Plugins importlib_metadata zipp numpy
RESULT_VARIABLE PIP_RESULT
)
if(PIP_RESULT)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ def _plugin_metadata(self, media):
metadata = media.media_source().get_metadata(
"/colour_pipeline"
)
if not metadata:
metadata = {}
return metadata.get("ocio_py_plugin", {})

def _set_plugin_metadata(self, media, plugin_metadata):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@ long DecklinkAudioOutputDevice::desired_samples() {
}

long DecklinkAudioOutputDevice::latency_microseconds() {
if (!bmd_output_) {
return 0;
}
return (bmd_output_->num_samples_in_buffer() * 1000000) / sample_rate_;
}

bool DecklinkAudioOutputDevice::push_samples(const void *sample_data, const long num_samples) {
if (!bmd_output_) {
return false;
}
bmd_output_->receive_samples_from_xstudio((int16_t *)sample_data, num_samples);
return true;
}
}
23 changes: 19 additions & 4 deletions src/plugin/video_output/bmd_decklink/src/decklink_output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ DecklinkOutput::DecklinkOutput(BMDecklinkPlugin *decklink_xstudio_plugin)
decklink_output_interface_(NULL),
decklink_xstudio_plugin_(decklink_xstudio_plugin) {

init_decklink();
is_available_ = init_decklink();
}

DecklinkOutput::~DecklinkOutput() {
Expand Down Expand Up @@ -436,6 +436,10 @@ bool DecklinkOutput::start_sdi_output() {

try {

if (!decklink_output_interface_) {
throw std::runtime_error("No DeckLink device is available.");
}

bool mode_matched = false;
// Get first avaliable video mode for Output
if (decklink_output_interface_->GetDisplayModeIterator(&display_mode_iterator) ==
Expand Down Expand Up @@ -532,9 +536,11 @@ bool DecklinkOutput::stop_sdi_output(const std::string &error_message) {

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

decklink_output_interface_->StopScheduledPlayback(0, NULL, 0);
decklink_output_interface_->DisableVideoOutput();
decklink_output_interface_->DisableAudioOutput();
if (decklink_output_interface_) {
decklink_output_interface_->StopScheduledPlayback(0, NULL, 0);
decklink_output_interface_->DisableVideoOutput();
decklink_output_interface_->DisableAudioOutput();
}

mutex_.lock();

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

if (!decklink_output_interface_) {
fetch_more_samples_from_xstudio_ = true;
audio_samples_cv_.notify_one();
return;
}

std::unique_lock lk0(bmd_mutex_);

// How many samples are sitting on the SDI card ready to be played?
Expand Down
5 changes: 4 additions & 1 deletion src/plugin/video_output/bmd_decklink/src/decklink_output.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ namespace bm_decklink_plugin_1_0 {
hdr_metadata_mutex_.unlock();
}

[[nodiscard]] bool is_available() const { return is_available_; }

private:
AVOutputCallback *output_callback_;
std::mutex mutex_;
Expand Down Expand Up @@ -195,6 +197,7 @@ namespace bm_decklink_plugin_1_0 {

HDRMetadata hdr_metadata_;
std::mutex hdr_metadata_mutex_;
bool is_available_ = {false};
};

class AVOutputCallback : public IDeckLinkVideoOutputCallback,
Expand Down Expand Up @@ -234,4 +237,4 @@ namespace bm_decklink_plugin_1_0 {
};

} // namespace bm_decklink_plugin_1_0
} // namespace xstudio
} // namespace xstudio
10 changes: 10 additions & 0 deletions src/plugin/video_output/bmd_decklink/src/decklink_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,9 @@ void BMDecklinkPlugin::attribute_changed(const utility::Uuid &attribute_uuid, co

audio::AudioOutputDevice *
BMDecklinkPlugin::make_audio_output_device(const utility::JsonStore &prefs) {
if (!dcl_output_ || !dcl_output_->is_available()) {
return nullptr;
}
return static_cast<audio::AudioOutputDevice *>(
new DecklinkAudioOutputDevice(prefs, dcl_output_));
}
Expand All @@ -295,6 +298,13 @@ void BMDecklinkPlugin::initialise() {
dcl_output_ = new DecklinkOutput(this);
set_hdr_mode_and_metadata();

if (!dcl_output_->is_available()) {
status_message_->set_value("No DeckLink device detected.");
is_in_error_->set_value(true);
spdlog::warn("Decklink drivers found, but no DeckLink device is available.");
return;
}

resolutions_->set_role_data(
module::Attribute::StringChoices, dcl_output_->output_resolution_names());

Expand Down
Loading