diff options
author | Andreas Huber <andih@google.com> | 2009-10-15 13:46:54 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2009-10-16 11:22:43 -0700 |
commit | 318ad9c1d9d6515026dfc2c021359d27decaa7a1 (patch) | |
tree | 28a58c4e3f20528b01c2abd08ba5f62d8755650c /media/libstagefright/omx/OMXNodeInstance.cpp | |
parent | 89e69da4d86348409994c9dafbbb2634ccd7c196 (diff) | |
download | frameworks_av-318ad9c1d9d6515026dfc2c021359d27decaa7a1.zip frameworks_av-318ad9c1d9d6515026dfc2c021359d27decaa7a1.tar.gz frameworks_av-318ad9c1d9d6515026dfc2c021359d27decaa7a1.tar.bz2 |
Reimplement the OMX backend for stagefright.
Besides a major cleanup and refactoring, OMX is now a singleton living in the media server, it listens for death notifications of node observers/clients that allocated OMX nodes and performs/attempts cleanup.
Changed APIs to conform to the rest of the system.
Diffstat (limited to 'media/libstagefright/omx/OMXNodeInstance.cpp')
-rw-r--r-- | media/libstagefright/omx/OMXNodeInstance.cpp | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp new file mode 100644 index 0000000..d277587 --- /dev/null +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * 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. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "OMXNodeInstance" +#include <utils/Log.h> + +#include "../include/OMXNodeInstance.h" + +#include "pv_omxcore.h" + +#include <binder/IMemory.h> +#include <media/stagefright/MediaDebug.h> + +namespace android { + +struct BufferMeta { + BufferMeta(const sp<IMemory> &mem, bool is_backup = false) + : mMem(mem), + mIsBackup(is_backup) { + } + + BufferMeta(size_t size) + : mSize(size), + mIsBackup(false) { + } + + void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { + if (!mIsBackup) { + return; + } + + memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, + header->pBuffer + header->nOffset, + header->nFilledLen); + } + + void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { + if (!mIsBackup) { + return; + } + + memcpy(header->pBuffer + header->nOffset, + (const OMX_U8 *)mMem->pointer() + header->nOffset, + header->nFilledLen); + } + +private: + sp<IMemory> mMem; + size_t mSize; + bool mIsBackup; + + BufferMeta(const BufferMeta &); + BufferMeta &operator=(const BufferMeta &); +}; + +// static +OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = { + &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone +}; + +OMXNodeInstance::OMXNodeInstance( + OMX *owner, const sp<IOMXObserver> &observer) + : mOwner(owner), + mNodeID(NULL), + mHandle(NULL), + mObserver(observer) { +} + +OMXNodeInstance::~OMXNodeInstance() { + CHECK_EQ(mHandle, NULL); +} + +void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) { + CHECK_EQ(mHandle, NULL); + mNodeID = node_id; + mHandle = handle; +} + +OMX *OMXNodeInstance::owner() { + return mOwner; +} + +sp<IOMXObserver> OMXNodeInstance::observer() { + return mObserver; +} + +OMX::node_id OMXNodeInstance::nodeID() { + return mNodeID; +} + +static status_t StatusFromOMXError(OMX_ERRORTYPE err) { + return (err == OMX_ErrorNone) ? OK : UNKNOWN_ERROR; +} + +status_t OMXNodeInstance::freeNode() { + Mutex::Autolock autoLock(mLock); + + OMX_ERRORTYPE err = OMX_MasterFreeHandle(mHandle); + mHandle = NULL; + + if (err != OMX_ErrorNone) { + LOGE("FreeHandle FAILED with error 0x%08x.", err); + } + + mOwner->invalidateNodeID(mNodeID); + mNodeID = NULL; + + LOGI("OMXNodeInstance going away."); + delete this; + + return StatusFromOMXError(err); +} + +status_t OMXNodeInstance::sendCommand( + OMX_COMMANDTYPE cmd, OMX_S32 param) { + Mutex::Autolock autoLock(mLock); + + OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); + return StatusFromOMXError(err); +} + +status_t OMXNodeInstance::getParameter( + OMX_INDEXTYPE index, void *params, size_t size) { + Mutex::Autolock autoLock(mLock); + + OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); + return StatusFromOMXError(err); +} + +status_t OMXNodeInstance::setParameter( + OMX_INDEXTYPE index, const void *params, size_t size) { + Mutex::Autolock autoLock(mLock); + + OMX_ERRORTYPE err = OMX_SetParameter( + mHandle, index, const_cast<void *>(params)); + + return StatusFromOMXError(err); +} + +status_t OMXNodeInstance::getConfig( + OMX_INDEXTYPE index, void *params, size_t size) { + Mutex::Autolock autoLock(mLock); + + OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); + return StatusFromOMXError(err); +} + +status_t OMXNodeInstance::setConfig( + OMX_INDEXTYPE index, const void *params, size_t size) { + Mutex::Autolock autoLock(mLock); + + OMX_ERRORTYPE err = OMX_SetConfig( + mHandle, index, const_cast<void *>(params)); + + return StatusFromOMXError(err); +} + +status_t OMXNodeInstance::useBuffer( + OMX_U32 portIndex, const sp<IMemory> ¶ms, + OMX::buffer_id *buffer) { + Mutex::Autolock autoLock(mLock); + + BufferMeta *buffer_meta = new BufferMeta(params); + + OMX_BUFFERHEADERTYPE *header; + + OMX_ERRORTYPE err = OMX_UseBuffer( + mHandle, &header, portIndex, buffer_meta, + params->size(), static_cast<OMX_U8 *>(params->pointer())); + + if (err != OMX_ErrorNone) { + LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); + + delete buffer_meta; + buffer_meta = NULL; + + *buffer = 0; + + return UNKNOWN_ERROR; + } + + *buffer = header; + + return OK; +} + +status_t OMXNodeInstance::allocateBuffer( + OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer) { + Mutex::Autolock autoLock(mLock); + + BufferMeta *buffer_meta = new BufferMeta(size); + + OMX_BUFFERHEADERTYPE *header; + + OMX_ERRORTYPE err = OMX_AllocateBuffer( + mHandle, &header, portIndex, buffer_meta, size); + + if (err != OMX_ErrorNone) { + LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); + + delete buffer_meta; + buffer_meta = NULL; + + *buffer = 0; + + return UNKNOWN_ERROR; + } + + *buffer = header; + + return OK; +} + +status_t OMXNodeInstance::allocateBufferWithBackup( + OMX_U32 portIndex, const sp<IMemory> ¶ms, + OMX::buffer_id *buffer) { + Mutex::Autolock autoLock(mLock); + + BufferMeta *buffer_meta = new BufferMeta(params, true); + + OMX_BUFFERHEADERTYPE *header; + + OMX_ERRORTYPE err = OMX_AllocateBuffer( + mHandle, &header, portIndex, buffer_meta, params->size()); + + if (err != OMX_ErrorNone) { + LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); + + delete buffer_meta; + buffer_meta = NULL; + + *buffer = 0; + + return UNKNOWN_ERROR; + } + + *buffer = header; + + return OK; +} + +status_t OMXNodeInstance::freeBuffer( + OMX_U32 portIndex, OMX::buffer_id buffer) { + Mutex::Autolock autoLock(mLock); + + OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; + BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); + + OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); + + delete buffer_meta; + buffer_meta = NULL; + + return StatusFromOMXError(err); +} + +status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { + Mutex::Autolock autoLock(mLock); + + OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; + header->nFilledLen = 0; + header->nOffset = 0; + header->nFlags = 0; + + OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); + + return StatusFromOMXError(err); +} + +status_t OMXNodeInstance::emptyBuffer( + OMX::buffer_id buffer, + OMX_U32 rangeOffset, OMX_U32 rangeLength, + OMX_U32 flags, OMX_TICKS timestamp) { + Mutex::Autolock autoLock(mLock); + + OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; + header->nFilledLen = rangeLength; + header->nOffset = rangeOffset; + header->nFlags = flags; + header->nTimeStamp = timestamp; + + BufferMeta *buffer_meta = + static_cast<BufferMeta *>(header->pAppPrivate); + buffer_meta->CopyToOMX(header); + + OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); + + return StatusFromOMXError(err); +} + +status_t OMXNodeInstance::getExtensionIndex( + const char *parameterName, OMX_INDEXTYPE *index) { + Mutex::Autolock autoLock(mLock); + + OMX_ERRORTYPE err = OMX_GetExtensionIndex( + mHandle, const_cast<char *>(parameterName), index); + + return StatusFromOMXError(err); +} + +void OMXNodeInstance::onMessage(const omx_message &msg) { + if (msg.type == omx_message::FILL_BUFFER_DONE) { + OMX_BUFFERHEADERTYPE *buffer = + static_cast<OMX_BUFFERHEADERTYPE *>( + msg.u.extended_buffer_data.buffer); + + BufferMeta *buffer_meta = + static_cast<BufferMeta *>(buffer->pAppPrivate); + + buffer_meta->CopyFromOMX(buffer); + } + + mObserver->onMessage(msg); +} + +void OMXNodeInstance::onObserverDied() { + LOGE("!!! Observer died. Quickly, do something, ... anything..."); + + // Try to force shutdown of the node and hope for the best. + freeNode(); +} + +void OMXNodeInstance::onGetHandleFailed() { + delete this; +} + +// static +OMX_ERRORTYPE OMXNodeInstance::OnEvent( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, + OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData) { + OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); + return instance->owner()->OnEvent( + instance->nodeID(), eEvent, nData1, nData2, pEventData); +} + +// static +OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { + OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); + return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer); +} + +// static +OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { + OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); + return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer); +} + +} // namespace android + |