From 87ac48b4ce39948ddec175895e805a10759d0df8 Mon Sep 17 00:00:00 2001 From: Helge Norberg Date: Mon, 8 Feb 2016 18:37:28 +0100 Subject: [PATCH] Made decklink < 10.2 work while at the same time providing compatibility with newer versions (Even those completely missing the backwards compatibility with IDeckLinkConfiguration_v10_2) --- common/CMakeLists.txt | 1 + common/software_version.h | 81 +++++++++++++++++++ .../decklink/consumer/decklink_consumer.cpp | 72 ++++++++++++----- modules/decklink/decklink.cpp | 4 +- modules/decklink/decklink.h | 1 + 5 files changed, 136 insertions(+), 23 deletions(-) create mode 100644 common/software_version.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 7136354d3..9c5449fd4 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -85,6 +85,7 @@ set(HEADERS ptree.h scope_exit.h semaphore.h + software_version.h stdafx.h thread_info.h timer.h diff --git a/common/software_version.h b/common/software_version.h new file mode 100644 index 000000000..9ffb9944a --- /dev/null +++ b/common/software_version.h @@ -0,0 +1,81 @@ +/* +* Copyright 2013 Sveriges Television AB http://casparcg.com/ +* +* This file is part of CasparCG (www.casparcg.com). +* +* CasparCG is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* CasparCG is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with CasparCG. If not, see . +* +* Author: Helge Norberg, helge.norberg@svt.se +*/ + +#pragma once + +#include +#include + +#include +#include + +namespace caspar { + +template +class software_version +{ + boost::array numbers_; + std::string version_; +public: + software_version(std::string version) + : version_(std::move(version)) + { + std::fill(numbers_.begin(), numbers_.end(), 0); + std::vector tokens; + boost::split(tokens, version_, boost::is_any_of(".")); + auto num = std::min(NUM, tokens.size()); + + for (size_t i = 0; i < num; ++i) + { + try + { + numbers_[i] = boost::lexical_cast(tokens[i]); + } + catch (const boost::bad_lexical_cast&) + { + return; + } + } + }; + + const std::string& to_string() const + { + return version_; + } + + bool operator<(const software_version& other) const + { + for (int i = 0; i < NUM; ++i) + { + int this_num = numbers_[i]; + int other_num = other.numbers_[i]; + + if (this_num < other_num) + return true; + else if (this_num > other_num) + return false; + } + + return false; + } +}; + +} diff --git a/modules/decklink/consumer/decklink_consumer.cpp b/modules/decklink/consumer/decklink_consumer.cpp index 11d89bf7b..8766eca65 100644 --- a/modules/decklink/consumer/decklink_consumer.cpp +++ b/modules/decklink/consumer/decklink_consumer.cpp @@ -24,6 +24,7 @@ #include "decklink_consumer.h" #include "../util/util.h" +#include "../decklink.h" #include "../decklink_api.h" @@ -47,6 +48,7 @@ #include #include #include +#include #include @@ -119,8 +121,9 @@ struct configuration } }; +template void set_latency( - const com_iface_ptr& config, + const com_iface_ptr& config, configuration::latency_t latency, const std::wstring& print) { @@ -280,16 +283,17 @@ public: } }; +template struct key_video_context : public IDeckLinkVideoOutputCallback, boost::noncopyable { - const configuration config_; - com_ptr decklink_ = get_device(config_.key_device_index()); - com_iface_ptr output_ = iface_cast(decklink_); - com_iface_ptr keyer_ = iface_cast(decklink_); - com_iface_ptr attributes_ = iface_cast(decklink_); - com_iface_ptr configuration_ = iface_cast(decklink_); - tbb::atomic current_presentation_delay_; - tbb::atomic scheduled_frames_completed_; + const configuration config_; + com_ptr decklink_ = get_device(config_.key_device_index()); + com_iface_ptr output_ = iface_cast(decklink_); + com_iface_ptr keyer_ = iface_cast(decklink_); + com_iface_ptr attributes_ = iface_cast(decklink_); + com_iface_ptr configuration_ = iface_cast(decklink_); + tbb::atomic current_presentation_delay_; + tbb::atomic scheduled_frames_completed_; key_video_context(const configuration& config, const std::wstring& print) : config_(config) @@ -350,6 +354,7 @@ struct key_video_context : public IDeckLinkVideoOutputCallback, boost::noncopyab } }; +template struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLinkAudioOutputCallback, boost::noncopyable { const int channel_index_; @@ -357,7 +362,7 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLink com_ptr decklink_ = get_device(config_.device_index); com_iface_ptr output_ = iface_cast(decklink_); - com_iface_ptr configuration_ = iface_cast(decklink_); + com_iface_ptr configuration_ = iface_cast(decklink_); com_iface_ptr keyer_ = iface_cast(decklink_); com_iface_ptr attributes_ = iface_cast(decklink_); @@ -390,7 +395,7 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLink reference_signal_detector reference_signal_detector_ { output_ }; tbb::atomic current_presentation_delay_; tbb::atomic scheduled_frames_completed_; - std::unique_ptr key_context_; + std::unique_ptr> key_context_; public: decklink_consumer( @@ -415,7 +420,7 @@ public: audio_frame_buffer_.set_capacity((format_desc.fps > 50.0) ? 2 : 1); if (config.keyer == configuration::keyer_t::external_separate_device_keyer) - key_context_.reset(new key_video_context(config, print())); + key_context_.reset(new key_video_context(config, print())); graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f)); graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f)); @@ -695,13 +700,14 @@ public: } }; +template struct decklink_consumer_proxy : public core::frame_consumer { - core::monitor::subject monitor_subject_; - const configuration config_; - std::unique_ptr consumer_; - core::video_format_desc format_desc_; - executor executor_; + core::monitor::subject monitor_subject_; + const configuration config_; + std::unique_ptr> consumer_; + core::video_format_desc format_desc_; + executor executor_; public: decklink_consumer_proxy(const configuration& config) @@ -733,7 +739,7 @@ public: executor_.invoke([=] { consumer_.reset(); - consumer_.reset(new decklink_consumer(config_, format_desc, channel_layout, channel_index)); + consumer_.reset(new decklink_consumer(config_, format_desc, channel_layout, channel_index)); }); } @@ -790,7 +796,21 @@ public: { return monitor_subject_; } -}; +}; + +const software_version<3>& get_driver_version() +{ + static software_version<3> version(u8(get_version())); + + return version; +} + +const software_version<3> get_new_configuration_api_version() +{ + static software_version<3> NEW_CONFIGURATION_API("10.2"); + + return NEW_CONFIGURATION_API; +} void describe_consumer(core::help_sink& sink, const core::help_repository& repo) { @@ -865,7 +885,12 @@ spl::shared_ptr create_consumer( config.out_channel_layout = *found_layout; } - return spl::make_shared(config); + bool old_configuration_api = get_driver_version() < get_new_configuration_api_version(); + + if (old_configuration_api) + return spl::make_shared>(config); + else + return spl::make_shared>(config); } spl::shared_ptr create_preconfigured_consumer( @@ -907,7 +932,12 @@ spl::shared_ptr create_preconfigured_consumer( config.embedded_audio = ptree.get(L"embedded-audio", config.embedded_audio); config.base_buffer_depth = ptree.get(L"buffer-depth", config.base_buffer_depth); - return spl::make_shared(config); + bool old_configuration_api = get_driver_version() < get_new_configuration_api_version(); + + if (old_configuration_api) + return spl::make_shared>(config); + else + return spl::make_shared>(config); } }} diff --git a/modules/decklink/decklink.cpp b/modules/decklink/decklink.cpp index db1d639cd..bf6de45be 100644 --- a/modules/decklink/decklink.cpp +++ b/modules/decklink/decklink.cpp @@ -37,7 +37,7 @@ namespace caspar { namespace decklink { -std::wstring version() +std::wstring get_version() { std::wstring ver = L"Not found"; @@ -87,7 +87,7 @@ void init(core::module_dependencies dependencies) dependencies.producer_registry->register_producer_factory(L"Decklink Producer", create_producer, describe_producer); dependencies.system_info_provider_repo->register_system_info_provider([](boost::property_tree::wptree& info) { - info.add(L"system.decklink.version", version()); + info.add(L"system.decklink.version", get_version()); for (auto device : device_list()) info.add(L"system.decklink.device", device); diff --git a/modules/decklink/decklink.h b/modules/decklink/decklink.h index 4231e5c16..e9ea0f9ee 100644 --- a/modules/decklink/decklink.h +++ b/modules/decklink/decklink.h @@ -25,6 +25,7 @@ namespace caspar { namespace decklink { +std::wstring get_version(); void init(core::module_dependencies dependencies); }} -- 2.39.2