]> git.sesse.net Git - casparcg/blob - core/frame/frame.cpp
2.1.0: -Fixed ffmpeg input crash. -Log throwing call-stack.
[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/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<array<std::uint8_t>>                        buffers_;\r
40         core::audio_buffer                                                      audio_data_;\r
41         const core::pixel_format_desc                           desc_;\r
42         const void*                                                                     tag_;\r
43         \r
44         impl(std::vector<array<std::uint8_t>> buffers, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) \r
45                 : buffers_(std::move(buffers))\r
46                 , audio_data_(std::move(audio_buffer))\r
47                 , desc_(desc)\r
48                 , tag_(tag)\r
49         {\r
50                 BOOST_FOREACH(auto& buffer, buffers_)\r
51                         if(!buffer.data())\r
52                                 CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info("mutable_frame: null argument"));\r
53         }\r
54 };\r
55         \r
56 mutable_frame::mutable_frame(std::vector<array<std::uint8_t>> image_buffers, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) \r
57         : impl_(new impl(std::move(image_buffers), std::move(audio_buffer), tag, desc)){}\r
58 mutable_frame::~mutable_frame(){}\r
59 mutable_frame::mutable_frame(mutable_frame&& other) : impl_(std::move(other.impl_)){}\r
60 mutable_frame& mutable_frame::operator=(mutable_frame&& other)\r
61 {\r
62         impl_ = std::move(other.impl_);\r
63         return *this;\r
64 }\r
65 void mutable_frame::swap(mutable_frame& other){impl_.swap(other.impl_);}\r
66 const core::pixel_format_desc& mutable_frame::pixel_format_desc() const{return impl_->desc_;}\r
67 const array<std::uint8_t>& mutable_frame::image_data(std::size_t index) const{return impl_->buffers_.at(index);}\r
68 const core::audio_buffer& mutable_frame::audio_data() const{return impl_->audio_data_;}\r
69 array<std::uint8_t>& mutable_frame::image_data(std::size_t index){return impl_->buffers_.at(index);}\r
70 core::audio_buffer& mutable_frame::audio_data(){return impl_->audio_data_;}\r
71 std::size_t mutable_frame::width() const{return impl_->desc_.planes.at(0).width;}\r
72 std::size_t mutable_frame::height() const{return impl_->desc_.planes.at(0).height;}                                             \r
73 const void* mutable_frame::stream_tag()const{return impl_->tag_;}                               \r
74 const void* mutable_frame::data_tag()const{return impl_.get();} \r
75 \r
76 const const_frame& const_frame::empty()\r
77 {\r
78         static int dummy;\r
79         static const_frame empty(&dummy);\r
80         return empty;\r
81 }\r
82 \r
83 struct const_frame::impl : boost::noncopyable\r
84 {                       \r
85         mutable std::vector<boost::shared_future<array<const std::uint8_t>>>    future_buffers_;\r
86         int                                                                                     id_;\r
87         core::audio_buffer                                                      audio_data_;\r
88         const core::pixel_format_desc                           desc_;\r
89         const void*                                                                     tag_;\r
90 \r
91         impl(const void* tag)\r
92                 : desc_(core::pixel_format::invalid)\r
93                 , tag_(tag)     \r
94                 , id_(0)\r
95         {\r
96         }\r
97         \r
98         impl(boost::shared_future<array<const std::uint8_t>> image, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) \r
99                 : audio_data_(std::move(audio_buffer))\r
100                 , desc_(desc)\r
101                 , tag_(tag)\r
102                 , id_(reinterpret_cast<int>(this))\r
103         {\r
104                 if(desc.format != core::pixel_format::bgra)\r
105                         CASPAR_THROW_EXCEPTION(not_implemented());\r
106                 \r
107                 future_buffers_.push_back(std::move(image));\r
108         }\r
109 \r
110         impl(mutable_frame&& other)\r
111                 : audio_data_(other.audio_data())\r
112                 , desc_(other.pixel_format_desc())\r
113                 , tag_(other.stream_tag())\r
114                 , id_(reinterpret_cast<int>(this))\r
115         {\r
116                 for(std::size_t n = 0; n < desc_.planes.size(); ++n)\r
117                 {\r
118                         boost::promise<array<const std::uint8_t>> p;\r
119                         p.set_value(std::move(other.image_data(n)));\r
120                         future_buffers_.push_back(p.get_future());\r
121                 }\r
122         }\r
123 \r
124         array<const std::uint8_t> image_data(int index) const\r
125         {\r
126                 return tag_ != empty().stream_tag() ? future_buffers_.at(index).get() : array<const std::uint8_t>(nullptr, 0, true, 0);\r
127         }\r
128 \r
129         std::size_t width() const\r
130         {\r
131                 return tag_ != empty().stream_tag() ? desc_.planes.at(0).width : 0;\r
132         }\r
133 \r
134         std::size_t height() const\r
135         {\r
136                 return tag_ != empty().stream_tag() ? desc_.planes.at(0).height : 0;\r
137         }\r
138 \r
139         std::size_t size() const\r
140         {\r
141                 return tag_ != empty().stream_tag() ? desc_.planes.at(0).size : 0;\r
142         }\r
143 };\r
144         \r
145 const_frame::const_frame(const void* tag) : impl_(new impl(tag)){}\r
146 const_frame::const_frame(boost::shared_future<array<const std::uint8_t>> image, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) \r
147         : impl_(new impl(std::move(image), std::move(audio_buffer), tag, desc)){}\r
148 const_frame::const_frame(mutable_frame&& other) : impl_(new impl(std::move(other))){}\r
149 const_frame::~const_frame(){}\r
150 const_frame::const_frame(const_frame&& other) : impl_(std::move(other.impl_)){}\r
151 const_frame& const_frame::operator=(const_frame&& other)\r
152 {\r
153         impl_ = std::move(other.impl_);\r
154         return *this;\r
155 }\r
156 const_frame::const_frame(const const_frame& other) : impl_(other.impl_){}\r
157 const_frame& const_frame::operator=(const const_frame& other)\r
158 {\r
159         impl_ = other.impl_;\r
160         return *this;\r
161 }\r
162 bool const_frame::operator==(const const_frame& other){return impl_ == other.impl_;}\r
163 bool const_frame::operator!=(const const_frame& other){return !(*this == other);}\r
164 bool const_frame::operator<(const const_frame& other){return impl_< other.impl_;}\r
165 bool const_frame::operator>(const const_frame& other){return impl_> other.impl_;}\r
166 const core::pixel_format_desc& const_frame::pixel_format_desc()const{return impl_->desc_;}\r
167 array<const std::uint8_t> const_frame::image_data(int index)const{return impl_->image_data(index);}\r
168 const core::audio_buffer& const_frame::audio_data()const{return impl_->audio_data_;}\r
169 std::size_t const_frame::width()const{return impl_->width();}\r
170 std::size_t const_frame::height()const{return impl_->height();} \r
171 std::size_t const_frame::size()const{return impl_->size();}                                             \r
172 const void* const_frame::stream_tag()const{return impl_->tag_;}                         \r
173 const void* const_frame::data_tag()const{return impl_.get();}   \r
174 \r
175 }}