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