]> git.sesse.net Git - casparcg/blob - core/producer/layer.cpp
2.0.0.2: Mayor flash producer readability and maintainability improvements.
[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(size_t index) : foreground_(frame_producer::empty()), background_(frame_producer::empty()), last_frame_(draw_frame::empty()), index_(index) {}\r
15         \r
16         void load(const safe_ptr<frame_producer>& 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_ = frame_producer::empty();  \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                 background_->set_leading_producer(foreground_);\r
31                 foreground_ = background_;\r
32                 background_ = frame_producer::empty();\r
33                 is_paused_ = false;\r
34                 CASPAR_LOG(info) << L"layer[" << index_ << L"] Started: " << foreground_->print();\r
35         }\r
36 \r
37         void pause()\r
38         {\r
39                 is_paused_ = true;\r
40         }\r
41 \r
42         void stop()\r
43         {\r
44                 foreground_ = frame_producer::empty();\r
45                 last_frame_ = draw_frame::empty();\r
46         }\r
47 \r
48         void clear()\r
49         {\r
50                 foreground_ = frame_producer::empty();\r
51                 background_ = frame_producer::empty();\r
52                 last_frame_ = draw_frame::empty();\r
53         }\r
54         \r
55         safe_ptr<draw_frame> receive()\r
56         {               \r
57                 if(foreground_ == frame_producer::empty() || is_paused_)\r
58                         return last_frame_;\r
59 \r
60                 try\r
61                 {\r
62                         last_frame_ = foreground_->receive();\r
63 \r
64                         if(last_frame_ == draw_frame::eof())\r
65                         {\r
66                                 CASPAR_LOG(info) << L"layer[" << index_ << L"] Ended:" << foreground_->print();\r
67                                 auto following = foreground_->get_following_producer();\r
68                                 following->set_leading_producer(foreground_);\r
69                                 foreground_ = following;\r
70                                 if(foreground_ != frame_producer::empty())\r
71                                         CASPAR_LOG(info) << L"layer[" << index_ << L"] Started:" << foreground_->print();\r
72                                 last_frame_ = receive();\r
73                         }\r
74                 }\r
75                 catch(...)\r
76                 {\r
77                         try\r
78                         {\r
79                                 CASPAR_LOG_CURRENT_EXCEPTION();\r
80                                 CASPAR_LOG(warning) << L"layer[" << index_ << L"] Error. Removed " << foreground_->print() << L" from layer.";\r
81                                 foreground_ = frame_producer::empty();\r
82                                 last_frame_ = draw_frame::empty();\r
83                         }\r
84                         catch(...){}\r
85                 }\r
86 \r
87                 return last_frame_;\r
88         }       \r
89                 \r
90         tbb::atomic<bool>                       is_paused_;\r
91         safe_ptr<draw_frame>            last_frame_;\r
92         safe_ptr<frame_producer>        foreground_;\r
93         safe_ptr<frame_producer>        background_;\r
94         size_t                                          index_;\r
95 };\r
96 \r
97 layer::layer(size_t index) : impl_(new implementation(index)){}\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 safe_ptr<frame_producer>& 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 bool layer::empty() const { return impl_->foreground_ == frame_producer::empty() && impl_->background_ == frame_producer::empty();}\r
111 safe_ptr<draw_frame> layer::receive() {return impl_->receive();}\r
112 safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
113 safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
114 }}