OMXNodeInstance::OMXNodeInstance(
OMX *owner, const sp<IOMXObserver> &observer, const char *name)
: mOwner(owner),
- mNodeID(NULL),
+ mNodeID(0),
mHandle(NULL),
mObserver(observer),
mDying(false),
mSailed(false),
- mQueriedProhibitedExtensions(false) {
+ mQueriedProhibitedExtensions(false),
+ mBufferIDCount(0)
+{
mUsingMetadata[0] = false;
mUsingMetadata[1] = false;
mIsSecure = AString(name).endsWith(".secure");
status_t OMXNodeInstance::freeNode(OMXMaster *master) {
static int32_t kMaxNumIterations = 10;
+ // exit if we have already freed the node
+ if (mHandle == NULL) {
+ return OK;
+ }
+
// Transition the node from its current state all the way down
// to "Loaded".
// This ensures that all active buffers are properly freed even
}
mOwner->invalidateNodeID(mNodeID);
- mNodeID = NULL;
+ mNodeID = 0;
ALOGV("OMXNodeInstance going away.");
delete this;
static const char *restricted_extensions[] = {
"OMX.google.android.index.storeMetaDataInBuffers",
"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",
|| (index > OMX_IndexVideoStartUnused && index <= OMX_IndexConfigVideoNalSize)
|| (index > OMX_IndexCommonStartUnused
&& index <= OMX_IndexConfigCommonTransitionEffect)
+ || (index > (OMX_INDEXTYPE)OMX_IndexExtAudioStartUnused
+ && index <= (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation)
|| (index > (OMX_INDEXTYPE)OMX_IndexExtVideoStartUnused
- && index <= (OMX_INDEXTYPE)OMX_IndexConfigVideoVp8ReferenceFrameType)) {
+ && index <= (OMX_INDEXTYPE)OMX_IndexParamSliceSegments)) {
return false;
}
}
status_t OMXNodeInstance::getParameter(
- OMX_INDEXTYPE index, void *params, size_t size) {
+ OMX_INDEXTYPE index, void *params, size_t /* size */) {
Mutex::Autolock autoLock(mLock);
if (isProhibitedIndex_l(index)) {
}
OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
-
+ ALOGE_IF(err != OMX_ErrorNone, "getParameter(%d) ERROR: %#x", index, err);
return StatusFromOMXError(err);
}
status_t OMXNodeInstance::setParameter(
- OMX_INDEXTYPE index, const void *params, size_t size) {
+ OMX_INDEXTYPE index, const void *params, size_t /* size */) {
Mutex::Autolock autoLock(mLock);
if (isProhibitedIndex_l(index)) {
OMX_ERRORTYPE err = OMX_SetParameter(
mHandle, index, const_cast<void *>(params));
-
+ ALOGE_IF(err != OMX_ErrorNone, "setParameter(%d) ERROR: %#x", index, err);
return StatusFromOMXError(err);
}
status_t OMXNodeInstance::getConfig(
- OMX_INDEXTYPE index, void *params, size_t size) {
+ OMX_INDEXTYPE index, void *params, size_t /* size */) {
Mutex::Autolock autoLock(mLock);
if (isProhibitedIndex_l(index)) {
}
status_t OMXNodeInstance::setConfig(
- OMX_INDEXTYPE index, const void *params, size_t size) {
+ OMX_INDEXTYPE index, const void *params, size_t /* size */) {
Mutex::Autolock autoLock(mLock);
if (isProhibitedIndex_l(index)) {
OMX_U32 portIndex,
OMX_BOOL enable) {
Mutex::Autolock autolock(mLock);
- return storeMetaDataInBuffers_l(portIndex, enable);
+ return storeMetaDataInBuffers_l(
+ portIndex, enable,
+ OMX_FALSE /* useGraphicBuffer */, NULL /* usingGraphicBufferInMetadata */);
}
status_t OMXNodeInstance::storeMetaDataInBuffers_l(
OMX_U32 portIndex,
- OMX_BOOL enable) {
+ OMX_BOOL enable,
+ OMX_BOOL useGraphicBuffer,
+ OMX_BOOL *usingGraphicBufferInMetadata) {
if (mSailed) {
android_errorWriteLog(0x534e4554, "29422020");
return INVALID_OPERATION;
OMX_STRING name = const_cast<OMX_STRING>(
"OMX.google.android.index.storeMetaDataInBuffers");
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
+ OMX_STRING graphicBufferName = const_cast<OMX_STRING>(
+ "OMX.google.android.index.storeGraphicBufferInMetaData");
+ if (usingGraphicBufferInMetadata == NULL) {
+ usingGraphicBufferInMetadata = &useGraphicBuffer;
+ }
+
+ OMX_ERRORTYPE err =
+ (useGraphicBuffer && portIndex == kPortIndexInput)
+ ? OMX_GetExtensionIndex(mHandle, graphicBufferName, &index)
+ : OMX_ErrorBadParameter;
+ if (err == OMX_ErrorNone) {
+ *usingGraphicBufferInMetadata = OMX_TRUE;
+ } else {
+ *usingGraphicBufferInMetadata = OMX_FALSE;
+ err = OMX_GetExtensionIndex(mHandle, name, &index);
+ }
+
if (err != OMX_ErrorNone) {
ALOGE("OMX_GetExtensionIndex %s failed", name);
-
return StatusFromOMXError(err);
}
params.bStoreMetaData = enable;
if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) {
ALOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err);
+ *usingGraphicBufferInMetadata = OMX_FALSE;
if (enable) {
mUsingMetadata[portIndex] = false;
}
return err;
}
+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;
+ }
+
+ OMX_INDEXTYPE index;
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.configureVideoTunnelMode");
+
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
+ if (err != OMX_ErrorNone) {
+ ALOGE("configureVideoTunnelMode extension is missing!");
+ return StatusFromOMXError(err);
+ }
+
+ ConfigureVideoTunnelModeParams tunnelParams;
+ tunnelParams.nSize = sizeof(tunnelParams);
+ tunnelParams.nVersion.s.nVersionMajor = 1;
+ tunnelParams.nVersion.s.nVersionMinor = 0;
+ tunnelParams.nVersion.s.nRevision = 0;
+ tunnelParams.nVersion.s.nStep = 0;
+
+ tunnelParams.nPortIndex = portIndex;
+ tunnelParams.bTunneled = tunneled;
+ tunnelParams.nAudioHwSync = audioHwSync;
+ err = OMX_SetParameter(mHandle, index, &tunnelParams);
+ if (err != OMX_ErrorNone) {
+ ALOGE("configureVideoTunnelMode failed! (err %d).", err);
+ return UNKNOWN_ERROR;
+ }
+
+ err = OMX_GetParameter(mHandle, index, &tunnelParams);
+ if (err != OMX_ErrorNone) {
+ ALOGE("GetVideoTunnelWindow failed! (err %d).", err);
+ return UNKNOWN_ERROR;
+ }
+ if (sidebandHandle) {
+ *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;
+ }
+
+ return err;
+}
+
status_t OMXNodeInstance::useBuffer(
OMX_U32 portIndex, const sp<IMemory> ¶ms,
OMX::buffer_id *buffer, OMX_BOOL crossProcess) {
CHECK_EQ(header->pAppPrivate, buffer_meta);
- *buffer = header;
+ *buffer = makeBufferID(header);
addActiveBuffer(portIndex, *buffer);
CHECK_EQ(header->pBuffer, bufferHandle);
CHECK_EQ(header->pAppPrivate, bufferMeta);
- *buffer = header;
+ *buffer = makeBufferID(header);
addActiveBuffer(portIndex, *buffer);
CHECK_EQ(header->pAppPrivate, bufferMeta);
- *buffer = header;
+ *buffer = makeBufferID(header);
addActiveBuffer(portIndex, *buffer);
OMX::buffer_id buffer) {
Mutex::Autolock autoLock(mLock);
- OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)(buffer);
+ OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
+ if (header == NULL) {
+ return BAD_VALUE;
+ }
VideoDecoderOutputMetaData *metadata =
(VideoDecoderOutputMetaData *)(header->pBuffer);
BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
- if (bufferMeta->getPortIndex() != portIndex) {
- ALOGW("buffer %u has an incorrect port index.", buffer);
- android_errorWriteLog(0x534e4554, "28816827");
- return UNKNOWN_ERROR;
- }
bufferMeta->setGraphicBuffer(graphicBuffer);
metadata->eType = kMetadataBufferTypeGrallocSource;
metadata->pHandle = graphicBuffer->handle;
}
// Input buffers will hold meta-data (gralloc references).
- err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE);
+ OMX_BOOL usingGraphicBuffer = OMX_FALSE;
+ err = storeMetaDataInBuffers_l(
+ portIndex, OMX_TRUE,
+ OMX_TRUE /* useGraphicBuffer */, &usingGraphicBuffer);
if (err != OK) {
return err;
}
GraphicBufferSource* bufferSource = new GraphicBufferSource(
this, def.format.video.nFrameWidth, def.format.video.nFrameHeight,
- def.nBufferCountActual);
+ def.nBufferCountActual, usingGraphicBuffer);
if ((err = bufferSource->initCheck()) != OK) {
delete bufferSource;
return err;
CHECK_EQ(header->pAppPrivate, buffer_meta);
- *buffer = header;
+ *buffer = makeBufferID(header);
*buffer_data = header->pBuffer;
addActiveBuffer(portIndex, *buffer);
CHECK_EQ(header->pAppPrivate, buffer_meta);
memset(header->pBuffer, 0, header->nAllocLen);
- *buffer = header;
+ *buffer = makeBufferID(header);
addActiveBuffer(portIndex, *buffer);
removeActiveBuffer(portIndex, buffer);
- OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
- BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
- if (buffer_meta->getPortIndex() != portIndex) {
- ALOGW("buffer %u has an incorrect port index.", buffer);
- android_errorWriteLog(0x534e4554, "28816827");
- // continue freeing
+ 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);
delete buffer_meta;
buffer_meta = NULL;
+ invalidateBufferID(buffer);
return StatusFromOMXError(err);
}
status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
Mutex::Autolock autoLock(mLock);
- OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+ OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexOutput);
+ if (header == NULL) {
+ return BAD_VALUE;
+ }
header->nFilledLen = 0;
header->nOffset = 0;
header->nFlags = 0;
- BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
- if (buffer_meta->getPortIndex() != kPortIndexOutput) {
- ALOGW("buffer %u has an incorrect port index.", buffer);
- android_errorWriteLog(0x534e4554, "28816827");
- return UNKNOWN_ERROR;
- }
-
OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
return StatusFromOMXError(err);
OMX_U32 flags, OMX_TICKS timestamp) {
Mutex::Autolock autoLock(mLock);
- OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
-
// no emptybuffer if using input surface
if (getGraphicBufferSource() != NULL) {
android_errorWriteLog(0x534e4554, "29422020");
return INVALID_OPERATION;
}
+ OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
// rangeLength and rangeOffset must be a subset of the allocated data in the buffer.
// corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0.
if (header == NULL
BufferMeta *buffer_meta =
static_cast<BufferMeta *>(header->pAppPrivate);
- if (buffer_meta->getPortIndex() != kPortIndexInput) {
- ALOGW("buffer %u has an incorrect port index.", buffer);
- android_errorWriteLog(0x534e4554, "28816827");
- return UNKNOWN_ERROR;
- }
buffer_meta->CopyToOMX(header);
OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
case IOMX::INTERNAL_OPTION_SUSPEND:
case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP:
+ case IOMX::INTERNAL_OPTION_START_TIME:
+ case IOMX::INTERNAL_OPTION_TIME_LAPSE:
{
const sp<GraphicBufferSource> &bufferSource =
getGraphicBufferSource();
int64_t delayUs = *(int64_t *)data;
return bufferSource->setRepeatPreviousFrameDelayUs(delayUs);
- } else {
+ } else if (type ==
+ IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP){
if (size != sizeof(int64_t)) {
return INVALID_OPERATION;
}
int64_t maxGapUs = *(int64_t *)data;
return bufferSource->setMaxTimestampGapUs(maxGapUs);
+ } else if (type == IOMX::INTERNAL_OPTION_START_TIME) {
+ if (size != sizeof(int64_t)) {
+ return INVALID_OPERATION;
+ }
+
+ int64_t skipFramesBeforeUs = *(int64_t *)data;
+
+ bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs);
+ } else { // IOMX::INTERNAL_OPTION_TIME_LAPSE
+ if (size != sizeof(int64_t) * 2) {
+ return INVALID_OPERATION;
+ }
+
+ bufferSource->setTimeLapseUs((int64_t *)data);
}
return OK;
if (msg.type == omx_message::FILL_BUFFER_DONE) {
OMX_BUFFERHEADERTYPE *buffer =
- static_cast<OMX_BUFFERHEADERTYPE *>(
- msg.u.extended_buffer_data.buffer);
+ findBufferHeader(msg.u.extended_buffer_data.buffer, kPortIndexOutput);
+ if (buffer == NULL) {
+ return;
+ }
BufferMeta *buffer_meta =
static_cast<BufferMeta *>(buffer->pAppPrivate);
- if (buffer_meta->getPortIndex() != kPortIndexOutput) {
- ALOGW("buffer %u has an incorrect port index.", buffer);
- android_errorWriteLog(0x534e4554, "28816827");
- } else {
- buffer_meta->CopyFromOMX(buffer);
- }
+
+ buffer_meta->CopyFromOMX(buffer);
if (bufferSource != NULL) {
// fix up the buffer info (especially timestamp) if needed
// be very confused.
OMX_BUFFERHEADERTYPE *buffer =
- static_cast<OMX_BUFFERHEADERTYPE *>(
- msg.u.buffer_data.buffer);
+ findBufferHeader(msg.u.buffer_data.buffer, kPortIndexInput);
+ if (buffer == NULL) {
+ return;
+ }
bufferSource->codecBufferEmptied(buffer);
return;
// static
OMX_ERRORTYPE OMXNodeInstance::OnEvent(
- OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_HANDLETYPE /* hComponent */,
OMX_IN OMX_PTR pAppData,
OMX_IN OMX_EVENTTYPE eEvent,
OMX_IN OMX_U32 nData1,
// static
OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
- OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_HANDLETYPE /* hComponent */,
OMX_IN OMX_PTR pAppData,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
if (instance->mDying) {
return OMX_ErrorNone;
}
- return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
+ return instance->owner()->OnEmptyBufferDone(instance->nodeID(),
+ instance->findBufferID(pBuffer), pBuffer);
}
// static
OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
- OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_HANDLETYPE /* hComponent */,
OMX_IN OMX_PTR pAppData,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
if (instance->mDying) {
return OMX_ErrorNone;
}
- return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer);
+ return instance->owner()->OnFillBufferDone(instance->nodeID(),
+ instance->findBufferID(pBuffer), pBuffer);
}
void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
}
}
+OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
+ if (bufferHeader == NULL) {
+ return 0;
+ }
+ Mutex::Autolock autoLock(mBufferIDLock);
+ OMX::buffer_id buffer;
+ do { // handle the very unlikely case of ID overflow
+ if (++mBufferIDCount == 0) {
+ ++mBufferIDCount;
+ }
+ buffer = (OMX::buffer_id)mBufferIDCount;
+ } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0);
+ mBufferIDToBufferHeader.add(buffer, bufferHeader);
+ mBufferHeaderToBufferID.add(bufferHeader, buffer);
+ return buffer;
+}
+
+OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(
+ OMX::buffer_id buffer, OMX_U32 portIndex) {
+ if (buffer == 0) {
+ return NULL;
+ }
+ Mutex::Autolock autoLock(mBufferIDLock);
+ ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
+ if (index < 0) {
+ ALOGW("findBufferHeader: buffer %u not found", buffer);
+ return NULL;
+ }
+ OMX_BUFFERHEADERTYPE *header = mBufferIDToBufferHeader.valueAt(index);
+ BufferMeta *buffer_meta =
+ static_cast<BufferMeta *>(header->pAppPrivate);
+ if (buffer_meta->getPortIndex() != portIndex) {
+ ALOGW("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) {
+ if (bufferHeader == NULL) {
+ return 0;
+ }
+ Mutex::Autolock autoLock(mBufferIDLock);
+ return mBufferHeaderToBufferID.valueFor(bufferHeader);
+}
+
+void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) {
+ if (buffer == 0) {
+ return;
+ }
+ Mutex::Autolock autoLock(mBufferIDLock);
+ mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueFor(buffer));
+ mBufferIDToBufferHeader.removeItem(buffer);
+}
+
} // namespace android