]> git.sesse.net Git - casparcg/blob - core/producer/layer.cpp
2.0.0.2:
[casparcg] / core / producer / layer.cpp
1 #include "../stdafx.h"\r
2 \r
3 #include "layer.h"\r
4 \r
5 #include "../mixer/frame/draw_frame.h"\r
6 #include "../mixer/image/image_mixer.h"\r
7 #include "../mixer/audio/audio_mixer.h"\r
8 #include "../producer/frame_producer.h"\r
9 \r
10 #include "../video_format.h"\r
11 \r
12 #include <common/utility/assert.h>\r
13 \r
14 namespace caspar { namespace core {\r
15 \r
16 struct layer::implementation : boost::noncopyable\r
17 {                                       \r
18         safe_ptr<frame_producer>        foreground_;\r
19         safe_ptr<frame_producer>        background_;\r
20         safe_ptr<draw_frame>            last_frame_;\r
21         bool                                            is_paused_;\r
22 \r
23 public:\r
24         implementation() \r
25                 : foreground_(frame_producer::empty())\r
26                 , background_(frame_producer::empty())\r
27                 , last_frame_(draw_frame::empty())\r
28                 , is_paused_(false){}\r
29         \r
30         void load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load)\r
31         {                       \r
32                 background_ = frame_producer;\r
33                 CASPAR_LOG(info) << print() << " " << frame_producer->print() << " => background";\r
34                 if(play_on_load)\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                         clear();\r
50                 }\r
51         }\r
52         \r
53         void play()\r
54         {                       \r
55                 if(is_paused_)                  \r
56                         is_paused_ = false;\r
57                 else\r
58                 {\r
59                         background_->set_leading_producer(foreground_);\r
60                         foreground_ = background_;\r
61                         background_ = frame_producer::empty();\r
62                         CASPAR_LOG(info) << print() << L" background => foreground";\r
63                 }\r
64         }\r
65 \r
66         void pause()\r
67         {\r
68                 is_paused_ = true;\r
69         }\r
70 \r
71         void stop()\r
72         {\r
73                 pause();\r
74                 last_frame_ = draw_frame::empty();\r
75                 foreground_ = frame_producer::empty();\r
76                 CASPAR_LOG(warning) << print() << L" empty => foreground";\r
77         }\r
78 \r
79         void clear()\r
80         {\r
81                 stop();\r
82                 background_ = frame_producer::empty();\r
83                 CASPAR_LOG(warning) << print() << L" empty => background";\r
84         }\r
85         \r
86         safe_ptr<draw_frame> receive()\r
87         {               \r
88                 if(is_paused_)\r
89                         return last_frame_;\r
90 \r
91                 try\r
92                 {\r
93                         last_frame_ = foreground_->receive(); \r
94                         if(last_frame_ == draw_frame::eof())\r
95                         {\r
96                                 CASPAR_ASSERT(foreground_ != frame_producer::empty());\r
97 \r
98                                 auto following = foreground_->get_following_producer();\r
99                                 following->set_leading_producer(foreground_);\r
100                                 foreground_ = following;\r
101 \r
102                                 CASPAR_LOG(info) << print() << L" [EOF] " << foreground_->print() << " => foreground";\r
103 \r
104                                 last_frame_ = receive();\r
105                         }\r
106                 }\r
107                 catch(...)\r
108                 {\r
109                         CASPAR_LOG_CURRENT_EXCEPTION();\r
110                         stop();\r
111                 }\r
112 \r
113                 return last_frame_;\r
114         }\r
115 \r
116         std::wstring print() const { return L"layer[]"; }\r
117 };\r
118 \r
119 layer::layer() \r
120 {\r
121         impl_ = new implementation();\r
122 }\r
123 layer::layer(layer&& other) : impl_(std::move(other.impl_)){other.impl_ = nullptr;}\r
124 layer::~layer()\r
125 {\r
126         delete impl_.fetch_and_store(nullptr);\r
127 }\r
128 layer& layer::operator=(layer&& other)\r
129 {\r
130         impl_ = std::move(other.impl_); \r
131         other.impl_ = nullptr;\r
132         return *this;\r
133 }\r
134 void layer::swap(layer& other)\r
135 {\r
136         impl_ = other.impl_.compare_and_swap(impl_, other.impl_);\r
137 }\r
138 void layer::load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load){return impl_->load(frame_producer, play_on_load);}  \r
139 void layer::preview(const safe_ptr<frame_producer>& frame_producer){return impl_->preview(frame_producer);}     \r
140 void layer::play(){impl_->play();}\r
141 void layer::pause(){impl_->pause();}\r
142 void layer::stop(){impl_->stop();}\r
143 void layer::clear(){impl_->clear();}\r
144 safe_ptr<draw_frame> layer::receive() {return impl_->receive();}\r
145 safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
146 safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
147 }}