Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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<GMPVideoFrameType>(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, &mBuffer) ||
!Buffer()) {
return GMPAllocErr;
}
}
mSize = aSize;
return GMPNoErr;
}
GMPErr GMPVideoEncodedFrameImpl::CopyFrame(const GMPVideoEncodedFrame& aFrame) {
auto& f = static_cast<const GMPVideoEncodedFrameImpl&>(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, &new_mem) ||
!new_mem.get<uint8_t>()) {
return;
}
if (mBuffer.IsReadable()) {
memcpy(new_mem.get<uint8_t>(), Buffer(), mSize);
}
DestroyBuffer();
mBuffer = new_mem;
}
uint32_t GMPVideoEncodedFrameImpl::AllocatedSize() {
if (mBuffer.IsWritable()) {
return mBuffer.Size<uint8_t>();
}
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>();
}
uint8_t* GMPVideoEncodedFrameImpl::Buffer() { return mBuffer.get<uint8_t>(); }
void GMPVideoEncodedFrameImpl::Destroy() { delete this; }
GMPBufferType GMPVideoEncodedFrameImpl::BufferType() const {
return mBufferType;
}
void GMPVideoEncodedFrameImpl::SetBufferType(GMPBufferType aBufferType) {
mBufferType = aBufferType;
}
} // namespace mozilla::gmp