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
9 #include "../processor/draw_frame.h"
\r
11 #include "../../common/utility/scope_exit.h"
\r
12 #include "../../common/concurrency/executor.h"
\r
14 #include <boost/thread.hpp>
\r
15 #include <boost/range/algorithm_ext/erase.hpp>
\r
16 #include <boost/range/algorithm.hpp>
\r
17 #include <boost/foreach.hpp>
\r
19 #include <tbb/concurrent_vector.h>
\r
20 #include <tbb/parallel_for.h>
\r
21 #include <tbb/mutex.h>
\r
23 namespace caspar { namespace core {
\r
25 std::vector<safe_ptr<draw_frame>> receive(std::map<int, layer>& layers)
\r
27 std::vector<safe_ptr<draw_frame>> frames(layers.size(), draw_frame::empty());
\r
28 tbb::parallel_for(tbb::blocked_range<size_t>(0, frames.size()),
\r
29 [&](const tbb::blocked_range<size_t>& r)
\r
31 auto it = layers.begin();
\r
32 std::advance(it, r.begin());
\r
33 for(size_t i = r.begin(); i != r.end(); ++i, ++it)
\r
34 frames[i] = it->second.receive();
\r
36 boost::range::remove_erase(frames, draw_frame::eof());
\r
37 boost::range::remove_erase(frames, draw_frame::empty());
\r
41 struct frame_producer_device::implementation : boost::noncopyable
\r
43 implementation(const safe_ptr<frame_processor_device>& frame_processor) : frame_processor_(frame_processor)
\r
46 executor_.begin_invoke([=]{tick();});
\r
51 frame_processor_->send(composite_frame(receive(layers_)));
\r
52 executor_.begin_invoke([=]{tick();});
\r
55 void load(int render_layer, const safe_ptr<frame_producer>& producer, load_option::type option)
\r
57 producer->initialize(frame_processor_);
\r
58 executor_.begin_invoke([=]
\r
60 layers_[render_layer].load(producer, option);
\r
64 void pause(int render_layer)
\r
66 executor_.begin_invoke([=]
\r
68 auto it = layers_.find(render_layer);
\r
69 if(it != layers_.end())
\r
70 it->second.pause();
\r
74 void play(int render_layer)
\r
76 executor_.begin_invoke([=]
\r
78 auto it = layers_.find(render_layer);
\r
79 if(it != layers_.end())
\r
84 void stop(int render_layer)
\r
86 executor_.begin_invoke([=]
\r
88 auto it = layers_.find(render_layer);
\r
89 if(it != layers_.end())
\r
91 if(it->second.empty())
\r
96 void clear(int render_layer)
\r
98 executor_.begin_invoke([=]
\r
100 auto it = layers_.find(render_layer);
\r
101 if(it != layers_.end())
\r
103 it->second.clear();
\r
111 executor_.begin_invoke([=]
\r
117 boost::unique_future<safe_ptr<frame_producer>> foreground(int render_layer) const
\r
119 return executor_.begin_invoke([=]() -> safe_ptr<frame_producer>
\r
121 auto it = layers_.find(render_layer);
\r
122 return it != layers_.end() ? it->second.foreground() : frame_producer::empty();
\r
126 boost::unique_future<safe_ptr<frame_producer>> background(int render_layer) const
\r
128 return executor_.begin_invoke([=]() -> safe_ptr<frame_producer>
\r
130 auto it = layers_.find(render_layer);
\r
131 return it != layers_.end() ? it->second.background() : frame_producer::empty();
\r
135 mutable executor executor_;
\r
137 safe_ptr<frame_processor_device> frame_processor_;
\r
139 std::map<int, layer> layers_;
\r
142 frame_producer_device::frame_producer_device(frame_producer_device&& other) : impl_(std::move(other.impl_)){}
\r
143 frame_producer_device::frame_producer_device(const safe_ptr<frame_processor_device>& frame_processor) : impl_(new implementation(frame_processor)){}
\r
144 void frame_producer_device::load(int render_layer, const safe_ptr<frame_producer>& producer, load_option::type option){impl_->load(render_layer, producer, option);}
\r
145 void frame_producer_device::pause(int render_layer){impl_->pause(render_layer);}
\r
146 void frame_producer_device::play(int render_layer){impl_->play(render_layer);}
\r
147 void frame_producer_device::stop(int render_layer){impl_->stop(render_layer);}
\r
148 void frame_producer_device::clear(int render_layer){impl_->clear(render_layer);}
\r
149 void frame_producer_device::clear(){impl_->clear();}
\r
150 boost::unique_future<safe_ptr<frame_producer>> frame_producer_device::foreground(int render_layer) const {return impl_->foreground(render_layer);}
\r
151 boost::unique_future<safe_ptr<frame_producer>> frame_producer_device::background(int render_layer) const {return impl_->background(render_layer);}
\r