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