/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GMPVideoEncodedFrameImpl.h" #include "GMPVideoHost.h" #include "mozilla/gmp/GMPTypes.h" #include "GMPSharedMemManager.h" namespace mozilla::gmp { GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl(GMPVideoHostImpl* aHost) : mEncodedWidth(0), mEncodedHeight(0), mTimeStamp(0ll), mDuration(0ll), mFrameType(kGMPDeltaFrame), mSize(0), mCompleteFrame(false), mHost(aHost), mBufferType(GMP_BufferSingle) { MOZ_ASSERT(aHost); aHost->EncodedFrameCreated(this); } GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl( const GMPVideoEncodedFrameData& aFrameData, GMPVideoHostImpl* aHost) : mEncodedWidth(aFrameData.mEncodedWidth()), mEncodedHeight(aFrameData.mEncodedHeight()), mTimeStamp(aFrameData.mTimestamp()), mDuration(aFrameData.mDuration()), mFrameType(static_cast(aFrameData.mFrameType())), mSize(aFrameData.mSize()), mCompleteFrame(aFrameData.mCompleteFrame()), mHost(aHost), mBuffer(aFrameData.mBuffer()), mBufferType(aFrameData.mBufferType()) { MOZ_ASSERT(aHost); aHost->EncodedFrameCreated(this); } GMPVideoEncodedFrameImpl::~GMPVideoEncodedFrameImpl() { DestroyBuffer(); if (mHost) { mHost->EncodedFrameDestroyed(this); } } GMPVideoFrameFormat GMPVideoEncodedFrameImpl::GetFrameFormat() { return kGMPEncodedVideoFrame; } void GMPVideoEncodedFrameImpl::DoneWithAPI() { DestroyBuffer(); // Do this after destroying the buffer because destruction // involves deallocation, which requires a host. mHost = nullptr; } void GMPVideoEncodedFrameImpl::ActorDestroyed() { // Simply clear out Shmem reference, do not attempt to // properly free it. It has already been freed. mBuffer = ipc::Shmem(); // No more host. mHost = nullptr; } bool GMPVideoEncodedFrameImpl::RelinquishFrameData( GMPVideoEncodedFrameData& aFrameData) { aFrameData.mEncodedWidth() = mEncodedWidth; aFrameData.mEncodedHeight() = mEncodedHeight; aFrameData.mTimestamp() = mTimeStamp; aFrameData.mDuration() = mDuration; aFrameData.mFrameType() = mFrameType; aFrameData.mSize() = mSize; aFrameData.mCompleteFrame() = mCompleteFrame; aFrameData.mBuffer() = mBuffer; aFrameData.mBufferType() = mBufferType; // This method is called right before Shmem is sent to another process. // We need to effectively zero out our member copy so that we don't // try to delete Shmem we don't own later. mBuffer = ipc::Shmem(); return true; } void GMPVideoEncodedFrameImpl::DestroyBuffer() { if (mHost && mBuffer.IsWritable()) { mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPEncodedData, mBuffer); } mBuffer = ipc::Shmem(); } GMPErr GMPVideoEncodedFrameImpl::CreateEmptyFrame(uint32_t aSize) { if (aSize == 0) { DestroyBuffer(); } else if (aSize > AllocatedSize()) { DestroyBuffer(); if (!mHost->SharedMemMgr()->MgrAllocShmem( GMPSharedMem::kGMPEncodedData, aSize, ipc::SharedMemory::TYPE_BASIC, &mBuffer) || !Buffer()) { return GMPAllocErr; } } mSize = aSize; return GMPNoErr; } GMPErr GMPVideoEncodedFrameImpl::CopyFrame(const GMPVideoEncodedFrame& aFrame) { auto& f = static_cast(aFrame); if (f.mSize != 0) { GMPErr err = CreateEmptyFrame(f.mSize); if (err != GMPNoErr) { return err; } memcpy(Buffer(), f.Buffer(), f.mSize); } mEncodedWidth = f.mEncodedWidth; mEncodedHeight = f.mEncodedHeight; mTimeStamp = f.mTimeStamp; mDuration = f.mDuration; mFrameType = f.mFrameType; mSize = f.mSize; // already set... mCompleteFrame = f.mCompleteFrame; mBufferType = f.mBufferType; // Don't copy host, that should have been set properly on object creation via // host. return GMPNoErr; } void GMPVideoEncodedFrameImpl::SetEncodedWidth(uint32_t aEncodedWidth) { mEncodedWidth = aEncodedWidth; } uint32_t GMPVideoEncodedFrameImpl::EncodedWidth() { return mEncodedWidth; } void GMPVideoEncodedFrameImpl::SetEncodedHeight(uint32_t aEncodedHeight) { mEncodedHeight = aEncodedHeight; } uint32_t GMPVideoEncodedFrameImpl::EncodedHeight() { return mEncodedHeight; } void GMPVideoEncodedFrameImpl::SetTimeStamp(uint64_t aTimeStamp) { mTimeStamp = aTimeStamp; } uint64_t GMPVideoEncodedFrameImpl::TimeStamp() { return mTimeStamp; } void GMPVideoEncodedFrameImpl::SetDuration(uint64_t aDuration) { mDuration = aDuration; } uint64_t GMPVideoEncodedFrameImpl::Duration() const { return mDuration; } void GMPVideoEncodedFrameImpl::SetFrameType(GMPVideoFrameType aFrameType) { mFrameType = aFrameType; } GMPVideoFrameType GMPVideoEncodedFrameImpl::FrameType() { return mFrameType; } void GMPVideoEncodedFrameImpl::SetAllocatedSize(uint32_t aNewSize) { if (aNewSize <= AllocatedSize()) { return; } if (!mHost) { return; } ipc::Shmem new_mem; if (!mHost->SharedMemMgr()->MgrAllocShmem( GMPSharedMem::kGMPEncodedData, aNewSize, ipc::SharedMemory::TYPE_BASIC, &new_mem) || !new_mem.get()) { return; } if (mBuffer.IsReadable()) { memcpy(new_mem.get(), Buffer(), mSize); } DestroyBuffer(); mBuffer = new_mem; } uint32_t GMPVideoEncodedFrameImpl::AllocatedSize() { if (mBuffer.IsWritable()) { return mBuffer.Size(); } return 0; } void GMPVideoEncodedFrameImpl::SetSize(uint32_t aSize) { mSize = aSize; } uint32_t GMPVideoEncodedFrameImpl::Size() { return mSize; } void GMPVideoEncodedFrameImpl::SetCompleteFrame(bool aCompleteFrame) { mCompleteFrame = aCompleteFrame; } bool GMPVideoEncodedFrameImpl::CompleteFrame() { return mCompleteFrame; } const uint8_t* GMPVideoEncodedFrameImpl::Buffer() const { return mBuffer.get(); } uint8_t* GMPVideoEncodedFrameImpl::Buffer() { return mBuffer.get(); } void GMPVideoEncodedFrameImpl::Destroy() { delete this; } GMPBufferType GMPVideoEncodedFrameImpl::BufferType() const { return mBufferType; } void GMPVideoEncodedFrameImpl::SetBufferType(GMPBufferType aBufferType) { mBufferType = aBufferType; } } // namespace mozilla::gmp