diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /dom/media/platforms/omx/PureOmxPlatformLayer.cpp | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/media/platforms/omx/PureOmxPlatformLayer.cpp')
-rw-r--r-- | dom/media/platforms/omx/PureOmxPlatformLayer.cpp | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/dom/media/platforms/omx/PureOmxPlatformLayer.cpp b/dom/media/platforms/omx/PureOmxPlatformLayer.cpp new file mode 100644 index 0000000000..dd6b259ac6 --- /dev/null +++ b/dom/media/platforms/omx/PureOmxPlatformLayer.cpp @@ -0,0 +1,405 @@ +/* -*- 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 "OmxDataDecoder.h" +#include "OmxPromiseLayer.h" +#include "PureOmxPlatformLayer.h" +#include "OmxCoreLibLinker.h" + +#ifdef LOG +# undef LOG +#endif + +#define LOG(arg, ...) \ + MOZ_LOG( \ + sPDMLog, mozilla::LogLevel::Debug, \ + ("PureOmxPlatformLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) +#define LOG_BUF(arg, ...) \ + MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, \ + ("PureOmxBufferData(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) + +namespace mozilla { + +#define OMX_FUNC(func) extern typeof(func)* func; +#include "OmxFunctionList.h" +#undef OMX_FUNC + +PureOmxBufferData::PureOmxBufferData( + const PureOmxPlatformLayer& aPlatformLayer, + const OMX_PARAM_PORTDEFINITIONTYPE& aPortDef) + : BufferData(nullptr), mPlatformLayer(aPlatformLayer), mPortDef(aPortDef) { + LOG_BUF(""); + + if (ShouldUseEGLImage()) { + // TODO + LOG_BUF( + "OMX_UseEGLImage() seems available but using it isn't implemented " + "yet."); + } + + OMX_ERRORTYPE err; + err = OMX_AllocateBuffer(mPlatformLayer.GetComponent(), &mBuffer, + mPortDef.nPortIndex, this, mPortDef.nBufferSize); + if (err != OMX_ErrorNone) { + LOG_BUF("Failed to allocate the buffer!: 0x%08x", err); + } +} + +PureOmxBufferData::~PureOmxBufferData() { + LOG_BUF(""); + ReleaseBuffer(); +} + +void PureOmxBufferData::ReleaseBuffer() { + LOG_BUF(""); + + if (mBuffer) { + OMX_ERRORTYPE err; + err = OMX_FreeBuffer(mPlatformLayer.GetComponent(), mPortDef.nPortIndex, + mBuffer); + if (err != OMX_ErrorNone) { + LOG_BUF("Failed to free the buffer!: 0x%08x", err); + } + mBuffer = nullptr; + } +} + +bool PureOmxBufferData::ShouldUseEGLImage() { + OMX_ERRORTYPE err; + err = OMX_UseEGLImage(mPlatformLayer.GetComponent(), nullptr, + mPortDef.nPortIndex, nullptr, nullptr); + return (err != OMX_ErrorNotImplemented); +} + +/* static */ +bool PureOmxPlatformLayer::Init(void) { + if (!OmxCoreLibLinker::Link()) { + return false; + } + + OMX_ERRORTYPE err = OMX_Init(); + if (err != OMX_ErrorNone) { + MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, + ("PureOmxPlatformLayer::%s: Failed to initialize OMXCore: 0x%08x", + __func__, err)); + return false; + } + + return true; +} + +/* static */ +OMX_CALLBACKTYPE PureOmxPlatformLayer::sCallbacks = { + EventHandler, EmptyBufferDone, FillBufferDone}; + +PureOmxPlatformLayer::PureOmxPlatformLayer( + OmxDataDecoder* aDataDecoder, OmxPromiseLayer* aPromiseLayer, + TaskQueue* aTaskQueue, layers::ImageContainer* aImageContainer) + : mComponent(nullptr), + mDataDecoder(aDataDecoder), + mPromiseLayer(aPromiseLayer), + mTaskQueue(aTaskQueue), + mImageContainer(aImageContainer) { + LOG(""); +} + +PureOmxPlatformLayer::~PureOmxPlatformLayer() { LOG(""); } + +OMX_ERRORTYPE +PureOmxPlatformLayer::InitOmxToStateLoaded(const TrackInfo* aInfo) { + LOG(""); + + if (!aInfo) { + return OMX_ErrorUndefined; + } + mInfo = aInfo; + + return CreateComponent(); +} + +OMX_ERRORTYPE +PureOmxPlatformLayer::EmptyThisBuffer(BufferData* aData) { + LOG(""); + return OMX_EmptyThisBuffer(mComponent, aData->mBuffer); +} + +OMX_ERRORTYPE +PureOmxPlatformLayer::FillThisBuffer(BufferData* aData) { + LOG(""); + return OMX_FillThisBuffer(mComponent, aData->mBuffer); +} + +OMX_ERRORTYPE +PureOmxPlatformLayer::SendCommand(OMX_COMMANDTYPE aCmd, OMX_U32 aParam1, + OMX_PTR aCmdData) { + LOG("aCmd: 0x%08x", aCmd); + if (!mComponent) { + return OMX_ErrorUndefined; + } + return OMX_SendCommand(mComponent, aCmd, aParam1, aCmdData); +} + +nsresult PureOmxPlatformLayer::FindPortDefinition( + OMX_DIRTYPE aType, OMX_PARAM_PORTDEFINITIONTYPE& portDef) { + nsTArray<uint32_t> portIndex; + GetPortIndices(portIndex); + for (auto idx : portIndex) { + InitOmxParameter(&portDef); + portDef.nPortIndex = idx; + + OMX_ERRORTYPE err; + err = GetParameter(OMX_IndexParamPortDefinition, &portDef, + sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (err != OMX_ErrorNone) { + return NS_ERROR_FAILURE; + } else if (portDef.eDir == aType) { + LOG("Found OMX_IndexParamPortDefinition: port: %d, type: %d", + portDef.nPortIndex, portDef.eDir); + return NS_OK; + } + } + return NS_ERROR_FAILURE; +} + +nsresult PureOmxPlatformLayer::AllocateOmxBuffer(OMX_DIRTYPE aType, + BUFFERLIST* aBufferList) { + LOG("aType: %d", aType); + + OMX_PARAM_PORTDEFINITIONTYPE portDef; + nsresult result = FindPortDefinition(aType, portDef); + if (result != NS_OK) { + return result; + } + + LOG("nBufferCountActual: %d, nBufferSize: %d", portDef.nBufferCountActual, + portDef.nBufferSize); + + for (OMX_U32 i = 0; i < portDef.nBufferCountActual; ++i) { + RefPtr<PureOmxBufferData> buffer = new PureOmxBufferData(*this, portDef); + aBufferList->AppendElement(buffer); + } + + return NS_OK; +} + +nsresult PureOmxPlatformLayer::ReleaseOmxBuffer(OMX_DIRTYPE aType, + BUFFERLIST* aBufferList) { + LOG("aType: 0x%08x", aType); + + uint32_t len = aBufferList->Length(); + for (uint32_t i = 0; i < len; i++) { + PureOmxBufferData* buffer = + static_cast<PureOmxBufferData*>(aBufferList->ElementAt(i).get()); + + // All raw OpenMAX buffers have to be released here to flush + // OMX_CommandStateSet for switching the state to OMX_StateLoaded. + // See OmxDataDecoder::DoAsyncShutdown() for more detail. + buffer->ReleaseBuffer(); + } + aBufferList->Clear(); + + return NS_OK; +} + +OMX_ERRORTYPE +PureOmxPlatformLayer::GetState(OMX_STATETYPE* aType) { + LOG(""); + + if (mComponent) { + return OMX_GetState(mComponent, aType); + } + + return OMX_ErrorUndefined; +} + +OMX_ERRORTYPE +PureOmxPlatformLayer::GetParameter(OMX_INDEXTYPE aParamIndex, + OMX_PTR aComponentParameterStructure, + OMX_U32 aComponentParameterSize) { + LOG("aParamIndex: 0x%08x", aParamIndex); + + if (!mComponent) { + return OMX_ErrorUndefined; + } + + return OMX_GetParameter(mComponent, aParamIndex, + aComponentParameterStructure); +} + +OMX_ERRORTYPE +PureOmxPlatformLayer::SetParameter(OMX_INDEXTYPE aParamIndex, + OMX_PTR aComponentParameterStructure, + OMX_U32 aComponentParameterSize) { + LOG("aParamIndex: 0x%08x", aParamIndex); + + if (!mComponent) { + return OMX_ErrorUndefined; + } + + return OMX_SetParameter(mComponent, aParamIndex, + aComponentParameterStructure); +} + +nsresult PureOmxPlatformLayer::Shutdown() { + LOG(""); + if (mComponent) { + OMX_FreeHandle(mComponent); + mComponent = nullptr; + } + mPromiseLayer = nullptr; + mDataDecoder = nullptr; + return NS_OK; +} + +/* static */ +OMX_ERRORTYPE PureOmxPlatformLayer::EventHandler(OMX_HANDLETYPE hComponent, + OMX_PTR pAppData, + OMX_EVENTTYPE eEventType, + OMX_U32 nData1, OMX_U32 nData2, + OMX_PTR pEventData) { + PureOmxPlatformLayer* self = static_cast<PureOmxPlatformLayer*>(pAppData); + nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( + "mozilla::PureOmxPlatformLayer::EventHandler", + [self, eEventType, nData1, nData2, pEventData]() { + self->EventHandler(eEventType, nData1, nData2, pEventData); + }); + nsresult rv = self->mTaskQueue->Dispatch(r.forget()); + return NS_SUCCEEDED(rv) ? OMX_ErrorNone : OMX_ErrorUndefined; +} + +/* static */ +OMX_ERRORTYPE PureOmxPlatformLayer::EmptyBufferDone( + OMX_HANDLETYPE hComponent, OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { + PureOmxPlatformLayer* self = static_cast<PureOmxPlatformLayer*>(pAppData); + nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( + "mozilla::PureOmxPlatformLayer::EmptyBufferDone", + [self, pBuffer]() { self->EmptyBufferDone(pBuffer); }); + nsresult rv = self->mTaskQueue->Dispatch(r.forget()); + return NS_SUCCEEDED(rv) ? OMX_ErrorNone : OMX_ErrorUndefined; +} + +/* static */ +OMX_ERRORTYPE PureOmxPlatformLayer::FillBufferDone( + OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, + OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) { + PureOmxPlatformLayer* self = static_cast<PureOmxPlatformLayer*>(pAppData); + nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( + "mozilla::PureOmxPlatformLayer::FillBufferDone", + [self, pBuffer]() { self->FillBufferDone(pBuffer); }); + nsresult rv = self->mTaskQueue->Dispatch(r.forget()); + return NS_SUCCEEDED(rv) ? OMX_ErrorNone : OMX_ErrorUndefined; +} + +OMX_ERRORTYPE +PureOmxPlatformLayer::EventHandler(OMX_EVENTTYPE eEventType, OMX_U32 nData1, + OMX_U32 nData2, OMX_PTR pEventData) { + bool handled = mPromiseLayer->Event(eEventType, nData1, nData2); + LOG("eEventType: 0x%08x, handled: %d", eEventType, handled); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE +PureOmxPlatformLayer::EmptyBufferDone(OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { + PureOmxBufferData* buffer = + static_cast<PureOmxBufferData*>(pBuffer->pAppPrivate); + OMX_DIRTYPE portDirection = buffer->GetPortDirection(); + LOG("PortDirection: %d", portDirection); + mPromiseLayer->EmptyFillBufferDone(portDirection, buffer); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE +PureOmxPlatformLayer::FillBufferDone(OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) { + PureOmxBufferData* buffer = + static_cast<PureOmxBufferData*>(pBuffer->pAppPrivate); + OMX_DIRTYPE portDirection = buffer->GetPortDirection(); + LOG("PortDirection: %d", portDirection); + mPromiseLayer->EmptyFillBufferDone(portDirection, buffer); + return OMX_ErrorNone; +} + +bool PureOmxPlatformLayer::SupportsMimeType(const nsACString& aMimeType) { + return FindStandardComponent(aMimeType, nullptr); +} + +static bool GetStandardComponentRole(const nsACString& aMimeType, + nsACString& aRole) { + if (aMimeType.EqualsLiteral("video/avc") || + aMimeType.EqualsLiteral("video/mp4") || + aMimeType.EqualsLiteral("video/mp4v-es")) { + aRole.Assign("video_decoder.avc"); + return true; + } else if (aMimeType.EqualsLiteral("audio/mp4a-latm") || + aMimeType.EqualsLiteral("audio/mp4") || + aMimeType.EqualsLiteral("audio/aac")) { + aRole.Assign("audio_decoder.aac"); + return true; + } + return false; +} + +/* static */ +bool PureOmxPlatformLayer::FindStandardComponent(const nsACString& aMimeType, + nsACString* aComponentName) { + nsAutoCString role; + if (!GetStandardComponentRole(aMimeType, role)) return false; + + OMX_U32 nComponents = 0; + OMX_ERRORTYPE err; + err = OMX_GetComponentsOfRole(const_cast<OMX_STRING>(role.Data()), + &nComponents, nullptr); + if (err != OMX_ErrorNone || nComponents <= 0) { + return false; + } + if (!aComponentName) { + return true; + } + + // TODO: + // Only the first component will be used. + // We should detect the most preferred component. + OMX_U8* componentNames[1]; + UniquePtr<OMX_U8[]> componentName; + componentName = MakeUniqueFallible<OMX_U8[]>(OMX_MAX_STRINGNAME_SIZE); + componentNames[0] = componentName.get(); + nComponents = 1; + err = OMX_GetComponentsOfRole(const_cast<OMX_STRING>(role.Data()), + &nComponents, componentNames); + if (err == OMX_ErrorNone) { + MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, + ("PureOmxPlatformLayer::%s: A component has been found for %s: %s", + __func__, aMimeType.Data(), componentNames[0])); + aComponentName->Assign(reinterpret_cast<char*>(componentNames[0])); + } + + return err == OMX_ErrorNone; +} + +OMX_ERRORTYPE +PureOmxPlatformLayer::CreateComponent(const nsACString* aComponentName) { + nsAutoCString componentName; + if (aComponentName) { + componentName = *aComponentName; + } else if (!FindStandardComponent(mInfo->mMimeType, &componentName)) { + return OMX_ErrorComponentNotFound; + } + + OMX_ERRORTYPE err; + err = OMX_GetHandle(&mComponent, const_cast<OMX_STRING>(componentName.Data()), + this, &sCallbacks); + + const char* mime = mInfo->mMimeType.Data(); + if (err == OMX_ErrorNone) { + LOG("Succeeded to create the component for %s", mime); + } else { + LOG("Failed to create the component for %s: 0x%08x", mime, err); + } + + return err; +} + +} // namespace mozilla |