]> 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 \r
5 #include "../mixer/frame/draw_frame.h"\r
6 #include "../mixer/image/image_mixer.h"\r
7 #include "../mixer/audio/audio_mixer.h"\r
8 #include "../producer/frame_producer.h"\r
9 \r
10 #include "../video_format.h"\r
11 \r
12 #include <common/utility/assert.h>\r
13 \r
14 namespace caspar { namespace core {\r
15 \r
16 struct layer::implementation : boost::noncopyable\r
17 {                                       \r
18         safe_ptr<frame_producer>        foreground_;\r
19         safe_ptr<frame_producer>        background_;\r
20         safe_ptr<draw_frame>            last_frame_;\r
21         const int                                       index_;\r
22         bool                                            is_paused_;\r
23 \r
24         double                                          video_gain_;\r
25         double                                          video_opacity_;\r
26         \r
27         double                                          audio_gain_;\r
28 \r
29 public:\r
30         implementation(int index) \r
31                 : foreground_(frame_producer::empty())\r
32                 , background_(frame_producer::empty())\r
33                 , last_frame_(draw_frame::empty())\r
34                 , index_(index) \r
35                 , is_paused_(false)\r
36                 , video_gain_(1.0)\r
37                 , video_opacity_(1.0)\r
38                 , audio_gain_(1.0){}\r
39         \r
40         void load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load)\r
41         {                       \r
42                 background_ = frame_producer;\r
43                 CASPAR_LOG(info) << print() << " " << frame_producer->print() << " => background";\r
44                 if(play_on_load)\r
45                         play();                 \r
46         }\r
47 \r
48         void preview(const safe_ptr<frame_producer>& frame_producer)\r
49         {\r
50                 stop();\r
51                 load(frame_producer, false);            \r
52                 try\r
53                 {\r
54                         last_frame_ = frame_producer->receive();\r
55                 }\r
56                 catch(...)\r
57                 {\r
58                         CASPAR_LOG_CURRENT_EXCEPTION();\r
59                         clear();\r
60                 }\r
61         }\r
62         \r
63         void play()\r
64         {                       \r
65                 if(is_paused_)                  \r
66                         is_paused_ = false;\r
67                 else\r
68                 {\r
69                         background_->set_leading_producer(foreground_);\r
70                         foreground_ = background_;\r
71                         background_ = frame_producer::empty();\r
72                         CASPAR_LOG(info) << print() << L" background => foreground";\r
73                 }\r
74         }\r
75 \r
76         void pause()\r
77         {\r
78                 is_paused_ = true;\r
79         }\r
80 \r
81         void stop()\r
82         {\r
83                 pause();\r
84                 last_frame_ = draw_frame::empty();\r
85                 foreground_ = frame_producer::empty();\r
86                 CASPAR_LOG(warning) << print() << L" empty => foreground";\r
87         }\r
88 \r
89         void clear()\r
90         {\r
91                 stop();\r
92                 background_ = frame_producer::empty();\r
93                 CASPAR_LOG(warning) << print() << L" empty => background";\r
94         }\r
95         \r
96         safe_ptr<draw_frame> receive()\r
97         {               \r
98                 if(is_paused_)\r
99                         return last_frame_;\r
100 \r
101                 try\r
102                 {\r
103                         last_frame_ = foreground_->receive(); \r
104                         if(last_frame_ == draw_frame::eof())\r
105                         {\r
106                                 CASPAR_ASSERT(foreground_ != frame_producer::empty());\r
107 \r
108                                 auto following = foreground_->get_following_producer();\r
109                                 following->set_leading_producer(foreground_);\r
110                                 foreground_ = following;\r
111 \r
112                                 CASPAR_LOG(info) << print() << L" [EOF] " << foreground_->print() << " => foreground";\r
113 \r
114                                 last_frame_ = receive();\r
115                         }\r
116                         else\r
117                         {\r
118                                 last_frame_ = draw_frame(last_frame_);\r
119                                 last_frame_->get_image_transform().gain *= video_gain_;\r
120                                 last_frame_->get_image_transform().alpha *= video_opacity_;\r
121                                 last_frame_->get_audio_transform().gain *= audio_gain_;\r
122                         }\r
123                 }\r
124                 catch(...)\r
125                 {\r
126                         CASPAR_LOG_CURRENT_EXCEPTION();\r
127                         stop();\r
128                 }\r
129 \r
130                 return last_frame_;\r
131         }\r
132 \r
133         std::wstring print() const { return L"layer[" + boost::lexical_cast<std::wstring>(index_) + L"]"; }\r
134 };\r
135 \r
136 layer::layer(int index) : impl_(new implementation(index)){}\r
137 layer::layer(layer&& other) : impl_(std::move(other.impl_)){other.impl_ = nullptr;}\r
138 layer& layer::operator=(layer&& other)\r
139 {\r
140         impl_ = std::move(other.impl_); \r
141         other.impl_ = nullptr;\r
142         return *this;\r
143 }\r
144 void layer::load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load){return impl_->load(frame_producer, play_on_load);}  \r
145 void layer::preview(const safe_ptr<frame_producer>& frame_producer){return impl_->preview(frame_producer);}     \r
146 void layer::set_video_gain(double value) { impl_->video_gain_ = value;}\r
147 void layer::set_video_opacity(double value) { impl_->video_opacity_ = value;}\r
148 void layer::set_audio_gain(double value) { impl_->audio_gain_ = value;}\r
149 void layer::play(){impl_->play();}\r
150 void layer::pause(){impl_->pause();}\r
151 void layer::stop(){impl_->stop();}\r
152 void layer::clear(){impl_->clear();}\r
153 safe_ptr<draw_frame> layer::receive() {return impl_->receive();}\r
154 safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
155 safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
156 }}