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