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 win32_exception::install_handler();
\r
62 std::vector<frame_ptr> frames;
\r
64 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
65 frames = render_frames(layers_);
\r
67 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
78 void load(int render_layer, const frame_producer_ptr& producer, load_option::type option)
\r
80 producer->initialize(frame_processor_);
\r
81 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
82 layers_[render_layer].load(producer, option);
\r
85 void pause(int render_layer)
\r
87 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
88 auto it = layers_.find(render_layer);
\r
89 if(it != layers_.end())
\r
90 it->second.pause();
\r
93 void play(int render_layer)
\r
95 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
96 auto it = layers_.find(render_layer);
\r
97 if(it != layers_.end())
\r
101 void stop(int render_layer)
\r
103 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
104 auto it = layers_.find(render_layer);
\r
105 if(it != layers_.end())
\r
109 void clear(int render_layer)
\r
111 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
112 auto it = layers_.find(render_layer);
\r
113 if(it != layers_.end())
\r
114 it->second.clear();
\r
119 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
123 frame_producer_ptr foreground(int render_layer) const
\r
125 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
126 auto it = layers_.find(render_layer);
\r
127 return it != layers_.end() ? it->second.foreground() : nullptr;
\r
130 frame_producer_ptr background(int render_layer) const
\r
132 tbb::mutex::scoped_lock lock(layers_mutex_);
\r
133 auto it = layers_.find(render_layer);
\r
134 return it != layers_.end() ? it->second.background() : nullptr;
\r
137 frame_processor_device_ptr frame_processor_;
\r
139 boost::thread render_thread_;
\r
141 mutable tbb::mutex layers_mutex_;
\r
142 std::map<int, layer> layers_;
\r
144 tbb::atomic<bool> is_running_;
\r
147 frame_producer_device::frame_producer_device(const frame_processor_device_ptr& frame_processor)
\r
148 : impl_(new implementation(frame_processor)){}
\r
149 void frame_producer_device::load(int render_layer, const frame_producer_ptr& producer, load_option::type option){impl_->load(render_layer, producer, option);}
\r
150 void frame_producer_device::pause(int render_layer){impl_->pause(render_layer);}
\r
151 void frame_producer_device::play(int render_layer){impl_->play(render_layer);}
\r
152 void frame_producer_device::stop(int render_layer){impl_->stop(render_layer);}
\r
153 void frame_producer_device::clear(int render_layer){impl_->clear(render_layer);}
\r
154 void frame_producer_device::clear(){impl_->clear();}
\r
155 frame_producer_ptr frame_producer_device::foreground(int render_layer) const {return impl_->foreground(render_layer);}
\r
156 frame_producer_ptr frame_producer_device::background(int render_layer) const {return impl_->background(render_layer);}
\r