status_t OMXNodeInstance::getState(OMX_STATETYPE* state) { Mutex::Autolock autoLock(mLock); OMX_ERRORTYPE err = OMX_GetState(mHandle, state); 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::storeMetaDataInBuffers( OMX_U32 portIndex, OMX_BOOL enable) { Mutex::Autolock autolock(mLock); OMX_INDEXTYPE index; OMX_STRING name = const_cast<OMX_STRING>( "OMX.google.android.index.storeMetaDataInBuffers"); OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); if (err != OMX_ErrorNone) { ALOGE("OMX_GetExtensionIndex %s failed", name); return StatusFromOMXError(err); } StoreMetaDataInBuffersParams params; memset(¶ms, 0, sizeof(params)); params.nSize = sizeof(params); // Version: 1.0.0.0 params.nVersion.s.nVersionMajor = 1; params.nPortIndex = portIndex; params.bStoreMetaData = enable; if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) { ALOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err); return UNKNOWN_ERROR; } return err; }
// XXX: This function is here for backwards compatibility. Once the OMX // implementations have been updated this can be removed and useGraphicBuffer2 // can be renamed to useGraphicBuffer. status_t OMXNodeInstance::useGraphicBuffer( OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, OMX::buffer_id *buffer) { Mutex::Autolock autoLock(mLock); // See if the newer version of the extension is present. OMX_INDEXTYPE index; if (OMX_GetExtensionIndex( mHandle, const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"), &index) == OMX_ErrorNone) { return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer); } OMX_STRING name = const_cast<OMX_STRING>( "OMX.google.android.index.useAndroidNativeBuffer"); OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); if (err != OMX_ErrorNone) { ALOGE("OMX_GetExtensionIndex %s failed", name); return StatusFromOMXError(err); } BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); OMX_BUFFERHEADERTYPE *header; OMX_VERSIONTYPE ver; ver.s.nVersionMajor = 1; ver.s.nVersionMinor = 0; ver.s.nRevision = 0; ver.s.nStep = 0; UseAndroidNativeBufferParams params = { sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta, &header, graphicBuffer, }; err = OMX_SetParameter(mHandle, index, ¶ms); if (err != OMX_ErrorNone) { ALOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err, err); delete bufferMeta; bufferMeta = NULL; *buffer = 0; return UNKNOWN_ERROR; } CHECK_EQ(header->pAppPrivate, bufferMeta); *buffer = header; addActiveBuffer(portIndex, *buffer); return OK; }
status_t OMXNodeInstance::prepareForAdaptivePlayback( OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) { Mutex::Autolock autolock(mLock); OMX_INDEXTYPE index; OMX_STRING name = const_cast<OMX_STRING>( "OMX.google.android.index.prepareForAdaptivePlayback"); OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); if (err != OMX_ErrorNone) { ALOGW_IF(enable, "OMX_GetExtensionIndex %s failed", name); return StatusFromOMXError(err); } PrepareForAdaptivePlaybackParams params; params.nSize = sizeof(params); params.nVersion.s.nVersionMajor = 1; params.nVersion.s.nVersionMinor = 0; params.nVersion.s.nRevision = 0; params.nVersion.s.nStep = 0; params.nPortIndex = portIndex; params.bEnable = enable; params.nMaxFrameWidth = maxFrameWidth; params.nMaxFrameHeight = maxFrameHeight; if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) { ALOGW("OMX_SetParameter failed for PrepareForAdaptivePlayback " "with error %d (0x%08x)", err, err); return UNKNOWN_ERROR; } return err; }
status_t OMX::allocateNode( const char *name, const sp<IOMXObserver> &observer, node_id *node) { Mutex::Autolock autoLock(mLock); *node = 0; OMXNodeInstance *instance = new OMXNodeInstance(this, observer, name); OMX_COMPONENTTYPE *handle; OMX_ERRORTYPE err = mMaster->makeComponentInstance( name, &OMXNodeInstance::kCallbacks, instance, &handle); if (err != OMX_ErrorNone) { ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err); instance->onGetHandleFailed(); return StatusFromOMXError(err); } *node = makeNodeID(instance); mDispatchers.add(*node, new CallbackDispatcher(instance)); instance->setHandle(*node, handle); mLiveNodes.add(IInterface::asBinder(observer), instance); IInterface::asBinder(observer)->linkToDeath(this); return OK; }
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::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); }
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::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::freeBuffer( OMX_U32 portIndex, OMX::buffer_id buffer) { Mutex::Autolock autoLock(mLock); removeActiveBuffer(portIndex, buffer); 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); }
// like emptyBuffer, but the data is already in header->pBuffer status_t OMXNodeInstance::emptyDirectBuffer( OMX_BUFFERHEADERTYPE *header, OMX_U32 rangeOffset, OMX_U32 rangeLength, OMX_U32 flags, OMX_TICKS timestamp) { Mutex::Autolock autoLock(mLock); header->nFilledLen = rangeLength; header->nOffset = rangeOffset; header->nFlags = flags; header->nTimeStamp = timestamp; OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); if (err != OMX_ErrorNone) { ALOGW("emptyDirectBuffer failed, OMX err=0x%x", err); } 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::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); if (err != OMX_ErrorNone) { ALOGW("OMX_FreeBuffer failed w/ err %x, do not remove from active buffer list", err); } else { ALOGE("OMX_FreeBuffer for buffer header %p successful", header); removeActiveBuffer(portIndex, buffer); delete buffer_meta; buffer_meta = NULL; } return StatusFromOMXError(err); }
status_t OMXNodeInstance::getGraphicBufferUsage( OMX_U32 portIndex, OMX_U32* usage) { Mutex::Autolock autoLock(mLock); OMX_INDEXTYPE index; OMX_ERRORTYPE err = OMX_GetExtensionIndex( mHandle, const_cast<OMX_STRING>( "OMX.google.android.index.getAndroidNativeBufferUsage"), &index); if (err != OMX_ErrorNone) { ALOGE("OMX_GetExtensionIndex failed"); return StatusFromOMXError(err); } OMX_VERSIONTYPE ver; ver.s.nVersionMajor = 1; ver.s.nVersionMinor = 0; ver.s.nRevision = 0; ver.s.nStep = 0; GetAndroidNativeBufferUsageParams params = { sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0, }; err = OMX_GetParameter(mHandle, index, ¶ms); if (err != OMX_ErrorNone) { ALOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)", err, err); return UNKNOWN_ERROR; } *usage = params.nUsage; return OK; }
status_t OMXNodeInstance::enableGraphicBuffers( OMX_U32 portIndex, OMX_BOOL enable) { Mutex::Autolock autoLock(mLock); OMX_STRING name = const_cast<OMX_STRING>( "OMX.google.android.index.enableAndroidNativeBuffers"); OMX_INDEXTYPE index; OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); if (err != OMX_ErrorNone) { if (enable) { ALOGE("OMX_GetExtensionIndex %s failed", name); } return StatusFromOMXError(err); } OMX_VERSIONTYPE ver; ver.s.nVersionMajor = 1; ver.s.nVersionMinor = 0; ver.s.nRevision = 0; ver.s.nStep = 0; EnableAndroidNativeBuffersParams params = { sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable, }; err = OMX_SetParameter(mHandle, index, ¶ms); if (err != OMX_ErrorNone) { ALOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)", err, err); return UNKNOWN_ERROR; } return OK; }
status_t OMXNodeInstance::sendCommand( OMX_COMMANDTYPE cmd, OMX_S32 param) { const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); if (bufferSource != NULL && cmd == OMX_CommandStateSet) { if (param == OMX_StateIdle) { // Initiating transition from Executing -> Idle // ACodec is waiting for all buffers to be returned, do NOT // submit any more buffers to the codec. bufferSource->omxIdle(); } else if (param == OMX_StateLoaded) { // Initiating transition from Idle/Executing -> Loaded // Buffers are about to be freed. bufferSource->omxLoaded(); setGraphicBufferSource(NULL); } // fall through } Mutex::Autolock autoLock(mLock); OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); return StatusFromOMXError(err); }
status_t OMXNodeInstance::freeNode() { // Transition the node from its current state all the way down // to "Loaded". // This ensures that all active buffers are properly freed even // for components that don't do this themselves on a call to // "FreeHandle". OMX_STATETYPE state; CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone); switch (state) { case OMX_StateExecuting: { LOGV("forcing Executing->Idle"); sendCommand(OMX_CommandStateSet, OMX_StateIdle); OMX_ERRORTYPE err; while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone && state != OMX_StateIdle) { usleep(100000); } CHECK_EQ(err, OMX_ErrorNone); // fall through } case OMX_StateIdle: { LOGV("forcing Idle->Loaded"); sendCommand(OMX_CommandStateSet, OMX_StateLoaded); freeActiveBuffers(); OMX_ERRORTYPE err; while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone && state != OMX_StateLoaded) { LOGV("waiting for Loaded state..."); usleep(100000); } CHECK_EQ(err, OMX_ErrorNone); // fall through } case OMX_StateLoaded: case OMX_StateInvalid: break; default: CHECK(!"should not be here, unknown state."); break; } 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; LOGV("OMXNodeInstance going away."); delete this; return StatusFromOMXError(err); }
status_t OMXNodeInstance::freeNode(OMXMaster *master) { static int32_t kMaxNumIterations = 10; // Transition the node from its current state all the way down // to "Loaded". // This ensures that all active buffers are properly freed even // for components that don't do this themselves on a call to // "FreeHandle". // The code below may trigger some more events to be dispatched // by the OMX component - we want to ignore them as our client // does not expect them. mDying = true; OMX_STATETYPE state; CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone); switch (state) { case OMX_StateExecuting: { ALOGV("forcing Executing->Idle"); sendCommand(OMX_CommandStateSet, OMX_StateIdle); OMX_ERRORTYPE err; int32_t iteration = 0; while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone && state != OMX_StateIdle && state != OMX_StateInvalid) { if (++iteration > kMaxNumIterations) { ALOGE("component failed to enter Idle state, aborting."); state = OMX_StateInvalid; break; } usleep(100000); } CHECK_EQ(err, OMX_ErrorNone); if (state == OMX_StateInvalid) { break; } // fall through } case OMX_StateIdle: { ALOGV("forcing Idle->Loaded"); sendCommand(OMX_CommandStateSet, OMX_StateLoaded); freeActiveBuffers(); OMX_ERRORTYPE err; int32_t iteration = 0; while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone && state != OMX_StateLoaded && state != OMX_StateInvalid) { if (++iteration > kMaxNumIterations) { ALOGE("component failed to enter Loaded state, aborting."); state = OMX_StateInvalid; break; } ALOGV("waiting for Loaded state..."); usleep(100000); } CHECK_EQ(err, OMX_ErrorNone); // fall through } case OMX_StateLoaded: case OMX_StateInvalid: break; default: CHECK(!"should not be here, unknown state."); break; } ALOGV("calling destroyComponentInstance"); OMX_ERRORTYPE err = master->destroyComponentInstance( static_cast<OMX_COMPONENTTYPE *>(mHandle)); ALOGV("destroyComponentInstance returned err %d", err); mHandle = NULL; if (err != OMX_ErrorNone) { ALOGE("FreeHandle FAILED with error 0x%08x.", err); } mOwner->invalidateNodeID(mNodeID); mNodeID = NULL; ALOGV("OMXNodeInstance going away."); delete this; return StatusFromOMXError(err); }