]> git.sesse.net Git - casparcg/blob - core/frame/draw_frame.cpp
5e90638fd888bde3261cbfcc126321fef3a6f19e
[casparcg] / core / frame / draw_frame.cpp
1 /*\r
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 * This file is part of CasparCG (www.casparcg.com).\r
5 *\r
6 * CasparCG is free software: you can redistribute it and/or modify\r
7 * it under the terms of the GNU General Public License as published by\r
8 * the Free Software Foundation, either version 3 of the License, or\r
9 * (at your option) any later version.\r
10 *\r
11 * CasparCG is distributed in the hope that it will be useful,\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 * GNU General Public License for more details.\r
15 *\r
16 * You should have received a copy of the GNU General Public License\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 * Author: Robert Nagy, ronag89@gmail.com\r
20 */\r
21 \r
22 #include "../stdafx.h"\r
23 \r
24 #include "draw_frame.h"\r
25 \r
26 #include "data_frame.h"\r
27 \r
28 #include "frame_transform.h"\r
29 \r
30 #include <boost/foreach.hpp>\r
31 \r
32 namespace caspar { namespace core {\r
33                 \r
34 struct draw_frame::impl\r
35 {               \r
36         int                                                                                                     tag_;\r
37         std::vector<draw_frame>                                                         frames_;\r
38         std::shared_ptr<spl::unique_ptr<const data_frame>>      data_frame_;\r
39 \r
40         core::frame_transform frame_transform_;         \r
41 public:         \r
42         enum tags\r
43         {\r
44                 frame_tag = 0,\r
45                 empty_tag,\r
46                 eof_tag,\r
47                 late_tag\r
48         };\r
49 \r
50         impl(int tag = impl::empty_tag)\r
51                 : tag_(tag)\r
52         {\r
53         }\r
54 \r
55         impl(spl::unique_ptr<const data_frame>&& frame) \r
56                 : tag_(frame_tag)\r
57                 , data_frame_(new spl::unique_ptr<const data_frame>(std::move(frame)))\r
58         {\r
59         }\r
60         \r
61         impl(std::vector<draw_frame> frames)\r
62                 : tag_(frame_tag)\r
63                 , frames_(std::move(frames))\r
64         {\r
65         }\r
66                 \r
67         void accept(frame_visitor& visitor) const\r
68         {\r
69                 visitor.push(frame_transform_);\r
70                 if(data_frame_)\r
71                 {\r
72                         visitor.visit(**data_frame_);\r
73                 }\r
74                 else\r
75                 {\r
76                         BOOST_FOREACH(auto frame, frames_)\r
77                                 frame.accept(visitor);\r
78                 }\r
79                 visitor.pop();\r
80         }       \r
81 \r
82         bool operator==(const impl& other)\r
83         {\r
84                 return  tag_ == other.tag_ && \r
85                                 frames_ == other.frames_ && \r
86                                 data_frame_ == other.data_frame_;\r
87         }\r
88 };\r
89         \r
90 draw_frame::draw_frame() : impl_(new impl()){}\r
91 draw_frame::draw_frame(int tag) : impl_(new impl(std::move(tag))){}\r
92 draw_frame::draw_frame(const draw_frame& other) : impl_(new impl(*other.impl_)){}\r
93 draw_frame::draw_frame(draw_frame&& other) : impl_(std::move(other.impl_)){}\r
94 draw_frame::draw_frame(spl::unique_ptr<const data_frame>&& frame)  : impl_(new impl(std::move(frame))){}\r
95 draw_frame::draw_frame(std::vector<draw_frame> frames) : impl_(new impl(frames)){}\r
96 draw_frame::~draw_frame(){}\r
97 draw_frame& draw_frame::operator=(draw_frame other)\r
98 {\r
99         other.swap(*this);\r
100         return *this;\r
101 }\r
102 void draw_frame::swap(draw_frame& other){impl_.swap(other.impl_);}\r
103 \r
104 const core::frame_transform& draw_frame::transform() const { return impl_->frame_transform_;}\r
105 core::frame_transform& draw_frame::transform() { return impl_->frame_transform_;}\r
106 void draw_frame::accept(frame_visitor& visitor) const{impl_->accept(visitor);}\r
107 bool draw_frame::operator==(const draw_frame& other)const{return *impl_ == *other.impl_;}\r
108 bool draw_frame::operator!=(const draw_frame& other)const{return !(*this == other);}\r
109 \r
110 draw_frame draw_frame::interlace(draw_frame frame1, draw_frame frame2, core::field_mode mode)\r
111 {                               \r
112         if(frame1 == draw_frame::eof() || frame2 == draw_frame::eof())\r
113                 return draw_frame::eof();\r
114 \r
115         if(frame1 == draw_frame::empty() && frame2 == draw_frame::empty())\r
116                 return draw_frame::empty();\r
117         \r
118         if(frame1 == frame2 || mode == field_mode::progressive)\r
119                 return frame2;\r
120 \r
121         if(mode == field_mode::upper)\r
122         {\r
123                 frame1.transform().image_transform.field_mode = field_mode::upper;      \r
124                 frame2.transform().image_transform.field_mode = field_mode::lower;      \r
125         }                                                                        \r
126         else                                                             \r
127         {                                                                        \r
128                 frame1.transform().image_transform.field_mode = field_mode::lower;      \r
129                 frame2.transform().image_transform.field_mode = field_mode::upper;      \r
130         }\r
131 \r
132         std::vector<draw_frame> frames;\r
133         frames.push_back(std::move(frame1));\r
134         frames.push_back(std::move(frame2));\r
135         return draw_frame(std::move(frames));\r
136 }\r
137 \r
138 draw_frame draw_frame::over(draw_frame frame1, draw_frame frame2)\r
139 {       \r
140         if(frame1 == draw_frame::eof() || frame2 == draw_frame::eof())\r
141                 return draw_frame::eof();\r
142         \r
143         if(frame1 == draw_frame::empty() && frame2 == draw_frame::empty())\r
144                 return draw_frame::empty();\r
145 \r
146         std::vector<draw_frame> frames;\r
147         frames.push_back(std::move(frame1));\r
148         frames.push_back(std::move(frame2));\r
149         return draw_frame(std::move(frames));\r
150 }\r
151 \r
152 draw_frame draw_frame::mask(draw_frame fill, draw_frame key)\r
153 {       \r
154         if(fill == draw_frame::eof() || key == draw_frame::eof())\r
155                 return draw_frame::eof();\r
156 \r
157         if(fill == draw_frame::empty() || key == draw_frame::empty())\r
158                 return draw_frame::empty();\r
159 \r
160         std::vector<draw_frame> frames;\r
161         key.transform().image_transform.is_key = true;\r
162         frames.push_back(std::move(key));\r
163         frames.push_back(std::move(fill));\r
164         return draw_frame(std::move(frames));\r
165 }\r
166 \r
167 draw_frame draw_frame::still(draw_frame frame)\r
168 {\r
169         frame.transform().image_transform.is_still      = true; \r
170         frame.transform().audio_transform.volume        = 0.0;          \r
171         return frame;\r
172 }\r
173 \r
174 const draw_frame& draw_frame::eof()\r
175 {\r
176         static draw_frame frame(impl::eof_tag);\r
177         return frame;\r
178 }\r
179 \r
180 const draw_frame& draw_frame::empty()\r
181 {\r
182         static draw_frame frame(impl::empty_tag);\r
183         return frame;\r
184 }\r
185 \r
186 const draw_frame& draw_frame::late()\r
187 {\r
188         static draw_frame frame(impl::late_tag);\r
189         return frame;\r
190 }\r
191         \r
192 \r
193 }}