1 #include "..\StdAfx.h"
\r
3 #include "frame_producer_device.h"
\r
7 #include "../format/video_format.h"
\r
8 #include "../processor/composite_frame.h"
\r
10 #include "../../common/utility/scope_exit.h"
\r
12 #include <boost/thread.hpp>
\r
13 #include <boost/range/algorithm_ext/erase.hpp>
\r
14 #include <boost/range/algorithm.hpp>
\r
15 #include <boost/foreach.hpp>
\r
17 #include <tbb/concurrent_vector.h>
\r
18 #include <tbb/parallel_for.h>
\r
19 #include <tbb/mutex.h>
\r
21 namespace caspar { namespace core {
\r
23 std::vector<frame_ptr> render_frames(std::map<int, layer>& layers)
\r
25 std::vector<frame_ptr> frames(layers.size(), nullptr);
\r
26 tbb::parallel_for(tbb::blocked_range<size_t>(0, frames.size()),
\r
27 [&](const tbb::blocked_range<size_t>& r)
\r
29 auto it = layers.begin();
\r
30 std::advance(it, r.begin());
\r
31 for(size_t i = r.begin(); i != r.end(); ++i, ++it)
\r
32 frames[i] = it->second.render_frame();
\r
37 struct frame_producer_device::implementation : boost::noncopyable
\r
39 implementation(const frame_processor_device_ptr& frame_processor)
\r
40 : frame_processor_(frame_processor)
\r
42 render_thread_ = boost::thread([=]{run();});
\r
47 is_running_ = false;
\r
48 frame_processor_->clear();
\r
49 render_thread_.join();
\r
54 win32_exception::install_handler();
\r
61 std::vector<frame_ptr> frames;
\r
63 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
64 frames = render_frames(layers_);
\r
66 frame_processor_->send(std::make_shared<composite_frame>(frames));
\r
72 CASPAR_LOG_CURRENT_EXCEPTION();
\r
74 CASPAR_LOG(error) << "Unexpected exception. Cleared layers in render-device";
\r
81 void load(int render_layer, const frame_producer_ptr& producer, load_option::type option)
\r
83 producer->initialize(frame_processor_);
\r
84 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
85 layers_[render_layer].load(producer, option);
\r
88 void pause(int render_layer)
\r
90 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
91 auto it = layers_.find(render_layer);
\r
92 if(it != layers_.end())
\r
93 it->second.pause();
\r
96 void play(int render_layer)
\r
98 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
99 auto it = layers_.find(render_layer);
\r
100 if(it != layers_.end())
\r
101 it->second.play();
\r
104 void stop(int render_layer)
\r
106 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
107 auto it = layers_.find(render_layer);
\r
108 if(it != layers_.end())
\r
112 void clear(int render_layer)
\r
114 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
115 auto it = layers_.find(render_layer);
\r
116 if(it != layers_.end())
\r
117 it->second.clear();
\r
122 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
126 frame_producer_ptr foreground(int render_layer) const
\r
128 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
129 auto it = layers_.find(render_layer);
\r
130 return it != layers_.end() ? it->second.foreground() : nullptr;
\r
133 frame_producer_ptr background(int render_layer) const
\r
135 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
136 auto it = layers_.find(render_layer);
\r
137 return it != layers_.end() ? it->second.background() : nullptr;
\r
140 frame_processor_device_ptr frame_processor_;
\r
142 boost::thread render_thread_;
\r
144 mutable tbb::mutex layers_mutex_;
\r
145 std::map<int, layer> layers_;
\r
147 tbb::atomic<bool> is_running_;
\r
150 frame_producer_device::frame_producer_device(const frame_processor_device_ptr& frame_processor)
\r
151 : impl_(new implementation(frame_processor)){}
\r
152 void frame_producer_device::load(int render_layer, const frame_producer_ptr& producer, load_option::type option){impl_->load(render_layer, producer, option);}
\r
153 void frame_producer_device::pause(int render_layer){impl_->pause(render_layer);}
\r
154 void frame_producer_device::play(int render_layer){impl_->play(render_layer);}
\r
155 void frame_producer_device::stop(int render_layer){impl_->stop(render_layer);}
\r
156 void frame_producer_device::clear(int render_layer){impl_->clear(render_layer);}
\r
157 void frame_producer_device::clear(){impl_->clear();}
\r
158 frame_producer_ptr frame_producer_device::foreground(int render_layer) const {return impl_->foreground(render_layer);}
\r
159 frame_producer_ptr frame_producer_device::background(int render_layer) const {return impl_->background(render_layer);}
\r