diff options
Diffstat (limited to 'dom/media/platforms')
-rw-r--r-- | dom/media/platforms/omx/GonkOmxPlatformLayer.cpp | 667 | ||||
-rw-r--r-- | dom/media/platforms/omx/GonkOmxPlatformLayer.h | 205 | ||||
-rw-r--r-- | dom/media/platforms/omx/moz.build | 23 |
3 files changed, 0 insertions, 895 deletions
diff --git a/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp b/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp deleted file mode 100644 index 870566cf5..000000000 --- a/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp +++ /dev/null @@ -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 diff --git a/dom/media/platforms/omx/GonkOmxPlatformLayer.h b/dom/media/platforms/omx/GonkOmxPlatformLayer.h deleted file mode 100644 index aaa8c654d..000000000 --- a/dom/media/platforms/omx/GonkOmxPlatformLayer.h +++ /dev/null @@ -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_ diff --git a/dom/media/platforms/omx/moz.build b/dom/media/platforms/omx/moz.build index 9f641d937..661e280e0 100644 --- a/dom/media/platforms/omx/moz.build +++ b/dom/media/platforms/omx/moz.build @@ -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']: |