Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/gmp/GMPVideoi420FrameImpl.cpp
Line
Count
Source (jump to first uncovered line)
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
GMPVideoi420FrameImpl::GMPVideoi420FrameImpl(GMPVideoHostImpl* aHost)
14
: mYPlane(aHost),
15
  mUPlane(aHost),
16
  mVPlane(aHost),
17
  mWidth(0),
18
  mHeight(0),
19
  mTimestamp(0ll),
20
  mDuration(0ll)
21
0
{
22
0
  MOZ_ASSERT(aHost);
23
0
}
24
25
GMPVideoi420FrameImpl::GMPVideoi420FrameImpl(const GMPVideoi420FrameData& aFrameData,
26
                                             GMPVideoHostImpl* aHost)
27
: mYPlane(aFrameData.mYPlane(), aHost),
28
  mUPlane(aFrameData.mUPlane(), aHost),
29
  mVPlane(aFrameData.mVPlane(), aHost),
30
  mWidth(aFrameData.mWidth()),
31
  mHeight(aFrameData.mHeight()),
32
  mTimestamp(aFrameData.mTimestamp()),
33
  mDuration(aFrameData.mDuration())
34
0
{
35
0
  MOZ_ASSERT(aHost);
36
0
}
37
38
GMPVideoi420FrameImpl::~GMPVideoi420FrameImpl()
39
0
{
40
0
}
41
42
bool
43
GMPVideoi420FrameImpl::InitFrameData(GMPVideoi420FrameData& aFrameData)
44
0
{
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
0
}
54
55
GMPVideoFrameFormat
56
GMPVideoi420FrameImpl::GetFrameFormat()
57
0
{
58
0
  return kGMPI420VideoFrame;
59
0
}
60
61
void
62
GMPVideoi420FrameImpl::Destroy()
63
0
{
64
0
  delete this;
65
0
}
66
67
/* static */ bool
68
GMPVideoi420FrameImpl::CheckFrameData(const GMPVideoi420FrameData& aFrameData)
69
0
{
70
0
  // We may be passed the "wrong" shmem (one smaller than the actual size).
71
0
  // This implies a bug or serious error on the child size.  Ignore this frame if so.
72
0
  // 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
0
  {
87
0
    return false;
88
0
  }
89
0
  return true;
90
0
}
91
92
bool
93
GMPVideoi420FrameImpl::CheckDimensions(int32_t aWidth, int32_t aHeight,
94
                                       int32_t aStride_y, int32_t aStride_u, int32_t aStride_v)
95
0
{
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
0
  }
104
0
  return true;
105
0
}
106
107
const GMPPlaneImpl*
108
0
GMPVideoi420FrameImpl::GetPlane(GMPPlaneType aType) const {
109
0
  switch (aType) {
110
0
    case kGMPYPlane:
111
0
      return &mYPlane;
112
0
    case kGMPUPlane:
113
0
      return &mUPlane;
114
0
    case kGMPVPlane:
115
0
      return &mVPlane;
116
0
    default:
117
0
      MOZ_CRASH("Unknown plane type!");
118
0
  }
119
0
  return nullptr;
120
0
}
121
122
GMPPlaneImpl*
123
0
GMPVideoi420FrameImpl::GetPlane(GMPPlaneType aType) {
124
0
  switch (aType) {
125
0
    case kGMPYPlane :
126
0
      return &mYPlane;
127
0
    case kGMPUPlane :
128
0
      return &mUPlane;
129
0
    case kGMPVPlane :
130
0
      return &mVPlane;
131
0
    default:
132
0
      MOZ_CRASH("Unknown plane type!");
133
0
  }
134
0
  return nullptr;
135
0
}
136
137
GMPErr
138
GMPVideoi420FrameImpl::CreateEmptyFrame(int32_t aWidth, int32_t aHeight,
139
                                        int32_t aStride_y, int32_t aStride_u, int32_t aStride_v)
140
0
{
141
0
  if (!CheckDimensions(aWidth, aHeight, aStride_y, aStride_u, aStride_v)) {
142
0
    return GMPGenericErr;
143
0
  }
144
0
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
0
150
0
  GMPErr err = mYPlane.CreateEmptyPlane(size_y, aStride_y, size_y);
151
0
  if (err != GMPNoErr) {
152
0
    return err;
153
0
  }
154
0
  err = mUPlane.CreateEmptyPlane(size_u, aStride_u, size_u);
155
0
  if (err != GMPNoErr) {
156
0
    return err;
157
0
  }
158
0
  err = mVPlane.CreateEmptyPlane(size_v, aStride_v, size_v);
159
0
  if (err != GMPNoErr) {
160
0
    return err;
161
0
  }
162
0
163
0
  mWidth = aWidth;
164
0
  mHeight = aHeight;
165
0
  mTimestamp = 0ll;
166
0
  mDuration = 0ll;
167
0
168
0
  return GMPNoErr;
169
0
}
170
171
GMPErr
172
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
0
{
178
0
  MOZ_ASSERT(aBuffer_y);
179
0
  MOZ_ASSERT(aBuffer_u);
180
0
  MOZ_ASSERT(aBuffer_v);
181
0
182
0
  if (aSize_y < 1 || aSize_u < 1 || aSize_v < 1) {
183
0
    return GMPGenericErr;
184
0
  }
185
0
186
0
  if (!CheckDimensions(aWidth, aHeight, aStride_y, aStride_u, aStride_v)) {
187
0
    return GMPGenericErr;
188
0
  }
189
0
190
0
  GMPErr err = mYPlane.Copy(aSize_y, aStride_y, aBuffer_y);
191
0
  if (err != GMPNoErr) {
192
0
    return err;
193
0
  }
194
0
  err = mUPlane.Copy(aSize_u, aStride_u, aBuffer_u);
195
0
  if (err != GMPNoErr) {
196
0
    return err;
197
0
  }
198
0
  err = mVPlane.Copy(aSize_v, aStride_v, aBuffer_v);
199
0
  if (err != GMPNoErr) {
200
0
    return err;
201
0
  }
202
0
203
0
  mWidth = aWidth;
204
0
  mHeight = aHeight;
205
0
206
0
  return GMPNoErr;
207
0
}
208
209
GMPErr
210
GMPVideoi420FrameImpl::CopyFrame(const GMPVideoi420Frame& aFrame)
211
0
{
212
0
  auto& f = static_cast<const GMPVideoi420FrameImpl&>(aFrame);
213
0
214
0
  GMPErr err = mYPlane.Copy(f.mYPlane);
215
0
  if (err != GMPNoErr) {
216
0
    return err;
217
0
  }
218
0
219
0
  err = mUPlane.Copy(f.mUPlane);
220
0
  if (err != GMPNoErr) {
221
0
    return err;
222
0
  }
223
0
224
0
  err = mVPlane.Copy(f.mVPlane);
225
0
  if (err != GMPNoErr) {
226
0
    return err;
227
0
  }
228
0
229
0
  mWidth = f.mWidth;
230
0
  mHeight = f.mHeight;
231
0
  mTimestamp = f.mTimestamp;
232
0
  mDuration = f.mDuration;
233
0
234
0
  return GMPNoErr;
235
0
}
236
237
void
238
GMPVideoi420FrameImpl::SwapFrame(GMPVideoi420Frame* aFrame)
239
0
{
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
GMPVideoi420FrameImpl::Buffer(GMPPlaneType aType)
252
0
{
253
0
  GMPPlane* p = GetPlane(aType);
254
0
  if (p) {
255
0
    return p->Buffer();
256
0
  }
257
0
  return nullptr;
258
0
}
259
260
const uint8_t*
261
GMPVideoi420FrameImpl::Buffer(GMPPlaneType aType) const
262
0
{
263
0
 const GMPPlane* p = GetPlane(aType);
264
0
  if (p) {
265
0
    return p->Buffer();
266
0
  }
267
0
  return nullptr;
268
0
}
269
270
int32_t
271
GMPVideoi420FrameImpl::AllocatedSize(GMPPlaneType aType) const
272
0
{
273
0
  const GMPPlane* p = GetPlane(aType);
274
0
  if (p) {
275
0
    return p->AllocatedSize();
276
0
  }
277
0
  return -1;
278
0
}
279
280
int32_t
281
GMPVideoi420FrameImpl::Stride(GMPPlaneType aType) const
282
0
{
283
0
  const GMPPlane* p = GetPlane(aType);
284
0
  if (p) {
285
0
    return p->Stride();
286
0
  }
287
0
  return -1;
288
0
}
289
290
GMPErr
291
GMPVideoi420FrameImpl::SetWidth(int32_t aWidth)
292
0
{
293
0
  if (!CheckDimensions(aWidth, mHeight,
294
0
                       mYPlane.Stride(), mUPlane.Stride(),
295
0
                       mVPlane.Stride())) {
296
0
    return GMPGenericErr;
297
0
  }
298
0
  mWidth = aWidth;
299
0
  return GMPNoErr;
300
0
}
301
302
GMPErr
303
GMPVideoi420FrameImpl::SetHeight(int32_t aHeight)
304
0
{
305
0
  if (!CheckDimensions(mWidth, aHeight,
306
0
                       mYPlane.Stride(), mUPlane.Stride(),
307
0
                       mVPlane.Stride())) {
308
0
    return GMPGenericErr;
309
0
  }
310
0
  mHeight = aHeight;
311
0
  return GMPNoErr;
312
0
}
313
314
int32_t
315
GMPVideoi420FrameImpl::Width() const
316
0
{
317
0
  return mWidth;
318
0
}
319
320
int32_t
321
GMPVideoi420FrameImpl::Height() const
322
0
{
323
0
  return mHeight;
324
0
}
325
326
void
327
GMPVideoi420FrameImpl::SetTimestamp(uint64_t aTimestamp)
328
0
{
329
0
  mTimestamp = aTimestamp;
330
0
}
331
332
uint64_t
333
GMPVideoi420FrameImpl::Timestamp() const
334
0
{
335
0
  return mTimestamp;
336
0
}
337
338
void
339
GMPVideoi420FrameImpl::SetDuration(uint64_t aDuration)
340
0
{
341
0
  mDuration = aDuration;
342
0
}
343
344
uint64_t
345
GMPVideoi420FrameImpl::Duration() const
346
0
{
347
0
  return mDuration;
348
0
}
349
350
bool
351
GMPVideoi420FrameImpl::IsZeroSize() const
352
0
{
353
0
  return (mYPlane.IsZeroSize() && mUPlane.IsZeroSize() && mVPlane.IsZeroSize());
354
0
}
355
356
void
357
GMPVideoi420FrameImpl::ResetSize()
358
0
{
359
0
  mYPlane.ResetSize();
360
0
  mUPlane.ResetSize();
361
0
  mVPlane.ResetSize();
362
0
}
363
364
} // namespace gmp
365
} // namespace mozilla