Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "GMPVideoi420FrameImpl.h"
7 : #include "mozilla/gmp/GMPTypes.h"
8 : #include "mozilla/CheckedInt.h"
9 :
10 : namespace mozilla {
11 : namespace gmp {
12 :
13 0 : GMPVideoi420FrameImpl::GMPVideoi420FrameImpl(GMPVideoHostImpl* aHost)
14 : : mYPlane(aHost),
15 : mUPlane(aHost),
16 : mVPlane(aHost),
17 : mWidth(0),
18 : mHeight(0),
19 : mTimestamp(0ll),
20 0 : mDuration(0ll)
21 : {
22 0 : MOZ_ASSERT(aHost);
23 0 : }
24 :
25 0 : GMPVideoi420FrameImpl::GMPVideoi420FrameImpl(const GMPVideoi420FrameData& aFrameData,
26 0 : GMPVideoHostImpl* aHost)
27 0 : : mYPlane(aFrameData.mYPlane(), aHost),
28 0 : mUPlane(aFrameData.mUPlane(), aHost),
29 0 : mVPlane(aFrameData.mVPlane(), aHost),
30 0 : mWidth(aFrameData.mWidth()),
31 0 : mHeight(aFrameData.mHeight()),
32 0 : mTimestamp(aFrameData.mTimestamp()),
33 0 : mDuration(aFrameData.mDuration())
34 : {
35 0 : MOZ_ASSERT(aHost);
36 0 : }
37 :
38 0 : GMPVideoi420FrameImpl::~GMPVideoi420FrameImpl()
39 : {
40 0 : }
41 :
42 : bool
43 0 : GMPVideoi420FrameImpl::InitFrameData(GMPVideoi420FrameData& aFrameData)
44 : {
45 0 : mYPlane.InitPlaneData(aFrameData.mYPlane());
46 0 : mUPlane.InitPlaneData(aFrameData.mUPlane());
47 0 : mVPlane.InitPlaneData(aFrameData.mVPlane());
48 0 : aFrameData.mWidth() = mWidth;
49 0 : aFrameData.mHeight() = mHeight;
50 0 : aFrameData.mTimestamp() = mTimestamp;
51 0 : aFrameData.mDuration() = mDuration;
52 0 : return true;
53 : }
54 :
55 : GMPVideoFrameFormat
56 0 : GMPVideoi420FrameImpl::GetFrameFormat()
57 : {
58 0 : return kGMPI420VideoFrame;
59 : }
60 :
61 : void
62 0 : GMPVideoi420FrameImpl::Destroy()
63 : {
64 0 : delete this;
65 0 : }
66 :
67 : /* static */ bool
68 0 : GMPVideoi420FrameImpl::CheckFrameData(const GMPVideoi420FrameData& aFrameData)
69 : {
70 : // We may be passed the "wrong" shmem (one smaller than the actual size).
71 : // This implies a bug or serious error on the child size. Ignore this frame if so.
72 : // Note: Size() greater than expected is also an error, but with no negative consequences
73 0 : int32_t half_width = (aFrameData.mWidth() + 1) / 2;
74 0 : if ((aFrameData.mYPlane().mStride() <= 0) || (aFrameData.mYPlane().mSize() <= 0) ||
75 0 : (aFrameData.mUPlane().mStride() <= 0) || (aFrameData.mUPlane().mSize() <= 0) ||
76 0 : (aFrameData.mVPlane().mStride() <= 0) || (aFrameData.mVPlane().mSize() <= 0) ||
77 0 : (aFrameData.mYPlane().mSize() > (int32_t) aFrameData.mYPlane().mBuffer().Size<uint8_t>()) ||
78 0 : (aFrameData.mUPlane().mSize() > (int32_t) aFrameData.mUPlane().mBuffer().Size<uint8_t>()) ||
79 0 : (aFrameData.mVPlane().mSize() > (int32_t) aFrameData.mVPlane().mBuffer().Size<uint8_t>()) ||
80 0 : (aFrameData.mYPlane().mStride() < aFrameData.mWidth()) ||
81 0 : (aFrameData.mUPlane().mStride() < half_width) ||
82 0 : (aFrameData.mVPlane().mStride() < half_width) ||
83 0 : (aFrameData.mYPlane().mSize() < aFrameData.mYPlane().mStride() * aFrameData.mHeight()) ||
84 0 : (aFrameData.mUPlane().mSize() < aFrameData.mUPlane().mStride() * ((aFrameData.mHeight()+1)/2)) ||
85 0 : (aFrameData.mVPlane().mSize() < aFrameData.mVPlane().mStride() * ((aFrameData.mHeight()+1)/2)))
86 : {
87 0 : return false;
88 : }
89 0 : return true;
90 : }
91 :
92 : bool
93 0 : GMPVideoi420FrameImpl::CheckDimensions(int32_t aWidth, int32_t aHeight,
94 : int32_t aStride_y, int32_t aStride_u, int32_t aStride_v)
95 : {
96 0 : int32_t half_width = (aWidth + 1) / 2;
97 0 : if (aWidth < 1 || aHeight < 1 ||
98 0 : aStride_y < aWidth || aStride_u < half_width || aStride_v < half_width ||
99 0 : !(CheckedInt<int32_t>(aHeight) * aStride_y
100 0 : + ((CheckedInt<int32_t>(aHeight) + 1) / 2)
101 0 : * (CheckedInt<int32_t>(aStride_u) + aStride_v)).isValid()) {
102 0 : return false;
103 : }
104 0 : return true;
105 : }
106 :
107 : const GMPPlaneImpl*
108 0 : GMPVideoi420FrameImpl::GetPlane(GMPPlaneType aType) const {
109 0 : switch (aType) {
110 : case kGMPYPlane:
111 0 : return &mYPlane;
112 : case kGMPUPlane:
113 0 : return &mUPlane;
114 : case kGMPVPlane:
115 0 : return &mVPlane;
116 : default:
117 0 : MOZ_CRASH("Unknown plane type!");
118 : }
119 : return nullptr;
120 : }
121 :
122 : GMPPlaneImpl*
123 0 : GMPVideoi420FrameImpl::GetPlane(GMPPlaneType aType) {
124 0 : switch (aType) {
125 : case kGMPYPlane :
126 0 : return &mYPlane;
127 : case kGMPUPlane :
128 0 : return &mUPlane;
129 : case kGMPVPlane :
130 0 : return &mVPlane;
131 : default:
132 0 : MOZ_CRASH("Unknown plane type!");
133 : }
134 : return nullptr;
135 : }
136 :
137 : GMPErr
138 0 : GMPVideoi420FrameImpl::CreateEmptyFrame(int32_t aWidth, int32_t aHeight,
139 : int32_t aStride_y, int32_t aStride_u, int32_t aStride_v)
140 : {
141 0 : if (!CheckDimensions(aWidth, aHeight, aStride_y, aStride_u, aStride_v)) {
142 0 : return GMPGenericErr;
143 : }
144 :
145 0 : int32_t size_y = aStride_y * aHeight;
146 0 : int32_t half_height = (aHeight + 1) / 2;
147 0 : int32_t size_u = aStride_u * half_height;
148 0 : int32_t size_v = aStride_v * half_height;
149 :
150 0 : GMPErr err = mYPlane.CreateEmptyPlane(size_y, aStride_y, size_y);
151 0 : if (err != GMPNoErr) {
152 0 : return err;
153 : }
154 0 : err = mUPlane.CreateEmptyPlane(size_u, aStride_u, size_u);
155 0 : if (err != GMPNoErr) {
156 0 : return err;
157 : }
158 0 : err = mVPlane.CreateEmptyPlane(size_v, aStride_v, size_v);
159 0 : if (err != GMPNoErr) {
160 0 : return err;
161 : }
162 :
163 0 : mWidth = aWidth;
164 0 : mHeight = aHeight;
165 0 : mTimestamp = 0ll;
166 0 : mDuration = 0ll;
167 :
168 0 : return GMPNoErr;
169 : }
170 :
171 : GMPErr
172 0 : GMPVideoi420FrameImpl::CreateFrame(int32_t aSize_y, const uint8_t* aBuffer_y,
173 : int32_t aSize_u, const uint8_t* aBuffer_u,
174 : int32_t aSize_v, const uint8_t* aBuffer_v,
175 : int32_t aWidth, int32_t aHeight,
176 : int32_t aStride_y, int32_t aStride_u, int32_t aStride_v)
177 : {
178 0 : MOZ_ASSERT(aBuffer_y);
179 0 : MOZ_ASSERT(aBuffer_u);
180 0 : MOZ_ASSERT(aBuffer_v);
181 :
182 0 : if (aSize_y < 1 || aSize_u < 1 || aSize_v < 1) {
183 0 : return GMPGenericErr;
184 : }
185 :
186 0 : if (!CheckDimensions(aWidth, aHeight, aStride_y, aStride_u, aStride_v)) {
187 0 : return GMPGenericErr;
188 : }
189 :
190 0 : GMPErr err = mYPlane.Copy(aSize_y, aStride_y, aBuffer_y);
191 0 : if (err != GMPNoErr) {
192 0 : return err;
193 : }
194 0 : err = mUPlane.Copy(aSize_u, aStride_u, aBuffer_u);
195 0 : if (err != GMPNoErr) {
196 0 : return err;
197 : }
198 0 : err = mVPlane.Copy(aSize_v, aStride_v, aBuffer_v);
199 0 : if (err != GMPNoErr) {
200 0 : return err;
201 : }
202 :
203 0 : mWidth = aWidth;
204 0 : mHeight = aHeight;
205 :
206 0 : return GMPNoErr;
207 : }
208 :
209 : GMPErr
210 0 : GMPVideoi420FrameImpl::CopyFrame(const GMPVideoi420Frame& aFrame)
211 : {
212 0 : auto& f = static_cast<const GMPVideoi420FrameImpl&>(aFrame);
213 :
214 0 : GMPErr err = mYPlane.Copy(f.mYPlane);
215 0 : if (err != GMPNoErr) {
216 0 : return err;
217 : }
218 :
219 0 : err = mUPlane.Copy(f.mUPlane);
220 0 : if (err != GMPNoErr) {
221 0 : return err;
222 : }
223 :
224 0 : err = mVPlane.Copy(f.mVPlane);
225 0 : if (err != GMPNoErr) {
226 0 : return err;
227 : }
228 :
229 0 : mWidth = f.mWidth;
230 0 : mHeight = f.mHeight;
231 0 : mTimestamp = f.mTimestamp;
232 0 : mDuration = f.mDuration;
233 :
234 0 : return GMPNoErr;
235 : }
236 :
237 : void
238 0 : GMPVideoi420FrameImpl::SwapFrame(GMPVideoi420Frame* aFrame)
239 : {
240 0 : auto f = static_cast<GMPVideoi420FrameImpl*>(aFrame);
241 0 : mYPlane.Swap(f->mYPlane);
242 0 : mUPlane.Swap(f->mUPlane);
243 0 : mVPlane.Swap(f->mVPlane);
244 0 : std::swap(mWidth, f->mWidth);
245 0 : std::swap(mHeight, f->mHeight);
246 0 : std::swap(mTimestamp, f->mTimestamp);
247 0 : std::swap(mDuration, f->mDuration);
248 0 : }
249 :
250 : uint8_t*
251 0 : GMPVideoi420FrameImpl::Buffer(GMPPlaneType aType)
252 : {
253 0 : GMPPlane* p = GetPlane(aType);
254 0 : if (p) {
255 0 : return p->Buffer();
256 : }
257 0 : return nullptr;
258 : }
259 :
260 : const uint8_t*
261 0 : GMPVideoi420FrameImpl::Buffer(GMPPlaneType aType) const
262 : {
263 0 : const GMPPlane* p = GetPlane(aType);
264 0 : if (p) {
265 0 : return p->Buffer();
266 : }
267 0 : return nullptr;
268 : }
269 :
270 : int32_t
271 0 : GMPVideoi420FrameImpl::AllocatedSize(GMPPlaneType aType) const
272 : {
273 0 : const GMPPlane* p = GetPlane(aType);
274 0 : if (p) {
275 0 : return p->AllocatedSize();
276 : }
277 0 : return -1;
278 : }
279 :
280 : int32_t
281 0 : GMPVideoi420FrameImpl::Stride(GMPPlaneType aType) const
282 : {
283 0 : const GMPPlane* p = GetPlane(aType);
284 0 : if (p) {
285 0 : return p->Stride();
286 : }
287 0 : return -1;
288 : }
289 :
290 : GMPErr
291 0 : GMPVideoi420FrameImpl::SetWidth(int32_t aWidth)
292 : {
293 0 : if (!CheckDimensions(aWidth, mHeight,
294 : mYPlane.Stride(), mUPlane.Stride(),
295 : mVPlane.Stride())) {
296 0 : return GMPGenericErr;
297 : }
298 0 : mWidth = aWidth;
299 0 : return GMPNoErr;
300 : }
301 :
302 : GMPErr
303 0 : GMPVideoi420FrameImpl::SetHeight(int32_t aHeight)
304 : {
305 0 : if (!CheckDimensions(mWidth, aHeight,
306 : mYPlane.Stride(), mUPlane.Stride(),
307 : mVPlane.Stride())) {
308 0 : return GMPGenericErr;
309 : }
310 0 : mHeight = aHeight;
311 0 : return GMPNoErr;
312 : }
313 :
314 : int32_t
315 0 : GMPVideoi420FrameImpl::Width() const
316 : {
317 0 : return mWidth;
318 : }
319 :
320 : int32_t
321 0 : GMPVideoi420FrameImpl::Height() const
322 : {
323 0 : return mHeight;
324 : }
325 :
326 : void
327 0 : GMPVideoi420FrameImpl::SetTimestamp(uint64_t aTimestamp)
328 : {
329 0 : mTimestamp = aTimestamp;
330 0 : }
331 :
332 : uint64_t
333 0 : GMPVideoi420FrameImpl::Timestamp() const
334 : {
335 0 : return mTimestamp;
336 : }
337 :
338 : void
339 0 : GMPVideoi420FrameImpl::SetDuration(uint64_t aDuration)
340 : {
341 0 : mDuration = aDuration;
342 0 : }
343 :
344 : uint64_t
345 0 : GMPVideoi420FrameImpl::Duration() const
346 : {
347 0 : return mDuration;
348 : }
349 :
350 : bool
351 0 : GMPVideoi420FrameImpl::IsZeroSize() const
352 : {
353 0 : return (mYPlane.IsZeroSize() && mUPlane.IsZeroSize() && mVPlane.IsZeroSize());
354 : }
355 :
356 : void
357 0 : GMPVideoi420FrameImpl::ResetSize()
358 : {
359 0 : mYPlane.ResetSize();
360 0 : mUPlane.ResetSize();
361 0 : mVPlane.ResetSize();
362 0 : }
363 :
364 : } // namespace gmp
365 : } // namespace mozilla
|