]> 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 "../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                 if(play_on_load)\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                         clear();\r
49                 }\r
50         }\r
51         \r
52         void play()\r
53         {                       \r
54                 if(is_paused_)                  \r
55                         is_paused_ = false;\r
56                 else\r
57                 {\r
58                         background_->set_leading_producer(foreground_);\r
59                         foreground_ = background_;\r
60                         background_ = frame_producer::empty();\r
61                 }\r
62         }\r
63 \r
64         void pause()\r
65         {\r
66                 is_paused_ = true;\r
67         }\r
68 \r
69         void stop()\r
70         {\r
71                 pause();\r
72                 last_frame_ = draw_frame::empty();\r
73                 foreground_ = frame_producer::empty();\r
74         }\r
75 \r
76         void clear()\r
77         {\r
78                 stop();\r
79                 background_ = frame_producer::empty();\r
80         }\r
81         \r
82         safe_ptr<draw_frame> receive()\r
83         {               \r
84                 if(is_paused_)\r
85                         return last_frame_;\r
86 \r
87                 try\r
88                 {\r
89                         last_frame_ = foreground_->receive(); \r
90                         if(last_frame_ == draw_frame::eof())\r
91                         {\r
92                                 CASPAR_ASSERT(foreground_ != frame_producer::empty());\r
93 \r
94                                 auto following = foreground_->get_following_producer();\r
95                                 following->set_leading_producer(foreground_);\r
96                                 foreground_ = following;\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 \r
111 layer::layer() \r
112 {\r
113         impl_ = new implementation();\r
114 }\r
115 layer::layer(layer&& other) \r
116 {\r
117         impl_ = other.impl_.compare_and_swap(nullptr, other.impl_);\r
118 }\r
119 layer::~layer()\r
120 {\r
121         delete impl_.fetch_and_store(nullptr);\r
122 }\r
123 layer& layer::operator=(layer&& other)\r
124 {\r
125         impl_ = other.impl_.compare_and_swap(nullptr, other.impl_);\r
126         return *this;\r
127 }\r
128 void layer::swap(layer& other)\r
129 {\r
130         impl_ = other.impl_.compare_and_swap(impl_, other.impl_);\r
131 }\r
132 void layer::load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load){return impl_->load(frame_producer, play_on_load);}  \r
133 void layer::preview(const safe_ptr<frame_producer>& frame_producer){return impl_->preview(frame_producer);}     \r
134 void layer::play(){impl_->play();}\r
135 void layer::pause(){impl_->pause();}\r
136 void layer::stop(){impl_->stop();}\r
137 void layer::clear(){impl_->clear();}\r
138 safe_ptr<draw_frame> layer::receive() {return impl_->receive();}\r
139 safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
140 safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
141 }}