]> git.sesse.net Git - casparcg/commitdiff
Made decklink < 10.2 work while at the same time providing compatibility with newer...
authorHelge Norberg <helge.norberg@svt.se>
Mon, 8 Feb 2016 17:37:28 +0000 (18:37 +0100)
committerHelge Norberg <helge.norberg@svt.se>
Mon, 8 Feb 2016 17:37:28 +0000 (18:37 +0100)
common/CMakeLists.txt
common/software_version.h [new file with mode: 0644]
modules/decklink/consumer/decklink_consumer.cpp
modules/decklink/decklink.cpp
modules/decklink/decklink.h

index 7136354d30e23e48bcdc34cb0342db099672dd94..9c5449fd451a23823958a353c6d7c83ab2d810d1 100644 (file)
@@ -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 (file)
index 0000000..9ffb994
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <boost/array.hpp>
+#include <boost/algorithm/string/split.hpp>
+
+namespace caspar {
+
+template<size_t NUM>
+class software_version
+{
+       boost::array<int, NUM> numbers_;
+       std::string version_;
+public:
+       software_version(std::string version)
+               : version_(std::move(version))
+       {
+               std::fill(numbers_.begin(), numbers_.end(), 0);
+               std::vector<std::string> 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<int>(tokens[i]);
+                       }
+                       catch (const boost::bad_lexical_cast&)
+                       {
+                               return;
+                       }
+               }
+       };
+
+       const std::string& to_string() const
+       {
+               return version_;
+       }
+
+       bool operator<(const software_version<NUM>& 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;
+       }
+};
+
+}
index 11d89bf7b380f4f3ceefadf3ba6653741055a0d0..8766eca6506b0ef974b02d96d5ab9173069d4e65 100644 (file)
@@ -24,6 +24,7 @@
 #include "decklink_consumer.h"
 
 #include "../util/util.h"
+#include "../decklink.h"
 
 #include "../decklink_api.h"
 
@@ -47,6 +48,7 @@
 #include <common/cache_aligned_vector.h>
 #include <common/timer.h>
 #include <common/param.h>
+#include <common/software_version.h>
 
 #include <tbb/concurrent_queue.h>
 
@@ -119,8 +121,9 @@ struct configuration
        }
 };
 
+template <typename Configuration>
 void set_latency(
-               const com_iface_ptr<IDeckLinkConfiguration_v10_2>& config,
+               const com_iface_ptr<Configuration>& config,
                configuration::latency_t latency,
                const std::wstring& print)
 {
@@ -280,16 +283,17 @@ public:
        }
 };
 
+template <typename Configuration>
 struct key_video_context : public IDeckLinkVideoOutputCallback, boost::noncopyable
 {
-       const configuration                                                                             config_;
-       com_ptr<IDeckLink>                                                                              decklink_                                       = get_device(config_.key_device_index());
-       com_iface_ptr<IDeckLinkOutput>                                                  output_                                         = iface_cast<IDeckLinkOutput>(decklink_);
-       com_iface_ptr<IDeckLinkKeyer>                                                   keyer_                                          = iface_cast<IDeckLinkKeyer>(decklink_);
-       com_iface_ptr<IDeckLinkAttributes>                                              attributes_                                     = iface_cast<IDeckLinkAttributes>(decklink_);
-       com_iface_ptr<IDeckLinkConfiguration_v10_2>                             configuration_                          = iface_cast<IDeckLinkConfiguration_v10_2>(decklink_);
-       tbb::atomic<int64_t>                                                                    current_presentation_delay_;
-       tbb::atomic<int64_t>                                                                    scheduled_frames_completed_;
+       const configuration                                     config_;
+       com_ptr<IDeckLink>                                      decklink_                                       = get_device(config_.key_device_index());
+       com_iface_ptr<IDeckLinkOutput>          output_                                         = iface_cast<IDeckLinkOutput>(decklink_);
+       com_iface_ptr<IDeckLinkKeyer>           keyer_                                          = iface_cast<IDeckLinkKeyer>(decklink_);
+       com_iface_ptr<IDeckLinkAttributes>      attributes_                                     = iface_cast<IDeckLinkAttributes>(decklink_);
+       com_iface_ptr<Configuration>            configuration_                          = iface_cast<Configuration>(decklink_);
+       tbb::atomic<int64_t>                            current_presentation_delay_;
+       tbb::atomic<int64_t>                            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 <typename Configuration>
 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<IDeckLink>                                                                      decklink_                               = get_device(config_.device_index);
        com_iface_ptr<IDeckLinkOutput>                                          output_                                 = iface_cast<IDeckLinkOutput>(decklink_);
-       com_iface_ptr<IDeckLinkConfiguration_v10_2>                     configuration_                  = iface_cast<IDeckLinkConfiguration_v10_2>(decklink_);
+       com_iface_ptr<Configuration>                                            configuration_                  = iface_cast<Configuration>(decklink_);
        com_iface_ptr<IDeckLinkKeyer>                                           keyer_                                  = iface_cast<IDeckLinkKeyer>(decklink_);
        com_iface_ptr<IDeckLinkAttributes>                                      attributes_                             = iface_cast<IDeckLinkAttributes>(decklink_);
 
@@ -390,7 +395,7 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLink
        reference_signal_detector                                                       reference_signal_detector_      { output_ };
        tbb::atomic<int64_t>                                                            current_presentation_delay_;
        tbb::atomic<int64_t>                                                            scheduled_frames_completed_;
-       std::unique_ptr<key_video_context>                                      key_context_;
+       std::unique_ptr<key_video_context<Configuration>>       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<Configuration>(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 <typename Configuration>
 struct decklink_consumer_proxy : public core::frame_consumer
 {
-       core::monitor::subject                          monitor_subject_;
-       const configuration                                     config_;
-       std::unique_ptr<decklink_consumer>      consumer_;
-       core::video_format_desc                         format_desc_;
-       executor                                                        executor_;
+       core::monitor::subject                                                          monitor_subject_;
+       const configuration                                                                     config_;
+       std::unique_ptr<decklink_consumer<Configuration>>       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<Configuration>(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<core::frame_consumer> create_consumer(
                config.out_channel_layout = *found_layout;
        }
 
-       return spl::make_shared<decklink_consumer_proxy>(config);
+       bool old_configuration_api = get_driver_version() < get_new_configuration_api_version();
+
+       if (old_configuration_api)
+               return spl::make_shared<decklink_consumer_proxy<IDeckLinkConfiguration_v10_2>>(config);
+       else
+               return spl::make_shared<decklink_consumer_proxy<IDeckLinkConfiguration>>(config);
 }
 
 spl::shared_ptr<core::frame_consumer> create_preconfigured_consumer(
@@ -907,7 +932,12 @@ spl::shared_ptr<core::frame_consumer> 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<decklink_consumer_proxy>(config);
+       bool old_configuration_api = get_driver_version() < get_new_configuration_api_version();
+
+       if (old_configuration_api)
+               return spl::make_shared<decklink_consumer_proxy<IDeckLinkConfiguration_v10_2>>(config);
+       else
+               return spl::make_shared<decklink_consumer_proxy<IDeckLinkConfiguration>>(config);
 }
 
 }}
index db1d639cd1a6a6811bdc39bea8d63efbd5b9621b..bf6de45bea995c7ab9a0184972e83a4ea4edb369 100644 (file)
@@ -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);
index 4231e5c16cfab5de3728385997635d1a95378e3a..e9ea0f9eea375ab77f7b1aef34b61c5c13f62775 100644 (file)
@@ -25,6 +25,7 @@
 
 namespace caspar { namespace decklink {
 
+std::wstring get_version();
 void init(core::module_dependencies dependencies);
 
 }}