5 #include "consumer/frame_consumer_device.h"
\r
7 #include "processor/draw_frame.h"
\r
8 #include "processor/frame_processor_device.h"
\r
10 #include "producer/layer.h"
\r
12 #include <common/concurrency/executor.h>
\r
14 #include <boost/range/algorithm_ext/erase.hpp>
\r
16 #include <tbb/parallel_for.h>
\r
21 namespace caspar { namespace core {
\r
23 struct channel::implementation : boost::noncopyable
\r
25 const safe_ptr<frame_processor_device> processor_device_;
\r
26 frame_consumer_device consumer_device_;
\r
28 std::map<int, layer> layers_;
\r
30 const video_format_desc format_desc_;
\r
32 mutable executor executor_;
\r
35 implementation(const video_format_desc& format_desc)
\r
36 : format_desc_(format_desc)
\r
37 , processor_device_(frame_processor_device(format_desc))
\r
38 , consumer_device_(format_desc)
\r
41 executor_.begin_invoke([=]{tick();});
\r
46 auto drawed_frame = draw();
\r
47 auto processed_frame = processor_device_->process(std::move(drawed_frame));
\r
48 consumer_device_.consume(std::move(processed_frame));
\r
50 executor_.begin_invoke([=]{tick();});
\r
53 safe_ptr<draw_frame> draw()
\r
55 std::vector<safe_ptr<draw_frame>> frames(layers_.size(), draw_frame::empty());
\r
56 tbb::parallel_for(tbb::blocked_range<size_t>(0, frames.size()),
\r
57 [&](const tbb::blocked_range<size_t>& r)
\r
59 auto it = layers_.begin();
\r
60 std::advance(it, r.begin());
\r
61 for(size_t i = r.begin(); i != r.end(); ++i, ++it)
\r
62 frames[i] = it->second.receive();
\r
64 boost::range::remove_erase(frames, draw_frame::eof());
\r
65 boost::range::remove_erase(frames, draw_frame::empty());
\r
66 return draw_frame(frames);
\r
69 void add(int index, const safe_ptr<frame_consumer>& consumer)
\r
71 consumer_device_.add(index, consumer);
\r
74 void remove(int index)
\r
76 consumer_device_.remove(index);
\r
79 void load(int index, const safe_ptr<frame_producer>& producer, bool play_on_load)
\r
81 CASPAR_LOG(trace) << executor_.size();
\r
82 producer->initialize(processor_device_);
\r
83 executor_.begin_invoke([=]
\r
85 auto it = layers_.insert(std::make_pair(index, layer(index))).first;
\r
86 it->second.load(producer, play_on_load);
\r
90 void preview(int index, const safe_ptr<frame_producer>& producer)
\r
92 producer->initialize(processor_device_);
\r
93 executor_.begin_invoke([=]
\r
95 auto it = layers_.insert(std::make_pair(index, layer(index))).first;
\r
96 it->second.preview(producer);
\r
100 void pause(int index)
\r
102 executor_.begin_invoke([=]
\r
104 auto it = layers_.find(index);
\r
105 if(it != layers_.end())
\r
106 it->second.pause();
\r
110 void play(int index)
\r
112 executor_.begin_invoke([=]
\r
114 auto it = layers_.find(index);
\r
115 if(it != layers_.end())
\r
120 void stop(int index)
\r
122 executor_.begin_invoke([=]
\r
124 auto it = layers_.find(index);
\r
125 if(it != layers_.end())
\r
127 it->second.stop();
\r
128 if(it->second.empty())
\r
134 void clear(int index)
\r
136 executor_.begin_invoke([=]
\r
138 auto it = layers_.find(index);
\r
139 if(it != layers_.end())
\r
141 it->second.clear();
\r
149 executor_.begin_invoke([=]
\r
155 boost::unique_future<safe_ptr<frame_producer>> foreground(int index) const
\r
157 return executor_.begin_invoke([=]() -> safe_ptr<frame_producer>
\r
159 auto it = layers_.find(index);
\r
160 return it != layers_.end() ? it->second.foreground() : frame_producer::empty();
\r
164 boost::unique_future<safe_ptr<frame_producer>> background(int index) const
\r
166 return executor_.begin_invoke([=]() -> safe_ptr<frame_producer>
\r
168 auto it = layers_.find(index);
\r
169 return it != layers_.end() ? it->second.background() : frame_producer::empty();
\r
174 channel::channel(channel&& other) : impl_(std::move(other.impl_)){}
\r
175 channel::channel(const video_format_desc& format_desc) : impl_(new implementation(format_desc)){}
\r
176 void channel::add(int index, const safe_ptr<frame_consumer>& consumer){impl_->add(index, consumer);}
\r
177 void channel::remove(int index){impl_->remove(index);}
\r
178 void channel::load(int index, const safe_ptr<frame_producer>& producer, bool play_on_load){impl_->load(index, producer, play_on_load);}
\r
179 void channel::preview(int index, const safe_ptr<frame_producer>& producer){impl_->preview(index, producer);}
\r
180 void channel::pause(int index){impl_->pause(index);}
\r
181 void channel::play(int index){impl_->play(index);}
\r
182 void channel::stop(int index){impl_->stop(index);}
\r
183 void channel::clear(int index){impl_->clear(index);}
\r
184 void channel::clear(){impl_->clear();}
\r
185 boost::unique_future<safe_ptr<frame_producer>> channel::foreground(int index) const{ return impl_->foreground(index);}
\r
186 boost::unique_future<safe_ptr<frame_producer>> channel::background(int index) const{return impl_->background(index);}
\r
187 const video_format_desc& channel::get_video_format_desc() const{ return impl_->format_desc_;}
\r