diff options
Diffstat (limited to 'media/libstagefright/omx/OMXNodeInstance.cpp')
-rw-r--r-- | media/libstagefright/omx/OMXNodeInstance.cpp | 252 |
1 files changed, 221 insertions, 31 deletions
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index 8c949cb..c09064f 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -101,23 +101,34 @@ static void InitOMXParams(T *params) { namespace android { struct BufferMeta { - BufferMeta(const sp<IMemory> &mem, bool is_backup = false) + BufferMeta( + const sp<IMemory> &mem, OMX_U32 portIndex, bool copyToOmx, + bool copyFromOmx, OMX_U8 *backup) : mMem(mem), - mIsBackup(is_backup) { + mCopyFromOmx(copyFromOmx), + mCopyToOmx(copyToOmx), + mPortIndex(portIndex), + mBackup(backup) { } - BufferMeta(size_t size) + BufferMeta(size_t size, OMX_U32 portIndex) : mSize(size), - mIsBackup(false) { + mCopyFromOmx(false), + mCopyToOmx(false), + mPortIndex(portIndex), + mBackup(NULL) { } - BufferMeta(const sp<GraphicBuffer> &graphicBuffer) + BufferMeta(const sp<GraphicBuffer> &graphicBuffer, OMX_U32 portIndex) : mGraphicBuffer(graphicBuffer), - mIsBackup(false) { + mCopyFromOmx(false), + mCopyToOmx(false), + mPortIndex(portIndex), + mBackup(NULL) { } void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { - if (!mIsBackup) { + if (!mCopyFromOmx) { return; } @@ -129,7 +140,7 @@ struct BufferMeta { } void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { - if (!mIsBackup) { + if (!mCopyToOmx) { return; } @@ -159,15 +170,30 @@ struct BufferMeta { return buf; } + bool copyToOmx() const { + return mCopyToOmx; + } + void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) { mGraphicBuffer = graphicBuffer; } + OMX_U32 getPortIndex() { + return mPortIndex; + } + + ~BufferMeta() { + delete[] mBackup; + } + private: sp<GraphicBuffer> mGraphicBuffer; sp<IMemory> mMem; size_t mSize; - bool mIsBackup; + bool mCopyFromOmx; + bool mCopyToOmx; + OMX_U32 mPortIndex; + OMX_U8 *mBackup; BufferMeta(const BufferMeta &); BufferMeta &operator=(const BufferMeta &); @@ -193,6 +219,8 @@ OMXNodeInstance::OMXNodeInstance( mNodeID(0), mHandle(NULL), mObserver(observer), + mSailed(false), + mQueriedProhibitedExtensions(false), mBufferIDCount(0) { mName = ADebug::GetDebugName(name); @@ -366,7 +394,11 @@ status_t OMXNodeInstance::freeNode(OMXMaster *master) { status_t OMXNodeInstance::sendCommand( OMX_COMMANDTYPE cmd, OMX_S32 param) { - const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); + if (cmd == OMX_CommandStateSet) { + // There are no configurations past first StateSet command. + mSailed = true; + } + const sp<GraphicBufferSource> bufferSource(getGraphicBufferSource()); if (bufferSource != NULL && cmd == OMX_CommandStateSet) { if (param == OMX_StateIdle) { // Initiating transition from Executing -> Idle @@ -399,10 +431,57 @@ status_t OMXNodeInstance::sendCommand( return StatusFromOMXError(err); } +bool OMXNodeInstance::isProhibitedIndex_l(OMX_INDEXTYPE index) { + // these extensions can only be used from OMXNodeInstance, not by clients directly. + static const char *restricted_extensions[] = { + "OMX.google.android.index.storeMetaDataInBuffers", + "OMX.google.android.index.storeANWBufferInMetadata", + "OMX.google.android.index.prepareForAdaptivePlayback", + "OMX.google.android.index.configureVideoTunnelMode", + "OMX.google.android.index.useAndroidNativeBuffer2", + "OMX.google.android.index.useAndroidNativeBuffer", + "OMX.google.android.index.enableAndroidNativeBuffers", + "OMX.google.android.index.allocateNativeHandle", + "OMX.google.android.index.getAndroidNativeBufferUsage", + }; + + if ((index > OMX_IndexComponentStartUnused && index <= OMX_IndexParamStandardComponentRole) + || (index > OMX_IndexPortStartUnused && index <= OMX_IndexParamCompBufferSupplier) + || (index > OMX_IndexAudioStartUnused && index <= OMX_IndexConfigAudioChannelVolume) + || (index > OMX_IndexVideoStartUnused && index <= OMX_IndexConfigVideoNalSize) + || (index > OMX_IndexCommonStartUnused + && index <= OMX_IndexConfigCommonTransitionEffect) + || (index > (OMX_INDEXTYPE)OMX_IndexExtAudioStartUnused + && index <= (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3) + || (index > (OMX_INDEXTYPE)OMX_IndexExtVideoStartUnused + && index <= (OMX_INDEXTYPE)OMX_IndexParamSliceSegments) + || (index > (OMX_INDEXTYPE)OMX_IndexExtOtherStartUnused + && index <= (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits)) { + return false; + } + + if (!mQueriedProhibitedExtensions) { + for (size_t i = 0; i < NELEM(restricted_extensions); ++i) { + OMX_INDEXTYPE ext; + if (OMX_GetExtensionIndex(mHandle, (OMX_STRING)restricted_extensions[i], &ext) == OMX_ErrorNone) { + mProhibitedExtensions.add(ext); + } + } + mQueriedProhibitedExtensions = true; + } + + return mProhibitedExtensions.indexOf(index) >= 0; +} + status_t OMXNodeInstance::getParameter( OMX_INDEXTYPE index, void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); + if (isProhibitedIndex_l(index)) { + android_errorWriteLog(0x534e4554, "29422020"); + return BAD_INDEX; + } + OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; // some errors are expected for getParameter @@ -418,6 +497,11 @@ status_t OMXNodeInstance::setParameter( OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params); + if (isProhibitedIndex_l(index)) { + android_errorWriteLog(0x534e4554, "29422020"); + return BAD_INDEX; + } + OMX_ERRORTYPE err = OMX_SetParameter( mHandle, index, const_cast<void *>(params)); CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index); @@ -428,6 +512,11 @@ status_t OMXNodeInstance::getConfig( OMX_INDEXTYPE index, void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); + if (isProhibitedIndex_l(index)) { + android_errorWriteLog(0x534e4554, "29422020"); + return BAD_INDEX; + } + OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; // some errors are expected for getConfig @@ -443,6 +532,11 @@ status_t OMXNodeInstance::setConfig( OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index; CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params); + if (isProhibitedIndex_l(index)) { + android_errorWriteLog(0x534e4554, "29422020"); + return BAD_INDEX; + } + OMX_ERRORTYPE err = OMX_SetConfig( mHandle, index, const_cast<void *>(params)); CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index); @@ -522,7 +616,12 @@ status_t OMXNodeInstance::storeMetaDataInBuffers( status_t OMXNodeInstance::storeMetaDataInBuffers_l( OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) { + if (mSailed) { + android_errorWriteLog(0x534e4554, "29422020"); + return INVALID_OPERATION; + } if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) { + android_errorWriteLog(0x534e4554, "26324358"); return BAD_VALUE; } @@ -588,6 +687,10 @@ status_t OMXNodeInstance::prepareForAdaptivePlayback( OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) { Mutex::Autolock autolock(mLock); + if (mSailed) { + android_errorWriteLog(0x534e4554, "29422020"); + return INVALID_OPERATION; + } CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u", portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight); @@ -618,6 +721,10 @@ status_t OMXNodeInstance::configureVideoTunnelMode( OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync, native_handle_t **sidebandHandle) { Mutex::Autolock autolock(mLock); + if (mSailed) { + android_errorWriteLog(0x534e4554, "29422020"); + return INVALID_OPERATION; + } CLOG_CONFIG(configureVideoTunnelMode, "%s:%u tun=%d sync=%u", portString(portIndex), portIndex, tunneled, audioHwSync); @@ -658,23 +765,48 @@ status_t OMXNodeInstance::configureVideoTunnelMode( status_t OMXNodeInstance::useBuffer( OMX_U32 portIndex, const sp<IMemory> ¶ms, - OMX::buffer_id *buffer, OMX_U32 allottedSize) { + OMX::buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess) { Mutex::Autolock autoLock(mLock); - if (allottedSize > params->size()) { + if (allottedSize > params->size() || portIndex >= NELEM(mNumPortBuffers)) { return BAD_VALUE; } - BufferMeta *buffer_meta = new BufferMeta(params); + // metadata buffers are not connected cross process + BufferMeta *buffer_meta; + bool isMeta = mMetadataType[portIndex] != kMetadataBufferTypeInvalid; + bool useBackup = crossProcess && isMeta; // use a backup buffer instead of the actual buffer + OMX_U8 *data = static_cast<OMX_U8 *>(params->pointer()); + // allocate backup buffer + if (useBackup) { + data = new (std::nothrow) OMX_U8[allottedSize]; + if (data == NULL) { + return NO_MEMORY; + } + memset(data, 0, allottedSize); + + // if we are not connecting the buffers, the sizes must match + if (allottedSize != params->size()) { + CLOG_ERROR(useBuffer, BAD_VALUE, SIMPLE_BUFFER(portIndex, (size_t)allottedSize, data)); + delete[] data; + return BAD_VALUE; + } + + buffer_meta = new BufferMeta( + params, portIndex, false /* copyToOmx */, false /* copyFromOmx */, data); + } else { + buffer_meta = new BufferMeta( + params, portIndex, false /* copyToOmx */, false /* copyFromOmx */, NULL); + } OMX_BUFFERHEADERTYPE *header; OMX_ERRORTYPE err = OMX_UseBuffer( mHandle, &header, portIndex, buffer_meta, - allottedSize, static_cast<OMX_U8 *>(params->pointer())); + allottedSize, data); if (err != OMX_ErrorNone) { CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER( - portIndex, (size_t)allottedSize, params->pointer())); + portIndex, (size_t)allottedSize, data)); delete buffer_meta; buffer_meta = NULL; @@ -716,7 +848,7 @@ status_t OMXNodeInstance::useGraphicBuffer2_l( return UNKNOWN_ERROR; } - BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); + BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex); OMX_BUFFERHEADERTYPE *header = NULL; OMX_U8* bufferHandle = const_cast<OMX_U8*>( @@ -774,7 +906,7 @@ status_t OMXNodeInstance::useGraphicBuffer( return StatusFromOMXError(err); } - BufferMeta *bufferMeta = new BufferMeta(graphicBuffer); + BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex); OMX_BUFFERHEADERTYPE *header; @@ -815,6 +947,9 @@ status_t OMXNodeInstance::useGraphicBuffer( status_t OMXNodeInstance::updateGraphicBufferInMeta_l( OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) { + if (header == NULL) { + return BAD_VALUE; + } if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) { return BAD_VALUE; } @@ -848,7 +983,7 @@ status_t OMXNodeInstance::updateGraphicBufferInMeta( OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, OMX::buffer_id buffer) { Mutex::Autolock autoLock(mLock); - OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); + OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex); return updateGraphicBufferInMeta_l(portIndex, graphicBuffer, buffer, header); } @@ -856,7 +991,16 @@ status_t OMXNodeInstance::createGraphicBufferSource( OMX_U32 portIndex, sp<IGraphicBufferConsumer> bufferConsumer, MetadataBufferType *type) { status_t err; - const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource(); + // only allow graphic source on input port, when there are no allocated buffers yet + if (portIndex != kPortIndexInput) { + android_errorWriteLog(0x534e4554, "29422020"); + return BAD_VALUE; + } else if (mNumPortBuffers[portIndex] > 0) { + android_errorWriteLog(0x534e4554, "29422020"); + return INVALID_OPERATION; + } + + const sp<GraphicBufferSource> surfaceCheck = getGraphicBufferSource(); if (surfaceCheck != NULL) { if (portIndex < NELEM(mMetadataType) && type != NULL) { *type = mMetadataType[portIndex]; @@ -977,7 +1121,7 @@ status_t OMXNodeInstance::allocateBuffer( void **buffer_data) { Mutex::Autolock autoLock(mLock); - BufferMeta *buffer_meta = new BufferMeta(size); + BufferMeta *buffer_meta = new BufferMeta(size, portIndex); OMX_BUFFERHEADERTYPE *header; @@ -1012,13 +1156,21 @@ status_t OMXNodeInstance::allocateBuffer( status_t OMXNodeInstance::allocateBufferWithBackup( OMX_U32 portIndex, const sp<IMemory> ¶ms, - OMX::buffer_id *buffer, OMX_U32 allottedSize) { + OMX::buffer_id *buffer, OMX_U32 allottedSize, OMX_BOOL crossProcess) { Mutex::Autolock autoLock(mLock); - if (allottedSize > params->size()) { + if (allottedSize > params->size() || portIndex >= NELEM(mNumPortBuffers)) { return BAD_VALUE; } - BufferMeta *buffer_meta = new BufferMeta(params, true); + // metadata buffers are not connected cross process + bool isMeta = mMetadataType[portIndex] != kMetadataBufferTypeInvalid; + bool copy = !(crossProcess && isMeta); + + BufferMeta *buffer_meta = new BufferMeta( + params, portIndex, + (portIndex == kPortIndexInput) && copy /* copyToOmx */, + (portIndex == kPortIndexOutput) && copy /* copyFromOmx */, + NULL /* data */); OMX_BUFFERHEADERTYPE *header; @@ -1059,7 +1211,10 @@ status_t OMXNodeInstance::freeBuffer( removeActiveBuffer(portIndex, buffer); - OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); + OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex); + if (header == NULL) { + return BAD_VALUE; + } BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); @@ -1075,7 +1230,10 @@ status_t OMXNodeInstance::freeBuffer( status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer, int fenceFd) { Mutex::Autolock autoLock(mLock); - OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); + OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexOutput); + if (header == NULL) { + return BAD_VALUE; + } header->nFilledLen = 0; header->nOffset = 0; header->nFlags = 0; @@ -1108,7 +1266,16 @@ status_t OMXNodeInstance::emptyBuffer( OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { Mutex::Autolock autoLock(mLock); - OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); + // no emptybuffer if using input surface + if (getGraphicBufferSource() != NULL) { + android_errorWriteLog(0x534e4554, "29422020"); + return INVALID_OPERATION; + } + + OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput); + if (header == NULL) { + return BAD_VALUE; + } BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); sp<ABuffer> backup = buffer_meta->getBuffer(header, true /* backup */, false /* limit */); @@ -1116,7 +1283,8 @@ status_t OMXNodeInstance::emptyBuffer( // convert incoming ANW meta buffers if component is configured for gralloc metadata mode // ignore rangeOffset in this case - if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource + if (buffer_meta->copyToOmx() + && mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource && backup->capacity() >= sizeof(VideoNativeMetadata) && codec->capacity() >= sizeof(VideoGrallocMetadata) && ((VideoNativeMetadata *)backup->base())->eType @@ -1388,7 +1556,10 @@ bool OMXNodeInstance::handleMessage(omx_message &msg) { if (msg.type == omx_message::FILL_BUFFER_DONE) { OMX_BUFFERHEADERTYPE *buffer = - findBufferHeader(msg.u.extended_buffer_data.buffer); + findBufferHeader(msg.u.extended_buffer_data.buffer, kPortIndexOutput); + if (buffer == NULL) { + return false; + } { Mutex::Autolock _l(mDebugLock); @@ -1419,7 +1590,10 @@ bool OMXNodeInstance::handleMessage(omx_message &msg) { } } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) { OMX_BUFFERHEADERTYPE *buffer = - findBufferHeader(msg.u.buffer_data.buffer); + findBufferHeader(msg.u.buffer_data.buffer, kPortIndexInput); + if (buffer == NULL) { + return false; + } { Mutex::Autolock _l(mDebugLock); @@ -1520,6 +1694,13 @@ void OMXNodeInstance::onEvent( && arg2 == OMX_StateExecuting) { bufferSource->omxExecuting(); } + + // allow configuration if we return to the loaded state + if (event == OMX_EventCmdComplete + && arg1 == OMX_CommandStateSet + && arg2 == OMX_StateLoaded) { + mSailed = false; + } } // static @@ -1620,7 +1801,8 @@ OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) return buffer; } -OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) { +OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader( + OMX::buffer_id buffer, OMX_U32 portIndex) { if (buffer == 0) { return NULL; } @@ -1630,7 +1812,15 @@ OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) { CLOGW("findBufferHeader: buffer %u not found", buffer); return NULL; } - return mBufferIDToBufferHeader.valueAt(index); + OMX_BUFFERHEADERTYPE *header = mBufferIDToBufferHeader.valueAt(index); + BufferMeta *buffer_meta = + static_cast<BufferMeta *>(header->pAppPrivate); + if (buffer_meta->getPortIndex() != portIndex) { + CLOGW("findBufferHeader: buffer %u found but with incorrect port index.", buffer); + android_errorWriteLog(0x534e4554, "28816827"); + return NULL; + } + return header; } OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { |