]> 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                         clear();\r
48                 }\r
49         }\r
50         \r
51         void play()\r
52         {                       \r
53                 background_->set_leading_producer(foreground_);\r
54                 foreground_ = background_;\r
55                 background_ = frame_producer::empty();\r
56                 is_paused_ = false;\r
57                 CASPAR_LOG(info) << print() << L" background => foreground";\r
58         }\r
59 \r
60         void pause()\r
61         {\r
62                 is_paused_ = true;\r
63         }\r
64 \r
65         void stop()\r
66         {\r
67                 pause();\r
68                 last_frame_ = draw_frame::empty();\r
69                 foreground_ = frame_producer::empty();\r
70                 CASPAR_LOG(warning) << print() << L" empty => foreground";\r
71         }\r
72 \r
73         void clear()\r
74         {\r
75                 stop();\r
76                 background_ = frame_producer::empty();\r
77                 CASPAR_LOG(warning) << print() << L" empty => background";\r
78         }\r
79         \r
80         safe_ptr<draw_frame> receive()\r
81         {               \r
82                 if(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                                 assert(foreground_ != frame_producer::empty());\r
91 \r
92                                 auto following = foreground_->get_following_producer();\r
93                                 following->set_leading_producer(foreground_);\r
94                                 foreground_ = following;\r
95 \r
96                                 CASPAR_LOG(info) << print() << L" [EOF] " << foreground_->print() << " => foreground";\r
97 \r
98                                 last_frame_ = receive();\r
99                         }\r
100                 }\r
101                 catch(...)\r
102                 {\r
103                         CASPAR_LOG_CURRENT_EXCEPTION();\r
104                         stop();\r
105                 }\r
106 \r
107                 return last_frame_;\r
108         }\r
109 \r
110         std::wstring print() const { return L"layer[" + boost::lexical_cast<std::wstring>(index_) + L"]"; }\r
111 };\r
112 \r
113 layer::layer(int index) : impl_(new implementation(index)){}\r
114 layer::layer(layer&& other) : impl_(std::move(other.impl_)){other.impl_ = nullptr;}\r
115 layer& layer::operator=(layer&& other)\r
116 {\r
117         impl_ = std::move(other.impl_); \r
118         other.impl_ = nullptr;\r
119         return *this;\r
120 }\r
121 void layer::load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load){return impl_->load(frame_producer, play_on_load);}  \r
122 void layer::preview(const safe_ptr<frame_producer>& frame_producer){return impl_->preview(frame_producer);}     \r
123 void layer::play(){impl_->play();}\r
124 void layer::pause(){impl_->pause();}\r
125 void layer::stop(){impl_->stop();}\r
126 void layer::clear(){impl_->clear();}\r
127 bool layer::empty() const { return impl_->foreground_ == frame_producer::empty() && impl_->background_ == frame_producer::empty();}\r
128 safe_ptr<draw_frame> layer::receive() {return impl_->receive();}\r
129 safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
130 safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
131 }}