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