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