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