2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
4 * This file is part of CasparCG (www.casparcg.com).
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
19 * Author: Helge Norberg, helge.norberg@svt.se
22 #include "../StdAfx.h"
26 #include "frame_producer.h"
28 #include "../video_channel.h"
29 #include "../diagnostics/call_context.h"
31 #include <common/env.h>
33 #include <boost/thread/mutex.hpp>
34 #include <boost/thread/lock_guard.hpp>
35 #include <boost/filesystem.hpp>
36 #include <boost/algorithm/string/predicate.hpp>
37 #include <boost/optional.hpp>
42 namespace caspar { namespace core {
44 const spl::shared_ptr<cg_proxy>& cg_proxy::empty()
46 class empty_proxy : public cg_proxy
48 void add(int, const std::wstring&, bool, const std::wstring&, const std::wstring&) override {}
49 void remove(int) override {}
50 void play(int) override {}
51 void stop(int, unsigned int) override {}
52 void next(int) override {}
53 void update(int, const std::wstring&) override {}
54 std::wstring invoke(int, const std::wstring&) override { return L""; }
55 std::wstring description(int) override { return L"empty cg producer"; }
56 std::wstring template_host_info() override { return L"empty cg producer"; }
59 static spl::shared_ptr<cg_proxy> instance = spl::make_shared<empty_proxy>();
63 using namespace boost::multi_index;
65 struct cg_producer_registry::impl
71 std::set<std::wstring> file_extensions;
72 meta_info_extractor info_extractor;
73 cg_proxy_factory proxy_factory;
74 cg_producer_factory producer_factory;
75 bool reusable_producer_instance;
81 mutable boost::mutex mutex_;
82 std::vector<record> records_;
84 void register_cg_producer(
85 std::wstring cg_producer_name,
86 std::set<std::wstring> file_extensions,
87 meta_info_extractor info_extractor,
88 cg_proxy_factory proxy_factory,
89 cg_producer_factory producer_factory,
90 bool reusable_producer_instance)
92 boost::lock_guard<boost::mutex> lock(mutex_);
96 std::move(cg_producer_name),
97 std::move(file_extensions),
98 std::move(info_extractor),
99 std::move(proxy_factory),
100 std::move(producer_factory),
101 reusable_producer_instance
105 spl::shared_ptr<frame_producer> create_producer(
106 const spl::shared_ptr<video_channel>& video_channel,
107 const std::wstring& filename) const
109 auto found = find_record(filename);
112 return frame_producer::empty();
114 return found->producer_factory(
115 video_channel->frame_factory(),
116 video_channel->video_format_desc(),
120 spl::shared_ptr<cg_proxy> get_proxy(const spl::shared_ptr<frame_producer>& producer) const
122 auto producer_name = producer->name();
124 boost::lock_guard<boost::mutex> lock(mutex_);
126 for (auto& elem : records_)
128 if (elem.name == producer_name)
129 return elem.proxy_factory(producer);
132 return cg_proxy::empty();
135 spl::shared_ptr<cg_proxy> get_proxy(
136 const spl::shared_ptr<class video_channel>& video_channel,
137 int render_layer) const
139 auto producer = spl::make_shared_ptr(video_channel->stage().foreground(render_layer).get());
141 return get_proxy(producer);
144 spl::shared_ptr<cg_proxy> get_or_create_proxy(
145 const spl::shared_ptr<class video_channel>& video_channel,
147 const std::wstring& filename) const
149 using namespace boost::filesystem;
151 auto found = find_record(filename);
154 return cg_proxy::empty();
156 auto producer = spl::make_shared_ptr(video_channel->stage().foreground(render_layer).get());
157 auto current_producer_name = producer->name();
158 bool create_new = current_producer_name != found->name || !found->reusable_producer_instance;
162 diagnostics::scoped_call_context save;
163 diagnostics::call_context::for_thread().video_channel = video_channel->index();
164 diagnostics::call_context::for_thread().layer = render_layer;
166 producer = found->producer_factory(
167 video_channel->frame_factory(),
168 video_channel->video_format_desc(),
170 video_channel->stage().load(render_layer, producer);
171 video_channel->stage().play(render_layer);
174 return found->proxy_factory(producer);
177 std::string read_meta_info(const std::wstring& filename) const
179 using namespace boost::filesystem;
181 auto basepath = path(env::template_folder()) / path(filename);
183 boost::lock_guard<boost::mutex> lock(mutex_);
185 for (auto& rec : records_)
187 for (auto& file_extension : rec.file_extensions)
189 auto p = path(basepath.wstring() + file_extension);
193 return rec.info_extractor(filename);
198 BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(L"No meta info extractor for " + filename));
201 bool is_cg_extension(const std::wstring& extension) const
203 boost::lock_guard<boost::mutex> lock(mutex_);
205 for (auto& rec : records_)
207 for (auto& file_extension : rec.file_extensions)
209 if (boost::algorithm::iequals(file_extension, extension))
217 boost::optional<record> find_record(const std::wstring& filename) const
219 using namespace boost::filesystem;
221 auto basepath = path(env::template_folder()) / path(filename);
223 boost::lock_guard<boost::mutex> lock(mutex_);
225 for (auto& rec : records_)
227 for (auto& file_extension : rec.file_extensions)
229 auto p = path(basepath.wstring() + file_extension);
240 cg_producer_registry::cg_producer_registry() : impl_(new impl) { }
242 void cg_producer_registry::register_cg_producer(
243 std::wstring cg_producer_name,
244 std::set<std::wstring> file_extensions,
245 meta_info_extractor info_extractor,
246 cg_proxy_factory proxy_factory,
247 cg_producer_factory producer_factory,
248 bool reusable_producer_instance)
250 impl_->register_cg_producer(
251 std::move(cg_producer_name),
252 std::move(file_extensions),
253 std::move(info_extractor),
254 std::move(proxy_factory),
255 std::move(producer_factory),
256 reusable_producer_instance);
259 spl::shared_ptr<frame_producer> cg_producer_registry::create_producer(
260 const spl::shared_ptr<video_channel>& video_channel,
261 const std::wstring& filename) const
263 return impl_->create_producer(video_channel, filename);
266 spl::shared_ptr<cg_proxy> cg_producer_registry::get_proxy(
267 const spl::shared_ptr<frame_producer>& producer) const
269 return impl_->get_proxy(producer);
272 spl::shared_ptr<cg_proxy> cg_producer_registry::get_proxy(
273 const spl::shared_ptr<video_channel>& video_channel,
274 int render_layer) const
276 return impl_->get_proxy(video_channel, render_layer);
279 spl::shared_ptr<cg_proxy> cg_producer_registry::get_or_create_proxy(
280 const spl::shared_ptr<video_channel>& video_channel,
282 const std::wstring& filename) const
284 return impl_->get_or_create_proxy(video_channel, render_layer, filename);
287 std::string cg_producer_registry::read_meta_info(const std::wstring& filename) const
289 return impl_->read_meta_info(filename);
292 bool cg_producer_registry::is_cg_extension(const std::wstring& extension) const
294 return impl_->is_cg_extension(extension);