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
11 #include "../../common/utility/memory.h"
\r
13 #include <boost/thread.hpp>
\r
14 #include <boost/range/algorithm_ext/erase.hpp>
\r
15 #include <boost/range/algorithm.hpp>
\r
16 #include <boost/foreach.hpp>
\r
18 #include <tbb/concurrent_vector.h>
\r
19 #include <tbb/parallel_for.h>
\r
20 #include <tbb/mutex.h>
\r
22 namespace caspar { namespace core {
\r
24 std::vector<frame_ptr> render_frames(std::map<int, layer>& layers)
\r
26 std::vector<frame_ptr> frames(layers.size(), nullptr);
\r
27 tbb::parallel_for(tbb::blocked_range<size_t>(0, frames.size()),
\r
28 [&](const tbb::blocked_range<size_t>& r)
\r
30 auto it = layers.begin();
\r
31 std::advance(it, r.begin());
\r
32 for(size_t i = r.begin(); i != r.end(); ++i, ++it)
\r
33 frames[i] = it->second.render_frame();
\r
38 struct frame_producer_device::implementation : boost::noncopyable
\r
40 implementation(const frame_processor_device_ptr& frame_processor)
\r
41 : frame_processor_(frame_processor)
\r
43 render_thread_ = boost::thread([=]{run();});
\r
48 frame_processor_->clear();
\r
49 is_running_ = false;
\r
50 render_thread_.join();
\r
55 CASPAR_LOG(info) << L"Started frame_producer_device thread";
\r
56 win32_exception::install_handler();
\r
63 std::vector<frame_ptr> frames;
\r
65 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
66 frames = render_frames(layers_);
\r
68 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
78 CASPAR_LOG(info) << L"Ended frame_producer_device thread";
\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 active(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.active() : 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::active(int render_layer) const {return impl_->active(render_layer);}
\r
159 frame_producer_ptr frame_producer_device::background(int render_layer) const {return impl_->background(render_layer);}
\r