]> 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 "../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() : foreground_(nullptr), background_(nullptr), last_frame_(draw_frame::empty()) {}\r
15         \r
16         void load(const frame_producer_ptr& frame_producer, load_option::type option)\r
17         {                       \r
18                 background_ = frame_producer;\r
19                 if(option == load_option::preview)              \r
20                 {\r
21                         foreground_ = nullptr;  \r
22                         last_frame_ = frame_producer->receive();\r
23                 }\r
24                 else if(option == load_option::auto_play)\r
25                         play();                 \r
26         }\r
27         \r
28         void play()\r
29         {                       \r
30                 if(background_ != nullptr)\r
31                 {\r
32                         background_->set_leading_producer(foreground_);\r
33                         foreground_ = std::move(background_);\r
34                 }\r
35 \r
36                 is_paused_ = false;\r
37         }\r
38 \r
39         void pause()\r
40         {\r
41                 is_paused_ = true;\r
42         }\r
43 \r
44         void stop()\r
45         {\r
46                 foreground_ = nullptr;\r
47                 last_frame_ = draw_frame::empty();\r
48         }\r
49 \r
50         void clear()\r
51         {\r
52                 foreground_ = nullptr;\r
53                 background_ = nullptr;\r
54                 last_frame_ = draw_frame::empty();\r
55         }\r
56         \r
57         draw_frame receive()\r
58         {               \r
59                 if(!foreground_ || is_paused_)\r
60                         return last_frame_;\r
61 \r
62                 try\r
63                 {\r
64                         last_frame_ = foreground_->receive();\r
65 \r
66                         if(last_frame_ == draw_frame::eof())\r
67                         {\r
68                                 CASPAR_LOG(info) << L"EOF: " << foreground_->print();\r
69                                 auto following = foreground_->get_following_producer();\r
70                                 if(following)\r
71                                         following->set_leading_producer(foreground_);\r
72                                 foreground_ = following;\r
73                                 last_frame_ = receive();\r
74                         }\r
75                 }\r
76                 catch(...)\r
77                 {\r
78                         try\r
79                         {\r
80                                 CASPAR_LOG_CURRENT_EXCEPTION();\r
81                                 CASPAR_LOG(warning) << L"Removed " << (foreground_ ? foreground_->print() : L"empty") << L" from layer.";\r
82                                 foreground_ = nullptr;\r
83                                 last_frame_ = draw_frame::empty();\r
84                         }\r
85                         catch(...){}\r
86                 }\r
87 \r
88                 return last_frame_;\r
89         }       \r
90                 \r
91         tbb::atomic<bool>       is_paused_;\r
92         draw_frame              last_frame_;\r
93         frame_producer_ptr      foreground_;\r
94         frame_producer_ptr      background_;\r
95 };\r
96 \r
97 layer::layer() : impl_(new implementation()){}\r
98 layer::layer(layer&& other) : impl_(std::move(other.impl_)){other.impl_ = nullptr;}\r
99 layer& layer::operator=(layer&& other)\r
100 {\r
101         impl_ = std::move(other.impl_); \r
102         other.impl_ = nullptr;\r
103         return *this;\r
104 }\r
105 void layer::load(const frame_producer_ptr& frame_producer, load_option::type option){return impl_->load(frame_producer, option);}       \r
106 void layer::play(){impl_->play();}\r
107 void layer::pause(){impl_->pause();}\r
108 void layer::stop(){impl_->stop();}\r
109 void layer::clear(){impl_->clear();}\r
110 draw_frame layer::receive() {return impl_->receive();}\r
111 frame_producer_ptr layer::foreground() const { return impl_->foreground_;}\r
112 frame_producer_ptr layer::background() const { return impl_->background_;}\r
113 }}