]> git.sesse.net Git - casparcg/blob - core/producer/frame_producer_device.cpp
2.0.0.2:
[casparcg] / core / producer / frame_producer_device.cpp
1 #include "..\StdAfx.h"\r
2 \r
3 #include "frame_producer_device.h"\r
4 \r
5 #include "layer.h"\r
6 \r
7 #include "../format/video_format.h"\r
8 #include "../processor/composite_frame.h"\r
9 #include "../processor/draw_frame.h"\r
10 \r
11 #include "../../common/utility/scope_exit.h"\r
12 #include "../../common/concurrency/executor.h"\r
13 \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
18 \r
19 #include <tbb/concurrent_vector.h>\r
20 #include <tbb/parallel_for.h>\r
21 #include <tbb/mutex.h>\r
22         \r
23 namespace caspar { namespace core {\r
24         \r
25 std::vector<safe_ptr<draw_frame>> receive(std::map<int, layer>& layers)\r
26 {       \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
30         {\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
35         });             \r
36         boost::range::remove_erase(frames, draw_frame::eof());\r
37         boost::range::remove_erase(frames, draw_frame::empty());\r
38         return frames;\r
39 }\r
40 \r
41 struct frame_producer_device::implementation : boost::noncopyable\r
42 {       \r
43         implementation(const safe_ptr<frame_processor_device>& frame_processor)  : frame_processor_(frame_processor)\r
44         {\r
45                 executor_.start();\r
46                 executor_.begin_invoke([=]{tick();});\r
47         }\r
48                                         \r
49         void tick()\r
50         {               \r
51                 frame_processor_->send(composite_frame(receive(layers_)));\r
52                 executor_.begin_invoke([=]{tick();});\r
53         }\r
54 \r
55         void load(int render_layer, const safe_ptr<frame_producer>& producer, load_option::type option)\r
56         {\r
57                 producer->initialize(frame_processor_);\r
58                 executor_.begin_invoke([=]\r
59                 {\r
60                         layers_[render_layer].load(producer, option);\r
61                 });\r
62         }\r
63                         \r
64         void pause(int render_layer)\r
65         {               \r
66                 executor_.begin_invoke([=]\r
67                 {                       \r
68                         auto it = layers_.find(render_layer);\r
69                         if(it != layers_.end())\r
70                                 it->second.pause();             \r
71                 });\r
72         }\r
73 \r
74         void play(int render_layer)\r
75         {               \r
76                 executor_.begin_invoke([=]\r
77                 {\r
78                         auto it = layers_.find(render_layer);\r
79                         if(it != layers_.end())\r
80                                 it->second.play();              \r
81                 });\r
82         }\r
83 \r
84         void stop(int render_layer)\r
85         {               \r
86                 executor_.begin_invoke([=]\r
87                 {\r
88                         auto it = layers_.find(render_layer);\r
89                         if(it != layers_.end())                 \r
90                                 it->second.stop();      \r
91                         if(it->second.empty())\r
92                                 layers_.erase(it);\r
93                 });\r
94         }\r
95 \r
96         void clear(int render_layer)\r
97         {\r
98                 executor_.begin_invoke([=]\r
99                 {                       \r
100                         auto it = layers_.find(render_layer);\r
101                         if(it != layers_.end())\r
102                         {\r
103                                 it->second.clear();             \r
104                                 layers_.erase(it);\r
105                         }\r
106                 });\r
107         }\r
108                 \r
109         void clear()\r
110         {\r
111                 executor_.begin_invoke([=]\r
112                 {                       \r
113                         layers_.clear();\r
114                 });\r
115         }               \r
116 \r
117         boost::unique_future<safe_ptr<frame_producer>> foreground(int render_layer) const\r
118         {\r
119                 return executor_.begin_invoke([=]() -> safe_ptr<frame_producer>\r
120                 {                       \r
121                         auto it = layers_.find(render_layer);\r
122                         return it != layers_.end() ? it->second.foreground() : frame_producer::empty();\r
123                 });\r
124         }\r
125         \r
126         boost::unique_future<safe_ptr<frame_producer>> background(int render_layer) const\r
127         {\r
128                 return executor_.begin_invoke([=]() -> safe_ptr<frame_producer>\r
129                 {\r
130                         auto it = layers_.find(render_layer);\r
131                         return it != layers_.end() ? it->second.background() : frame_producer::empty();\r
132                 });\r
133         }\r
134 \r
135         mutable executor executor_;\r
136                                 \r
137         safe_ptr<frame_processor_device> frame_processor_;\r
138                                                 \r
139         std::map<int, layer> layers_;           \r
140 };\r
141 \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
152 }}\r