]> 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 public:\r
25         implementation(int index) \r
26                 : foreground_(frame_producer::empty())\r
27                 , background_(frame_producer::empty())\r
28                 , last_frame_(draw_frame::empty())\r
29                 , index_(index) \r
30                 , is_paused_(false){}\r
31         \r
32         void load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load)\r
33         {                       \r
34                 background_ = frame_producer;\r
35                 CASPAR_LOG(info) << print() << " " << frame_producer->print() << " => background";\r
36                 if(play_on_load)\r
37                         play();                 \r
38         }\r
39 \r
40         void preview(const safe_ptr<frame_producer>& frame_producer)\r
41         {\r
42                 stop();\r
43                 load(frame_producer, false);            \r
44                 try\r
45                 {\r
46                         last_frame_ = frame_producer->receive();\r
47                 }\r
48                 catch(...)\r
49                 {\r
50                         CASPAR_LOG_CURRENT_EXCEPTION();\r
51                         clear();\r
52                 }\r
53         }\r
54         \r
55         void play()\r
56         {                       \r
57                 if(is_paused_)                  \r
58                         is_paused_ = false;\r
59                 else\r
60                 {\r
61                         background_->set_leading_producer(foreground_);\r
62                         foreground_ = background_;\r
63                         background_ = frame_producer::empty();\r
64                         CASPAR_LOG(info) << print() << L" background => foreground";\r
65                 }\r
66         }\r
67 \r
68         void pause()\r
69         {\r
70                 is_paused_ = true;\r
71         }\r
72 \r
73         void stop()\r
74         {\r
75                 pause();\r
76                 last_frame_ = draw_frame::empty();\r
77                 foreground_ = frame_producer::empty();\r
78                 CASPAR_LOG(warning) << print() << L" empty => foreground";\r
79         }\r
80 \r
81         void clear()\r
82         {\r
83                 stop();\r
84                 background_ = frame_producer::empty();\r
85                 CASPAR_LOG(warning) << print() << L" empty => background";\r
86         }\r
87         \r
88         safe_ptr<draw_frame> receive()\r
89         {               \r
90                 if(is_paused_)\r
91                         return last_frame_;\r
92 \r
93                 try\r
94                 {\r
95                         last_frame_ = foreground_->receive(); \r
96                         last_frame_->set_layer_index(index_);\r
97                         if(last_frame_ == draw_frame::eof())\r
98                         {\r
99                                 CASPAR_ASSERT(foreground_ != frame_producer::empty());\r
100 \r
101                                 auto following = foreground_->get_following_producer();\r
102                                 following->set_leading_producer(foreground_);\r
103                                 foreground_ = following;\r
104 \r
105                                 CASPAR_LOG(info) << print() << L" [EOF] " << foreground_->print() << " => foreground";\r
106 \r
107                                 last_frame_ = receive();\r
108                         }\r
109                 }\r
110                 catch(...)\r
111                 {\r
112                         CASPAR_LOG_CURRENT_EXCEPTION();\r
113                         stop();\r
114                 }\r
115 \r
116                 return last_frame_;\r
117         }\r
118 \r
119         std::wstring print() const { return L"layer[" + boost::lexical_cast<std::wstring>(index_) + L"]"; }\r
120 };\r
121 \r
122 layer::layer(int index) : impl_(new implementation(index)){}\r
123 layer::layer(layer&& other) : impl_(std::move(other.impl_)){other.impl_ = nullptr;}\r
124 layer& layer::operator=(layer&& other)\r
125 {\r
126         impl_ = std::move(other.impl_); \r
127         other.impl_ = nullptr;\r
128         return *this;\r
129 }\r
130 void layer::load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load){return impl_->load(frame_producer, play_on_load);}  \r
131 void layer::preview(const safe_ptr<frame_producer>& frame_producer){return impl_->preview(frame_producer);}     \r
132 void layer::play(){impl_->play();}\r
133 void layer::pause(){impl_->pause();}\r
134 void layer::stop(){impl_->stop();}\r
135 void layer::clear(){impl_->clear();}\r
136 safe_ptr<draw_frame> layer::receive() {return impl_->receive();}\r
137 safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
138 safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
139 }}