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 "GMPVideoEncodedFrameImpl.h"
7 #include "GMPVideoHost.h"
8 #include "mozilla/gmp/GMPTypes.h"
9 #include "GMPSharedMemManager.h"
10 #include "GMPEncryptedBufferDataImpl.h"
11
12 namespace mozilla {
13 namespace gmp {
14
GMPVideoEncodedFrameImpl(GMPVideoHostImpl * aHost)15 GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl(GMPVideoHostImpl* aHost)
16 : mEncodedWidth(0),
17 mEncodedHeight(0),
18 mTimeStamp(0ll),
19 mDuration(0ll),
20 mFrameType(kGMPDeltaFrame),
21 mSize(0),
22 mCompleteFrame(false),
23 mHost(aHost),
24 mBufferType(GMP_BufferSingle)
25 {
26 MOZ_ASSERT(aHost);
27 aHost->EncodedFrameCreated(this);
28 }
29
GMPVideoEncodedFrameImpl(const GMPVideoEncodedFrameData & aFrameData,GMPVideoHostImpl * aHost)30 GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl(const GMPVideoEncodedFrameData& aFrameData,
31 GMPVideoHostImpl* aHost)
32 : mEncodedWidth(aFrameData.mEncodedWidth()),
33 mEncodedHeight(aFrameData.mEncodedHeight()),
34 mTimeStamp(aFrameData.mTimestamp()),
35 mDuration(aFrameData.mDuration()),
36 mFrameType(static_cast<GMPVideoFrameType>(aFrameData.mFrameType())),
37 mSize(aFrameData.mSize()),
38 mCompleteFrame(aFrameData.mCompleteFrame()),
39 mHost(aHost),
40 mBuffer(aFrameData.mBuffer()),
41 mBufferType(aFrameData.mBufferType())
42 {
43 MOZ_ASSERT(aHost);
44 if (aFrameData.mDecryptionData().mKeyId().Length() > 0) {
45 mCrypto = new GMPEncryptedBufferDataImpl(aFrameData.mDecryptionData());
46 }
47 aHost->EncodedFrameCreated(this);
48 }
49
~GMPVideoEncodedFrameImpl()50 GMPVideoEncodedFrameImpl::~GMPVideoEncodedFrameImpl()
51 {
52 DestroyBuffer();
53 if (mHost) {
54 mHost->EncodedFrameDestroyed(this);
55 }
56 }
57
58 void
InitCrypto(const CryptoSample & aCrypto)59 GMPVideoEncodedFrameImpl::InitCrypto(const CryptoSample& aCrypto)
60 {
61 mCrypto = new GMPEncryptedBufferDataImpl(aCrypto);
62 }
63
64 const GMPEncryptedBufferMetadata*
GetDecryptionData() const65 GMPVideoEncodedFrameImpl::GetDecryptionData() const
66 {
67 return mCrypto;
68 }
69
70 GMPVideoFrameFormat
GetFrameFormat()71 GMPVideoEncodedFrameImpl::GetFrameFormat()
72 {
73 return kGMPEncodedVideoFrame;
74 }
75
76 void
DoneWithAPI()77 GMPVideoEncodedFrameImpl::DoneWithAPI()
78 {
79 DestroyBuffer();
80
81 // Do this after destroying the buffer because destruction
82 // involves deallocation, which requires a host.
83 mHost = nullptr;
84 }
85
86 void
ActorDestroyed()87 GMPVideoEncodedFrameImpl::ActorDestroyed()
88 {
89 // Simply clear out Shmem reference, do not attempt to
90 // properly free it. It has already been freed.
91 mBuffer = ipc::Shmem();
92 // No more host.
93 mHost = nullptr;
94 }
95
96 bool
RelinquishFrameData(GMPVideoEncodedFrameData & aFrameData)97 GMPVideoEncodedFrameImpl::RelinquishFrameData(GMPVideoEncodedFrameData& aFrameData)
98 {
99 aFrameData.mEncodedWidth() = mEncodedWidth;
100 aFrameData.mEncodedHeight() = mEncodedHeight;
101 aFrameData.mTimestamp() = mTimeStamp;
102 aFrameData.mDuration() = mDuration;
103 aFrameData.mFrameType() = mFrameType;
104 aFrameData.mSize() = mSize;
105 aFrameData.mCompleteFrame() = mCompleteFrame;
106 aFrameData.mBuffer() = mBuffer;
107 aFrameData.mBufferType() = mBufferType;
108 if (mCrypto) {
109 mCrypto->RelinquishData(aFrameData.mDecryptionData());
110 }
111
112 // This method is called right before Shmem is sent to another process.
113 // We need to effectively zero out our member copy so that we don't
114 // try to delete Shmem we don't own later.
115 mBuffer = ipc::Shmem();
116
117 return true;
118 }
119
120 void
DestroyBuffer()121 GMPVideoEncodedFrameImpl::DestroyBuffer()
122 {
123 if (mHost && mBuffer.IsWritable()) {
124 mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPEncodedData, mBuffer);
125 }
126 mBuffer = ipc::Shmem();
127 }
128
129 GMPErr
CreateEmptyFrame(uint32_t aSize)130 GMPVideoEncodedFrameImpl::CreateEmptyFrame(uint32_t aSize)
131 {
132 if (aSize == 0) {
133 DestroyBuffer();
134 } else if (aSize > AllocatedSize()) {
135 DestroyBuffer();
136 if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPEncodedData, aSize,
137 ipc::SharedMemory::TYPE_BASIC, &mBuffer) ||
138 !Buffer()) {
139 return GMPAllocErr;
140 }
141 }
142 mSize = aSize;
143
144 return GMPNoErr;
145 }
146
147 GMPErr
CopyFrame(const GMPVideoEncodedFrame & aFrame)148 GMPVideoEncodedFrameImpl::CopyFrame(const GMPVideoEncodedFrame& aFrame)
149 {
150 auto& f = static_cast<const GMPVideoEncodedFrameImpl&>(aFrame);
151
152 if (f.mSize != 0) {
153 GMPErr err = CreateEmptyFrame(f.mSize);
154 if (err != GMPNoErr) {
155 return err;
156 }
157 memcpy(Buffer(), f.Buffer(), f.mSize);
158 }
159 mEncodedWidth = f.mEncodedWidth;
160 mEncodedHeight = f.mEncodedHeight;
161 mTimeStamp = f.mTimeStamp;
162 mDuration = f.mDuration;
163 mFrameType = f.mFrameType;
164 mSize = f.mSize; // already set...
165 mCompleteFrame = f.mCompleteFrame;
166 mBufferType = f.mBufferType;
167 mCrypto = new GMPEncryptedBufferDataImpl(*(f.mCrypto));
168 // Don't copy host, that should have been set properly on object creation via host.
169
170 return GMPNoErr;
171 }
172
173 void
SetEncodedWidth(uint32_t aEncodedWidth)174 GMPVideoEncodedFrameImpl::SetEncodedWidth(uint32_t aEncodedWidth)
175 {
176 mEncodedWidth = aEncodedWidth;
177 }
178
179 uint32_t
EncodedWidth()180 GMPVideoEncodedFrameImpl::EncodedWidth()
181 {
182 return mEncodedWidth;
183 }
184
185 void
SetEncodedHeight(uint32_t aEncodedHeight)186 GMPVideoEncodedFrameImpl::SetEncodedHeight(uint32_t aEncodedHeight)
187 {
188 mEncodedHeight = aEncodedHeight;
189 }
190
191 uint32_t
EncodedHeight()192 GMPVideoEncodedFrameImpl::EncodedHeight()
193 {
194 return mEncodedHeight;
195 }
196
197 void
SetTimeStamp(uint64_t aTimeStamp)198 GMPVideoEncodedFrameImpl::SetTimeStamp(uint64_t aTimeStamp)
199 {
200 mTimeStamp = aTimeStamp;
201 }
202
203 uint64_t
TimeStamp()204 GMPVideoEncodedFrameImpl::TimeStamp()
205 {
206 return mTimeStamp;
207 }
208
209 void
SetDuration(uint64_t aDuration)210 GMPVideoEncodedFrameImpl::SetDuration(uint64_t aDuration)
211 {
212 mDuration = aDuration;
213 }
214
215 uint64_t
Duration() const216 GMPVideoEncodedFrameImpl::Duration() const
217 {
218 return mDuration;
219 }
220
221 void
SetFrameType(GMPVideoFrameType aFrameType)222 GMPVideoEncodedFrameImpl::SetFrameType(GMPVideoFrameType aFrameType)
223 {
224 mFrameType = aFrameType;
225 }
226
227 GMPVideoFrameType
FrameType()228 GMPVideoEncodedFrameImpl::FrameType()
229 {
230 return mFrameType;
231 }
232
233 void
SetAllocatedSize(uint32_t aNewSize)234 GMPVideoEncodedFrameImpl::SetAllocatedSize(uint32_t aNewSize)
235 {
236 if (aNewSize <= AllocatedSize()) {
237 return;
238 }
239
240 if (!mHost) {
241 return;
242 }
243
244 ipc::Shmem new_mem;
245 if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPEncodedData, aNewSize,
246 ipc::SharedMemory::TYPE_BASIC, &new_mem) ||
247 !new_mem.get<uint8_t>()) {
248 return;
249 }
250
251 if (mBuffer.IsReadable()) {
252 memcpy(new_mem.get<uint8_t>(), Buffer(), mSize);
253 }
254
255 DestroyBuffer();
256
257 mBuffer = new_mem;
258 }
259
260 uint32_t
AllocatedSize()261 GMPVideoEncodedFrameImpl::AllocatedSize()
262 {
263 if (mBuffer.IsWritable()) {
264 return mBuffer.Size<uint8_t>();
265 }
266 return 0;
267 }
268
269 void
SetSize(uint32_t aSize)270 GMPVideoEncodedFrameImpl::SetSize(uint32_t aSize)
271 {
272 mSize = aSize;
273 }
274
275 uint32_t
Size()276 GMPVideoEncodedFrameImpl::Size()
277 {
278 return mSize;
279 }
280
281 void
SetCompleteFrame(bool aCompleteFrame)282 GMPVideoEncodedFrameImpl::SetCompleteFrame(bool aCompleteFrame)
283 {
284 mCompleteFrame = aCompleteFrame;
285 }
286
287 bool
CompleteFrame()288 GMPVideoEncodedFrameImpl::CompleteFrame()
289 {
290 return mCompleteFrame;
291 }
292
293 const uint8_t*
Buffer() const294 GMPVideoEncodedFrameImpl::Buffer() const
295 {
296 return mBuffer.get<uint8_t>();
297 }
298
299 uint8_t*
Buffer()300 GMPVideoEncodedFrameImpl::Buffer()
301 {
302 return mBuffer.get<uint8_t>();
303 }
304
305 void
Destroy()306 GMPVideoEncodedFrameImpl::Destroy()
307 {
308 delete this;
309 }
310
311 GMPBufferType
BufferType() const312 GMPVideoEncodedFrameImpl::BufferType() const
313 {
314 return mBufferType;
315 }
316
317 void
SetBufferType(GMPBufferType aBufferType)318 GMPVideoEncodedFrameImpl::SetBufferType(GMPBufferType aBufferType)
319 {
320 mBufferType = aBufferType;
321 }
322
323 } // namespace gmp
324 } // namespace mozilla
325