]> git.sesse.net Git - casparcg/blob - core/producer/layer.cpp
2.0.0.0:
[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                         CASPAR_LOG_CURRENT_EXCEPTION();\r
82                         CASPAR_LOG(warning) << L"Removed " << (foreground_ ? foreground_->print() : L"null producer") << L" from layer.";\r
83                         foreground_ = nullptr;\r
84                         last_frame_ = nullptr;\r
85                 }\r
86 \r
87                 return last_frame_;\r
88         }       \r
89                 \r
90         tbb::atomic<bool>       is_paused_;\r
91         frame_ptr                       last_frame_;\r
92         frame_producer_ptr      foreground_;\r
93         frame_producer_ptr      background_;\r
94 };\r
95 \r
96 layer::layer() : impl_(new implementation()){}\r
97 layer::layer(layer&& other) : impl_(std::move(other.impl_)){other.impl_ = nullptr;}\r
98 layer& layer::operator=(layer&& other)\r
99 {\r
100         impl_ = std::move(other.impl_); \r
101         other.impl_ = nullptr;\r
102         return *this;\r
103 }\r
104 void layer::load(const frame_producer_ptr& frame_producer, load_option::type option){return impl_->load(frame_producer, option);}       \r
105 void layer::play(){impl_->play();}\r
106 void layer::pause(){impl_->pause();}\r
107 void layer::stop(){impl_->stop();}\r
108 void layer::clear(){impl_->clear();}\r
109 frame_ptr layer::render_frame() {return impl_->render_frame();}\r
110 frame_producer_ptr layer::foreground() const { return impl_->foreground_;}\r
111 frame_producer_ptr layer::background() const { return impl_->background_;}\r
112 }}