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<gpu_frame_ptr> receives(std::map<int, layer>& layers)
\r
25 std::vector<gpu_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.receive();
\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 render_thread_.join();
\r
53 win32_exception::install_handler();
\r
60 std::vector<gpu_frame_ptr> frames;
\r
62 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
63 frames = receives(layers_);
\r
65 frame_processor_->send(std::make_shared<composite_frame>(frames));
\r
71 CASPAR_LOG_CURRENT_EXCEPTION();
\r
73 CASPAR_LOG(error) << "Unexpected exception. Cleared layers in render-device";
\r
80 void load(int render_layer, const frame_producer_ptr& producer, load_option::type option)
\r
82 producer->initialize(frame_processor_);
\r
83 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
84 layers_[render_layer].load(producer, option);
\r
87 void pause(int render_layer)
\r
89 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
90 auto it = layers_.find(render_layer);
\r
91 if(it != layers_.end())
\r
92 it->second.pause();
\r
95 void play(int render_layer)
\r
97 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
98 auto it = layers_.find(render_layer);
\r
99 if(it != layers_.end())
\r
100 it->second.play();
\r
103 void stop(int render_layer)
\r
105 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
106 auto it = layers_.find(render_layer);
\r
107 if(it != layers_.end())
\r
111 void clear(int render_layer)
\r
113 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
114 auto it = layers_.find(render_layer);
\r
115 if(it != layers_.end())
\r
116 it->second.clear();
\r
121 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
125 frame_producer_ptr foreground(int render_layer) const
\r
127 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
128 auto it = layers_.find(render_layer);
\r
129 return it != layers_.end() ? it->second.foreground() : nullptr;
\r
132 frame_producer_ptr background(int render_layer) const
\r
134 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
135 auto it = layers_.find(render_layer);
\r
136 return it != layers_.end() ? it->second.background() : nullptr;
\r
139 frame_processor_device_ptr frame_processor_;
\r
141 boost::thread render_thread_;
\r
143 mutable tbb::mutex layers_mutex_;
\r
144 std::map<int, layer> layers_;
\r
146 tbb::atomic<bool> is_running_;
\r
149 frame_producer_device::frame_producer_device(const frame_processor_device_ptr& frame_processor)
\r
150 : impl_(new implementation(frame_processor)){}
\r
151 void frame_producer_device::load(int render_layer, const frame_producer_ptr& producer, load_option::type option){impl_->load(render_layer, producer, option);}
\r
152 void frame_producer_device::pause(int render_layer){impl_->pause(render_layer);}
\r
153 void frame_producer_device::play(int render_layer){impl_->play(render_layer);}
\r
154 void frame_producer_device::stop(int render_layer){impl_->stop(render_layer);}
\r
155 void frame_producer_device::clear(int render_layer){impl_->clear(render_layer);}
\r
156 void frame_producer_device::clear(){impl_->clear();}
\r
157 frame_producer_ptr frame_producer_device::foreground(int render_layer) const {return impl_->foreground(render_layer);}
\r
158 frame_producer_ptr frame_producer_device::background(int render_layer) const {return impl_->background(render_layer);}
\r