]> git.sesse.net Git - casparcg/blob - core/producer/layer.cpp
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
[casparcg] / core / producer / layer.cpp
1 #include "../stdafx.h"\r
2 \r
3 #include "layer.h"\r
4 #include "frame_producer.h"\r
5 \r
6 #include "../video_format.h"\r
7 \r
8 #include <common/concurrency/executor.h>\r
9 #include <common/utility/assert.h>\r
10 \r
11 #include <mixer/frame/draw_frame.h>\r
12 #include <mixer/image/image_mixer.h>\r
13 #include <mixer/audio/audio_mixer.h>\r
14 #include <mixer/audio/audio_transform.h>\r
15 \r
16 namespace caspar { namespace core {\r
17 \r
18 class frame_producer_remover\r
19 {\r
20         executor executor_;\r
21         tbb::atomic<int> count_;\r
22 \r
23         void do_remove(safe_ptr<frame_producer>& producer)\r
24         {\r
25                 producer = frame_producer::empty();\r
26                 CASPAR_LOG(info) << L"frame_remover[" + boost::lexical_cast<std::wstring>(--count_) + L"] removed: " << producer->print();\r
27         }\r
28 public:\r
29 \r
30         frame_producer_remover()\r
31         {\r
32                 executor_.start();\r
33                 count_ = 0;\r
34         }\r
35 \r
36         void remove(safe_ptr<frame_producer>&& producer)\r
37         {\r
38                 CASPAR_ASSERT(producer.unique());\r
39                 CASPAR_LOG(info) << L"frame_remover[" + boost::lexical_cast<std::wstring>(++count_) + L"] removing: " << producer->print();\r
40                 executor_.begin_invoke(std::bind(&frame_producer_remover::do_remove, this, std::move(producer)));\r
41         }\r
42 };\r
43 \r
44 frame_producer_remover g_remover;\r
45 \r
46 struct layer::implementation : boost::noncopyable\r
47 {                                       \r
48         safe_ptr<frame_producer>        foreground_;\r
49         safe_ptr<frame_producer>        background_;\r
50         safe_ptr<draw_frame>            last_frame_;\r
51         bool                                            is_paused_;\r
52 \r
53 public:\r
54         implementation() \r
55                 : foreground_(frame_producer::empty())\r
56                 , background_(frame_producer::empty())\r
57                 , last_frame_(draw_frame::empty())\r
58                 , is_paused_(false){}\r
59         \r
60         void load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load)\r
61         {                       \r
62                 background_ = frame_producer;\r
63                 is_paused_ = false;\r
64                 if(play_on_load)\r
65                         play();         \r
66         }\r
67 \r
68         void preview(const safe_ptr<frame_producer>& frame_producer)\r
69         {\r
70                 load(frame_producer, true);\r
71                 receive();\r
72                 pause();\r
73         }\r
74         \r
75         void play()\r
76         {                       \r
77                 if(!is_paused_)                 \r
78                 {\r
79                         background_->set_leading_producer(foreground_);\r
80                         foreground_ = background_;\r
81                         CASPAR_LOG(info) << foreground_->print() << L" started";\r
82                         background_ = frame_producer::empty();\r
83                 }\r
84                 is_paused_ = false;\r
85         }\r
86 \r
87         void pause()\r
88         {\r
89                 is_paused_ = true;\r
90         }\r
91 \r
92         void stop()\r
93         {\r
94                 pause();\r
95                 last_frame_ = draw_frame::empty();\r
96                 foreground_ = frame_producer::empty();\r
97         }\r
98 \r
99         void clear()\r
100         {\r
101                 stop();\r
102                 background_ = frame_producer::empty();\r
103         }\r
104         \r
105         safe_ptr<draw_frame> receive()\r
106         {               \r
107                 if(is_paused_)\r
108                 {\r
109                         last_frame_->get_audio_transform().set_gain(0.0);\r
110                         return last_frame_;\r
111                 }\r
112 \r
113                 try\r
114                 {\r
115                         last_frame_ = foreground_->receive(); \r
116                         if(last_frame_ == draw_frame::eof())\r
117                         {\r
118                                 CASPAR_ASSERT(foreground_ != frame_producer::empty());\r
119 \r
120                                 auto following = foreground_->get_following_producer();\r
121                                 following->set_leading_producer(foreground_);\r
122                                 g_remover.remove(std::move(foreground_));\r
123                                 foreground_ = following;\r
124                                 CASPAR_LOG(info) << foreground_->print() << L" started";\r
125 \r
126                                 last_frame_ = receive();\r
127                         }\r
128                 }\r
129                 catch(...)\r
130                 {\r
131                         CASPAR_LOG_CURRENT_EXCEPTION();\r
132                         stop();\r
133                 }\r
134 \r
135                 return last_frame_;\r
136         }\r
137 };\r
138 \r
139 layer::layer() \r
140 {\r
141         impl_ = new implementation();\r
142 }\r
143 layer::layer(layer&& other) \r
144 {\r
145         impl_ = other.impl_.compare_and_swap(nullptr, other.impl_);\r
146 }\r
147 layer::~layer()\r
148 {\r
149         delete impl_.fetch_and_store(nullptr);\r
150 }\r
151 layer& layer::operator=(layer&& other)\r
152 {\r
153         impl_ = other.impl_.compare_and_swap(nullptr, other.impl_);\r
154         return *this;\r
155 }\r
156 void layer::swap(layer& other)\r
157 {\r
158         impl_ = other.impl_.compare_and_swap(impl_, other.impl_);\r
159 }\r
160 void layer::load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load){return impl_->load(frame_producer, play_on_load);}  \r
161 void layer::preview(const safe_ptr<frame_producer>& frame_producer){return impl_->preview(frame_producer);}     \r
162 void layer::play(){impl_->play();}\r
163 void layer::pause(){impl_->pause();}\r
164 void layer::stop(){impl_->stop();}\r
165 void layer::clear(){impl_->clear();}\r
166 safe_ptr<draw_frame> layer::receive() {return impl_->receive();}\r
167 safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
168 safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
169 }}