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 
11 namespace mozilla {
12 namespace gmp {
13 
GMPVideoEncodedFrameImpl(GMPVideoHostImpl * aHost)14 GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl(GMPVideoHostImpl* aHost)
15     : mEncodedWidth(0),
16       mEncodedHeight(0),
17       mTimeStamp(0ll),
18       mDuration(0ll),
19       mFrameType(kGMPDeltaFrame),
20       mSize(0),
21       mCompleteFrame(false),
22       mHost(aHost),
23       mBufferType(GMP_BufferSingle) {
24   MOZ_ASSERT(aHost);
25   aHost->EncodedFrameCreated(this);
26 }
27 
GMPVideoEncodedFrameImpl(const GMPVideoEncodedFrameData & aFrameData,GMPVideoHostImpl * aHost)28 GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl(
29     const GMPVideoEncodedFrameData& aFrameData, GMPVideoHostImpl* aHost)
30     : mEncodedWidth(aFrameData.mEncodedWidth()),
31       mEncodedHeight(aFrameData.mEncodedHeight()),
32       mTimeStamp(aFrameData.mTimestamp()),
33       mDuration(aFrameData.mDuration()),
34       mFrameType(static_cast<GMPVideoFrameType>(aFrameData.mFrameType())),
35       mSize(aFrameData.mSize()),
36       mCompleteFrame(aFrameData.mCompleteFrame()),
37       mHost(aHost),
38       mBuffer(aFrameData.mBuffer()),
39       mBufferType(aFrameData.mBufferType()) {
40   MOZ_ASSERT(aHost);
41   aHost->EncodedFrameCreated(this);
42 }
43 
~GMPVideoEncodedFrameImpl()44 GMPVideoEncodedFrameImpl::~GMPVideoEncodedFrameImpl() {
45   DestroyBuffer();
46   if (mHost) {
47     mHost->EncodedFrameDestroyed(this);
48   }
49 }
50 
GetFrameFormat()51 GMPVideoFrameFormat GMPVideoEncodedFrameImpl::GetFrameFormat() {
52   return kGMPEncodedVideoFrame;
53 }
54 
DoneWithAPI()55 void GMPVideoEncodedFrameImpl::DoneWithAPI() {
56   DestroyBuffer();
57 
58   // Do this after destroying the buffer because destruction
59   // involves deallocation, which requires a host.
60   mHost = nullptr;
61 }
62 
ActorDestroyed()63 void GMPVideoEncodedFrameImpl::ActorDestroyed() {
64   // Simply clear out Shmem reference, do not attempt to
65   // properly free it. It has already been freed.
66   mBuffer = ipc::Shmem();
67   // No more host.
68   mHost = nullptr;
69 }
70 
RelinquishFrameData(GMPVideoEncodedFrameData & aFrameData)71 bool GMPVideoEncodedFrameImpl::RelinquishFrameData(
72     GMPVideoEncodedFrameData& aFrameData) {
73   aFrameData.mEncodedWidth() = mEncodedWidth;
74   aFrameData.mEncodedHeight() = mEncodedHeight;
75   aFrameData.mTimestamp() = mTimeStamp;
76   aFrameData.mDuration() = mDuration;
77   aFrameData.mFrameType() = mFrameType;
78   aFrameData.mSize() = mSize;
79   aFrameData.mCompleteFrame() = mCompleteFrame;
80   aFrameData.mBuffer() = mBuffer;
81   aFrameData.mBufferType() = mBufferType;
82 
83   // This method is called right before Shmem is sent to another process.
84   // We need to effectively zero out our member copy so that we don't
85   // try to delete Shmem we don't own later.
86   mBuffer = ipc::Shmem();
87 
88   return true;
89 }
90 
DestroyBuffer()91 void GMPVideoEncodedFrameImpl::DestroyBuffer() {
92   if (mHost && mBuffer.IsWritable()) {
93     mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPEncodedData,
94                                            mBuffer);
95   }
96   mBuffer = ipc::Shmem();
97 }
98 
CreateEmptyFrame(uint32_t aSize)99 GMPErr GMPVideoEncodedFrameImpl::CreateEmptyFrame(uint32_t aSize) {
100   if (aSize == 0) {
101     DestroyBuffer();
102   } else if (aSize > AllocatedSize()) {
103     DestroyBuffer();
104     if (!mHost->SharedMemMgr()->MgrAllocShmem(
105             GMPSharedMem::kGMPEncodedData, aSize, ipc::SharedMemory::TYPE_BASIC,
106             &mBuffer) ||
107         !Buffer()) {
108       return GMPAllocErr;
109     }
110   }
111   mSize = aSize;
112 
113   return GMPNoErr;
114 }
115 
CopyFrame(const GMPVideoEncodedFrame & aFrame)116 GMPErr GMPVideoEncodedFrameImpl::CopyFrame(const GMPVideoEncodedFrame& aFrame) {
117   auto& f = static_cast<const GMPVideoEncodedFrameImpl&>(aFrame);
118 
119   if (f.mSize != 0) {
120     GMPErr err = CreateEmptyFrame(f.mSize);
121     if (err != GMPNoErr) {
122       return err;
123     }
124     memcpy(Buffer(), f.Buffer(), f.mSize);
125   }
126   mEncodedWidth = f.mEncodedWidth;
127   mEncodedHeight = f.mEncodedHeight;
128   mTimeStamp = f.mTimeStamp;
129   mDuration = f.mDuration;
130   mFrameType = f.mFrameType;
131   mSize = f.mSize;  // already set...
132   mCompleteFrame = f.mCompleteFrame;
133   mBufferType = f.mBufferType;
134   // Don't copy host, that should have been set properly on object creation via
135   // host.
136 
137   return GMPNoErr;
138 }
139 
SetEncodedWidth(uint32_t aEncodedWidth)140 void GMPVideoEncodedFrameImpl::SetEncodedWidth(uint32_t aEncodedWidth) {
141   mEncodedWidth = aEncodedWidth;
142 }
143 
EncodedWidth()144 uint32_t GMPVideoEncodedFrameImpl::EncodedWidth() { return mEncodedWidth; }
145 
SetEncodedHeight(uint32_t aEncodedHeight)146 void GMPVideoEncodedFrameImpl::SetEncodedHeight(uint32_t aEncodedHeight) {
147   mEncodedHeight = aEncodedHeight;
148 }
149 
EncodedHeight()150 uint32_t GMPVideoEncodedFrameImpl::EncodedHeight() { return mEncodedHeight; }
151 
SetTimeStamp(uint64_t aTimeStamp)152 void GMPVideoEncodedFrameImpl::SetTimeStamp(uint64_t aTimeStamp) {
153   mTimeStamp = aTimeStamp;
154 }
155 
TimeStamp()156 uint64_t GMPVideoEncodedFrameImpl::TimeStamp() { return mTimeStamp; }
157 
SetDuration(uint64_t aDuration)158 void GMPVideoEncodedFrameImpl::SetDuration(uint64_t aDuration) {
159   mDuration = aDuration;
160 }
161 
Duration() const162 uint64_t GMPVideoEncodedFrameImpl::Duration() const { return mDuration; }
163 
SetFrameType(GMPVideoFrameType aFrameType)164 void GMPVideoEncodedFrameImpl::SetFrameType(GMPVideoFrameType aFrameType) {
165   mFrameType = aFrameType;
166 }
167 
FrameType()168 GMPVideoFrameType GMPVideoEncodedFrameImpl::FrameType() { return mFrameType; }
169 
SetAllocatedSize(uint32_t aNewSize)170 void GMPVideoEncodedFrameImpl::SetAllocatedSize(uint32_t aNewSize) {
171   if (aNewSize <= AllocatedSize()) {
172     return;
173   }
174 
175   if (!mHost) {
176     return;
177   }
178 
179   ipc::Shmem new_mem;
180   if (!mHost->SharedMemMgr()->MgrAllocShmem(
181           GMPSharedMem::kGMPEncodedData, aNewSize,
182           ipc::SharedMemory::TYPE_BASIC, &new_mem) ||
183       !new_mem.get<uint8_t>()) {
184     return;
185   }
186 
187   if (mBuffer.IsReadable()) {
188     memcpy(new_mem.get<uint8_t>(), Buffer(), mSize);
189   }
190 
191   DestroyBuffer();
192 
193   mBuffer = new_mem;
194 }
195 
AllocatedSize()196 uint32_t GMPVideoEncodedFrameImpl::AllocatedSize() {
197   if (mBuffer.IsWritable()) {
198     return mBuffer.Size<uint8_t>();
199   }
200   return 0;
201 }
202 
SetSize(uint32_t aSize)203 void GMPVideoEncodedFrameImpl::SetSize(uint32_t aSize) { mSize = aSize; }
204 
Size()205 uint32_t GMPVideoEncodedFrameImpl::Size() { return mSize; }
206 
SetCompleteFrame(bool aCompleteFrame)207 void GMPVideoEncodedFrameImpl::SetCompleteFrame(bool aCompleteFrame) {
208   mCompleteFrame = aCompleteFrame;
209 }
210 
CompleteFrame()211 bool GMPVideoEncodedFrameImpl::CompleteFrame() { return mCompleteFrame; }
212 
Buffer() const213 const uint8_t* GMPVideoEncodedFrameImpl::Buffer() const {
214   return mBuffer.get<uint8_t>();
215 }
216 
Buffer()217 uint8_t* GMPVideoEncodedFrameImpl::Buffer() { return mBuffer.get<uint8_t>(); }
218 
Destroy()219 void GMPVideoEncodedFrameImpl::Destroy() { delete this; }
220 
BufferType() const221 GMPBufferType GMPVideoEncodedFrameImpl::BufferType() const {
222   return mBufferType;
223 }
224 
SetBufferType(GMPBufferType aBufferType)225 void GMPVideoEncodedFrameImpl::SetBufferType(GMPBufferType aBufferType) {
226   mBufferType = aBufferType;
227 }
228 
229 }  // namespace gmp
230 }  // namespace mozilla
231