Backed out 5 changesets (bug 1020760, bug 1035653, bug 1020090) for leaks on a CLOSED TREE.

Backed out changeset f0b20e3db93c (bug 1020760)
Backed out changeset 412b654e5cd2 (bug 1035653)
Backed out changeset 01ba0892af29 (bug 1020760)
Backed out changeset c7de1f4b078f (bug 1020760)
Backed out changeset 96aa9d33a1f5 (bug 1020090)
This commit is contained in:
Ryan VanderMeulen 2014-07-10 21:43:04 -04:00
parent 671530fba0
commit 1dea3b300a
52 changed files with 815 additions and 1711 deletions

View File

@ -7,24 +7,9 @@
#define GMPMessageUtils_h_
#include "gmp-video-codec.h"
#include "gmp-video-frame-encoded.h"
namespace IPC {
template <>
struct ParamTraits<GMPErr>
: public ContiguousEnumSerializer<GMPErr,
GMPNoErr,
GMPLastErr>
{};
template <>
struct ParamTraits<GMPVideoFrameType>
: public ContiguousEnumSerializer<GMPVideoFrameType,
kGMPKeyFrame,
kGMPSkipFrame>
{};
template <>
struct ParamTraits<GMPVideoCodecComplexity>
: public ContiguousEnumSerializer<GMPVideoCodecComplexity,
@ -54,11 +39,57 @@ struct ParamTraits<GMPVideoCodecMode>
{};
template <>
struct ParamTraits<GMPBufferType>
: public ContiguousEnumSerializer<GMPBufferType,
GMP_BufferSingle,
GMP_BufferInvalid>
{};
struct ParamTraits<GMPVideoCodecVP8>
{
typedef GMPVideoCodecVP8 paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mPictureLossIndicationOn);
WriteParam(aMsg, aParam.mFeedbackModeOn);
WriteParam(aMsg, aParam.mComplexity);
WriteParam(aMsg, aParam.mResilience);
WriteParam(aMsg, aParam.mNumberOfTemporalLayers);
WriteParam(aMsg, aParam.mDenoisingOn);
WriteParam(aMsg, aParam.mErrorConcealmentOn);
WriteParam(aMsg, aParam.mAutomaticResizeOn);
WriteParam(aMsg, aParam.mFrameDroppingOn);
WriteParam(aMsg, aParam.mKeyFrameInterval);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
if (ReadParam(aMsg, aIter, &(aResult->mPictureLossIndicationOn)) &&
ReadParam(aMsg, aIter, &(aResult->mFeedbackModeOn)) &&
ReadParam(aMsg, aIter, &(aResult->mComplexity)) &&
ReadParam(aMsg, aIter, &(aResult->mResilience)) &&
ReadParam(aMsg, aIter, &(aResult->mNumberOfTemporalLayers)) &&
ReadParam(aMsg, aIter, &(aResult->mDenoisingOn)) &&
ReadParam(aMsg, aIter, &(aResult->mErrorConcealmentOn)) &&
ReadParam(aMsg, aIter, &(aResult->mAutomaticResizeOn)) &&
ReadParam(aMsg, aIter, &(aResult->mFrameDroppingOn)) &&
ReadParam(aMsg, aIter, &(aResult->mKeyFrameInterval))) {
return true;
}
return false;
}
static void Log(const paramType& aParam, std::wstring* aLog)
{
aLog->append(StringPrintf(L"[%d, %d, %d, %d, %u, %d, %d, %d, %d, %d]",
aParam.mPictureLossIndicationOn,
aParam.mFeedbackModeOn,
aParam.mComplexity,
aParam.mResilience,
aParam.mNumberOfTemporalLayers,
aParam.mDenoisingOn,
aParam.mErrorConcealmentOn,
aParam.mAutomaticResizeOn,
aParam.mFrameDroppingOn,
aParam.mKeyFrameInterval));
}
};
template <>
struct ParamTraits<GMPSimulcastStream>
@ -105,7 +136,6 @@ struct ParamTraits<GMPVideoCodec>
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mGMPApiVersion);
WriteParam(aMsg, aParam.mCodecType);
WriteParam(aMsg, nsAutoCString(aParam.mPLName));
WriteParam(aMsg, aParam.mPLType);
@ -115,8 +145,11 @@ struct ParamTraits<GMPVideoCodec>
WriteParam(aMsg, aParam.mMaxBitrate);
WriteParam(aMsg, aParam.mMinBitrate);
WriteParam(aMsg, aParam.mMaxFramerate);
WriteParam(aMsg, aParam.mFrameDroppingOn);
WriteParam(aMsg, aParam.mKeyFrameInterval);
if (aParam.mCodecType == kGMPVideoCodecVP8) {
WriteParam(aMsg, aParam.mCodecSpecific.mVP8);
} else {
MOZ_ASSERT(false, "Serializing unknown codec type!");
}
WriteParam(aMsg, aParam.mQPMax);
WriteParam(aMsg, aParam.mNumberOfSimulcastStreams);
for (uint32_t i = 0; i < aParam.mNumberOfSimulcastStreams; i++) {
@ -127,11 +160,6 @@ struct ParamTraits<GMPVideoCodec>
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
// NOTE: make sure this matches any versions supported
if (!ReadParam(aMsg, aIter, &(aResult->mGMPApiVersion)) ||
aResult->mGMPApiVersion != kGMPVersion33) {
return false;
}
if (!ReadParam(aMsg, aIter, &(aResult->mCodecType))) {
return false;
}
@ -150,9 +178,16 @@ struct ParamTraits<GMPVideoCodec>
!ReadParam(aMsg, aIter, &(aResult->mStartBitrate)) ||
!ReadParam(aMsg, aIter, &(aResult->mMaxBitrate)) ||
!ReadParam(aMsg, aIter, &(aResult->mMinBitrate)) ||
!ReadParam(aMsg, aIter, &(aResult->mMaxFramerate)) ||
!ReadParam(aMsg, aIter, &(aResult->mFrameDroppingOn)) ||
!ReadParam(aMsg, aIter, &(aResult->mKeyFrameInterval))) {
!ReadParam(aMsg, aIter, &(aResult->mMaxFramerate))) {
return false;
}
if (aResult->mCodecType == kGMPVideoCodecVP8) {
if (!ReadParam(aMsg, aIter, &(aResult->mCodecSpecific.mVP8))) {
return false;
}
} else {
MOZ_ASSERT(false, "De-serializing unknown codec type!");
return false;
}
@ -191,6 +226,104 @@ struct ParamTraits<GMPVideoCodec>
}
};
template <>
struct ParamTraits<GMPCodecSpecificInfoVP8>
{
typedef GMPCodecSpecificInfoVP8 paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mHasReceivedSLI);
WriteParam(aMsg, aParam.mPictureIdSLI);
WriteParam(aMsg, aParam.mHasReceivedRPSI);
WriteParam(aMsg, aParam.mPictureIdRPSI);
WriteParam(aMsg, aParam.mPictureId);
WriteParam(aMsg, aParam.mNonReference);
WriteParam(aMsg, aParam.mSimulcastIdx);
WriteParam(aMsg, aParam.mTemporalIdx);
WriteParam(aMsg, aParam.mLayerSync);
WriteParam(aMsg, aParam.mTL0PicIdx);
WriteParam(aMsg, aParam.mKeyIdx);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
if (ReadParam(aMsg, aIter, &(aResult->mHasReceivedSLI)) &&
ReadParam(aMsg, aIter, &(aResult->mPictureIdSLI)) &&
ReadParam(aMsg, aIter, &(aResult->mHasReceivedRPSI)) &&
ReadParam(aMsg, aIter, &(aResult->mPictureIdRPSI)) &&
ReadParam(aMsg, aIter, &(aResult->mPictureId)) &&
ReadParam(aMsg, aIter, &(aResult->mNonReference)) &&
ReadParam(aMsg, aIter, &(aResult->mSimulcastIdx)) &&
ReadParam(aMsg, aIter, &(aResult->mTemporalIdx)) &&
ReadParam(aMsg, aIter, &(aResult->mLayerSync)) &&
ReadParam(aMsg, aIter, &(aResult->mTL0PicIdx)) &&
ReadParam(aMsg, aIter, &(aResult->mKeyIdx))) {
return true;
}
return false;
}
static void Log(const paramType& aParam, std::wstring* aLog)
{
aLog->append(StringPrintf(L"[%d, %u, %d, %u, %d, %d, %u, %u, %d, %d, %d]",
aParam.mHasReceivedSLI,
aParam.mPictureIdSLI,
aParam.mHasReceivedRPSI,
aParam.mPictureIdRPSI,
aParam.mPictureId,
aParam.mNonReference,
aParam.mSimulcastIdx,
aParam.mTemporalIdx,
aParam.mLayerSync,
aParam.mTL0PicIdx,
aParam.mKeyIdx));
}
};
template <>
struct ParamTraits<GMPCodecSpecificInfo>
{
typedef GMPCodecSpecificInfo paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mCodecType);
if (aParam.mCodecType == kGMPVideoCodecVP8) {
WriteParam(aMsg, aParam.mCodecSpecific.mVP8);
} else {
MOZ_ASSERT(false, "Serializing unknown codec type!");
}
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
if (!ReadParam(aMsg, aIter, &(aResult->mCodecType))) {
return false;
}
if (aResult->mCodecType == kGMPVideoCodecVP8) {
if (!ReadParam(aMsg, aIter, &(aResult->mCodecSpecific.mVP8))) {
return false;
}
} else {
MOZ_ASSERT(false, "De-serializing unknown codec type!");
return false;
}
return true;
}
static void Log(const paramType& aParam, std::wstring* aLog)
{
const char* codecName = nullptr;
if (aParam.mCodecType == kGMPVideoCodecVP8) {
codecName = "VP8";
}
aLog->append(StringPrintf(L"[%s]", codecName));
}
};
} // namespace IPC
#endif // GMPMessageUtils_h_

View File

@ -16,7 +16,6 @@
#include "nsString.h"
#include "nsTArray.h"
#include "nsIFile.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
class nsILineInputStream;
class nsIThread;
@ -39,7 +38,7 @@ enum GMPState {
class GMPParent MOZ_FINAL : public PGMPParent
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(GMPParent)
NS_INLINE_DECL_REFCOUNTING(GMPParent)
GMPParent();

View File

@ -27,7 +27,6 @@ public:
void Run()
{
mTask->Run();
mTask->Destroy();
mTask = nullptr;
}
@ -36,7 +35,7 @@ private:
{
}
GMPTask* mTask;
nsAutoPtr<GMPTask> mTask;
};
class SyncRunnable MOZ_FINAL
@ -72,7 +71,6 @@ public:
void Run()
{
mTask->Run();
mTask->Destroy();
mTask = nullptr;
MonitorAutoLock lock(mMonitor);
mDone = true;
@ -85,7 +83,7 @@ private:
}
bool mDone;
GMPTask* mTask;
nsAutoPtr<GMPTask> mTask;
MessageLoop* mMessageLoop;
Monitor mMonitor;
};
@ -110,6 +108,7 @@ RunOnMainThread(GMPTask* aTask)
}
nsRefPtr<Runnable> r = new Runnable(aTask);
sMainLoop->PostTask(FROM_HERE, NewRunnableMethod(r.get(), &Runnable::Run));
return GMPNoErr;
@ -153,9 +152,6 @@ InitPlatformAPI(GMPPlatformAPI& aPlatformAPI)
aPlatformAPI.runonmainthread = &RunOnMainThread;
aPlatformAPI.syncrunonmainthread = &SyncRunOnMainThread;
aPlatformAPI.createmutex = &CreateMutex;
aPlatformAPI.createrecord = nullptr;
aPlatformAPI.settimer = nullptr;
aPlatformAPI.getcurrenttime = nullptr;
}
GMPThreadImpl::GMPThreadImpl()

View File

@ -13,8 +13,6 @@
namespace mozilla {
namespace gmp {
class GMPChild;
void InitPlatformAPI(GMPPlatformAPI& aPlatformAPI);
class GMPThreadImpl : public GMPThread

View File

@ -183,7 +183,7 @@ NS_IMETHODIMP
GeckoMediaPluginService::GetGMPVideoDecoder(nsTArray<nsCString>* aTags,
const nsAString& aOrigin,
GMPVideoHost** aOutVideoHost,
GMPVideoDecoderProxy** aGMPVD)
GMPVideoDecoder** aGMPVD)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
@ -217,7 +217,7 @@ NS_IMETHODIMP
GeckoMediaPluginService::GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
const nsAString& aOrigin,
GMPVideoHost** aOutVideoHost,
GMPVideoEncoderProxy** aGMPVE)
GMPVideoEncoder** aGMPVE)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
@ -364,19 +364,6 @@ GeckoMediaPluginService::SelectPluginForAPI(const nsAString& aOrigin,
return nullptr;
}
class CreateGMPParentTask : public nsRunnable {
public:
NS_IMETHOD Run() {
MOZ_ASSERT(NS_IsMainThread());
mParent = new GMPParent();
return NS_OK;
}
already_AddRefed<GMPParent> GetParent() {
return mParent.forget();
}
private:
nsRefPtr<GMPParent> mParent;
};
void
GeckoMediaPluginService::AddOnGMPThread(const nsAString& aDirectory)
@ -389,16 +376,9 @@ GeckoMediaPluginService::AddOnGMPThread(const nsAString& aDirectory)
return;
}
// The GMPParent inherits from IToplevelProtocol, which must be created
// on the main thread to be threadsafe. See Bug 1035653.
nsRefPtr<CreateGMPParentTask> task(new CreateGMPParentTask());
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
MOZ_ASSERT(mainThread);
mozilla::SyncRunnable::DispatchToThread(mainThread, task);
nsRefPtr<GMPParent> gmp = task->GetParent();
nsRefPtr<GMPParent> gmp = new GMPParent();
rv = gmp->Init(directory);
if (NS_FAILED(rv)) {
NS_WARNING("Can't Create GMPParent");
return;
}

View File

@ -6,7 +6,6 @@
#ifndef GMPService_h_
#define GMPService_h_
#include "nsString.h"
#include "mozIGeckoMediaPluginService.h"
#include "nsIObserver.h"
#include "nsTArray.h"

View File

@ -1,85 +0,0 @@
/* -*- 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 "GMPSharedMemManager.h"
#include "GMPMessageUtils.h"
#include "mozilla/ipc/SharedMemory.h"
namespace mozilla {
namespace gmp {
// Really one set of pools on each side of the plugin API.
// YUV buffers go from Encoder parent to child; pool there, and then return
// with Decoded() frames to the Decoder parent and goes into the parent pool.
// Compressed (encoded) data goes from the Decoder parent to the child;
// pool there, and then return with Encoded() frames and goes into the parent
// pool.
static nsTArray<ipc::Shmem> sGmpFreelist[GMPSharedMemManager::kGMPNumTypes];
static uint32_t sGmpAllocated[GMPSharedMemManager::kGMPNumTypes]; // 0's
bool
GMPSharedMemManager::MgrAllocShmem(GMPMemoryClasses aClass, size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem)
{
CheckThread();
// first look to see if we have a free buffer large enough
for (uint32_t i = 0; i < sGmpFreelist[aClass].Length(); i++) {
MOZ_ASSERT(sGmpFreelist[aClass][i].IsWritable());
if (aSize <= sGmpFreelist[aClass][i].Size<uint8_t>()) {
*aMem = sGmpFreelist[aClass][i];
sGmpFreelist[aClass].RemoveElementAt(i);
return true;
}
}
// Didn't find a buffer free with enough space; allocate one
size_t pagesize = ipc::SharedMemory::SystemPageSize();
aSize = (aSize + (pagesize-1)) & ~(pagesize-1); // round up to page size
bool retval = Alloc(aSize, aType, aMem);
if (retval) {
sGmpAllocated[aClass]++;
}
return retval;
}
bool
GMPSharedMemManager::MgrDeallocShmem(GMPMemoryClasses aClass, ipc::Shmem& aMem)
{
CheckThread();
size_t size = aMem.Size<uint8_t>();
size_t total = 0;
// XXX This works; there are better pool algorithms. We need to avoid
// "falling off a cliff" with too low a number
if (sGmpFreelist[aClass].Length() > 10) {
Dealloc(sGmpFreelist[aClass][0]);
sGmpFreelist[aClass].RemoveElementAt(0);
// The allocation numbers will be fubar on the Child!
sGmpAllocated[aClass]--;
}
for (uint32_t i = 0; i < sGmpFreelist[aClass].Length(); i++) {
MOZ_ASSERT(sGmpFreelist[aClass][i].IsWritable());
total += sGmpFreelist[aClass][i].Size<uint8_t>();
if (size < sGmpFreelist[aClass][i].Size<uint8_t>()) {
sGmpFreelist[aClass].InsertElementAt(i, aMem);
return true;
}
}
sGmpFreelist[aClass].AppendElement(aMem);
return true;
}
uint32_t
GMPSharedMemManager::NumInUse(GMPMemoryClasses aClass)
{
return sGmpAllocated[aClass] - sGmpFreelist[aClass].Length();
}
}
}

View File

@ -7,7 +7,6 @@
#define GMPSharedMemManager_h_
#include "mozilla/ipc/Shmem.h"
#include "nsTArray.h"
namespace mozilla {
namespace gmp {
@ -15,40 +14,10 @@ namespace gmp {
class GMPSharedMemManager
{
public:
typedef enum {
kGMPFrameData = 0,
kGMPEncodedData,
kGMPNumTypes
} GMPMemoryClasses;
// This is a heuristic - max of 10 free in the Child pool, plus those
// in-use for the encoder and decoder at the given moment and not yet
// returned to the parent pool (which is not included). If more than
// this are needed, we presume the client has either crashed or hung
// (perhaps temporarily).
static const uint32_t kGMPBufLimit = 20;
GMPSharedMemManager() {}
virtual ~GMPSharedMemManager() {
// XXX free everything in the freelist
}
virtual bool MgrAllocShmem(GMPMemoryClasses aClass, size_t aSize,
virtual bool MgrAllocShmem(size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem);
virtual bool MgrDeallocShmem(GMPMemoryClasses aClass, ipc::Shmem& aMem);
// So we can know if data is "piling up" for the plugin - I.e. it's hung or crashed
virtual uint32_t NumInUse(GMPMemoryClasses aClass);
// Parent and child impls will differ here
virtual void CheckThread() = 0;
// These have to be implemented using the AllocShmem/etc provided by the IPDL-generated interfaces,
// so have the Parent/Child implement them.
virtual bool Alloc(size_t aSize, ipc::Shmem::SharedMemory::SharedMemoryType aType, ipc::Shmem* aMem) = 0;
virtual void Dealloc(ipc::Shmem& aMem) = 0;
ipc::Shmem* aMem) = 0;
virtual bool MgrDeallocShmem(ipc::Shmem& aMem) = 0;
};
} // namespace gmp

View File

@ -8,10 +8,10 @@ namespace gmp {
struct GMPVideoEncodedFrameData
{
int64_t mCaptureTime_ms;
uint32_t mEncodedWidth;
uint32_t mEncodedHeight;
uint64_t mTimestamp; // microseconds
uint64_t mDuration; // microseconds
uint32_t mTimeStamp;
uint32_t mFrameType;
uint32_t mSize;
Shmem mBuffer;
@ -32,8 +32,8 @@ struct GMPVideoi420FrameData
GMPPlaneData mVPlane;
int32_t mWidth;
int32_t mHeight;
uint64_t mTimestamp; // microseconds
uint64_t mDuration; // microseconds
uint32_t mTimestamp;
int64_t mRenderTime_ms;
};
}

View File

@ -80,31 +80,26 @@ GMPVideoDecoderChild::InputDataExhausted()
SendInputDataExhausted();
}
void
GMPVideoDecoderChild::DrainComplete()
bool
GMPVideoDecoderChild::MgrAllocShmem(size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
SendDrainComplete();
return AllocShmem(aSize, aType, aMem);
}
void
GMPVideoDecoderChild::ResetComplete()
bool
GMPVideoDecoderChild::MgrDeallocShmem(Shmem& aMem)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
SendResetComplete();
}
void
GMPVideoDecoderChild::CheckThread()
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
return DeallocShmem(aMem);
}
bool
GMPVideoDecoderChild::RecvInitDecode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
const int32_t& aCoreCount)
{
if (!mVideoDecoder) {
@ -112,19 +107,15 @@ GMPVideoDecoderChild::RecvInitDecode(const GMPVideoCodec& aCodecSettings,
}
// Ignore any return code. It is OK for this to fail without killing the process.
mVideoDecoder->InitDecode(aCodecSettings,
aCodecSpecific.Elements(),
aCodecSpecific.Length(),
this,
aCoreCount);
mVideoDecoder->InitDecode(aCodecSettings, this, aCoreCount);
return true;
}
bool
GMPVideoDecoderChild::RecvDecode(const GMPVideoEncodedFrameData& aInputFrame,
const bool& aMissingFrames,
const GMPBufferType& aBufferType,
const nsTArray<uint8_t>& aCodecSpecificInfo,
const GMPCodecSpecificInfo& aCodecSpecificInfo,
const int64_t& aRenderTimeMs)
{
if (!mVideoDecoder) {
@ -134,26 +125,11 @@ GMPVideoDecoderChild::RecvDecode(const GMPVideoEncodedFrameData& aInputFrame,
auto f = new GMPVideoEncodedFrameImpl(aInputFrame, &mVideoHost);
// Ignore any return code. It is OK for this to fail without killing the process.
mVideoDecoder->Decode(f,
aMissingFrames,
aBufferType,
aCodecSpecificInfo.Elements(),
aCodecSpecificInfo.Length(),
aRenderTimeMs);
mVideoDecoder->Decode(f, aMissingFrames, aCodecSpecificInfo, aRenderTimeMs);
return true;
}
bool
GMPVideoDecoderChild::RecvChildShmemForPool(Shmem& aFrameBuffer)
{
if (aFrameBuffer.IsWritable()) {
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPFrameData,
aFrameBuffer);
}
return true;
}
bool
GMPVideoDecoderChild::RecvReset()
{

View File

@ -11,7 +11,6 @@
#include "gmp-video-decode.h"
#include "GMPSharedMemManager.h"
#include "GMPVideoHost.h"
#include "mozilla/gmp/GMPTypes.h"
namespace mozilla {
namespace gmp {
@ -19,7 +18,7 @@ namespace gmp {
class GMPChild;
class GMPVideoDecoderChild : public PGMPVideoDecoderChild,
public GMPVideoDecoderCallback,
public GMPDecoderCallback,
public GMPSharedMemManager
{
public:
@ -29,48 +28,26 @@ public:
void Init(GMPVideoDecoder* aDecoder);
GMPVideoHostImpl& Host();
// GMPVideoDecoderCallback
// GMPDecoderCallback
virtual void Decoded(GMPVideoi420Frame* decodedFrame) MOZ_OVERRIDE;
virtual void ReceivedDecodedReferenceFrame(const uint64_t pictureId) MOZ_OVERRIDE;
virtual void ReceivedDecodedFrame(const uint64_t pictureId) MOZ_OVERRIDE;
virtual void InputDataExhausted() MOZ_OVERRIDE;
virtual void DrainComplete() MOZ_OVERRIDE;
virtual void ResetComplete() MOZ_OVERRIDE;
// GMPSharedMemManager
virtual void CheckThread();
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem)
{
#ifndef SHMEM_ALLOC_IN_CHILD
return CallNeedShmem(aSize, aMem);
#else
#ifdef GMP_SAFE_SHMEM
return AllocShmem(aSize, aType, aMem);
#else
return AllocUnsafeShmem(aSize, aType, aMem);
#endif
#endif
}
virtual void Dealloc(Shmem& aMem)
{
#ifndef SHMEM_ALLOC_IN_CHILD
SendParentShmemForPool(aMem);
#else
DeallocShmem(aMem);
#endif
}
virtual bool MgrAllocShmem(size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem) MOZ_OVERRIDE;
virtual bool MgrDeallocShmem(Shmem& aMem) MOZ_OVERRIDE;
private:
// PGMPVideoDecoderChild
virtual bool RecvInitDecode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
const int32_t& aCoreCount) MOZ_OVERRIDE;
virtual bool RecvDecode(const GMPVideoEncodedFrameData& aInputFrame,
const bool& aMissingFrames,
const GMPBufferType& aBufferType,
const nsTArray<uint8_t>& aCodecSpecificInfo,
const int64_t& aRenderTimeMs) MOZ_OVERRIDE;
virtual bool RecvChildShmemForPool(Shmem& aFrameBuffer) MOZ_OVERRIDE;
virtual bool RecvInitDecode(const GMPVideoCodec& codecSettings,
const int32_t& coreCount) MOZ_OVERRIDE;
virtual bool RecvDecode(const GMPVideoEncodedFrameData& inputFrame,
const bool& missingFrames,
const GMPCodecSpecificInfo& codecSpecificInfo,
const int64_t& renderTimeMs) MOZ_OVERRIDE;
virtual bool RecvReset() MOZ_OVERRIDE;
virtual bool RecvDrain() MOZ_OVERRIDE;
virtual bool RecvDecodingComplete() MOZ_OVERRIDE;

View File

@ -12,7 +12,6 @@
#include "GMPMessageUtils.h"
#include "nsAutoRef.h"
#include "nsThreadUtils.h"
#include "mozilla/gmp/GMPTypes.h"
template <>
class nsAutoRefTraits<GMPVideoEncodedFrame> : public nsPointerRefTraits<GMPVideoEncodedFrame>
@ -43,44 +42,60 @@ GMPVideoDecoderParent::Host()
return mVideoHost;
}
nsresult
bool
GMPVideoDecoderParent::MgrAllocShmem(size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem)
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
return AllocShmem(aSize, aType, aMem);
}
bool
GMPVideoDecoderParent::MgrDeallocShmem(Shmem& aMem)
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
return DeallocShmem(aMem);
}
GMPVideoErr
GMPVideoDecoderParent::InitDecode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
GMPVideoDecoderCallback* aCallback,
GMPDecoderCallback* aCallback,
int32_t aCoreCount)
{
if (!mCanSendMessages) {
NS_WARNING("Trying to use an invalid GMP video decoder!");
return NS_ERROR_FAILURE;
return GMPVideoGenericErr;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (!aCallback) {
return NS_ERROR_FAILURE;
return GMPVideoGenericErr;
}
mCallback = aCallback;
if (!SendInitDecode(aCodecSettings, aCodecSpecific, aCoreCount)) {
return NS_ERROR_FAILURE;
if (!SendInitDecode(aCodecSettings, aCoreCount)) {
return GMPVideoGenericErr;
}
// Async IPC, we don't have access to a return value.
return NS_OK;
return GMPVideoNoErr;
}
nsresult
GMPVideoErr
GMPVideoDecoderParent::Decode(GMPVideoEncodedFrame* aInputFrame,
bool aMissingFrames,
GMPBufferType aBufferType,
const nsTArray<uint8_t>& aCodecSpecificInfo,
const GMPCodecSpecificInfo& aCodecSpecificInfo,
int64_t aRenderTimeMs)
{
nsAutoRef<GMPVideoEncodedFrame> autoDestroy(aInputFrame);
if (!mCanSendMessages) {
NS_WARNING("Trying to use an invalid GMP video decoder!");
return NS_ERROR_FAILURE;
return GMPVideoGenericErr;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
@ -90,69 +105,60 @@ GMPVideoDecoderParent::Decode(GMPVideoEncodedFrame* aInputFrame,
GMPVideoEncodedFrameData frameData;
inputFrameImpl->RelinquishFrameData(frameData);
// Very rough kill-switch if the plugin stops processing. If it's merely
// hung and continues, we'll come back to life eventually.
// 3* is because we're using 3 buffers per frame for i420 data for now.
if (NumInUse(kGMPFrameData) > 3*GMPSharedMemManager::kGMPBufLimit ||
NumInUse(kGMPEncodedData) > GMPSharedMemManager::kGMPBufLimit) {
return NS_ERROR_FAILURE;
}
if (!SendDecode(frameData,
aMissingFrames,
aBufferType,
aCodecSpecificInfo,
aRenderTimeMs)) {
return NS_ERROR_FAILURE;
return GMPVideoGenericErr;
}
// Async IPC, we don't have access to a return value.
return NS_OK;
return GMPVideoNoErr;
}
nsresult
GMPVideoErr
GMPVideoDecoderParent::Reset()
{
if (!mCanSendMessages) {
NS_WARNING("Trying to use an invalid GMP video decoder!");
return NS_ERROR_FAILURE;
return GMPVideoGenericErr;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (!SendReset()) {
return NS_ERROR_FAILURE;
return GMPVideoGenericErr;
}
// Async IPC, we don't have access to a return value.
return NS_OK;
return GMPVideoNoErr;
}
nsresult
GMPVideoErr
GMPVideoDecoderParent::Drain()
{
if (!mCanSendMessages) {
NS_WARNING("Trying to use an invalid GMP video decoder!");
return NS_ERROR_FAILURE;
return GMPVideoGenericErr;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (!SendDrain()) {
return NS_ERROR_FAILURE;
return GMPVideoGenericErr;
}
// Async IPC, we don't have access to a return value.
return NS_OK;
return GMPVideoNoErr;
}
// Note: Consider keeping ActorDestroy sync'd up when making changes here.
nsresult
void
GMPVideoDecoderParent::DecodingComplete()
{
if (!mCanSendMessages) {
NS_WARNING("Trying to use an invalid GMP video decoder!");
return NS_ERROR_FAILURE;
return;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
@ -164,8 +170,6 @@ GMPVideoDecoderParent::DecodingComplete()
mVideoHost.DoneWithAPI();
unused << SendDecodingComplete();
return NS_OK;
}
// Note: Keep this sync'd up with DecodingComplete
@ -182,12 +186,6 @@ GMPVideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy)
mVideoHost.ActorDestroyed();
}
void
GMPVideoDecoderParent::CheckThread()
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
}
bool
GMPVideoDecoderParent::RecvDecoded(const GMPVideoi420FrameData& aDecodedFrame)
{
@ -242,59 +240,6 @@ GMPVideoDecoderParent::RecvInputDataExhausted()
return true;
}
bool
GMPVideoDecoderParent::RecvDrainComplete()
{
if (!mCallback) {
return false;
}
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->DrainComplete();
return true;
}
bool
GMPVideoDecoderParent::RecvResetComplete()
{
if (!mCallback) {
return false;
}
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->ResetComplete();
return true;
}
bool
GMPVideoDecoderParent::RecvParentShmemForPool(Shmem& aEncodedBuffer)
{
if (aEncodedBuffer.IsWritable()) {
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPEncodedData,
aEncodedBuffer);
}
return true;
}
bool
GMPVideoDecoderParent::AnswerNeedShmem(const uint32_t& aFrameBufferSize,
Shmem* aMem)
{
ipc::Shmem mem;
if (!mVideoHost.SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPFrameData,
aFrameBufferSize,
ipc::SharedMemory::TYPE_BASIC, &mem))
{
return false;
}
*aMem = mem;
mem = ipc::Shmem();
return true;
}
bool
GMPVideoDecoderParent::Recv__delete__()
{

View File

@ -12,16 +12,15 @@
#include "GMPMessageUtils.h"
#include "GMPSharedMemManager.h"
#include "GMPVideoHost.h"
#include "GMPVideoDecoderProxy.h"
namespace mozilla {
namespace gmp {
class GMPParent;
class GMPVideoDecoderParent MOZ_FINAL : public PGMPVideoDecoderParent
class GMPVideoDecoderParent MOZ_FINAL : public GMPVideoDecoder
, public PGMPVideoDecoderParent
, public GMPSharedMemManager
, public GMPVideoDecoderProxy
{
public:
NS_INLINE_DECL_REFCOUNTING(GMPVideoDecoderParent)
@ -30,34 +29,23 @@ public:
GMPVideoHostImpl& Host();
// GMPVideoDecoder
virtual nsresult InitDecode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
GMPVideoDecoderCallback* aCallback,
int32_t aCoreCount) MOZ_OVERRIDE;
virtual nsresult Decode(GMPVideoEncodedFrame* aInputFrame,
bool aMissingFrames,
GMPBufferType aBufferType,
const nsTArray<uint8_t>& aCodecSpecificInfo,
int64_t aRenderTimeMs = -1) MOZ_OVERRIDE;
virtual nsresult Reset() MOZ_OVERRIDE;
virtual nsresult Drain() MOZ_OVERRIDE;
virtual nsresult DecodingComplete() MOZ_OVERRIDE;
// GMPSharedMemManager
virtual void CheckThread();
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem)
{
#ifdef GMP_SAFE_SHMEM
return AllocShmem(aSize, aType, aMem);
#else
return AllocUnsafeShmem(aSize, aType, aMem);
#endif
}
virtual void Dealloc(Shmem& aMem)
{
DeallocShmem(aMem);
}
virtual bool MgrAllocShmem(size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem) MOZ_OVERRIDE;
virtual bool MgrDeallocShmem(Shmem& aMem) MOZ_OVERRIDE;
// GMPVideoDecoder
virtual GMPVideoErr InitDecode(const GMPVideoCodec& aCodecSettings,
GMPDecoderCallback* aCallback,
int32_t aCoreCount) MOZ_OVERRIDE;
virtual GMPVideoErr Decode(GMPVideoEncodedFrame* aInputFrame,
bool aMissingFrames,
const GMPCodecSpecificInfo& aCodecSpecificInfo,
int64_t aRenderTimeMs = -1) MOZ_OVERRIDE;
virtual GMPVideoErr Reset() MOZ_OVERRIDE;
virtual GMPVideoErr Drain() MOZ_OVERRIDE;
virtual void DecodingComplete() MOZ_OVERRIDE;
private:
~GMPVideoDecoderParent();
@ -68,16 +56,11 @@ private:
virtual bool RecvReceivedDecodedReferenceFrame(const uint64_t& aPictureId) MOZ_OVERRIDE;
virtual bool RecvReceivedDecodedFrame(const uint64_t& aPictureId) MOZ_OVERRIDE;
virtual bool RecvInputDataExhausted() MOZ_OVERRIDE;
virtual bool RecvDrainComplete() MOZ_OVERRIDE;
virtual bool RecvResetComplete() MOZ_OVERRIDE;
virtual bool RecvParentShmemForPool(Shmem& aEncodedBuffer) MOZ_OVERRIDE;
virtual bool AnswerNeedShmem(const uint32_t& aFrameBufferSize,
Shmem* aMem) MOZ_OVERRIDE;
virtual bool Recv__delete__() MOZ_OVERRIDE;
bool mCanSendMessages;
GMPParent* mPlugin;
GMPVideoDecoderCallback* mCallback;
GMPDecoderCallback* mCallback;
GMPVideoHostImpl mVideoHost;
};

View File

@ -1,34 +0,0 @@
/* -*- 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/. */
#ifndef GMPVideoDecoderProxy_h_
#define GMPVideoDecoderProxy_h_
#include "nsTArray.h"
#include "gmp-video-decode.h"
#include "gmp-video-frame-i420.h"
#include "gmp-video-frame-encoded.h"
// A proxy to GMPVideoDecoder in the child process.
// GMPVideoDecoderParent exposes this to users the GMP.
// This enables Gecko to pass nsTArrays to the child GMP and avoid
// an extra copy when doing so.
class GMPVideoDecoderProxy {
public:
virtual nsresult InitDecode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
GMPVideoDecoderCallback* aCallback,
int32_t aCoreCount) = 0;
virtual nsresult Decode(GMPVideoEncodedFrame* aInputFrame,
bool aMissingFrames,
GMPBufferType aBufferType,
const nsTArray<uint8_t>& aCodecSpecificInfo,
int64_t aRenderTimeMs = -1) = 0;
virtual nsresult Reset() = 0;
virtual nsresult Drain() = 0;
virtual nsresult DecodingComplete() = 0;
};
#endif

View File

@ -14,8 +14,8 @@ namespace gmp {
GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl(GMPVideoHostImpl* aHost)
: mEncodedWidth(0),
mEncodedHeight(0),
mTimeStamp(0ll),
mDuration(0ll),
mTimeStamp(0),
mCaptureTime_ms(0),
mFrameType(kGMPDeltaFrame),
mSize(0),
mCompleteFrame(false),
@ -29,8 +29,8 @@ GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl(const GMPVideoEncodedFrameDat
GMPVideoHostImpl* aHost)
: mEncodedWidth(aFrameData.mEncodedWidth()),
mEncodedHeight(aFrameData.mEncodedHeight()),
mTimeStamp(aFrameData.mTimestamp()),
mDuration(aFrameData.mDuration()),
mTimeStamp(aFrameData.mTimeStamp()),
mCaptureTime_ms(aFrameData.mCaptureTime_ms()),
mFrameType(static_cast<GMPVideoFrameType>(aFrameData.mFrameType())),
mSize(aFrameData.mSize()),
mCompleteFrame(aFrameData.mCompleteFrame()),
@ -49,12 +49,6 @@ GMPVideoEncodedFrameImpl::~GMPVideoEncodedFrameImpl()
}
}
const GMPEncryptedBufferData*
GMPVideoEncodedFrameImpl::GetDecryptionData() const
{
return nullptr;
}
GMPVideoFrameFormat
GMPVideoEncodedFrameImpl::GetFrameFormat()
{
@ -86,8 +80,8 @@ GMPVideoEncodedFrameImpl::RelinquishFrameData(GMPVideoEncodedFrameData& aFrameDa
{
aFrameData.mEncodedWidth() = mEncodedWidth;
aFrameData.mEncodedHeight() = mEncodedHeight;
aFrameData.mTimestamp() = mTimeStamp;
aFrameData.mDuration() = mDuration;
aFrameData.mTimeStamp() = mTimeStamp;
aFrameData.mCaptureTime_ms() = mCaptureTime_ms;
aFrameData.mFrameType() = mFrameType;
aFrameData.mSize() = mSize;
aFrameData.mCompleteFrame() = mCompleteFrame;
@ -105,37 +99,36 @@ void
GMPVideoEncodedFrameImpl::DestroyBuffer()
{
if (mHost && mBuffer.IsWritable()) {
mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPEncodedData, mBuffer);
mHost->SharedMemMgr()->MgrDeallocShmem(mBuffer);
}
mBuffer = ipc::Shmem();
}
GMPErr
GMPVideoErr
GMPVideoEncodedFrameImpl::CreateEmptyFrame(uint32_t aSize)
{
if (aSize == 0) {
DestroyBuffer();
} else if (aSize > AllocatedSize()) {
DestroyBuffer();
if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPEncodedData, aSize,
ipc::SharedMemory::TYPE_BASIC, &mBuffer) ||
DestroyBuffer();
if (aSize != 0) {
if (!mHost->SharedMemMgr()->MgrAllocShmem(aSize, ipc::SharedMemory::TYPE_BASIC, &mBuffer) ||
!Buffer()) {
return GMPAllocErr;
return GMPVideoAllocErr;
}
}
mSize = aSize;
return GMPNoErr;
return GMPVideoNoErr;
}
GMPErr
GMPVideoErr
GMPVideoEncodedFrameImpl::CopyFrame(const GMPVideoEncodedFrame& aFrame)
{
auto& f = static_cast<const GMPVideoEncodedFrameImpl&>(aFrame);
if (f.mSize != 0) {
GMPErr err = CreateEmptyFrame(f.mSize);
if (err != GMPNoErr) {
GMPVideoErr err = CreateEmptyFrame(f.mSize);
if (err != GMPVideoNoErr) {
return err;
}
memcpy(Buffer(), f.Buffer(), f.mSize);
@ -143,13 +136,13 @@ GMPVideoEncodedFrameImpl::CopyFrame(const GMPVideoEncodedFrame& aFrame)
mEncodedWidth = f.mEncodedWidth;
mEncodedHeight = f.mEncodedHeight;
mTimeStamp = f.mTimeStamp;
mDuration = f.mDuration;
mCaptureTime_ms = f.mCaptureTime_ms;
mFrameType = f.mFrameType;
mSize = f.mSize; // already set...
mSize = f.mSize;
mCompleteFrame = f.mCompleteFrame;
// Don't copy host, that should have been set properly on object creation via host.
return GMPNoErr;
return GMPVideoNoErr;
}
void
@ -177,27 +170,27 @@ GMPVideoEncodedFrameImpl::EncodedHeight()
}
void
GMPVideoEncodedFrameImpl::SetTimeStamp(uint64_t aTimeStamp)
GMPVideoEncodedFrameImpl::SetTimeStamp(uint32_t aTimeStamp)
{
mTimeStamp = aTimeStamp;
}
uint64_t
uint32_t
GMPVideoEncodedFrameImpl::TimeStamp()
{
return mTimeStamp;
}
void
GMPVideoEncodedFrameImpl::SetDuration(uint64_t aDuration)
GMPVideoEncodedFrameImpl::SetCaptureTime(int64_t aCaptureTime)
{
mDuration = aDuration;
mCaptureTime_ms = aCaptureTime;
}
uint64_t
GMPVideoEncodedFrameImpl::Duration() const
int64_t
GMPVideoEncodedFrameImpl::CaptureTime()
{
return mDuration;
return mCaptureTime_ms;
}
void
@ -224,8 +217,7 @@ GMPVideoEncodedFrameImpl::SetAllocatedSize(uint32_t aNewSize)
}
ipc::Shmem new_mem;
if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPEncodedData, aNewSize,
ipc::SharedMemory::TYPE_BASIC, &new_mem) ||
if (!mHost->SharedMemMgr()->MgrAllocShmem(aNewSize, ipc::SharedMemory::TYPE_BASIC, &new_mem) ||
!new_mem.get<uint8_t>()) {
return;
}

View File

@ -31,10 +31,9 @@
#ifndef GMPVideoEncodedFrameImpl_h_
#define GMPVideoEncodedFrameImpl_h_
#include "gmp-errors.h"
#include "gmp-video-errors.h"
#include "gmp-video-frame.h"
#include "gmp-video-frame-encoded.h"
#include "gmp-decryption.h"
#include "mozilla/ipc/Shmem.h"
namespace mozilla {
@ -64,21 +63,16 @@ public:
virtual void Destroy() MOZ_OVERRIDE;
// GMPVideoEncodedFrame
virtual GMPErr CreateEmptyFrame(uint32_t aSize) MOZ_OVERRIDE;
virtual GMPErr CopyFrame(const GMPVideoEncodedFrame& aFrame) MOZ_OVERRIDE;
virtual GMPVideoErr CreateEmptyFrame(uint32_t aSize) MOZ_OVERRIDE;
virtual GMPVideoErr CopyFrame(const GMPVideoEncodedFrame& aFrame) MOZ_OVERRIDE;
virtual void SetEncodedWidth(uint32_t aEncodedWidth) MOZ_OVERRIDE;
virtual uint32_t EncodedWidth() MOZ_OVERRIDE;
virtual void SetEncodedHeight(uint32_t aEncodedHeight) MOZ_OVERRIDE;
virtual uint32_t EncodedHeight() MOZ_OVERRIDE;
// Microseconds
virtual void SetTimeStamp(uint64_t aTimeStamp) MOZ_OVERRIDE;
virtual uint64_t TimeStamp() MOZ_OVERRIDE;
// Set frame duration (microseconds)
// NOTE: next-frame's Timestamp() != this-frame's TimeStamp()+Duration()
// depending on rounding to avoid having to track roundoff errors
// and dropped/missing frames(!) (which may leave a large gap)
virtual void SetDuration(uint64_t aDuration) MOZ_OVERRIDE;
virtual uint64_t Duration() const MOZ_OVERRIDE;
virtual void SetTimeStamp(uint32_t aTimeStamp) MOZ_OVERRIDE;
virtual uint32_t TimeStamp() MOZ_OVERRIDE;
virtual void SetCaptureTime(int64_t aCaptureTime) MOZ_OVERRIDE;
virtual int64_t CaptureTime() MOZ_OVERRIDE;
virtual void SetFrameType(GMPVideoFrameType aFrameType) MOZ_OVERRIDE;
virtual GMPVideoFrameType FrameType() MOZ_OVERRIDE;
virtual void SetAllocatedSize(uint32_t aNewSize) MOZ_OVERRIDE;
@ -89,15 +83,14 @@ public:
virtual bool CompleteFrame() MOZ_OVERRIDE;
virtual const uint8_t* Buffer() const MOZ_OVERRIDE;
virtual uint8_t* Buffer() MOZ_OVERRIDE;
virtual const GMPEncryptedBufferData* GetDecryptionData() const MOZ_OVERRIDE;
private:
void DestroyBuffer();
uint32_t mEncodedWidth;
uint32_t mEncodedHeight;
uint64_t mTimeStamp;
uint64_t mDuration;
uint32_t mTimeStamp;
int64_t mCaptureTime_ms;
GMPVideoFrameType mFrameType;
uint32_t mSize;
bool mCompleteFrame;

View File

@ -40,9 +40,7 @@ GMPVideoEncoderChild::Host()
void
GMPVideoEncoderChild::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
GMPBufferType aBufferType,
const uint8_t* aCodecSpecificInfo,
uint32_t aCodecSpecificInfoLength)
const GMPCodecSpecificInfo& aCodecSpecificInfo)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
@ -51,22 +49,31 @@ GMPVideoEncoderChild::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
GMPVideoEncodedFrameData frameData;
ef->RelinquishFrameData(frameData);
nsTArray<uint8_t> codecSpecific;
codecSpecific.AppendElements(aCodecSpecificInfo, aCodecSpecificInfoLength);
SendEncoded(frameData, aBufferType, codecSpecific);
SendEncoded(frameData, aCodecSpecificInfo);
aEncodedFrame->Destroy();
}
void
GMPVideoEncoderChild::CheckThread()
bool
GMPVideoEncoderChild::MgrAllocShmem(size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
return AllocShmem(aSize, aType, aMem);
}
bool
GMPVideoEncoderChild::MgrDeallocShmem(Shmem& aMem)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
return DeallocShmem(aMem);
}
bool
GMPVideoEncoderChild::RecvInitEncode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
const int32_t& aNumberOfCores,
const uint32_t& aMaxPayloadSize)
{
@ -75,20 +82,15 @@ GMPVideoEncoderChild::RecvInitEncode(const GMPVideoCodec& aCodecSettings,
}
// Ignore any return code. It is OK for this to fail without killing the process.
mVideoEncoder->InitEncode(aCodecSettings,
aCodecSpecific.Elements(),
aCodecSpecific.Length(),
this,
aNumberOfCores,
aMaxPayloadSize);
mVideoEncoder->InitEncode(aCodecSettings, this, aNumberOfCores, aMaxPayloadSize);
return true;
}
bool
GMPVideoEncoderChild::RecvEncode(const GMPVideoi420FrameData& aInputFrame,
const nsTArray<uint8_t>& aCodecSpecificInfo,
const nsTArray<GMPVideoFrameType>& aFrameTypes)
const GMPCodecSpecificInfo& aCodecSpecificInfo,
const InfallibleTArray<int>& aFrameTypes)
{
if (!mVideoEncoder) {
return false;
@ -96,23 +98,14 @@ GMPVideoEncoderChild::RecvEncode(const GMPVideoi420FrameData& aInputFrame,
auto f = new GMPVideoi420FrameImpl(aInputFrame, &mVideoHost);
// Ignore any return code. It is OK for this to fail without killing the process.
mVideoEncoder->Encode(f,
aCodecSpecificInfo.Elements(),
aCodecSpecificInfo.Length(),
aFrameTypes.Elements(),
aFrameTypes.Length());
return true;
}
bool
GMPVideoEncoderChild::RecvChildShmemForPool(Shmem& aEncodedBuffer)
{
if (aEncodedBuffer.IsWritable()) {
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPEncodedData,
aEncodedBuffer);
std::vector<GMPVideoFrameType> frameTypes(aFrameTypes.Length());
for (uint32_t i = 0; i < aFrameTypes.Length(); i++) {
frameTypes[i] = static_cast<GMPVideoFrameType>(aFrameTypes[i]);
}
// Ignore any return code. It is OK for this to fail without killing the process.
mVideoEncoder->Encode(f, aCodecSpecificInfo, frameTypes);
return true;
}

View File

@ -18,7 +18,7 @@ namespace gmp {
class GMPChild;
class GMPVideoEncoderChild : public PGMPVideoEncoderChild,
public GMPVideoEncoderCallback,
public GMPEncoderCallback,
public GMPSharedMemManager
{
public:
@ -28,45 +28,24 @@ public:
void Init(GMPVideoEncoder* aEncoder);
GMPVideoHostImpl& Host();
// GMPVideoEncoderCallback
// GMPEncoderCallback
virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame,
GMPBufferType aBufferType,
const uint8_t* aCodecSpecificInfo,
uint32_t aCodecSpecificInfoLength) MOZ_OVERRIDE;
const GMPCodecSpecificInfo& aCodecSpecificInfo) MOZ_OVERRIDE;
// GMPSharedMemManager
virtual void CheckThread();
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem)
{
#ifndef SHMEM_ALLOC_IN_CHILD
return CallNeedShmem(aSize, aMem);
#else
#ifdef GMP_SAFE_SHMEM
return AllocShmem(aSize, aType, aMem);
#else
return AllocUnsafeShmem(aSize, aType, aMem);
#endif
#endif
}
virtual void Dealloc(Shmem& aMem)
{
#ifndef SHMEM_ALLOC_IN_CHILD
SendParentShmemForPool(aMem);
#else
DeallocShmem(aMem);
#endif
}
virtual bool MgrAllocShmem(size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem) MOZ_OVERRIDE;
virtual bool MgrDeallocShmem(Shmem& aMem) MOZ_OVERRIDE;
private:
// PGMPVideoEncoderChild
virtual bool RecvInitEncode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
const int32_t& aNumberOfCores,
const uint32_t& aMaxPayloadSize) MOZ_OVERRIDE;
virtual bool RecvEncode(const GMPVideoi420FrameData& aInputFrame,
const nsTArray<uint8_t>& aCodecSpecificInfo,
const nsTArray<GMPVideoFrameType>& aFrameTypes) MOZ_OVERRIDE;
virtual bool RecvChildShmemForPool(Shmem& aEncodedBuffer) MOZ_OVERRIDE;
const GMPCodecSpecificInfo& aCodecSpecificInfo,
const InfallibleTArray<int>& aFrameTypes) MOZ_OVERRIDE;
virtual bool RecvSetChannelParameters(const uint32_t& aPacketLoss,
const uint32_t& aRTT) MOZ_OVERRIDE;
virtual bool RecvSetRates(const uint32_t& aNewBitRate,

View File

@ -43,43 +43,60 @@ GMPVideoEncoderParent::Host()
return mVideoHost;
}
GMPErr
bool
GMPVideoEncoderParent::MgrAllocShmem(size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem)
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
return AllocShmem(aSize, aType, aMem);
}
bool
GMPVideoEncoderParent::MgrDeallocShmem(Shmem& aMem)
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
return DeallocShmem(aMem);
}
GMPVideoErr
GMPVideoEncoderParent::InitEncode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
GMPVideoEncoderCallbackProxy* aCallback,
GMPEncoderCallback* aCallback,
int32_t aNumberOfCores,
uint32_t aMaxPayloadSize)
{
if (!mCanSendMessages) {
NS_WARNING("Trying to use an invalid GMP video encoder!");
return GMPGenericErr;
return GMPVideoGenericErr;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (!aCallback) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
mCallback = aCallback;
if (!SendInitEncode(aCodecSettings, aCodecSpecific, aNumberOfCores, aMaxPayloadSize)) {
return GMPGenericErr;
if (!SendInitEncode(aCodecSettings, aNumberOfCores, aMaxPayloadSize)) {
return GMPVideoGenericErr;
}
// Async IPC, we don't have access to a return value.
return GMPNoErr;
return GMPVideoNoErr;
}
GMPErr
GMPVideoErr
GMPVideoEncoderParent::Encode(GMPVideoi420Frame* aInputFrame,
const nsTArray<uint8_t>& aCodecSpecificInfo,
const nsTArray<GMPVideoFrameType>& aFrameTypes)
const GMPCodecSpecificInfo& aCodecSpecificInfo,
const std::vector<GMPVideoFrameType>& aFrameTypes)
{
nsAutoRef<GMPVideoi420Frame> frameRef(aInputFrame);
if (!mCanSendMessages) {
NS_WARNING("Trying to use an invalid GMP video encoder!");
return GMPGenericErr;
return GMPVideoGenericErr;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
@ -89,76 +106,74 @@ GMPVideoEncoderParent::Encode(GMPVideoi420Frame* aInputFrame,
GMPVideoi420FrameData frameData;
inputFrameImpl->InitFrameData(frameData);
// Very rough kill-switch if the plugin stops processing. If it's merely
// hung and continues, we'll come back to life eventually.
// 3* is because we're using 3 buffers per frame for i420 data for now.
if (NumInUse(kGMPFrameData) > 3*GMPSharedMemManager::kGMPBufLimit ||
NumInUse(kGMPEncodedData) > GMPSharedMemManager::kGMPBufLimit) {
return GMPGenericErr;
InfallibleTArray<int> frameTypes;
frameTypes.SetCapacity(aFrameTypes.size());
for (std::vector<int>::size_type i = 0; i != aFrameTypes.size(); i++) {
frameTypes.AppendElement(static_cast<int>(aFrameTypes[i]));
}
if (!SendEncode(frameData,
aCodecSpecificInfo,
aFrameTypes)) {
return GMPGenericErr;
frameTypes)) {
return GMPVideoGenericErr;
}
// Async IPC, we don't have access to a return value.
return GMPNoErr;
return GMPVideoNoErr;
}
GMPErr
GMPVideoErr
GMPVideoEncoderParent::SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT)
{
if (!mCanSendMessages) {
NS_WARNING("Trying to use an invalid GMP video encoder!");
return GMPGenericErr;
return GMPVideoGenericErr;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (!SendSetChannelParameters(aPacketLoss, aRTT)) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
// Async IPC, we don't have access to a return value.
return GMPNoErr;
return GMPVideoNoErr;
}
GMPErr
GMPVideoErr
GMPVideoEncoderParent::SetRates(uint32_t aNewBitRate, uint32_t aFrameRate)
{
if (!mCanSendMessages) {
NS_WARNING("Trying to use an invalid GMP video encoder!");
return GMPGenericErr;
return GMPVideoGenericErr;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (!SendSetRates(aNewBitRate, aFrameRate)) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
// Async IPC, we don't have access to a return value.
return GMPNoErr;
return GMPVideoNoErr;
}
GMPErr
GMPVideoErr
GMPVideoEncoderParent::SetPeriodicKeyFrames(bool aEnable)
{
if (!mCanSendMessages) {
NS_WARNING("Trying to use an invalid GMP video encoder!");
return GMPGenericErr;
return GMPVideoGenericErr;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (!SendSetPeriodicKeyFrames(aEnable)) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
// Async IPC, we don't have access to a return value.
return GMPNoErr;
return GMPVideoNoErr;
}
// Note: Consider keeping ActorDestroy sync'd up when making changes here.
@ -195,16 +210,9 @@ GMPVideoEncoderParent::ActorDestroy(ActorDestroyReason aWhy)
mVideoHost.ActorDestroyed();
}
void
GMPVideoEncoderParent::CheckThread()
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
}
bool
GMPVideoEncoderParent::RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame,
const GMPBufferType& aBufferType,
const nsTArray<uint8_t>& aCodecSpecificInfo)
const GMPCodecSpecificInfo& aCodecSpecificInfo)
{
if (!mCallback) {
return false;
@ -213,37 +221,8 @@ GMPVideoEncoderParent::RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame
auto f = new GMPVideoEncodedFrameImpl(aEncodedFrame, &mVideoHost);
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->Encoded(f, aBufferType, aCodecSpecificInfo);
mCallback->Encoded(f, aCodecSpecificInfo);
// Return SHM to sender to recycle
//SendEncodedReturn(aEncodedFrame, aCodecSpecificInfo);
return true;
}
bool
GMPVideoEncoderParent::RecvParentShmemForPool(Shmem& aFrameBuffer)
{
if (aFrameBuffer.IsWritable()) {
mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPFrameData,
aFrameBuffer);
}
return true;
}
bool
GMPVideoEncoderParent::AnswerNeedShmem(const uint32_t& aEncodedBufferSize,
Shmem* aMem)
{
ipc::Shmem mem;
if (!mVideoHost.SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPEncodedData,
aEncodedBufferSize,
ipc::SharedMemory::TYPE_BASIC, &mem))
{
return false;
}
*aMem = mem;
mem = ipc::Shmem();
return true;
}

View File

@ -12,14 +12,13 @@
#include "GMPMessageUtils.h"
#include "GMPSharedMemManager.h"
#include "GMPVideoHost.h"
#include "GMPVideoEncoderProxy.h"
namespace mozilla {
namespace gmp {
class GMPParent;
class GMPVideoEncoderParent : public GMPVideoEncoderProxy,
class GMPVideoEncoderParent : public GMPVideoEncoder,
public PGMPVideoEncoderParent,
public GMPSharedMemManager
{
@ -30,34 +29,24 @@ public:
GMPVideoHostImpl& Host();
// GMPVideoEncoderProxy
virtual GMPErr InitEncode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
GMPVideoEncoderCallbackProxy* aCallback,
int32_t aNumberOfCores,
uint32_t aMaxPayloadSize) MOZ_OVERRIDE;
virtual GMPErr Encode(GMPVideoi420Frame* aInputFrame,
const nsTArray<uint8_t>& aCodecSpecificInfo,
const nsTArray<GMPVideoFrameType>& aFrameTypes) MOZ_OVERRIDE;
virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) MOZ_OVERRIDE;
virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) MOZ_OVERRIDE;
virtual GMPErr SetPeriodicKeyFrames(bool aEnable) MOZ_OVERRIDE;
virtual void EncodingComplete() MOZ_OVERRIDE;
// GMPSharedMemManager
virtual void CheckThread();
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem)
{
#ifdef GMP_SAFE_SHMEM
return AllocShmem(aSize, aType, aMem);
#else
return AllocUnsafeShmem(aSize, aType, aMem);
#endif
}
virtual void Dealloc(Shmem& aMem)
{
DeallocShmem(aMem);
}
virtual bool MgrAllocShmem(size_t aSize,
ipc::Shmem::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aMem) MOZ_OVERRIDE;
virtual bool MgrDeallocShmem(Shmem& aMem) MOZ_OVERRIDE;
// GMPVideoEncoder
virtual GMPVideoErr InitEncode(const GMPVideoCodec& aCodecSettings,
GMPEncoderCallback* aCallback,
int32_t aNumberOfCores,
uint32_t aMaxPayloadSize) MOZ_OVERRIDE;
virtual GMPVideoErr Encode(GMPVideoi420Frame* aInputFrame,
const GMPCodecSpecificInfo& aCodecSpecificInfo,
const std::vector<GMPVideoFrameType>& aFrameTypes) MOZ_OVERRIDE;
virtual GMPVideoErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) MOZ_OVERRIDE;
virtual GMPVideoErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) MOZ_OVERRIDE;
virtual GMPVideoErr SetPeriodicKeyFrames(bool aEnable) MOZ_OVERRIDE;
virtual void EncodingComplete() MOZ_OVERRIDE;
private:
virtual ~GMPVideoEncoderParent();
@ -65,16 +54,12 @@ private:
// PGMPVideoEncoderParent
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame,
const GMPBufferType& aBufferType,
const nsTArray<uint8_t>& aCodecSpecificInfo) MOZ_OVERRIDE;
virtual bool RecvParentShmemForPool(Shmem& aFrameBuffer) MOZ_OVERRIDE;
virtual bool AnswerNeedShmem(const uint32_t& aEncodedBufferSize,
Shmem* aMem) MOZ_OVERRIDE;
const GMPCodecSpecificInfo& aCodecSpecificInfo) MOZ_OVERRIDE;
virtual bool Recv__delete__() MOZ_OVERRIDE;
bool mCanSendMessages;
GMPParent* mPlugin;
GMPVideoEncoderCallbackProxy* mCallback;
GMPEncoderCallback* mCallback;
GMPVideoHostImpl mVideoHost;
};

View File

@ -1,41 +0,0 @@
/* -*- 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/. */
#ifndef GMPVideoEncoderProxy_h_
#define GMPVideoEncoderProxy_h_
#include "nsTArray.h"
#include "gmp-video-encode.h"
#include "gmp-video-frame-i420.h"
#include "gmp-video-frame-encoded.h"
class GMPVideoEncoderCallbackProxy {
public:
virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame,
GMPBufferType aBufferType,
const nsTArray<uint8_t>& aCodecSpecificInfo) = 0;
};
// A proxy to GMPVideoEncoder in the child process.
// GMPVideoEncoderParent exposes this to users the GMP.
// This enables Gecko to pass nsTArrays to the child GMP and avoid
// an extra copy when doing so.
class GMPVideoEncoderProxy {
public:
virtual GMPErr InitEncode(const GMPVideoCodec& aCodecSettings,
const nsTArray<uint8_t>& aCodecSpecific,
GMPVideoEncoderCallbackProxy* aCallback,
int32_t aNumberOfCores,
uint32_t aMaxPayloadSize) = 0;
virtual GMPErr Encode(GMPVideoi420Frame* aInputFrame,
const nsTArray<uint8_t>& aCodecSpecificInfo,
const nsTArray<GMPVideoFrameType>& aFrameTypes) = 0;
virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0;
virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0;
virtual GMPErr SetPeriodicKeyFrames(bool aEnable) = 0;
virtual void EncodingComplete() = 0;
};
#endif // GMPVideoEncoderProxy_h_

View File

@ -20,41 +20,41 @@ GMPVideoHostImpl::~GMPVideoHostImpl()
{
}
GMPErr
GMPVideoErr
GMPVideoHostImpl::CreateFrame(GMPVideoFrameFormat aFormat, GMPVideoFrame** aFrame)
{
if (!mSharedMemMgr) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
if (!aFrame) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
*aFrame = nullptr;
switch (aFormat) {
case kGMPI420VideoFrame:
*aFrame = new GMPVideoi420FrameImpl(this);
return GMPNoErr;
return GMPVideoNoErr;
case kGMPEncodedVideoFrame:
*aFrame = new GMPVideoEncodedFrameImpl(this);
return GMPNoErr;
return GMPVideoNoErr;
default:
NS_NOTREACHED("Unknown frame format!");
}
return GMPGenericErr;
return GMPVideoGenericErr;
}
GMPErr
GMPVideoErr
GMPVideoHostImpl::CreatePlane(GMPPlane** aPlane)
{
if (!mSharedMemMgr) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
if (!aPlane) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
*aPlane = nullptr;
@ -62,7 +62,7 @@ GMPVideoHostImpl::CreatePlane(GMPPlane** aPlane)
*aPlane = p;
return GMPNoErr;
return GMPVideoNoErr;
}
GMPSharedMemManager*

View File

@ -35,8 +35,8 @@ public:
void EncodedFrameDestroyed(GMPVideoEncodedFrameImpl* aFrame);
// GMPVideoHost
virtual GMPErr CreateFrame(GMPVideoFrameFormat aFormat, GMPVideoFrame** aFrame) MOZ_OVERRIDE;
virtual GMPErr CreatePlane(GMPPlane** aPlane) MOZ_OVERRIDE;
virtual GMPVideoErr CreateFrame(GMPVideoFrameFormat aFormat, GMPVideoFrame** aFrame) MOZ_OVERRIDE;
virtual GMPVideoErr CreatePlane(GMPPlane** aPlane) MOZ_OVERRIDE;
private:
// All shared memory allocations have to be made by an IPDL actor.

View File

@ -73,21 +73,20 @@ GMPPlaneImpl::InitPlaneData(GMPPlaneData& aPlaneData)
return true;
}
GMPErr
GMPVideoErr
GMPPlaneImpl::MaybeResize(int32_t aNewSize) {
if (aNewSize <= AllocatedSize()) {
return GMPNoErr;
return GMPVideoNoErr;
}
if (!mHost) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
ipc::Shmem new_mem;
if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPFrameData, aNewSize,
ipc::SharedMemory::TYPE_BASIC, &new_mem) ||
if (!mHost->SharedMemMgr()->MgrAllocShmem(aNewSize, ipc::SharedMemory::TYPE_BASIC, &new_mem) ||
!new_mem.get<uint8_t>()) {
return GMPAllocErr;
return GMPVideoAllocErr;
}
if (mBuffer.IsReadable()) {
@ -98,43 +97,43 @@ GMPPlaneImpl::MaybeResize(int32_t aNewSize) {
mBuffer = new_mem;
return GMPNoErr;
return GMPVideoNoErr;
}
void
GMPPlaneImpl::DestroyBuffer()
{
if (mHost && mBuffer.IsWritable()) {
mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPFrameData, mBuffer);
mHost->SharedMemMgr()->MgrDeallocShmem(mBuffer);
}
mBuffer = ipc::Shmem();
}
GMPErr
GMPVideoErr
GMPPlaneImpl::CreateEmptyPlane(int32_t aAllocatedSize, int32_t aStride, int32_t aPlaneSize)
{
if (aAllocatedSize < 1 || aStride < 1 || aPlaneSize < 1) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
GMPErr err = MaybeResize(aAllocatedSize);
if (err != GMPNoErr) {
GMPVideoErr err = MaybeResize(aAllocatedSize);
if (err != GMPVideoNoErr) {
return err;
}
mSize = aPlaneSize;
mStride = aStride;
return GMPNoErr;
return GMPVideoNoErr;
}
GMPErr
GMPVideoErr
GMPPlaneImpl::Copy(const GMPPlane& aPlane)
{
auto& planeimpl = static_cast<const GMPPlaneImpl&>(aPlane);
GMPErr err = MaybeResize(planeimpl.mSize);
if (err != GMPNoErr) {
GMPVideoErr err = MaybeResize(planeimpl.mSize);
if (err != GMPVideoNoErr) {
return err;
}
@ -145,14 +144,14 @@ GMPPlaneImpl::Copy(const GMPPlane& aPlane)
mSize = planeimpl.mSize;
mStride = planeimpl.mStride;
return GMPNoErr;
return GMPVideoNoErr;
}
GMPErr
GMPVideoErr
GMPPlaneImpl::Copy(int32_t aSize, int32_t aStride, const uint8_t* aBuffer)
{
GMPErr err = MaybeResize(aSize);
if (err != GMPNoErr) {
GMPVideoErr err = MaybeResize(aSize);
if (err != GMPVideoNoErr) {
return err;
}
@ -163,7 +162,7 @@ GMPPlaneImpl::Copy(int32_t aSize, int32_t aStride, const uint8_t* aBuffer)
mSize = aSize;
mStride = aStride;
return GMPNoErr;
return GMPVideoNoErr;
}
void

View File

@ -34,13 +34,13 @@ public:
bool InitPlaneData(GMPPlaneData& aPlaneData);
// GMPPlane
virtual GMPErr CreateEmptyPlane(int32_t aAllocatedSize,
int32_t aStride,
int32_t aPlaneSize) MOZ_OVERRIDE;
virtual GMPErr Copy(const GMPPlane& aPlane) MOZ_OVERRIDE;
virtual GMPErr Copy(int32_t aSize,
int32_t aStride,
const uint8_t* aBuffer) MOZ_OVERRIDE;
virtual GMPVideoErr CreateEmptyPlane(int32_t aAllocatedSize,
int32_t aStride,
int32_t aPlaneSize) MOZ_OVERRIDE;
virtual GMPVideoErr Copy(const GMPPlane& aPlane) MOZ_OVERRIDE;
virtual GMPVideoErr Copy(int32_t aSize,
int32_t aStride,
const uint8_t* aBuffer) MOZ_OVERRIDE;
virtual void Swap(GMPPlane& aPlane) MOZ_OVERRIDE;
virtual int32_t AllocatedSize() const MOZ_OVERRIDE;
virtual void ResetSize() MOZ_OVERRIDE;
@ -51,7 +51,7 @@ public:
virtual void Destroy() MOZ_OVERRIDE;
private:
GMPErr MaybeResize(int32_t aNewSize);
GMPVideoErr MaybeResize(int32_t aNewSize);
void DestroyBuffer();
ipc::Shmem mBuffer;

View File

@ -15,8 +15,8 @@ GMPVideoi420FrameImpl::GMPVideoi420FrameImpl(GMPVideoHostImpl* aHost)
mVPlane(aHost),
mWidth(0),
mHeight(0),
mTimestamp(0ll),
mDuration(0ll)
mTimestamp(0),
mRenderTime_ms(0)
{
MOZ_ASSERT(aHost);
}
@ -29,7 +29,7 @@ GMPVideoi420FrameImpl::GMPVideoi420FrameImpl(const GMPVideoi420FrameData& aFrame
mWidth(aFrameData.mWidth()),
mHeight(aFrameData.mHeight()),
mTimestamp(aFrameData.mTimestamp()),
mDuration(aFrameData.mDuration())
mRenderTime_ms(aFrameData.mRenderTime_ms())
{
MOZ_ASSERT(aHost);
}
@ -47,7 +47,7 @@ GMPVideoi420FrameImpl::InitFrameData(GMPVideoi420FrameData& aFrameData)
aFrameData.mWidth() = mWidth;
aFrameData.mHeight() = mHeight;
aFrameData.mTimestamp() = mTimestamp;
aFrameData.mDuration() = mDuration;
aFrameData.mRenderTime_ms() = mRenderTime_ms;
return true;
}
@ -106,12 +106,12 @@ GMPVideoi420FrameImpl::GetPlane(GMPPlaneType aType) {
return nullptr;
}
GMPErr
GMPVideoErr
GMPVideoi420FrameImpl::CreateEmptyFrame(int32_t aWidth, int32_t aHeight,
int32_t aStride_y, int32_t aStride_u, int32_t aStride_v)
{
if (!CheckDimensions(aWidth, aHeight, aStride_y, aStride_u, aStride_v)) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
int32_t size_y = aStride_y * aHeight;
@ -119,28 +119,28 @@ GMPVideoi420FrameImpl::CreateEmptyFrame(int32_t aWidth, int32_t aHeight,
int32_t size_u = aStride_u * half_height;
int32_t size_v = aStride_v * half_height;
GMPErr err = mYPlane.CreateEmptyPlane(size_y, aStride_y, size_y);
if (err != GMPNoErr) {
GMPVideoErr err = mYPlane.CreateEmptyPlane(size_y, aStride_y, size_y);
if (err != GMPVideoNoErr) {
return err;
}
err = mUPlane.CreateEmptyPlane(size_u, aStride_u, size_u);
if (err != GMPNoErr) {
if (err != GMPVideoNoErr) {
return err;
}
err = mVPlane.CreateEmptyPlane(size_v, aStride_v, size_v);
if (err != GMPNoErr) {
if (err != GMPVideoNoErr) {
return err;
}
mWidth = aWidth;
mHeight = aHeight;
mTimestamp = 0ll;
mDuration = 0ll;
mTimestamp = 0;
mRenderTime_ms = 0;
return GMPNoErr;
return GMPVideoNoErr;
}
GMPErr
GMPVideoErr
GMPVideoi420FrameImpl::CreateFrame(int32_t aSize_y, const uint8_t* aBuffer_y,
int32_t aSize_u, const uint8_t* aBuffer_u,
int32_t aSize_v, const uint8_t* aBuffer_v,
@ -152,58 +152,58 @@ GMPVideoi420FrameImpl::CreateFrame(int32_t aSize_y, const uint8_t* aBuffer_y,
MOZ_ASSERT(aBuffer_v);
if (aSize_y < 1 || aSize_u < 1 || aSize_v < 1) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
if (!CheckDimensions(aWidth, aHeight, aStride_y, aStride_u, aStride_v)) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
GMPErr err = mYPlane.Copy(aSize_y, aStride_y, aBuffer_y);
if (err != GMPNoErr) {
GMPVideoErr err = mYPlane.Copy(aSize_y, aStride_y, aBuffer_y);
if (err != GMPVideoNoErr) {
return err;
}
err = mUPlane.Copy(aSize_u, aStride_u, aBuffer_u);
if (err != GMPNoErr) {
if (err != GMPVideoNoErr) {
return err;
}
err = mVPlane.Copy(aSize_v, aStride_v, aBuffer_v);
if (err != GMPNoErr) {
if (err != GMPVideoNoErr) {
return err;
}
mWidth = aWidth;
mHeight = aHeight;
return GMPNoErr;
return GMPVideoNoErr;
}
GMPErr
GMPVideoErr
GMPVideoi420FrameImpl::CopyFrame(const GMPVideoi420Frame& aFrame)
{
auto& f = static_cast<const GMPVideoi420FrameImpl&>(aFrame);
GMPErr err = mYPlane.Copy(f.mYPlane);
if (err != GMPNoErr) {
GMPVideoErr err = mYPlane.Copy(f.mYPlane);
if (err != GMPVideoNoErr) {
return err;
}
err = mUPlane.Copy(f.mUPlane);
if (err != GMPNoErr) {
if (err != GMPVideoNoErr) {
return err;
}
err = mVPlane.Copy(f.mVPlane);
if (err != GMPNoErr) {
if (err != GMPVideoNoErr) {
return err;
}
mWidth = f.mWidth;
mHeight = f.mHeight;
mTimestamp = f.mTimestamp;
mDuration = f.mDuration;
mRenderTime_ms = f.mRenderTime_ms;
return GMPNoErr;
return GMPVideoNoErr;
}
void
@ -216,7 +216,7 @@ GMPVideoi420FrameImpl::SwapFrame(GMPVideoi420Frame* aFrame)
std::swap(mWidth, f->mWidth);
std::swap(mHeight, f->mHeight);
std::swap(mTimestamp, f->mTimestamp);
std::swap(mDuration, f->mDuration);
std::swap(mRenderTime_ms, f->mRenderTime_ms);
}
uint8_t*
@ -259,28 +259,28 @@ GMPVideoi420FrameImpl::Stride(GMPPlaneType aType) const
return -1;
}
GMPErr
GMPVideoErr
GMPVideoi420FrameImpl::SetWidth(int32_t aWidth)
{
if (!CheckDimensions(aWidth, mHeight,
mYPlane.Stride(), mUPlane.Stride(),
mVPlane.Stride())) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
mWidth = aWidth;
return GMPNoErr;
return GMPVideoNoErr;
}
GMPErr
GMPVideoErr
GMPVideoi420FrameImpl::SetHeight(int32_t aHeight)
{
if (!CheckDimensions(mWidth, aHeight,
mYPlane.Stride(), mUPlane.Stride(),
mVPlane.Stride())) {
return GMPGenericErr;
return GMPVideoGenericErr;
}
mHeight = aHeight;
return GMPNoErr;
return GMPVideoNoErr;
}
int32_t
@ -296,27 +296,27 @@ GMPVideoi420FrameImpl::Height() const
}
void
GMPVideoi420FrameImpl::SetTimestamp(uint64_t aTimestamp)
GMPVideoi420FrameImpl::SetTimestamp(uint32_t aTimestamp)
{
mTimestamp = aTimestamp;
}
uint64_t
uint32_t
GMPVideoi420FrameImpl::Timestamp() const
{
return mTimestamp;
}
void
GMPVideoi420FrameImpl::SetDuration(uint64_t aDuration)
GMPVideoi420FrameImpl::SetRenderTime_ms(int64_t aRenderTime_ms)
{
mDuration = aDuration;
mRenderTime_ms = aRenderTime_ms;
}
uint64_t
GMPVideoi420FrameImpl::Duration() const
int64_t
GMPVideoi420FrameImpl::RenderTime_ms() const
{
return mDuration;
return mRenderTime_ms;
}
bool

View File

@ -32,33 +32,33 @@ public:
virtual void Destroy() MOZ_OVERRIDE;
// GMPVideoi420Frame
virtual GMPErr CreateEmptyFrame(int32_t aWidth,
virtual GMPVideoErr CreateEmptyFrame(int32_t aWidth,
int32_t aHeight,
int32_t aStride_y,
int32_t aStride_u,
int32_t aStride_v) MOZ_OVERRIDE;
virtual GMPVideoErr CreateFrame(int32_t aSize_y, const uint8_t* aBuffer_y,
int32_t aSize_u, const uint8_t* aBuffer_u,
int32_t aSize_v, const uint8_t* aBuffer_v,
int32_t aWidth,
int32_t aHeight,
int32_t aStride_y,
int32_t aStride_u,
int32_t aStride_v) MOZ_OVERRIDE;
virtual GMPErr CreateFrame(int32_t aSize_y, const uint8_t* aBuffer_y,
int32_t aSize_u, const uint8_t* aBuffer_u,
int32_t aSize_v, const uint8_t* aBuffer_v,
int32_t aWidth,
int32_t aHeight,
int32_t aStride_y,
int32_t aStride_u,
int32_t aStride_v) MOZ_OVERRIDE;
virtual GMPErr CopyFrame(const GMPVideoi420Frame& aFrame) MOZ_OVERRIDE;
virtual GMPVideoErr CopyFrame(const GMPVideoi420Frame& aFrame) MOZ_OVERRIDE;
virtual void SwapFrame(GMPVideoi420Frame* aFrame) MOZ_OVERRIDE;
virtual uint8_t* Buffer(GMPPlaneType aType) MOZ_OVERRIDE;
virtual const uint8_t* Buffer(GMPPlaneType aType) const MOZ_OVERRIDE;
virtual int32_t AllocatedSize(GMPPlaneType aType) const MOZ_OVERRIDE;
virtual int32_t Stride(GMPPlaneType aType) const MOZ_OVERRIDE;
virtual GMPErr SetWidth(int32_t aWidth) MOZ_OVERRIDE;
virtual GMPErr SetHeight(int32_t aHeight) MOZ_OVERRIDE;
virtual GMPVideoErr SetWidth(int32_t aWidth) MOZ_OVERRIDE;
virtual GMPVideoErr SetHeight(int32_t aHeight) MOZ_OVERRIDE;
virtual int32_t Width() const MOZ_OVERRIDE;
virtual int32_t Height() const MOZ_OVERRIDE;
virtual void SetTimestamp(uint64_t aTimestamp) MOZ_OVERRIDE;
virtual uint64_t Timestamp() const MOZ_OVERRIDE;
virtual void SetDuration(uint64_t aDuration) MOZ_OVERRIDE;
virtual uint64_t Duration() const MOZ_OVERRIDE;
virtual void SetTimestamp(uint32_t aTimestamp) MOZ_OVERRIDE;
virtual uint32_t Timestamp() const MOZ_OVERRIDE;
virtual void SetRenderTime_ms(int64_t aRenderTime_ms) MOZ_OVERRIDE;
virtual int64_t RenderTime_ms() const MOZ_OVERRIDE;
virtual bool IsZeroSize() const MOZ_OVERRIDE;
virtual void ResetSize() MOZ_OVERRIDE;
@ -71,8 +71,8 @@ private:
GMPPlaneImpl mVPlane;
int32_t mWidth;
int32_t mHeight;
uint64_t mTimestamp;
uint64_t mDuration;
uint32_t mTimestamp;
int64_t mRenderTime_ms;
};
} // namespace gmp

View File

@ -9,13 +9,13 @@ include protocol PGMPVideoEncoder;
namespace mozilla {
namespace gmp {
intr protocol PGMP
async protocol PGMP
{
manages PGMPVideoDecoder;
manages PGMPVideoEncoder;
child:
async PGMPVideoDecoder();
async PGMPVideoEncoder();
PGMPVideoDecoder();
PGMPVideoEncoder();
};
} // namespace gmp

View File

@ -7,42 +7,32 @@ include protocol PGMP;
include GMPTypes;
using GMPVideoCodec from "gmp-video-codec.h";
using GMPBufferType from "gmp-video-codec.h";
using GMPCodecSpecificInfo from "gmp-video-codec.h";
include "GMPMessageUtils.h";
namespace mozilla {
namespace gmp {
intr protocol PGMPVideoDecoder
async protocol PGMPVideoDecoder
{
manager PGMP;
child:
async InitDecode(GMPVideoCodec aCodecSettings,
uint8_t[] aCodecSpecific,
int32_t aCoreCount);
async Decode(GMPVideoEncodedFrameData aInputFrame,
bool aMissingFrames,
GMPBufferType aBufferType,
uint8_t[] aCodecSpecificInfo,
int64_t aRenderTimeMs);
async Reset();
async Drain();
async DecodingComplete();
async ChildShmemForPool(Shmem aFrameBuffer);
InitDecode(GMPVideoCodec aCodecSettings,
int32_t aCoreCount);
Decode(GMPVideoEncodedFrameData aInputFrame,
bool aMissingFrames,
GMPCodecSpecificInfo aCodecSpecificInfo,
int64_t aRenderTimeMs);
Reset();
Drain();
DecodingComplete();
parent:
async __delete__();
async Decoded(GMPVideoi420FrameData aDecodedFrame);
async ReceivedDecodedReferenceFrame(uint64_t aPictureId);
async ReceivedDecodedFrame(uint64_t aPictureId);
async InputDataExhausted();
async DrainComplete();
async ResetComplete();
async ParentShmemForPool(Shmem aEncodedBuffer);
// MUST be intr - if sync and we create a new Shmem, when the returned
// Shmem is received in the Child it will fail to Deserialize
intr NeedShmem(uint32_t aFrameBufferSize) returns (Shmem aMem);
__delete__();
Decoded(GMPVideoi420FrameData aDecodedFrame);
ReceivedDecodedReferenceFrame(uint64_t aPictureId);
ReceivedDecodedFrame(uint64_t aPictureId);
InputDataExhausted();
};
} // namespace gmp

View File

@ -7,40 +7,32 @@ include protocol PGMP;
include GMPTypes;
using GMPVideoCodec from "gmp-video-codec.h";
using GMPVideoFrameType from "gmp-video-frame-encoded.h";
using GMPBufferType from "gmp-video-codec.h";
using GMPCodecSpecificInfo from "gmp-video-codec.h";
include "GMPMessageUtils.h";
namespace mozilla {
namespace gmp {
intr protocol PGMPVideoEncoder
async protocol PGMPVideoEncoder
{
manager PGMP;
child:
async InitEncode(GMPVideoCodec aCodecSettings,
uint8_t[] aCodecSpecific,
int32_t aNumberOfCores,
uint32_t aMaxPayloadSize);
async Encode(GMPVideoi420FrameData aInputFrame,
uint8_t[] aCodecSpecificInfo,
GMPVideoFrameType[] aFrameTypes);
async SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT);
async SetRates(uint32_t aNewBitRate, uint32_t aFrameRate);
async SetPeriodicKeyFrames(bool aEnable);
async EncodingComplete();
async ChildShmemForPool(Shmem aEncodedBuffer);
InitEncode(GMPVideoCodec aCodecSettings,
int32_t aNumberOfCores,
uint32_t aMaxPayloadSize);
Encode(GMPVideoi420FrameData aInputFrame,
GMPCodecSpecificInfo aCodecSpecificInfo,
int[] aFrameTypes);
SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT);
SetRates(uint32_t aNewBitRate, uint32_t aFrameRate);
SetPeriodicKeyFrames(bool aEnable);
EncodingComplete();
parent:
async __delete__();
async Encoded(GMPVideoEncodedFrameData aEncodedFrame,
GMPBufferType aBufferType,
uint8_t[] aCodecSpecificInfo);
async ParentShmemForPool(Shmem aFrameBuffer);
// MUST be intr - if sync and we create a new Shmem, when the returned
// Shmem is received in the Child it will fail to Deserialize
intr NeedShmem(uint32_t aEncodedBufferSize) returns (Shmem aMem);
__delete__();
Encoded(GMPVideoEncodedFrameData aEncodedFrame,
GMPCodecSpecificInfo aCodecSpecificInfo);
};
} // namespace gmp

View File

@ -1,52 +0,0 @@
/*
* Copyright 2013, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GMP_ASYNC_SHUTDOWN_H_
#define GMP_ASYNC_SHUTDOWN_H_
// API exposed by the plugin library to manage asynchronous shutdown.
// Some plugins require special cleanup which may need to make calls
// to host services and wait for async responses.
//
// To enable a plugins to block shutdown until its async shutdown is
// complete, implement the GMPAsyncShutdown interface and return it when
// your plugin's GMPGetAPI function is called with "async-shutdown".
// When your GMPAsyncShutdown's BeginShutdown() implementation is called
// by the GMP host, you should initate your async shutdown process.
// Once you have completed shutdown, call the ShutdownComplete() function
// of the GMPAsyncShutdownHost that is passed as the host argument to the
// GMPGetAPI() call.
//
// Note: Your GMP's GMPShutdown function will still be called after your
// call to ShutdownComplete().
//
// API name: "async-shutdown"
// Host API: GMPAsyncShutdownHost
class GMPAsyncShutdown {
public:
virtual ~GMPAsyncShutdown() {}
virtual void BeginShutdown() = 0;
};
class GMPAsyncShutdownHost {
public:
virtual ~GMPAsyncShutdownHost() {}
virtual void ShutdownComplete() = 0;
};
#endif // GMP_ASYNC_SHUTDOWN_H_

View File

@ -1,43 +0,0 @@
/*
* Copyright 2013, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GMP_AUDIO_CODEC_h_
#define GMP_AUDIO_CODEC_h_
#include <stdint.h>
enum GMPAudioCodecType
{
kGMPAudioCodecAAC,
kGMPAudioCodecVorbis,
kGMPAudioCodecInvalid // Should always be last.
};
struct GMPAudioCodec
{
GMPAudioCodecType mCodecType;
uint32_t mChannelCount;
uint32_t mBitsPerChannel;
uint32_t mSamplesPerSecond;
// Codec extra data, such as vorbis setup header, or
// AAC AudioSpecificConfig.
// These are null/0 if not externally negotiated
const uint8_t* mExtraData;
size_t mExtraDataLen;
};
#endif // GMP_AUDIO_CODEC_h_

View File

@ -1,72 +0,0 @@
/*
* Copyright 2013, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GMP_AUDIO_DECODE_h_
#define GMP_AUDIO_DECODE_h_
#include "gmp-errors.h"
#include "gmp-audio-samples.h"
#include "gmp-audio-codec.h"
#include <stdint.h>
// ALL METHODS MUST BE CALLED ON THE MAIN THREAD
class GMPAudioDecoderCallback
{
public:
virtual ~GMPAudioDecoderCallback() {}
virtual void Decoded(GMPAudioSamples* aDecodedSamples) = 0;
virtual void InputDataExhausted() = 0;
virtual void DrainComplete() = 0;
virtual void ResetComplete() = 0;
};
// ALL METHODS MUST BE CALLED ON THE MAIN THREAD
class GMPAudioDecoder
{
public:
virtual ~GMPAudioDecoder() {}
// aCallback: Subclass should retain reference to it until DecodingComplete
// is called. Do not attempt to delete it, host retains ownership.
// TODO: Pass AudioHost so decoder can create GMPAudioEncodedFrame objects?
virtual GMPErr InitDecode(const GMPAudioCodec& aCodecSettings,
GMPAudioDecoderCallback* aCallback) = 0;
// Decode encoded audio frames (as a part of an audio stream). The decoded
// frames must be returned to the user through the decode complete callback.
virtual GMPErr Decode(GMPAudioSamples* aEncodedSamples) = 0;
// Reset decoder state and prepare for a new call to Decode(...).
// Flushes the decoder pipeline.
// The decoder should enqueue a task to run ResetComplete() on the main
// thread once the reset has finished.
virtual GMPErr Reset() = 0;
// Output decoded frames for any data in the pipeline, regardless of ordering.
// All remaining decoded frames should be immediately returned via callback.
// The decoder should enqueue a task to run DrainComplete() on the main
// thread once the reset has finished.
virtual GMPErr Drain() = 0;
// May free decoder memory.
virtual void DecodingComplete() = 0;
};
#endif // GMP_VIDEO_DECODE_h_

View File

@ -1,32 +0,0 @@
/*
* Copyright 2013, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GMP_AUDIO_HOST_h_
#define GMP_AUDIO_HOST_h_
#include "gmp-errors.h"
#include "gmp-audio-samples.h"
class GMPAudioHost
{
public:
// Construct various Audio API objects. Host does not retain reference,
// caller is owner and responsible for deleting.
virtual GMPErr CreateSamples(GMPAudioFormat aFormat,
GMPAudioSamples** aSamples) = 0;
};
#endif // GMP_AUDIO_HOST_h_

View File

@ -1,57 +0,0 @@
/*
* Copyright 2013, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GMP_AUDIO_FRAME_h_
#define GMP_AUDIO_FRAME_h_
#include <stdint.h>
#include "gmp-errors.h"
#include "gmp-decryption.h"
enum GMPAudioFormat
{
kGMPAudioEncodedSamples, // Raw compressed data, i.e. an AAC/Vorbis packet.
kGMPAudioIS16Samples, // Interleaved int16_t PCM samples.
kGMPAudioSamplesFormatInvalid // Should always be last.
};
class GMPAudioSamples {
public:
// The format of the buffer.
virtual GMPAudioFormat GetFormat() = 0;
virtual void Destroy() = 0;
// MAIN THREAD ONLY
// Buffer size must be exactly what's required to contain all samples in
// the buffer; every byte is assumed to be part of a sample.
virtual GMPErr SetBufferSize(uint32_t aSize) = 0;
// Size of the buffer in bytes.
virtual uint32_t Size() = 0;
// Timestamps are in microseconds, and are the playback start time of the
// first sample in the buffer.
virtual void SetTimeStamp(uint64_t aTimeStamp) = 0;
virtual uint64_t TimeStamp() = 0;
virtual const uint8_t* Buffer() const = 0;
virtual uint8_t* Buffer() = 0;
// Get data describing how this frame is encrypted, or nullptr if the
// buffer is not encrypted.
virtual const GMPEncryptedBufferData* GetDecryptionData() const = 0;
};
#endif // GMP_AUDIO_FRAME_h_

View File

@ -1,208 +0,0 @@
/*
* Copyright 2013, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GMP_DECRYPTION_h_
#define GMP_DECRYPTION_h_
#include "gmp-platform.h"
class GMPEncryptedBufferData {
public:
// Key ID to identify the decryption key.
virtual const uint8_t* KeyId() const = 0;
// Size (in bytes) of |KeyId()|.
virtual uint32_t KeyIdSize() const = 0;
// Initialization vector.
virtual const uint8_t* IV() const = 0;
// Size (in bytes) of |IV|.
virtual uint32_t IVSize() const = 0;
// Number of enties returned by ClearBytes and CipherBytes().
virtual uint32_t NumSubsamples() const = 0;
virtual const uint32_t* ClearBytes() const = 0;
virtual const uint32_t* CipherBytes() const = 0;
};
// These match to the DOMException codes as per:
// http://www.w3.org/TR/dom/#domexception
enum GMPDOMException {
kGMPNoModificationAllowedError = 7,
kGMPNotFoundError = 8,
kGMPNotSupportedError = 9,
kGMPInvalidStateError = 11,
kGMPSyntaxError = 12,
kGMPInvalidModificationError = 13,
kGMPInvalidAccessError = 15,
kGMPSecurityError = 18,
kGMPAbortError = 20,
kGMPQuotaExceededError = 22,
kGMPTimeoutError = 23
};
// Time in milliseconds, as offset from epoch, 1 Jan 1970.
typedef int64_t GMPTimestamp;
class GMPDecryptorCallback {
public:
// Resolves a promise for a session created or loaded.
// Passes the session id to be exposed to JavaScript.
// Must be called before OnSessionMessage().
// aSessionId must be null terminated.
virtual void OnResolveNewSessionPromise(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) = 0;
// Called to resolve a specified promise with "undefined".
virtual void OnResolvePromise(uint32_t aPromiseId) = 0;
// Called to reject a promise with a DOMException.
// aMessage is logged to the WebConsole.
// aMessage is optional, but if present must be null terminated.
virtual void OnRejectPromise(uint32_t aPromiseId,
GMPDOMException aException,
const char* aMessage,
uint32_t aMessageLength) = 0;
// Called by the CDM when it has a message for session |session_id|.
// Length parameters should not include null termination.
// aSessionId must be null terminated.
virtual void OnSessionMessage(const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aMessage,
uint32_t aMessageLength,
const char* aDestinationURL,
uint32_t aDestinationURLLength) = 0;
// aSessionId must be null terminated.
virtual void OnExpirationChange(const char* aSessionId,
uint32_t aSessionIdLength,
GMPTimestamp aExpiryTime) = 0;
// Called by the GMP when a session is closed. All file IO
// that a session requires should be complete before calling this.
// aSessionId must be null terminated.
virtual void OnSessionClosed(const char* aSessionId,
uint32_t aSessionIdLength) = 0;
// Called by the GMP when an error occurs in a session.
// aSessionId must be null terminated.
// aMessage is logged to the WebConsole.
// aMessage is optional, but if present must be null terminated.
virtual void OnSessionError(const char* aSessionId,
uint32_t aSessionIdLength,
GMPDOMException aException,
uint32_t aSystemCode,
const char* aMessage,
uint32_t aMessageLength) = 0;
virtual void OnKeyIdUsable(const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aKeyId,
uint32_t aKeyIdLength) = 0;
// Marks a key as no longer usable.
// Note: Keys are assumed to be not usable when a session is closed or removed.
virtual void OnKeyIdNotUsable(const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aKeyId,
uint32_t aKeyIdLength) = 0;
};
// Host interface, passed to GetAPIFunc(), with "decrypt".
class GMPDecryptorHost {
public:
// Returns an origin specific string uniquely identifying the device.
// The node id contains a random component, and is consistent between
// plugin instantiations, unless the user clears it.
// Different origins have different node ids.
// The node id pointer returned here remains valid for the until shutdown
// begins.
// *aOutNodeId is null terminated.
virtual void GetNodeId(const char** aOutNodeId,
uint32_t* aOutNodeIdLength) = 0;
virtual void GetSandboxVoucher(const uint8_t** aVoucher,
uint8_t* aVoucherLength) = 0;
virtual void GetPluginVoucher(const uint8_t** aVoucher,
uint8_t* aVoucherLength) = 0;
};
enum GMPSessionType {
kGMPTemporySession = 0,
kGMPPersistentSession = 1
};
// API exposed by plugin library to manage decryption sessions.
// When the Host requests this by calling GMPGetAPIFunc().
//
// API name: "eme-decrypt".
// Host API: GMPDecryptorHost
class GMPDecryptor {
public:
// Sets the callback to use with the decryptor to return results
// to Gecko.
virtual void Init(GMPDecryptorCallback* aCallback) = 0;
// Requests the creation of a session given |aType| and |aInitData|.
// Decryptor should callback GMPDecryptorCallback::OnSessionCreated()
// with the web session ID on success, or OnSessionError() on failure,
// and then call OnSessionReady() once all keys for that session are
// available.
virtual void CreateSession(uint32_t aPromiseId,
const char* aInitDataType,
uint32_t aInitDataTypeSize,
const uint8_t* aInitData,
uint32_t aInitDataSize,
GMPSessionType aSessionType) = 0;
// Loads a previously loaded persistent session.
virtual void LoadSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) = 0;
// Updates the session with |aResponse|.
virtual void UpdateSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aResponse,
uint32_t aResponseSize) = 0;
// Releases the resources (keys) for the specified session.
virtual void CloseSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) = 0;
// Removes the resources (keys) for the specified session.
virtual void RemoveSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) = 0;
// Resolve/reject promise on completion.
virtual void SetServerCertificate(uint32_t aPromiseId,
const uint8_t* aServerCert,
uint32_t aServerCertSize) = 0;
};
#endif // GMP_DECRYPTION_h_

View File

@ -35,16 +35,7 @@
typedef enum {
GMPNoErr = 0,
GMPGenericErr = 1,
GMPClosedErr = 2,
GMPAllocErr = 3,
GMPNotImplementedErr = 4,
GMPNotClosedErr = 5,
GMPQuotaExceededErr = 6,
GMPLastErr // Placeholder, must be last. This enum's values must remain consecutive!
GMPGenericErr = 1
} GMPErr;
#define GMP_SUCCEEDED(x) ((x) == GMPNoErr)
#define GMP_FAILED(x) ((x) != GMPNoErr)
#endif // GMP_ERRORS_h_

View File

@ -34,14 +34,12 @@
#define GMP_PLATFORM_h_
#include "gmp-errors.h"
#include "gmp-storage.h"
#include <stdint.h>
/* Platform helper API. */
class GMPTask {
public:
virtual void Destroy() = 0;
virtual ~GMPTask() {}
virtual void Run() = 0;
};
@ -60,20 +58,10 @@ public:
virtual void Release() = 0;
};
// Time is defined as the number of milliseconds since the
// Epoch (00:00:00 UTC, January 1, 1970).
typedef int64_t GMPTimestamp;
typedef GMPErr (*GMPCreateThreadPtr)(GMPThread** aThread);
typedef GMPErr (*GMPRunOnMainThreadPtr)(GMPTask* aTask);
typedef GMPErr (*GMPSyncRunOnMainThreadPtr)(GMPTask* aTask);
typedef GMPErr (*GMPCreateMutexPtr)(GMPMutex** aMutex);
typedef GMPErr (*GMPCreateRecordPtr)(const char* aRecordName,
uint32_t aRecordNameSize,
GMPRecord** aOutRecord,
GMPRecordClient* aClient);
typedef GMPErr (*GMPSetTimerOnMainThreadPtr)(GMPTask* aTask, int64_t aTimeoutMS);
typedef GMPErr (*GMPGetCurrentTimePtr)(GMPTimestamp* aOutTime);
struct GMPPlatformAPI {
// Increment the version when things change. Can only add to the struct,
@ -86,9 +74,6 @@ struct GMPPlatformAPI {
GMPRunOnMainThreadPtr runonmainthread;
GMPSyncRunOnMainThreadPtr syncrunonmainthread;
GMPCreateMutexPtr createmutex;
GMPCreateRecordPtr createrecord;
GMPSetTimerOnMainThreadPtr settimer;
GMPGetCurrentTimePtr getcurrenttime;
};
#endif // GMP_PLATFORM_h_

View File

@ -1,90 +0,0 @@
/*
* Copyright 2013, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GMP_STORAGE_h_
#define GMP_STORAGE_h_
#include "gmp-errors.h"
#include <stdint.h>
// Provides basic per-origin storage for CDMs. GMPRecord instances can be
// retrieved by calling GMPPlatformAPI->openstorage. Multiple GMPRecord
// can be open at once. This interface is asynchronous, with results
// being returned via callbacks to the GMPRecordClient pointer provided
// to the GMPPlatformAPI->openstorage call, on the main thread.
class GMPRecord {
public:
// Opens the record. Calls OnOpenComplete() once the record is open.
// Note: OnReadComplete() is only called if this returns GMPNoErr.
virtual GMPErr Open() = 0;
// Reads the entire contents of the file, and calls
// GMPRecordClient::OnReadComplete() once the operation is complete.
// Note: OnReadComplete() is only called if this returns GMPNoErr.
virtual GMPErr Read() = 0;
// Writes aDataSize bytes of aData into the file, overwritting the contents
// of the file. Overwriting with 0 bytes "deletes" the file.
// Write 0 bytes to "delete" a file.
// Note: OnWriteComplete is only called if this returns GMPNoErr.
virtual GMPErr Write(const uint8_t* aData, uint32_t aDataSize) = 0;
// Closes a file. File must not be used after this is called. Cancels all
// callbacks.
virtual GMPErr Close() = 0;
virtual ~GMPRecord() {}
};
// Callback object that receives the results of GMPRecord calls. Callbacks
// run asynchronously to the GMPRecord call, on the main thread.
class GMPRecordClient {
public:
// Response to a GMPRecord::Open() call with the open |status|.
// aStatus values:
// - GMPNoErr - File opened successfully. File may be empty.
// - GMPFileInUse - There file is in use by another client.
// - GMPGenericErr - Unspecified error.
// Do not use the GMPRecord if aStatus is not GMPNoErr.
virtual void OnOpenComplete(GMPErr aStatus) = 0;
// Response to a GMPRecord::Read() call, where aData is the file contents,
// of length aDataSize.
// aData is only valid for the duration of the call to OnReadComplete.
// Copy it if you want to hang onto it!
// aStatus values:
// - GMPNoErr - File contents read successfully, aDataSize 0 means file
// is empty.
// - GMPFileInUse - There are other operations or clients in use on this file.
// - GMPGenericErr - Unspecified error.
// Do not continue to use the GMPRecord if aStatus is not GMPNoErr.
virtual void OnReadComplete(GMPErr aStatus,
const uint8_t* aData,
uint32_t aDataSize) = 0;
// Response to a GMPRecord::Write() call.
// - GMPNoErr - File contents written successfully.
// - GMPFileInUse - There are other operations or clients in use on this file.
// - GMPGenericErr - Unspecified error. File should be regarded as corrupt.
// Do not continue to use the GMPRecord if aStatus is not GMPNoErr.
virtual void OnWriteComplete(GMPErr aStatus) = 0;
virtual ~GMPRecordClient() {}
};
#endif // GMP_STORAGE_h_

View File

@ -72,50 +72,39 @@ struct GMPVideoCodecVP8
bool mDenoisingOn;
bool mErrorConcealmentOn;
bool mAutomaticResizeOn;
bool mFrameDroppingOn;
int32_t mKeyFrameInterval;
};
// H264 specific
// Needs to match a binary spec for this structure.
// Note: the mSPS at the end of this structure is variable length.
struct GMPVideoCodecH264AVCC
{
uint8_t mVersion; // == 0x01
uint8_t mProfile; // these 3 are profile_level_id
uint8_t mConstraints;
uint8_t mLevel;
uint8_t mLengthSizeMinusOne; // lower 2 bits (== GMPBufferType-1). Top 6 reserved (1's)
// SPS/PPS will not generally be present for interactive use unless SDP
// parameter-sets are used.
uint8_t mNumSPS; // lower 5 bits; top 5 reserved (1's)
/*** uint8_t mSPS[]; (Not defined due to compiler warnings and warnings-as-errors ...) **/
// Following mNumSPS is a variable number of bytes, which is the SPS and PPS.
// Each SPS == 16 bit size, ("N"), then "N" bytes,
// then uint8_t mNumPPS, then each PPS == 16 bit size ("N"), then "N" bytes.
};
// Codec specific data for H.264 decoding/encoding.
// Cast the "aCodecSpecific" parameter of GMPVideoDecoder::InitDecode() and
// GMPVideoEncoder::InitEncode() to this structure.
struct GMPVideoCodecH264
{
uint8_t mProfile;
uint8_t mConstraints;
uint8_t mLevel;
uint8_t mPacketizationMode; // 0 or 1
struct GMPVideoCodecH264AVCC mAVCC; // holds a variable-sized struct GMPVideoCodecH264AVCC mAVCC;
bool mFrameDroppingOn;
int32_t mKeyFrameInterval;
// These are null/0 if not externally negotiated
const uint8_t* mSPSData;
size_t mSPSLen;
const uint8_t* mPPSData;
size_t mPPSLen;
};
enum GMPVideoCodecType
{
kGMPVideoCodecVP8,
// Encoded frames are in AVCC format; NAL length field of 4 bytes, followed
// by frame data. May be multiple NALUs per sample. Codec specific extra data
// is the AVCC extra data (in AVCC format).
kGMPVideoCodecH264,
kGMPVideoCodecInvalid // Should always be last.
};
union GMPVideoCodecUnion
{
GMPVideoCodecVP8 mVP8;
GMPVideoCodecH264 mH264;
};
// Simulcast is when the same stream is encoded multiple times with different
// settings such as resolution.
struct GMPSimulcastStream
@ -132,19 +121,11 @@ struct GMPSimulcastStream
enum GMPVideoCodecMode {
kGMPRealtimeVideo,
kGMPScreensharing,
kGMPStreamingVideo,
kGMPCodecModeInvalid // Should always be last.
};
enum GMPApiVersion {
kGMPVersion32 = 1, // leveraging that V32 had mCodecType first, and only supported H264
kGMPVersion33 = 33,
};
struct GMPVideoCodec
{
uint32_t mGMPApiVersion;
GMPVideoCodecType mCodecType;
char mPLName[kGMPPayloadNameSize]; // Must be NULL-terminated!
uint32_t mPLType;
@ -157,8 +138,7 @@ struct GMPVideoCodec
uint32_t mMinBitrate; // kilobits/sec.
uint32_t mMaxFramerate;
bool mFrameDroppingOn;
int32_t mKeyFrameInterval;
GMPVideoCodecUnion mCodecSpecific;
uint32_t mQPMax;
uint32_t mNumberOfSimulcastStreams;
@ -177,7 +157,6 @@ enum GMPBufferType {
GMP_BufferLength16,
GMP_BufferLength24,
GMP_BufferLength32,
GMP_BufferInvalid,
};
struct GMPCodecSpecificInfoGeneric {
@ -209,7 +188,6 @@ union GMPCodecSpecificInfoUnion
{
GMPCodecSpecificInfoGeneric mGeneric;
GMPCodecSpecificInfoVP8 mVP8;
GMPCodecSpecificInfoH264 mH264;
};
// Note: if any pointers are added to this struct or its sub-structs, it

View File

@ -34,17 +34,17 @@
#ifndef GMP_VIDEO_DECODE_h_
#define GMP_VIDEO_DECODE_h_
#include "gmp-errors.h"
#include "gmp-video-errors.h"
#include "gmp-video-frame-i420.h"
#include "gmp-video-frame-encoded.h"
#include "gmp-video-codec.h"
#include <stdint.h>
// ALL METHODS MUST BE CALLED ON THE MAIN THREAD
class GMPVideoDecoderCallback
class GMPDecoderCallback
{
public:
virtual ~GMPVideoDecoderCallback() {}
virtual ~GMPDecoderCallback() {}
virtual void Decoded(GMPVideoi420Frame* aDecodedFrame) = 0;
@ -53,10 +53,6 @@ public:
virtual void ReceivedDecodedFrame(const uint64_t aPictureId) = 0;
virtual void InputDataExhausted() = 0;
virtual void DrainComplete() = 0;
virtual void ResetComplete() = 0;
};
// ALL METHODS MUST BE CALLED ON THE MAIN THREAD
@ -65,50 +61,37 @@ class GMPVideoDecoder
public:
virtual ~GMPVideoDecoder() {}
// - aCodecSettings: Details of decoder to create.
// - aCodecSpecific: codec specific data, cast to a GMPVideoCodecXXX struct
// to get codec specific config data.
// - aCodecSpecificLength: number of bytes in aCodecSpecific.
// - aCallback: Subclass should retain reference to it until DecodingComplete
// is called. Do not attempt to delete it, host retains ownership.
// aCoreCount: number of CPU cores.
virtual GMPErr InitDecode(const GMPVideoCodec& aCodecSettings,
const uint8_t* aCodecSpecific,
uint32_t aCodecSpecificLength,
GMPVideoDecoderCallback* aCallback,
int32_t aCoreCount) = 0;
// aCallback: Subclass should retain reference to it until DecodingComplete
// is called. Do not attempt to delete it, host retains ownership.
virtual GMPVideoErr InitDecode(const GMPVideoCodec& aCodecSettings,
GMPDecoderCallback* aCallback,
int32_t aCoreCount) = 0;
// Decode encoded frame (as a part of a video stream). The decoded frame
// will be returned to the user through the decode complete callback.
//
// - aInputFrame: Frame to decode. Call Destroy() on frame when it's decoded.
// - aMissingFrames: True if one or more frames have been lost since the
// previous decode call.
// - aBufferType : type of frame to encode
// - aCodecSpecificInfo : codec specific data, pointer to a
// GMPCodecSpecificInfo structure appropriate for
// this codec type.
// - aCodecSpecificInfoLength : number of bytes in aCodecSpecificInfo
// - renderTimeMs : System time to render in milliseconds. Only used by
// decoders with internal rendering.
virtual GMPErr Decode(GMPVideoEncodedFrame* aInputFrame,
bool aMissingFrames,
GMPBufferType aBufferType,
const uint8_t* aCodecSpecificInfo,
uint32_t aCodecSpecificInfoLength,
int64_t aRenderTimeMs = -1) = 0;
// inputFrame: Frame to decode.
//
// missingFrames: True if one or more frames have been lost since the previous decode call.
//
// fragmentation: Specifies where the encoded frame can be split into separate fragments.
// The meaning of fragment is codec specific, but often means that each
// fragment is decodable by itself.
//
// codecSpecificInfo: Codec-specific data
//
// renderTimeMs : System time to render in milliseconds. Only used by decoders with internal
// rendering.
virtual GMPVideoErr Decode(GMPVideoEncodedFrame* aInputFrame,
bool aMissingFrames,
const GMPCodecSpecificInfo& aCodecSpecificInfo,
int64_t aRenderTimeMs = -1) = 0;
// Reset decoder state and prepare for a new call to Decode(...).
// Flushes the decoder pipeline.
// The decoder should enqueue a task to run ResetComplete() on the main
// thread once the reset has finished.
virtual GMPErr Reset() = 0;
// Reset decoder state and prepare for a new call to Decode(...). Flushes the decoder pipeline.
virtual GMPVideoErr Reset() = 0;
// Output decoded frames for any data in the pipeline, regardless of ordering.
// All remaining decoded frames should be immediately returned via callback.
// The decoder should enqueue a task to run DrainComplete() on the main
// thread once the reset has finished.
virtual GMPErr Drain() = 0;
virtual GMPVideoErr Drain() = 0;
// May free decoder memory.
virtual void DecodingComplete() = 0;

View File

@ -37,21 +37,19 @@
#include <vector>
#include <stdint.h>
#include "gmp-errors.h"
#include "gmp-video-errors.h"
#include "gmp-video-frame-i420.h"
#include "gmp-video-frame-encoded.h"
#include "gmp-video-codec.h"
// ALL METHODS MUST BE CALLED ON THE MAIN THREAD
class GMPVideoEncoderCallback
class GMPEncoderCallback
{
public:
virtual ~GMPVideoEncoderCallback() {}
virtual ~GMPEncoderCallback() {}
virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame,
GMPBufferType aBufferType,
const uint8_t* aCodecSpecificInfo,
uint32_t aCodecSpecificInfoLength) = 0;
const GMPCodecSpecificInfo& aCodecSpecificInfo) = 0;
};
// ALL METHODS MUST BE CALLED ON THE MAIN THREAD
@ -64,38 +62,26 @@ public:
//
// Input:
// - codecSettings : Codec settings
// - aCodecSpecific : codec specific data, pointer to a
// GMPCodecSpecific structure appropriate for
// this codec type.
// - aCodecSpecificLength : number of bytes in aCodecSpecific
// - aCallback: Subclass should retain reference to it until EncodingComplete
// is called. Do not attempt to delete it, host retains ownership.
// - aNnumberOfCores : Number of cores available for the encoder
// - aMaxPayloadSize : The maximum size each payload is allowed
// - numberOfCores : Number of cores available for the encoder
// - maxPayloadSize : The maximum size each payload is allowed
// to have. Usually MTU - overhead.
virtual GMPErr InitEncode(const GMPVideoCodec& aCodecSettings,
const uint8_t* aCodecSpecific,
uint32_t aCodecSpecificLength,
GMPVideoEncoderCallback* aCallback,
int32_t aNumberOfCores,
uint32_t aMaxPayloadSize) = 0;
virtual GMPVideoErr InitEncode(const GMPVideoCodec& aCodecSettings,
GMPEncoderCallback* aCallback,
int32_t aNumberOfCores,
uint32_t aMaxPayloadSize) = 0;
// Encode an I420 frame (as a part of a video stream). The encoded frame
// will be returned to the user through the encode complete callback.
//
// Input:
// - aInputFrame : Frame to be encoded
// - aCodecSpecificInfo : codec specific data, pointer to a
// GMPCodecSpecificInfo structure appropriate for
// this codec type.
// - aCodecSpecificInfoLength : number of bytes in aCodecSpecific
// - aFrameTypes : The frame type to encode
// - aFrameTypesLength : The number of elements in aFrameTypes array.
virtual GMPErr Encode(GMPVideoi420Frame* aInputFrame,
const uint8_t* aCodecSpecificInfo,
uint32_t aCodecSpecificInfoLength,
const GMPVideoFrameType* aFrameTypes,
uint32_t aFrameTypesLength) = 0;
// - inputFrame : Frame to be encoded
// - codecSpecificInfo : Pointer to codec specific data
// - frame_types : The frame type to encode
virtual GMPVideoErr Encode(GMPVideoi420Frame* aInputFrame,
const GMPCodecSpecificInfo& aCodecSpecificInfo,
const std::vector<GMPVideoFrameType>& aFrameTypes) = 0;
// Inform the encoder about the packet loss and round trip time on the
// network used to decide the best pattern and signaling.
@ -103,19 +89,19 @@ public:
// - packetLoss : Fraction lost (loss rate in percent =
// 100 * packetLoss / 255)
// - rtt : Round-trip time in milliseconds
virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0;
virtual GMPVideoErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0;
// Inform the encoder about the new target bit rate.
//
// - newBitRate : New target bit rate
// - frameRate : The target frame rate
virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0;
virtual GMPVideoErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0;
// Use this function to enable or disable periodic key frames. Can be useful for codecs
// which have other ways of stopping error propagation.
//
// - enable : Enable or disable periodic key frames
virtual GMPErr SetPeriodicKeyFrames(bool aEnable) = 0;
virtual GMPVideoErr SetPeriodicKeyFrames(bool aEnable) = 0;
// May free Encoder memory.
virtual void EncodingComplete() = 0;

View File

@ -0,0 +1,43 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* Copyright (c) 2011, The WebRTC project authors. All rights reserved.
* Copyright (c) 2014, Mozilla
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
** Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
** Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
** Neither the name of Google nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GMP_VIDEO_ERRORS_h_
#define GMP_VIDEO_ERRORS_h_
enum GMPVideoErr {
GMPVideoNoErr = 0,
GMPVideoGenericErr = 1,
GMPVideoAllocErr = 2
};
#endif // GMP_VIDEO_ERRORS_h_

View File

@ -35,8 +35,6 @@
#define GMP_VIDEO_FRAME_ENCODED_h_
#include <stdint.h>
#include "gmp-decryption.h"
#include "gmp-video-frame.h"
enum GMPVideoFrameType
{
@ -60,22 +58,17 @@ class GMPVideoEncodedFrame : public GMPVideoFrame
{
public:
// MAIN THREAD ONLY
virtual GMPErr CreateEmptyFrame(uint32_t aSize) = 0;
virtual GMPVideoErr CreateEmptyFrame(uint32_t aSize) = 0;
// MAIN THREAD ONLY
virtual GMPErr CopyFrame(const GMPVideoEncodedFrame& aVideoFrame) = 0;
virtual GMPVideoErr CopyFrame(const GMPVideoEncodedFrame& aVideoFrame) = 0;
virtual void SetEncodedWidth(uint32_t aEncodedWidth) = 0;
virtual uint32_t EncodedWidth() = 0;
virtual void SetEncodedHeight(uint32_t aEncodedHeight) = 0;
virtual uint32_t EncodedHeight() = 0;
// Microseconds
virtual void SetTimeStamp(uint64_t aTimeStamp) = 0;
virtual uint64_t TimeStamp() = 0;
// Set frame duration (microseconds)
// NOTE: next-frame's Timestamp() != this-frame's TimeStamp()+Duration()
// depending on rounding to avoid having to track roundoff errors
// and dropped/missing frames(!) (which may leave a large gap)
virtual void SetDuration(uint64_t aDuration) = 0;
virtual uint64_t Duration() const = 0;
virtual void SetTimeStamp(uint32_t aTimeStamp) = 0;
virtual uint32_t TimeStamp() = 0;
virtual void SetCaptureTime(int64_t aCaptureTime) = 0;
virtual int64_t CaptureTime() = 0;
virtual void SetFrameType(GMPVideoFrameType aFrameType) = 0;
virtual GMPVideoFrameType FrameType() = 0;
virtual void SetAllocatedSize(uint32_t aNewSize) = 0;
@ -86,9 +79,6 @@ public:
virtual bool CompleteFrame() = 0;
virtual const uint8_t* Buffer() const = 0;
virtual uint8_t* Buffer() = 0;
// Get data describing how this frame is encrypted, or nullptr if the
// frame is not encrypted.
virtual const GMPEncryptedBufferData* GetDecryptionData() const = 0;
};
#endif // GMP_VIDEO_FRAME_ENCODED_h_

View File

@ -34,7 +34,7 @@
#ifndef GMP_VIDEO_FRAME_I420_h_
#define GMP_VIDEO_FRAME_I420_h_
#include "gmp-errors.h"
#include "gmp-video-errors.h"
#include "gmp-video-frame.h"
#include "gmp-video-plane.h"
@ -63,22 +63,22 @@ public:
// on set dimensions - height and plane stride.
// If required size is bigger than the allocated one, new buffers of adequate
// size will be allocated.
virtual GMPErr CreateEmptyFrame(int32_t aWidth, int32_t aHeight,
int32_t aStride_y, int32_t aStride_u, int32_t aStride_v) = 0;
virtual GMPVideoErr CreateEmptyFrame(int32_t aWidth, int32_t aHeight,
int32_t aStride_y, int32_t aStride_u, int32_t aStride_v) = 0;
// MAIN THREAD ONLY
// CreateFrame: Sets the frame's members and buffers. If required size is
// bigger than allocated one, new buffers of adequate size will be allocated.
virtual GMPErr CreateFrame(int32_t aSize_y, const uint8_t* aBuffer_y,
int32_t aSize_u, const uint8_t* aBuffer_u,
int32_t aSize_v, const uint8_t* aBuffer_v,
int32_t aWidth, int32_t aHeight,
int32_t aStride_y, int32_t aStride_u, int32_t aStride_v) = 0;
virtual GMPVideoErr CreateFrame(int32_t aSize_y, const uint8_t* aBuffer_y,
int32_t aSize_u, const uint8_t* aBuffer_u,
int32_t aSize_v, const uint8_t* aBuffer_v,
int32_t aWidth, int32_t aHeight,
int32_t aStride_y, int32_t aStride_u, int32_t aStride_v) = 0;
// MAIN THREAD ONLY
// Copy frame: If required size is bigger than allocated one, new buffers of
// adequate size will be allocated.
virtual GMPErr CopyFrame(const GMPVideoi420Frame& aVideoFrame) = 0;
virtual GMPVideoErr CopyFrame(const GMPVideoi420Frame& aVideoFrame) = 0;
// Swap Frame.
virtual void SwapFrame(GMPVideoi420Frame* aVideoFrame) = 0;
@ -96,10 +96,10 @@ public:
virtual int32_t Stride(GMPPlaneType aType) const = 0;
// Set frame width.
virtual GMPErr SetWidth(int32_t aWidth) = 0;
virtual GMPVideoErr SetWidth(int32_t aWidth) = 0;
// Set frame height.
virtual GMPErr SetHeight(int32_t aHeight) = 0;
virtual GMPVideoErr SetHeight(int32_t aHeight) = 0;
// Get frame width.
virtual int32_t Width() const = 0;
@ -107,20 +107,17 @@ public:
// Get frame height.
virtual int32_t Height() const = 0;
// Set frame timestamp (microseconds)
virtual void SetTimestamp(uint64_t aTimestamp) = 0;
// Set frame timestamp (90kHz).
virtual void SetTimestamp(uint32_t aTimestamp) = 0;
// Get frame timestamp (microseconds)
virtual uint64_t Timestamp() const = 0;
// Get frame timestamp (90kHz).
virtual uint32_t Timestamp() const = 0;
// Set frame duration (microseconds)
// NOTE: next-frame's Timestamp() != this-frame's TimeStamp()+Duration()
// depending on rounding to avoid having to track roundoff errors
// and dropped/missing frames(!) (which may leave a large gap)
virtual void SetDuration(uint64_t aDuration) = 0;
// Set render time in miliseconds.
virtual void SetRenderTime_ms(int64_t aRenderTime_ms) = 0;
// Get frame duration (microseconds)
virtual uint64_t Duration() const = 0;
// Get render time in miliseconds.
virtual int64_t RenderTime_ms() const = 0;
// Return true if underlying plane buffers are of zero size, false if not.
virtual bool IsZeroSize() const = 0;

View File

@ -34,6 +34,7 @@
#ifndef GMP_VIDEO_FRAME_h_
#define GMP_VIDEO_FRAME_h_
#include "gmp-video-errors.h"
#include "gmp-video-plane.h"
enum GMPVideoFrameFormat {

View File

@ -34,7 +34,7 @@
#ifndef GMP_VIDEO_HOST_h_
#define GMP_VIDEO_HOST_h_
#include "gmp-errors.h"
#include "gmp-video-errors.h"
#include "gmp-video-frame-i420.h"
#include "gmp-video-frame-encoded.h"
#include "gmp-video-codec.h"
@ -44,8 +44,8 @@ class GMPVideoHost
public:
// Construct various video API objects. Host does not retain reference,
// caller is owner and responsible for deleting.
virtual GMPErr CreateFrame(GMPVideoFrameFormat aFormat, GMPVideoFrame** aFrame) = 0;
virtual GMPErr CreatePlane(GMPPlane** aPlane) = 0;
virtual GMPVideoErr CreateFrame(GMPVideoFrameFormat aFormat, GMPVideoFrame** aFrame) = 0;
virtual GMPVideoErr CreatePlane(GMPPlane** aPlane) = 0;
};
#endif // GMP_VIDEO_HOST_h_

View File

@ -34,7 +34,7 @@
#ifndef GMP_VIDEO_PLANE_h_
#define GMP_VIDEO_PLANE_h_
#include "gmp-errors.h"
#include "gmp-video-errors.h"
#include <stdint.h>
// The implementation backing this interface uses shared memory for the
@ -52,18 +52,18 @@ public:
// CreateEmptyPlane - set allocated size, actual plane size and stride:
// If current size is smaller than current size, then a buffer of sufficient
// size will be allocated.
virtual GMPErr CreateEmptyPlane(int32_t aAllocatedSize,
int32_t aStride,
int32_t aPlaneSize) = 0;
virtual GMPVideoErr CreateEmptyPlane(int32_t aAllocatedSize,
int32_t aStride,
int32_t aPlaneSize) = 0;
// MAIN THREAD ONLY
// Copy the entire plane data.
virtual GMPErr Copy(const GMPPlane& aPlane) = 0;
virtual GMPVideoErr Copy(const GMPPlane& aPlane) = 0;
// MAIN THREAD ONLY
// Copy buffer: If current size is smaller
// than current size, then a buffer of sufficient size will be allocated.
virtual GMPErr Copy(int32_t aSize, int32_t aStride, const uint8_t* aBuffer) = 0;
virtual GMPVideoErr Copy(int32_t aSize, int32_t aStride, const uint8_t* aBuffer) = 0;
// Swap plane data.
virtual void Swap(GMPPlane& aPlane) = 0;

View File

@ -11,19 +11,13 @@ XPIDL_SOURCES += [
]
EXPORTS += [
'gmp-api/gmp-async-shutdown.h',
'gmp-api/gmp-audio-codec.h',
'gmp-api/gmp-audio-decode.h',
'gmp-api/gmp-audio-host.h',
'gmp-api/gmp-audio-samples.h',
'gmp-api/gmp-decryption.h',
'gmp-api/gmp-entrypoints.h',
'gmp-api/gmp-errors.h',
'gmp-api/gmp-platform.h',
'gmp-api/gmp-storage.h',
'gmp-api/gmp-video-codec.h',
'gmp-api/gmp-video-decode.h',
'gmp-api/gmp-video-encode.h',
'gmp-api/gmp-video-errors.h',
'gmp-api/gmp-video-frame-encoded.h',
'gmp-api/gmp-video-frame-i420.h',
'gmp-api/gmp-video-frame.h',
@ -39,11 +33,9 @@ EXPORTS += [
'GMPSharedMemManager.h',
'GMPVideoDecoderChild.h',
'GMPVideoDecoderParent.h',
'GMPVideoDecoderProxy.h',
'GMPVideoEncodedFrameImpl.h',
'GMPVideoEncoderChild.h',
'GMPVideoEncoderParent.h',
'GMPVideoEncoderProxy.h',
'GMPVideoHost.h',
'GMPVideoi420FrameImpl.h',
'GMPVideoPlaneImpl.h',
@ -56,7 +48,6 @@ UNIFIED_SOURCES += [
'GMPProcessChild.cpp',
'GMPProcessParent.cpp',
'GMPService.cpp',
'GMPSharedMemManager.cpp',
'GMPVideoDecoderChild.cpp',
'GMPVideoDecoderParent.cpp',
'GMPVideoEncodedFrameImpl.cpp',
@ -79,9 +70,6 @@ LIBRARY_NAME = 'mozgmp'
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
NO_VISIBILITY_FLAGS = True
# comment this out to use Unsafe Shmem for more performance
DEFINES['GMP_SAFE_SHMEM'] = True
FAIL_ON_WARNINGS = True
include('/ipc/chromium/chromium-config.mozbuild')

View File

@ -10,18 +10,18 @@
%{C++
#include "nsTArray.h"
#include "nsStringGlue.h"
class GMPVideoDecoderProxy;
class GMPVideoEncoderProxy;
class GMPVideoDecoder;
class GMPVideoEncoder;
class GMPVideoHost;
%}
[ptr] native GMPVideoDecoderProxy(GMPVideoDecoderProxy);
[ptr] native GMPVideoEncoderProxy(GMPVideoEncoderProxy);
[ptr] native GMPVideoDecoder(GMPVideoDecoder);
[ptr] native GMPVideoEncoder(GMPVideoEncoder);
[ptr] native GMPVideoHost(GMPVideoHost);
[ptr] native MessageLoop(MessageLoop);
[ptr] native TagArray(nsTArray<nsCString>);
[scriptable, uuid(7cef50ca-7a0f-41f2-9560-47abf709f0d7)]
[scriptable, uuid(63fc797f-9d01-43f4-8b93-5b1fe713c2f8)]
interface mozIGeckoMediaPluginService : nsISupports
{
/**
@ -36,9 +36,9 @@ interface mozIGeckoMediaPluginService : nsISupports
* Callable only on GMP thread.
*/
[noscript]
GMPVideoDecoderProxy getGMPVideoDecoder(in TagArray tags,
[optional] in AString origin,
out GMPVideoHost outVideoHost);
GMPVideoDecoder getGMPVideoDecoder(in TagArray tags,
[optional] in AString origin,
out GMPVideoHost outVideoHost);
/**
* Get a video encoder that supports the specified tags.
@ -47,9 +47,9 @@ interface mozIGeckoMediaPluginService : nsISupports
* Callable only on GMP thread.
*/
[noscript]
GMPVideoEncoderProxy getGMPVideoEncoder(in TagArray tags,
[optional] in AString origin,
out GMPVideoHost outVideoHost);
GMPVideoEncoder getGMPVideoEncoder(in TagArray tags,
[optional] in AString origin,
out GMPVideoHost outVideoHost);
/**
* Add a directory to scan for gecko media plugins.

View File

@ -14,8 +14,6 @@
#include "mozIGeckoMediaPluginService.h"
#include "nsServiceManagerUtils.h"
#include "GMPVideoDecoderProxy.h"
#include "GMPVideoEncoderProxy.h"
#include "gmp-video-host.h"
#include "gmp-video-frame-i420.h"
@ -25,26 +23,6 @@
namespace mozilla {
#ifdef LOG
#undef LOG
#endif
#ifdef PR_LOGGING
PRLogModuleInfo*
GetGMPLog()
{
static PRLogModuleInfo *sLog;
if (!sLog)
sLog = PR_NewLogModule("GMP");
return sLog;
}
#define LOGD(msg) PR_LOG(GetGMPLog(), PR_LOG_DEBUG, msg)
#define LOG(level, msg) PR_LOG(GetGMPLog(), (level), msg)
#else
#define LOGD(msg)
#define LOG(leve, msg)
#endif
// Encoder.
WebrtcGmpVideoEncoder::WebrtcGmpVideoEncoder()
: mGMPThread(nullptr)
@ -143,7 +121,7 @@ WebrtcGmpVideoEncoder::InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
uint32_t aMaxPayloadSize)
{
GMPVideoHost* host = nullptr;
GMPVideoEncoderProxy* gmp = nullptr;
GMPVideoEncoder* gmp = nullptr;
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("vp8"));
@ -166,7 +144,6 @@ WebrtcGmpVideoEncoder::InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
GMPVideoCodec codec;
memset(&codec, 0, sizeof(codec));
codec.mGMPApiVersion = 33;
codec.mWidth = aCodecSettings->width;
codec.mHeight = aCodecSettings->height;
codec.mStartBitrate = aCodecSettings->startBitrate;
@ -174,12 +151,8 @@ WebrtcGmpVideoEncoder::InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
codec.mMaxBitrate = aCodecSettings->maxBitrate;
codec.mMaxFramerate = aCodecSettings->maxFramerate;
// Pass dummy codecSpecific data for now...
nsTArray<uint8_t> codecSpecific;
// H.264 mode 1 only supported so far
GMPErr err = mGMP->InitEncode(codec, codecSpecific, this, 1, 256000 /*aMaxPayloadSize*/);
if (err != GMPNoErr) {
GMPVideoErr err = mGMP->InitEncode(codec, this, 1, aMaxPayloadSize);
if (err != GMPVideoNoErr) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
@ -215,8 +188,8 @@ WebrtcGmpVideoEncoder::Encode_g(const webrtc::I420VideoFrame* aInputImage,
MOZ_ASSERT(mGMP);
GMPVideoFrame* ftmp = nullptr;
GMPErr err = mHost->CreateFrame(kGMPI420VideoFrame, &ftmp);
if (err != GMPNoErr) {
GMPVideoErr err = mHost->CreateFrame(kGMPI420VideoFrame, &ftmp);
if (err != GMPVideoNoErr) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
GMPVideoi420Frame* frame = static_cast<GMPVideoi420Frame*>(ftmp);
@ -232,20 +205,17 @@ WebrtcGmpVideoEncoder::Encode_g(const webrtc::I420VideoFrame* aInputImage,
aInputImage->stride(webrtc::kYPlane),
aInputImage->stride(webrtc::kUPlane),
aInputImage->stride(webrtc::kVPlane));
if (err != GMPNoErr) {
if (err != GMPVideoNoErr) {
return err;
}
frame->SetTimestamp((aInputImage->timestamp() * 1000ll)/90); // note: rounds down!
//frame->SetDuration(1000000ll/30); // XXX base duration on measured current FPS - or don't bother
frame->SetTimestamp(aInputImage->timestamp());
frame->SetRenderTime_ms(aInputImage->render_time_ms());
// Bug XXXXXX: Set codecSpecific info
GMPCodecSpecificInfo info;
memset(&info, 0, sizeof(info));
info.mCodecType = kGMPVideoCodecH264;
nsTArray<uint8_t> codecSpecificInfo;
codecSpecificInfo.AppendElements((uint8_t*)&info, sizeof(GMPCodecSpecificInfo));
nsTArray<GMPVideoFrameType> gmp_frame_types;
std::vector<GMPVideoFrameType> gmp_frame_types;
for (auto it = aFrameTypes->begin(); it != aFrameTypes->end(); ++it) {
GMPVideoFrameType ft;
@ -254,12 +224,11 @@ WebrtcGmpVideoEncoder::Encode_g(const webrtc::I420VideoFrame* aInputImage,
return ret;
}
gmp_frame_types.AppendElement(ft);
gmp_frame_types.push_back(ft);
}
LOGD(("GMP Encode: %llu", (aInputImage->timestamp() * 1000ll)/90));
err = mGMP->Encode(frame, codecSpecificInfo, gmp_frame_types);
if (err != GMPNoErr) {
err = mGMP->Encode(frame, info, gmp_frame_types);
if (err != GMPVideoNoErr) {
return err;
}
@ -306,27 +275,104 @@ int32_t
WebrtcGmpVideoEncoder::SetRates_g(uint32_t aNewBitRate, uint32_t aFrameRate)
{
MOZ_ASSERT(mGMP);
GMPErr err = mGMP->SetRates(aNewBitRate, aFrameRate);
if (err != GMPNoErr) {
GMPVideoErr err = mGMP->SetRates(aNewBitRate, aFrameRate);
if (err != GMPVideoNoErr) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
return WEBRTC_VIDEO_CODEC_OK;
}
// GMPVideoEncoderCallback virtual functions.
#define GMP_ENCODE_HAS_START_CODES 1
#ifdef GMP_ENCODE_HAS_START_CODES
// Temporary until inside-sandbox-code switches from start codes to the API here
static int GetNextNALUnit(const uint8_t **aData,
const uint8_t *aEnd, // at first byte past end
size_t *aNalSize)
{
const uint8_t *data = *aData;
uint8_t zeros = 0;
MOZ_ASSERT(data);
// Don't assume we start with a start code (paranoia)
while (data < aEnd) {
if (*data == 0) {
zeros++;
if (zeros > 3) {
// internal format error; keep going anyways
zeros = 3;
}
} else {
if (*data == 0x01) {
if (zeros >= 2) {
// Found start code 0x000001 or 0x00000001
MOZ_ASSERT(zeros == 3); // current temp code only handles 4-byte codes
// now find the length of the NAL
*aData = ++data; // start of actual data
while (data < aEnd) {
if (*data == 0) {
zeros++;
if (zeros > 3) {
// internal format error; keep going anyways
zeros = 3;
}
} else {
if (*data == 0x01) {
if (zeros >= 2) {
// Found start code 0x000001 or 0x00000001
*aNalSize = (data - *aData) - zeros;
return 0;
}
}
zeros = 0;
}
data++;
}
// NAL ends at the end of the buffer
*aNalSize = (data - *aData);
return 0;
}
}
zeros = 0;
}
data++;
}
return -1; // no nals
}
#endif
// GMPEncoderCallback virtual functions.
void
WebrtcGmpVideoEncoder::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
GMPBufferType aBufferType,
const nsTArray<uint8_t>& aCodecSpecificInfo)
const GMPCodecSpecificInfo& aCodecSpecificInfo)
{
if (mCallback) { // paranoia
webrtc::VideoFrameType ft;
GmpFrameTypeToWebrtcFrameType(aEncodedFrame->FrameType(), &ft);
uint32_t timestamp = (aEncodedFrame->TimeStamp() * 90ll + 999)/1000;
GMPBufferType type = aCodecSpecificInfo.mBufferType;
LOGD(("GMP Encoded: %llu, type %d, len %d", aEncodedFrame->TimeStamp(), aBufferType,
aEncodedFrame->Size()));
#ifdef GMP_ENCODE_HAS_START_CODES
{
// This code will be removed when the code inside the plugin is updated
// Break input encoded data into NALUs and convert to length+data format
const uint8_t* data = aEncodedFrame->Buffer();
const uint8_t* end = data + aEncodedFrame->Size(); // at first byte past end
size_t nalSize = 0;
while (GetNextNALUnit(&data, end, &nalSize) == 0) {
// Assumes 4-byte start codes (0x00000001)
MOZ_ASSERT(data >= aEncodedFrame->Buffer() + 4);
uint8_t *start_code = const_cast<uint8_t*>(data-sizeof(uint32_t));
if (*start_code == 0x00 && *(start_code+1) == 0x00 &&
*(start_code+2) == 0x00 && *(start_code+3) == 0x01) {
*(reinterpret_cast<uint32_t*>(start_code)) = nalSize;
}
data += nalSize;
}
type = GMP_BufferLength32;
}
#endif
// Right now makes one Encoded() callback per unit
// XXX convert to FragmentationHeader format (array of offsets and sizes plus a buffer) in
@ -335,7 +381,7 @@ WebrtcGmpVideoEncoder::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
uint8_t *end = aEncodedFrame->Buffer() + aEncodedFrame->Size();
uint32_t size;
while (buffer < end) {
switch (aBufferType) {
switch (type) {
case GMP_BufferSingle:
size = aEncodedFrame->Size();
break;
@ -362,13 +408,13 @@ WebrtcGmpVideoEncoder::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
break;
default:
// really that it's not in the enum; gives more readable error
MOZ_ASSERT(aBufferType != GMP_BufferSingle);
MOZ_ASSERT(aCodecSpecificInfo.mBufferType != GMP_BufferSingle);
aEncodedFrame->Destroy();
return;
}
webrtc::EncodedImage unit(buffer, size, size);
unit._frameType = ft;
unit._timeStamp = timestamp;
unit._timeStamp = aEncodedFrame->TimeStamp();
unit._completeFrame = true;
mCallback->Encoded(unit, nullptr, nullptr);
@ -415,7 +461,7 @@ WebrtcGmpVideoDecoder::InitDecode_g(const webrtc::VideoCodec* aCodecSettings,
int32_t aNumberOfCores)
{
GMPVideoHost* host = nullptr;
GMPVideoDecoderProxy* gmp = nullptr;
GMPVideoDecoder* gmp = nullptr;
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("vp8"));
@ -435,14 +481,9 @@ WebrtcGmpVideoDecoder::InitDecode_g(const webrtc::VideoCodec* aCodecSettings,
// Bug XXXXXX: transfer settings from codecSettings to codec.
GMPVideoCodec codec;
memset(&codec, 0, sizeof(codec));
codec.mGMPApiVersion = 33;
// XXX this is currently a hack
//GMPVideoCodecUnion codecSpecific;
//memset(&codecSpecific, 0, sizeof(codecSpecific));
nsTArray<uint8_t> codecSpecific;
nsresult rv = mGMP->InitDecode(codec, codecSpecific, this, 1);
if (NS_FAILED(rv)) {
GMPVideoErr err = mGMP->InitDecode(codec, this, 1);
if (err != GMPVideoNoErr) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
@ -482,27 +523,22 @@ WebrtcGmpVideoDecoder::Decode_g(const webrtc::EncodedImage& aInputImage,
MOZ_ASSERT(mGMP);
GMPVideoFrame* ftmp = nullptr;
GMPErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
if (err != GMPNoErr) {
GMPVideoErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
if (err != GMPVideoNoErr) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
GMPVideoEncodedFrame* frame = static_cast<GMPVideoEncodedFrame*>(ftmp);
err = frame->CreateEmptyFrame(aInputImage._length);
if (err != GMPNoErr) {
if (err != GMPVideoNoErr) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
// XXX At this point, we only will get mode1 data (a single length and a buffer)
// Session_info.cc/etc code needs to change to support mode 0.
*(reinterpret_cast<uint32_t*>(frame->Buffer())) = frame->Size();
// XXX It'd be wonderful not to have to memcpy the encoded data!
memcpy(frame->Buffer()+4, aInputImage._buffer+4, frame->Size()-4);
memcpy(frame->Buffer(), aInputImage._buffer, frame->Size());
frame->SetEncodedWidth(aInputImage._encodedWidth);
frame->SetEncodedHeight(aInputImage._encodedHeight);
frame->SetTimeStamp((aInputImage._timeStamp * 1000ll)/90); // rounds down
frame->SetTimeStamp(aInputImage._timeStamp);
frame->SetCompleteFrame(aInputImage._completeFrame);
GMPVideoFrameType ft;
@ -514,18 +550,9 @@ WebrtcGmpVideoDecoder::Decode_g(const webrtc::EncodedImage& aInputImage,
// Bug XXXXXX: Set codecSpecific info
GMPCodecSpecificInfo info;
memset(&info, 0, sizeof(info));
info.mCodecType = kGMPVideoCodecH264;
info.mCodecSpecific.mH264.mSimulcastIdx = 0;
nsTArray<uint8_t> codecSpecificInfo;
codecSpecificInfo.AppendElements((uint8_t*)&info, sizeof(GMPCodecSpecificInfo));
LOGD(("GMP Decode: %llu, len %d", frame->TimeStamp(), aInputImage._length));
nsresult rv = mGMP->Decode(frame,
aMissingFrames,
GMP_BufferLength32,
codecSpecificInfo,
aRenderTimeMs);
if (NS_FAILED(rv)) {
err = mGMP->Decode(frame, aMissingFrames, info, aRenderTimeMs);
if (err != GMPVideoNoErr) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
@ -572,10 +599,9 @@ WebrtcGmpVideoDecoder::Decoded(GMPVideoi420Frame* aDecodedFrame)
if (ret != 0) {
return;
}
image.set_timestamp((aDecodedFrame->Timestamp() * 90ll + 999)/1000); // round up
image.set_timestamp(aDecodedFrame->Timestamp());
image.set_render_time_ms(0);
LOGD(("GMP Decoded: %llu", aDecodedFrame->Timestamp()));
mCallback->Decoded(image);
}
aDecodedFrame->Destroy();

View File

@ -30,15 +30,17 @@
#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
#include "gmp-video-host.h"
#include "GMPVideoDecoderProxy.h"
#include "GMPVideoEncoderProxy.h"
#include "gmp-video-encode.h"
#include "gmp-video-decode.h"
#include "gmp-video-frame-i420.h"
#include "gmp-video-frame-encoded.h"
#include "WebrtcGmpVideoCodec.h"
namespace mozilla {
class WebrtcGmpVideoEncoder : public WebrtcVideoEncoder,
public GMPVideoEncoderCallbackProxy
public GMPEncoderCallback
{
public:
WebrtcGmpVideoEncoder();
@ -64,10 +66,9 @@ public:
virtual int32_t SetRates(uint32_t aNewBitRate,
uint32_t aFrameRate) MOZ_OVERRIDE;
// GMPVideoEncoderCallback virtual functions.
// GMPEncoderCallback virtual functions.
virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame,
GMPBufferType aBufferType,
const nsTArray<uint8_t>& aCodecSpecificInfo) MOZ_OVERRIDE;
const GMPCodecSpecificInfo& aCodecSpecificInfo) MOZ_OVERRIDE;
private:
@ -84,14 +85,14 @@ private:
nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
nsIThread* mGMPThread;
GMPVideoEncoderProxy* mGMP;
GMPVideoEncoder* mGMP;
GMPVideoHost* mHost;
webrtc::EncodedImageCallback* mCallback;
};
class WebrtcGmpVideoDecoder : public WebrtcVideoDecoder,
public GMPVideoDecoderCallback
public GMPDecoderCallback
{
public:
WebrtcGmpVideoDecoder();
@ -125,14 +126,6 @@ public:
MOZ_CRASH();
}
virtual void DrainComplete() MOZ_OVERRIDE {
MOZ_CRASH();
}
virtual void ResetComplete() MOZ_OVERRIDE {
MOZ_CRASH();
}
private:
virtual int32_t InitDecode_g(const webrtc::VideoCodec* aCodecSettings,
int32_t aNumberOfCores);
@ -145,7 +138,7 @@ private:
nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
nsIThread* mGMPThread;
GMPVideoDecoderProxy* mGMP;
GMPVideoDecoder* mGMP;
GMPVideoHost* mHost;
webrtc::DecodedImageCallback* mCallback;
};