Remove other gonk widget conditionals and unused files.

Tag #288.
This commit is contained in:
wolfbeast 2018-05-13 22:46:04 +02:00 • committed by Roy Tam
commit 74df182488
232 changed files with 256 additions and 36730 deletions

View file

@ -1,667 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "GonkOmxPlatformLayer.h"
#include <binder/MemoryDealer.h>
#include <cutils/properties.h>
#include <media/IOMX.h>
#include <media/stagefright/MediaCodecList.h>
#include <utils/List.h>
#include "mozilla/Monitor.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/GrallocTextureClient.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/TextureClientRecycleAllocator.h"
#include "ImageContainer.h"
#include "MediaInfo.h"
#include "OmxDataDecoder.h"
#ifdef LOG
#undef LOG
#endif
#define LOG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, ("GonkOmxPlatformLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
#define CHECK_ERR(err) \
if (err != OK) { \
LOG("error %d at %s", err, __func__); \
return NS_ERROR_FAILURE; \
} \
// Android proprietary value.
#define ANDROID_OMX_VIDEO_CodingVP8 (static_cast<OMX_VIDEO_CODINGTYPE>(9))
using namespace android;
namespace mozilla {
// In Gonk, the software component name has prefix "OMX.google". It needs to
// have a way to use hardware codec first.
bool IsSoftwareCodec(const char* aComponentName)
{
nsAutoCString str(aComponentName);
return (str.Find(NS_LITERAL_CSTRING("OMX.google.")) == -1 ? false : true);
}
bool IsInEmulator()
{
char propQemu[PROPERTY_VALUE_MAX];
property_get("ro.kernel.qemu", propQemu, "");
return !strncmp(propQemu, "1", 1);
}
class GonkOmxObserver : public BnOMXObserver {
public:
void onMessage(const omx_message& aMsg)
{
switch (aMsg.type) {
case omx_message::EVENT:
{
sp<GonkOmxObserver> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () {
if (self->mClient && self->mClient->Event(aMsg.u.event_data.event,
aMsg.u.event_data.data1,
aMsg.u.event_data.data2))
{
return;
}
});
mTaskQueue->Dispatch(r.forget());
break;
}
case omx_message::EMPTY_BUFFER_DONE:
{
sp<GonkOmxObserver> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () {
if (!self->mPromiseLayer) {
return;
}
BufferData::BufferID id = (BufferData::BufferID)aMsg.u.buffer_data.buffer;
self->mPromiseLayer->EmptyFillBufferDone(OMX_DirInput, id);
});
mTaskQueue->Dispatch(r.forget());
break;
}
case omx_message::FILL_BUFFER_DONE:
{
sp<GonkOmxObserver> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () {
if (!self->mPromiseLayer) {
return;
}
// TODO: these codes look a little ugly, it'd be better to improve them.
RefPtr<BufferData> buf;
BufferData::BufferID id = (BufferData::BufferID)aMsg.u.extended_buffer_data.buffer;
buf = self->mPromiseLayer->FindAndRemoveBufferHolder(OMX_DirOutput, id);
MOZ_RELEASE_ASSERT(buf);
GonkBufferData* gonkBuffer = static_cast<GonkBufferData*>(buf.get());
// Copy the critical information to local buffer.
if (gonkBuffer->IsLocalBuffer()) {
gonkBuffer->mBuffer->nOffset = aMsg.u.extended_buffer_data.range_offset;
gonkBuffer->mBuffer->nFilledLen = aMsg.u.extended_buffer_data.range_length;
gonkBuffer->mBuffer->nFlags = aMsg.u.extended_buffer_data.flags;
gonkBuffer->mBuffer->nTimeStamp = aMsg.u.extended_buffer_data.timestamp;
}
self->mPromiseLayer->EmptyFillBufferDone(OMX_DirOutput, buf);
});
mTaskQueue->Dispatch(r.forget());
break;
}
default:
{
LOG("Unhandle event %d", aMsg.type);
}
}
}
void Shutdown()
{
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
mPromiseLayer = nullptr;
mClient = nullptr;
}
GonkOmxObserver(TaskQueue* aTaskQueue, OmxPromiseLayer* aPromiseLayer, OmxDataDecoder* aDataDecoder)
: mTaskQueue(aTaskQueue)
, mPromiseLayer(aPromiseLayer)
, mClient(aDataDecoder)
{}
protected:
RefPtr<TaskQueue> mTaskQueue;
// TODO:
// we should combine both event handlers into one. And we should provide
// an unified way for event handling in OmxPlatformLayer class.
RefPtr<OmxPromiseLayer> mPromiseLayer;
RefPtr<OmxDataDecoder> mClient;
};
// This class allocates Gralloc buffer and manages TextureClient's recycle.
class GonkTextureClientRecycleHandler : public layers::ITextureClientRecycleAllocator
{
typedef MozPromise<layers::TextureClient*, nsresult, /* IsExclusive = */ true> TextureClientRecyclePromise;
public:
GonkTextureClientRecycleHandler(OMX_VIDEO_PORTDEFINITIONTYPE& aDef)
: ITextureClientRecycleAllocator()
, mMonitor("GonkTextureClientRecycleHandler")
{
RefPtr<layers::ImageBridgeChild> bridge = layers::ImageBridgeChild::GetSingleton();
// Allocate Gralloc texture memory.
layers::GrallocTextureData* textureData =
layers::GrallocTextureData::Create(gfx::IntSize(aDef.nFrameWidth, aDef.nFrameHeight),
aDef.eColorFormat,
gfx::BackendType::NONE,
GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_READ_OFTEN,
bridge);
mGraphBuffer = textureData->GetGraphicBuffer();
MOZ_ASSERT(mGraphBuffer.get());
mTextureClient =
layers::TextureClient::CreateWithData(textureData,
layers::TextureFlags::DEALLOCATE_CLIENT | layers::TextureFlags::RECYCLE,
bridge);
MOZ_ASSERT(mTextureClient);
mPromise.SetMonitor(&mMonitor);
}
RefPtr<TextureClientRecyclePromise> WaitforRecycle()
{
MonitorAutoLock lock(mMonitor);
MOZ_ASSERT(!!mGraphBuffer.get());
mTextureClient->SetRecycleAllocator(this);
return mPromise.Ensure(__func__);
}
// DO NOT use smart pointer to receive TextureClient; otherwise it will
// distrupt the reference count.
layers::TextureClient* GetTextureClient()
{
return mTextureClient;
}
GraphicBuffer* GetGraphicBuffer()
{
MonitorAutoLock lock(mMonitor);
return mGraphBuffer.get();
}
// This function is called from layers thread.
void RecycleTextureClient(layers::TextureClient* aClient) override
{
MOZ_ASSERT(mTextureClient == aClient);
// Clearing the recycle allocator drops a reference, so make sure we stay alive
// for the duration of this function.
RefPtr<GonkTextureClientRecycleHandler> kungFuDeathGrip(this);
aClient->SetRecycleAllocator(nullptr);
{
MonitorAutoLock lock(mMonitor);
mPromise.ResolveIfExists(mTextureClient, __func__);
}
}
void Shutdown()
{
MonitorAutoLock lock(mMonitor);
mPromise.RejectIfExists(NS_ERROR_FAILURE, __func__);
// DO NOT clear TextureClient here.
// The ref count could be 1 and RecycleCallback will be called if we clear
// the ref count here. That breaks the whole mechanism. (RecycleCallback
// should be called from layers)
mGraphBuffer = nullptr;
}
private:
// Because TextureClient calls RecycleCallbackl when ref count is 1, so we
// should hold only one reference here and use raw pointer when out of this
// class.
RefPtr<layers::TextureClient> mTextureClient;
// It is protected by mMonitor.
sp<android::GraphicBuffer> mGraphBuffer;
// It is protected by mMonitor.
MozPromiseHolder<TextureClientRecyclePromise> mPromise;
Monitor mMonitor;
};
GonkBufferData::GonkBufferData(bool aLiveInLocal,
GonkOmxPlatformLayer* aGonkPlatformLayer)
: BufferData(nullptr)
, mId(0)
, mGonkPlatformLayer(aGonkPlatformLayer)
{
if (!aLiveInLocal) {
mMirrorBuffer = new OMX_BUFFERHEADERTYPE;
PodZero(mMirrorBuffer.get());
mBuffer = mMirrorBuffer.get();
}
}
void
GonkBufferData::ReleaseBuffer()
{
if (mTextureClientRecycleHandler) {
mTextureClientRecycleHandler->Shutdown();
mTextureClientRecycleHandler = nullptr;
}
}
nsresult
GonkBufferData::InitSharedMemory(android::IMemory* aMemory)
{
MOZ_RELEASE_ASSERT(mMirrorBuffer.get());
// aMemory is a IPC memory, it is safe to use it here.
mBuffer->pBuffer = (OMX_U8*)aMemory->pointer();
mBuffer->nAllocLen = aMemory->size();
return NS_OK;
}
nsresult
GonkBufferData::InitLocalBuffer(IOMX::buffer_id aId)
{
MOZ_RELEASE_ASSERT(!mMirrorBuffer.get());
mBuffer = (OMX_BUFFERHEADERTYPE*)aId;
return NS_OK;
}
nsresult
GonkBufferData::InitGraphicBuffer(OMX_VIDEO_PORTDEFINITIONTYPE& aDef)
{
mTextureClientRecycleHandler = new GonkTextureClientRecycleHandler(aDef);
if (!mTextureClientRecycleHandler->GetGraphicBuffer()) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
already_AddRefed<MediaData>
GonkBufferData::GetPlatformMediaData()
{
if (mGonkPlatformLayer->GetTrackInfo()->GetAsAudioInfo()) {
// This is audio decoding.
return nullptr;
}
if (!mTextureClientRecycleHandler) {
// There is no GraphicBuffer, it should fallback to normal YUV420 VideoData.
return nullptr;
}
VideoInfo info(*mGonkPlatformLayer->GetTrackInfo()->GetAsVideoInfo());
RefPtr<VideoData> data =
VideoData::CreateAndCopyIntoTextureClient(info,
0,
mBuffer->nTimeStamp,
1,
mTextureClientRecycleHandler->GetTextureClient(),
false,
0,
info.ImageRect());
LOG("%p, disp width %d, height %d, pic width %d, height %d, time %ld",
this, info.mDisplay.width, info.mDisplay.height,
info.mImage.width, info.mImage.height, mBuffer->nTimeStamp);
// Get TextureClient Promise here to wait for resolved.
RefPtr<GonkBufferData> self(this);
mTextureClientRecycleHandler->WaitforRecycle()
->Then(mGonkPlatformLayer->GetTaskQueue(), __func__,
[self] () {
self->mPromise.ResolveIfExists(self, __func__);
},
[self] () {
OmxBufferFailureHolder failure(OMX_ErrorUndefined, self);
self->mPromise.RejectIfExists(failure, __func__);
});
return data.forget();
}
GonkOmxPlatformLayer::GonkOmxPlatformLayer(OmxDataDecoder* aDataDecoder,
OmxPromiseLayer* aPromiseLayer,
TaskQueue* aTaskQueue,
layers::ImageContainer* aImageContainer)
: mTaskQueue(aTaskQueue)
, mImageContainer(aImageContainer)
, mNode(0)
{
mOmxObserver = new GonkOmxObserver(mTaskQueue, aPromiseLayer, aDataDecoder);
}
nsresult
GonkOmxPlatformLayer::AllocateOmxBuffer(OMX_DIRTYPE aType,
BUFFERLIST* aBufferList)
{
MOZ_ASSERT(!mMemoryDealer[aType].get());
// Get port definition.
OMX_PARAM_PORTDEFINITIONTYPE def;
nsTArray<uint32_t> portindex;
GetPortIndices(portindex);
for (auto idx : portindex) {
InitOmxParameter(&def);
def.nPortIndex = idx;
OMX_ERRORTYPE err = GetParameter(OMX_IndexParamPortDefinition,
&def,
sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
if (err != OMX_ErrorNone) {
return NS_ERROR_FAILURE;
} else if (def.eDir == aType) {
LOG("Get OMX_IndexParamPortDefinition: port: %d, type: %d", def.nPortIndex, def.eDir);
break;
}
}
size_t t = 0;
// Configure video output GraphicBuffer for video decoding acceleration.
bool useGralloc = false;
if (aType == OMX_DirOutput && mQuirks.test(kRequiresAllocateBufferOnOutputPorts) &&
(def.eDomain == OMX_PortDomainVideo)) {
if (NS_FAILED(EnableOmxGraphicBufferPort(def))) {
return NS_ERROR_FAILURE;
}
LOG("Enable OMX GraphicBuffer port, number %d, width %d, height %d", def.nBufferCountActual,
def.format.video.nFrameWidth, def.format.video.nFrameHeight);
useGralloc = true;
t = 1024; // MemoryDealer doesn't like 0, it's just for MemoryDealer happy.
} else {
t = def.nBufferCountActual * def.nBufferSize;
LOG("Buffer count %d, buffer size %d", def.nBufferCountActual, def.nBufferSize);
}
bool liveinlocal = mOmx->livesLocally(mNode, getpid());
// MemoryDealer is a IPC buffer allocator in Gonk because IOMX is actually
// lives in mediaserver.
mMemoryDealer[aType] = new MemoryDealer(t, "Gecko-OMX");
for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
RefPtr<GonkBufferData> buffer;
IOMX::buffer_id bufferID;
status_t st;
nsresult rv;
buffer = new GonkBufferData(liveinlocal, this);
if (useGralloc) {
// Buffer is lived remotely. Use GraphicBuffer for decoded video frame display.
rv = buffer->InitGraphicBuffer(def.format.video);
NS_ENSURE_SUCCESS(rv, rv);
st = mOmx->useGraphicBuffer(mNode,
def.nPortIndex,
buffer->mTextureClientRecycleHandler->GetGraphicBuffer(),
&bufferID);
CHECK_ERR(st);
} else {
sp<IMemory> mem = mMemoryDealer[aType]->allocate(def.nBufferSize);
MOZ_ASSERT(mem.get());
if ((mQuirks.test(kRequiresAllocateBufferOnInputPorts) && aType == OMX_DirInput) ||
(mQuirks.test(kRequiresAllocateBufferOnOutputPorts) && aType == OMX_DirOutput)) {
// Buffer is lived remotely. We allocate a local OMX_BUFFERHEADERTYPE
// as the mirror of the remote OMX_BUFFERHEADERTYPE.
st = mOmx->allocateBufferWithBackup(mNode, aType, mem, &bufferID);
CHECK_ERR(st);
rv = buffer->InitSharedMemory(mem.get());
NS_ENSURE_SUCCESS(rv, rv);
} else {
// Buffer is lived locally, bufferID is the actually OMX_BUFFERHEADERTYPE
// pointer.
st = mOmx->useBuffer(mNode, aType, mem, &bufferID);
CHECK_ERR(st);
rv = buffer->InitLocalBuffer(bufferID);
NS_ENSURE_SUCCESS(rv, rv);
}
}
rv = buffer->SetBufferId(bufferID);
NS_ENSURE_SUCCESS(rv, rv);
aBufferList->AppendElement(buffer);
}
return NS_OK;
}
nsresult
GonkOmxPlatformLayer::ReleaseOmxBuffer(OMX_DIRTYPE aType,
BUFFERLIST* aBufferList)
{
status_t st;
uint32_t len = aBufferList->Length();
for (uint32_t i = 0; i < len; i++) {
GonkBufferData* buffer = static_cast<GonkBufferData*>(aBufferList->ElementAt(i).get());
IOMX::buffer_id id = (OMX_BUFFERHEADERTYPE*) buffer->ID();
st = mOmx->freeBuffer(mNode, aType, id);
if (st != OK) {
return NS_ERROR_FAILURE;
}
buffer->ReleaseBuffer();
}
aBufferList->Clear();
mMemoryDealer[aType].clear();
return NS_OK;
}
nsresult
GonkOmxPlatformLayer::EnableOmxGraphicBufferPort(OMX_PARAM_PORTDEFINITIONTYPE& aDef)
{
status_t st;
st = mOmx->enableGraphicBuffers(mNode, aDef.nPortIndex, OMX_TRUE);
CHECK_ERR(st);
return NS_OK;
}
OMX_ERRORTYPE
GonkOmxPlatformLayer::GetState(OMX_STATETYPE* aType)
{
return (OMX_ERRORTYPE)mOmx->getState(mNode, aType);
}
OMX_ERRORTYPE
GonkOmxPlatformLayer::GetParameter(OMX_INDEXTYPE aParamIndex,
OMX_PTR aComponentParameterStructure,
OMX_U32 aComponentParameterSize)
{
return (OMX_ERRORTYPE)mOmx->getParameter(mNode,
aParamIndex,
aComponentParameterStructure,
aComponentParameterSize);
}
OMX_ERRORTYPE
GonkOmxPlatformLayer::SetParameter(OMX_INDEXTYPE aParamIndex,
OMX_PTR aComponentParameterStructure,
OMX_U32 aComponentParameterSize)
{
return (OMX_ERRORTYPE)mOmx->setParameter(mNode,
aParamIndex,
aComponentParameterStructure,
aComponentParameterSize);
}
nsresult
GonkOmxPlatformLayer::Shutdown()
{
mOmx->freeNode(mNode);
mOmxObserver->Shutdown();
mOmxObserver = nullptr;
mOmxClient.disconnect();
return NS_OK;
}
OMX_ERRORTYPE
GonkOmxPlatformLayer::InitOmxToStateLoaded(const TrackInfo* aInfo)
{
mInfo = aInfo;
status_t err = mOmxClient.connect();
if (err != OK) {
return OMX_ErrorUndefined;
}
mOmx = mOmxClient.interface();
if (!mOmx.get()) {
return OMX_ErrorUndefined;
}
LOG("find componenet for mime type %s", mInfo->mMimeType.Data());
nsTArray<ComponentInfo> components;
if (FindComponents(mInfo->mMimeType, &components)) {
for (auto comp : components) {
if (LoadComponent(comp)) {
return OMX_ErrorNone;
}
}
}
LOG("no component is loaded");
return OMX_ErrorUndefined;
}
OMX_ERRORTYPE
GonkOmxPlatformLayer::EmptyThisBuffer(BufferData* aData)
{
return (OMX_ERRORTYPE)mOmx->emptyBuffer(mNode,
(IOMX::buffer_id)aData->ID(),
aData->mBuffer->nOffset,
aData->mBuffer->nFilledLen,
aData->mBuffer->nFlags,
aData->mBuffer->nTimeStamp);
}
OMX_ERRORTYPE
GonkOmxPlatformLayer::FillThisBuffer(BufferData* aData)
{
return (OMX_ERRORTYPE)mOmx->fillBuffer(mNode, (IOMX::buffer_id)aData->ID());
}
OMX_ERRORTYPE
GonkOmxPlatformLayer::SendCommand(OMX_COMMANDTYPE aCmd,
OMX_U32 aParam1,
OMX_PTR aCmdData)
{
return (OMX_ERRORTYPE)mOmx->sendCommand(mNode, aCmd, aParam1);
}
bool
GonkOmxPlatformLayer::LoadComponent(const ComponentInfo& aComponent)
{
status_t err = mOmx->allocateNode(aComponent.mName, mOmxObserver, &mNode);
if (err == OK) {
mQuirks = aComponent.mQuirks;
LOG("Load OpenMax component %s, alloc input %d, alloc output %d, live locally %d",
aComponent.mName, mQuirks.test(kRequiresAllocateBufferOnInputPorts),
mQuirks.test(kRequiresAllocateBufferOnOutputPorts),
mOmx->livesLocally(mNode, getpid()));
return true;
}
return false;
}
layers::ImageContainer*
GonkOmxPlatformLayer::GetImageContainer()
{
return mImageContainer;
}
const TrackInfo*
GonkOmxPlatformLayer::GetTrackInfo()
{
return mInfo;
}
bool
GonkOmxPlatformLayer::FindComponents(const nsACString& aMimeType,
nsTArray<ComponentInfo>* aComponents)
{
static const MediaCodecList* codecs = MediaCodecList::getInstance();
bool useHardwareCodecOnly = false;
// H264 and H263 has different profiles, software codec doesn't support high profile.
// So we use hardware codec only.
if (!IsInEmulator() &&
(aMimeType.EqualsLiteral("video/avc") ||
aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/mp4v-es") ||
aMimeType.EqualsLiteral("video/3gp"))) {
useHardwareCodecOnly = true;
}
const char* mime = aMimeType.Data();
// Translate VP8 MIME type to Android format.
if (aMimeType.EqualsLiteral("video/webm; codecs=vp8")) {
mime = "video/x-vnd.on2.vp8";
}
size_t start = 0;
bool found = false;
while (true) {
ssize_t index = codecs->findCodecByType(mime, false /* encoder */, start);
if (index < 0) {
break;
}
start = index + 1;
const char* name = codecs->getCodecName(index);
if (IsSoftwareCodec(name) && useHardwareCodecOnly) {
continue;
}
found = true;
if (!aComponents) {
continue;
}
ComponentInfo* comp = aComponents->AppendElement();
comp->mName = name;
if (codecs->codecHasQuirk(index, "requires-allocate-on-input-ports")) {
comp->mQuirks.set(kRequiresAllocateBufferOnInputPorts);
}
if (codecs->codecHasQuirk(index, "requires-allocate-on-output-ports")) {
comp->mQuirks.set(kRequiresAllocateBufferOnOutputPorts);
}
}
return found;
}
OMX_VIDEO_CODINGTYPE
GonkOmxPlatformLayer::CompressionFormat()
{
MOZ_ASSERT(mInfo);
return mInfo->mMimeType.EqualsLiteral("video/webm; codecs=vp8") ?
ANDROID_OMX_VIDEO_CodingVP8 : OmxPlatformLayer::CompressionFormat();
}
} // mozilla

View file

@ -1,205 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#if !defined(GonkOmxPlatformLayer_h_)
#define GonkOmxPlatformLayer_h_
#pragma GCC visibility push(default)
#include <bitset>
#include <utils/RefBase.h>
#include <media/stagefright/OMXClient.h>
#include "nsAutoPtr.h"
#include "OMX_Component.h"
#include "OmxPlatformLayer.h"
class nsACString;
namespace android {
class IMemory;
class MemoryDealer;
}
namespace mozilla {
class GonkOmxObserver;
class GonkOmxPlatformLayer;
class GonkTextureClientRecycleHandler;
/*
* Due to Android's omx node could live in local process (client) or remote
* process (mediaserver). And there are 3 kinds of buffer in Android OMX.
*
* 1.
* When buffer is in local process, the IOMX::buffer_id is OMX_BUFFERHEADERTYPE
* pointer actually, it is safe to use it directly.
*
* 2.
* When buffer is in remote process, the OMX_BUFFERHEADERTYPE pointer is 'IN' the
* remote process. It can't be used in local process, so here it allocates a
* local OMX_BUFFERHEADERTYPE. The raw/decoded data is in the android shared
* memory, IMemory.
*
* 3.
* When buffer is in remote process for the display output port. It uses
* GraphicBuffer to accelerate the decoding and display.
*
*/
class GonkBufferData : public OmxPromiseLayer::BufferData {
protected:
virtual ~GonkBufferData() {}
public:
GonkBufferData(bool aLiveInLocal,
GonkOmxPlatformLayer* aLayer);
BufferID ID() override
{
return mId;
}
already_AddRefed<MediaData> GetPlatformMediaData() override;
bool IsLocalBuffer()
{
return !!mMirrorBuffer.get();
}
void ReleaseBuffer();
nsresult SetBufferId(android::IOMX::buffer_id aId)
{
mId = aId;
return NS_OK;
}
// The mBuffer is in local process. And aId is actually the OMX_BUFFERHEADERTYPE
// pointer. It doesn't need a mirror buffer.
nsresult InitLocalBuffer(android::IOMX::buffer_id aId);
// aMemory is an IPC based memory which will be used as the pBuffer in
// mBuffer. And the mBuffer will be the mirror OMX_BUFFERHEADERTYPE
// of the one in the remote process.
nsresult InitSharedMemory(android::IMemory* aMemory);
// GraphicBuffer is for video decoding acceleration on output port.
// Then mBuffer is the mirror OMX_BUFFERHEADERTYPE of the one in the remote
// process.
nsresult InitGraphicBuffer(OMX_VIDEO_PORTDEFINITIONTYPE& aDef);
// Android OMX uses this id to pass the buffer between OMX component and
// client.
android::IOMX::buffer_id mId;
// mMirrorBuffer are used only when the omx node is in mediaserver.
// Due to IPC problem, the mId is the OMX_BUFFERHEADERTYPE address in mediaserver.
// It can't mapping to client process, so we need a local OMX_BUFFERHEADERTYPE
// here to mirror the remote OMX_BUFFERHEADERTYPE in mediaserver.
nsAutoPtr<OMX_BUFFERHEADERTYPE> mMirrorBuffer;
// It creates GraphicBuffer and manages TextureClient.
RefPtr<GonkTextureClientRecycleHandler> mTextureClientRecycleHandler;
GonkOmxPlatformLayer* mGonkPlatformLayer;
};
class GonkOmxPlatformLayer : public OmxPlatformLayer {
public:
enum {
kRequiresAllocateBufferOnInputPorts = 0,
kRequiresAllocateBufferOnOutputPorts,
QUIRKS,
};
typedef std::bitset<QUIRKS> Quirks;
struct ComponentInfo {
const char* mName;
Quirks mQuirks;
};
GonkOmxPlatformLayer(OmxDataDecoder* aDataDecoder,
OmxPromiseLayer* aPromiseLayer,
TaskQueue* aTaskQueue,
layers::ImageContainer* aImageContainer);
nsresult AllocateOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBufferList) override;
nsresult ReleaseOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBufferList) override;
OMX_ERRORTYPE GetState(OMX_STATETYPE* aType) override;
OMX_ERRORTYPE GetParameter(OMX_INDEXTYPE aParamIndex,
OMX_PTR aComponentParameterStructure,
OMX_U32 aComponentParameterSize) override;
OMX_ERRORTYPE SetParameter(OMX_INDEXTYPE nIndex,
OMX_PTR aComponentParameterStructure,
OMX_U32 aComponentParameterSize) override;
OMX_ERRORTYPE InitOmxToStateLoaded(const TrackInfo* aInfo) override;
OMX_ERRORTYPE EmptyThisBuffer(BufferData* aData) override;
OMX_ERRORTYPE FillThisBuffer(BufferData* aData) override;
OMX_ERRORTYPE SendCommand(OMX_COMMANDTYPE aCmd,
OMX_U32 aParam1,
OMX_PTR aCmdData) override;
nsresult Shutdown() override;
static bool FindComponents(const nsACString& aMimeType,
nsTArray<ComponentInfo>* aComponents = nullptr);
// Android/QCOM decoder uses its own OMX_VIDEO_CodingVP8 definition in
// frameworks/native/media/include/openmax/OMX_Video.h, not the one defined
// in OpenMAX v1.1.2 OMX_VideoExt.h
OMX_VIDEO_CODINGTYPE CompressionFormat() override;
protected:
friend GonkBufferData;
layers::ImageContainer* GetImageContainer();
const TrackInfo* GetTrackInfo();
TaskQueue* GetTaskQueue()
{
return mTaskQueue;
}
nsresult EnableOmxGraphicBufferPort(OMX_PARAM_PORTDEFINITIONTYPE& aDef);
bool LoadComponent(const ComponentInfo& aComponent);
friend class GonkOmxObserver;
RefPtr<TaskQueue> mTaskQueue;
RefPtr<layers::ImageContainer> mImageContainer;
// OMX_DirInput is 0, OMX_DirOutput is 1.
android::sp<android::MemoryDealer> mMemoryDealer[2];
android::sp<GonkOmxObserver> mOmxObserver;
android::sp<android::IOMX> mOmx;
android::IOMX::node_id mNode;
android::OMXClient mOmxClient;
Quirks mQuirks;
};
}
#pragma GCC visibility pop
#endif // GonkOmxPlatformLayer_h_

View file

@ -21,29 +21,6 @@ LOCAL_INCLUDES += [
include('/ipc/chromium/chromium-config.mozbuild')
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and (CONFIG['ANDROID_VERSION'] == '19' or CONFIG['ANDROID_VERSION'] == '20'):
# Suppress some GCC/clang warnings being treated as errors:
# - about attributes on forward declarations for types that are already
# defined, which complains about an important MOZ_EXPORT for android::AString
# - about multi-character constants which are used in codec-related code
if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
CXXFLAGS += [
'-Wno-error=attributes',
'-Wno-error=multichar'
]
CXXFLAGS += [
'-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
'frameworks/base/include/binder',
'frameworks/base/include/utils',
]
]
UNIFIED_SOURCES += [
'GonkOmxPlatformLayer.cpp',
]
EXTRA_DSO_LDOPTS += [
'-libbinder',
]
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']: