]> git.sesse.net Git - casparcg/blob - core/frame/frame.cpp
2.1.0: array: Added "cacheable" property.
[casparcg] / core / frame / 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 "frame.h"\r
25 \r
26 #include <common/except.h>\r
27 #include <common/memory/array.h>\r
28 \r
29 #include <core/frame/frame_visitor.h>\r
30 #include <core/frame/pixel_format.h>\r
31 \r
32 #include <boost/lexical_cast.hpp>\r
33 #include <boost/thread/future.hpp>\r
34 \r
35 namespace caspar { namespace core {\r
36                 \r
37 struct mutable_frame::impl : boost::noncopyable\r
38 {                       \r
39         std::vector<mutable_array>                                      buffers_;\r
40         core::audio_buffer                                                      audio_data_;\r
41         const core::pixel_format_desc                           desc_;\r
42         const void*                                                                     tag_;\r
43         double                                                                          frame_rate_;\r
44         core::field_mode                                                        field_mode_;\r
45         \r
46         impl(std::vector<mutable_array> buffers, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) \r
47                 : buffers_(std::move(buffers))\r
48                 , audio_data_(std::move(audio_buffer))\r
49                 , desc_(desc)\r
50                 , tag_(tag)\r
51                 , frame_rate_(frame_rate)\r
52                 , field_mode_(field_mode)\r
53         {\r
54                 BOOST_FOREACH(auto& buffer, buffers_)\r
55                         if(!buffer.data())\r
56                                 BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("mutable_frame: null argument"));\r
57         }\r
58 };\r
59         \r
60 mutable_frame::mutable_frame(std::vector<mutable_array> image_buffers, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) \r
61         : impl_(new impl(std::move(image_buffers), std::move(audio_buffer), tag, desc, frame_rate, field_mode)){}\r
62 mutable_frame::~mutable_frame(){}\r
63 mutable_frame::mutable_frame(mutable_frame&& other) : impl_(std::move(other.impl_)){}\r
64 mutable_frame& mutable_frame::operator=(mutable_frame&& other)\r
65 {\r
66         impl_ = std::move(other.impl_);\r
67         return *this;\r
68 }\r
69 void mutable_frame::swap(mutable_frame& other){impl_.swap(other.impl_);}\r
70 const core::pixel_format_desc& mutable_frame::pixel_format_desc() const{return impl_->desc_;}\r
71 const mutable_array& mutable_frame::image_data(std::size_t index) const{return impl_->buffers_.at(index);}\r
72 const core::audio_buffer& mutable_frame::audio_data() const{return impl_->audio_data_;}\r
73 mutable_array& mutable_frame::image_data(std::size_t index){return impl_->buffers_.at(index);}\r
74 core::audio_buffer& mutable_frame::audio_data(){return impl_->audio_data_;}\r
75 double mutable_frame::frame_rate() const{return impl_->frame_rate_;}\r
76 core::field_mode mutable_frame::field_mode() const{return impl_->field_mode_;}\r
77 std::size_t mutable_frame::width() const{return impl_->desc_.planes.at(0).width;}\r
78 std::size_t mutable_frame::height() const{return impl_->desc_.planes.at(0).height;}                                             \r
79 const void* mutable_frame::tag() const{return impl_->tag_;}     \r
80 \r
81 \r
82 const const_frame& const_frame::empty()\r
83 {\r
84         static int dummy;\r
85         static const_frame empty(&dummy);\r
86         return empty;\r
87 }\r
88 \r
89 struct const_frame::impl : boost::noncopyable\r
90 {                       \r
91         mutable std::vector<boost::shared_future<const_array>>  future_buffers_;\r
92         int                                                                                     id_;\r
93         core::audio_buffer                                                      audio_data_;\r
94         const core::pixel_format_desc                           desc_;\r
95         const void*                                                                     tag_;\r
96         double                                                                          frame_rate_;\r
97         core::field_mode                                                        field_mode_;\r
98 \r
99         impl(const void* tag)\r
100                 : desc_(core::pixel_format::invalid)\r
101                 , tag_(tag)     \r
102                 , id_(0)\r
103                 , field_mode_(core::field_mode::empty)\r
104         {\r
105         }\r
106         \r
107         impl(boost::shared_future<const_array> image, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) \r
108                 : audio_data_(std::move(audio_buffer))\r
109                 , desc_(desc)\r
110                 , tag_(tag)\r
111                 , id_(reinterpret_cast<int>(this))\r
112                 , frame_rate_(frame_rate)\r
113                 , field_mode_(field_mode)\r
114         {\r
115                 if(desc.format != core::pixel_format::bgra)\r
116                         BOOST_THROW_EXCEPTION(not_implemented());\r
117                 \r
118                 future_buffers_.push_back(std::move(image));\r
119         }\r
120 \r
121         impl(mutable_frame&& other)\r
122                 : audio_data_(other.audio_data())\r
123                 , desc_(other.pixel_format_desc())\r
124                 , tag_(other.tag())\r
125                 , id_(reinterpret_cast<int>(this))\r
126                 , frame_rate_(other.frame_rate())\r
127                 , field_mode_(other.field_mode())\r
128         {\r
129                 for(std::size_t n = 0; n < desc_.planes.size(); ++n)\r
130                 {\r
131                         boost::promise<const_array> p;\r
132                         p.set_value(std::move(other.image_data(n)));\r
133                         future_buffers_.push_back(p.get_future());\r
134                 }\r
135         }\r
136 \r
137         const_array image_data(int index) const\r
138         {\r
139                 return tag_ != empty().tag() ? future_buffers_.at(index).get() : const_array(nullptr, 0, true, 0);\r
140         }\r
141 \r
142         std::size_t width() const\r
143         {\r
144                 return tag_ != empty().tag() ? desc_.planes.at(0).width : 0;\r
145         }\r
146 \r
147         std::size_t height() const\r
148         {\r
149                 return tag_ != empty().tag() ? desc_.planes.at(0).height : 0;\r
150         }\r
151 \r
152         std::size_t size() const\r
153         {\r
154                 return tag_ != empty().tag() ? desc_.planes.at(0).size : 0;\r
155         }\r
156 \r
157         bool operator==(const impl& other)\r
158         {\r
159                 return tag_ == other.tag_ && id_ == other.id_;\r
160         }\r
161 };\r
162         \r
163 const_frame::const_frame(const void* tag) : impl_(new impl(tag)){}\r
164 const_frame::const_frame(boost::shared_future<const_array> image, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) \r
165         : impl_(new impl(std::move(image), std::move(audio_buffer), tag, desc, frame_rate, field_mode)){}\r
166 const_frame::const_frame(mutable_frame&& other) : impl_(new impl(std::move(other))){}\r
167 const_frame::~const_frame(){}\r
168 const_frame::const_frame(const_frame&& other) : impl_(std::move(other.impl_)){}\r
169 const_frame& const_frame::operator=(const_frame&& other)\r
170 {\r
171         impl_ = std::move(other.impl_);\r
172         return *this;\r
173 }\r
174 const_frame::const_frame(const const_frame& other) : impl_(other.impl_){}\r
175 const_frame& const_frame::operator=(const const_frame& other)\r
176 {\r
177         impl_ = other.impl_;\r
178         return *this;\r
179 }\r
180 bool const_frame::operator==(const const_frame& other){return *impl_ == *other.impl_;}\r
181 bool const_frame::operator!=(const const_frame& other){return !(*this == other);}\r
182 const core::pixel_format_desc& const_frame::pixel_format_desc()const{return impl_->desc_;}\r
183 const_array const_frame::image_data(int index)const{return impl_->image_data(index);}\r
184 const core::audio_buffer& const_frame::audio_data()const{return impl_->audio_data_;}\r
185 double const_frame::frame_rate()const{return impl_->frame_rate_;}\r
186 core::field_mode const_frame::field_mode()const{return impl_->field_mode_;}\r
187 std::size_t const_frame::width()const{return impl_->width();}\r
188 std::size_t const_frame::height()const{return impl_->height();} \r
189 std::size_t const_frame::size()const{return impl_->size();}                                             \r
190 const void* const_frame::tag()const{return impl_->tag_;}        \r
191 \r
192 }}