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