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