summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/omx/OMXNodeInstance.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/omx/OMXNodeInstance.cpp')
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp181
1 files changed, 165 insertions, 16 deletions
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index bff3def..a9eb94f 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -20,14 +20,18 @@
#include "../include/OMXNodeInstance.h"
#include "OMXMaster.h"
+#include "GraphicBufferSource.h"
#include <OMX_Component.h>
#include <binder/IMemory.h>
+#include <gui/BufferQueue.h>
#include <HardwareAPI.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaErrors.h>
+static const OMX_U32 kPortIndexInput = 0;
+
namespace android {
struct BufferMeta {
@@ -100,6 +104,17 @@ void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
mHandle = handle;
}
+sp<GraphicBufferSource> OMXNodeInstance::getGraphicBufferSource() {
+ Mutex::Autolock autoLock(mGraphicBufferSourceLock);
+ return mGraphicBufferSource;
+}
+
+void OMXNodeInstance::setGraphicBufferSource(
+ const sp<GraphicBufferSource>& bufferSource) {
+ Mutex::Autolock autoLock(mGraphicBufferSourceLock);
+ mGraphicBufferSource = bufferSource;
+}
+
OMX *OMXNodeInstance::owner() {
return mOwner;
}
@@ -277,15 +292,16 @@ status_t OMXNodeInstance::getState(OMX_STATETYPE* state) {
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,
- const_cast<OMX_STRING>("OMX.google.android.index.enableAndroidNativeBuffers"),
- &index);
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex failed");
+ if (enable) {
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
+ }
return StatusFromOMXError(err);
}
@@ -316,14 +332,12 @@ status_t OMXNodeInstance::getGraphicBufferUsage(
Mutex::Autolock autoLock(mLock);
OMX_INDEXTYPE index;
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(
- mHandle,
- const_cast<OMX_STRING>(
- "OMX.google.android.index.getAndroidNativeBufferUsage"),
- &index);
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.getAndroidNativeBufferUsage");
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex failed");
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
return StatusFromOMXError(err);
}
@@ -354,7 +368,12 @@ status_t OMXNodeInstance::storeMetaDataInBuffers(
OMX_U32 portIndex,
OMX_BOOL enable) {
Mutex::Autolock autolock(mLock);
+ return storeMetaDataInBuffers_l(portIndex, enable);
+}
+status_t OMXNodeInstance::storeMetaDataInBuffers_l(
+ OMX_U32 portIndex,
+ OMX_BOOL enable) {
OMX_INDEXTYPE index;
OMX_STRING name = const_cast<OMX_STRING>(
"OMX.google.android.index.storeMetaDataInBuffers");
@@ -362,6 +381,7 @@ status_t OMXNodeInstance::storeMetaDataInBuffers(
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
ALOGE("OMX_GetExtensionIndex %s failed", name);
+
return StatusFromOMXError(err);
}
@@ -411,6 +431,11 @@ status_t OMXNodeInstance::useBuffer(
addActiveBuffer(portIndex, *buffer);
+ sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
+ if (bufferSource != NULL && portIndex == kPortIndexInput) {
+ bufferSource->addCodecBuffer(header);
+ }
+
return OK;
}
@@ -482,13 +507,12 @@ status_t OMXNodeInstance::useGraphicBuffer(
return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
}
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(
- mHandle,
- const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"),
- &index);
+ 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 failed");
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
return StatusFromOMXError(err);
}
@@ -530,6 +554,65 @@ status_t OMXNodeInstance::useGraphicBuffer(
return OK;
}
+status_t OMXNodeInstance::createInputSurface(
+ OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer) {
+ Mutex::Autolock autolock(mLock);
+ status_t err;
+
+ const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource();
+ if (surfaceCheck != NULL) {
+ return ALREADY_EXISTS;
+ }
+
+ // Input buffers will hold meta-data (gralloc references).
+ err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE);
+ if (err != OK) {
+ return err;
+ }
+
+ // Retrieve the width and height of the graphic buffer, set when the
+ // codec was configured.
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 0;
+ def.nVersion.s.nRevision = 0;
+ def.nVersion.s.nStep = 0;
+ def.nPortIndex = portIndex;
+ OMX_ERRORTYPE oerr = OMX_GetParameter(
+ mHandle, OMX_IndexParamPortDefinition, &def);
+ CHECK(oerr == OMX_ErrorNone);
+
+ if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) {
+ ALOGE("createInputSurface requires AndroidOpaque color format");
+ return INVALID_OPERATION;
+ }
+
+ GraphicBufferSource* bufferSource = new GraphicBufferSource(
+ this, def.format.video.nFrameWidth, def.format.video.nFrameHeight,
+ def.nBufferCountActual);
+ if ((err = bufferSource->initCheck()) != OK) {
+ delete bufferSource;
+ return err;
+ }
+ setGraphicBufferSource(bufferSource);
+
+ *bufferProducer = bufferSource->getIGraphicBufferProducer();
+ return OK;
+}
+
+status_t OMXNodeInstance::signalEndOfInputStream() {
+ // For non-Surface input, the MediaCodec should convert the call to a
+ // pair of requests (dequeue input buffer, queue input buffer with EOS
+ // flag set). Seems easier than doing the equivalent from here.
+ sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
+ if (bufferSource == NULL) {
+ ALOGW("signalEndOfInputStream can only be used with Surface input");
+ return INVALID_OPERATION;
+ };
+ return bufferSource->signalEndOfInputStream();
+}
+
status_t OMXNodeInstance::allocateBuffer(
OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
void **buffer_data) {
@@ -560,6 +643,11 @@ status_t OMXNodeInstance::allocateBuffer(
addActiveBuffer(portIndex, *buffer);
+ sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
+ if (bufferSource != NULL && portIndex == kPortIndexInput) {
+ bufferSource->addCodecBuffer(header);
+ }
+
return OK;
}
@@ -592,6 +680,11 @@ status_t OMXNodeInstance::allocateBufferWithBackup(
addActiveBuffer(portIndex, *buffer);
+ sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
+ if (bufferSource != NULL && portIndex == kPortIndexInput) {
+ bufferSource->addCodecBuffer(header);
+ }
+
return OK;
}
@@ -646,6 +739,26 @@ status_t OMXNodeInstance::emptyBuffer(
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::getExtensionIndex(
const char *parameterName, OMX_INDEXTYPE *index) {
Mutex::Autolock autoLock(mLock);
@@ -666,6 +779,23 @@ void OMXNodeInstance::onMessage(const omx_message &msg) {
static_cast<BufferMeta *>(buffer->pAppPrivate);
buffer_meta->CopyFromOMX(buffer);
+ } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
+ const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
+
+ if (bufferSource != NULL) {
+ // This is one of the buffers used exclusively by
+ // GraphicBufferSource.
+ // Don't dispatch a message back to ACodec, since it doesn't
+ // know that anyone asked to have the buffer emptied and will
+ // be very confused.
+
+ OMX_BUFFERHEADERTYPE *buffer =
+ static_cast<OMX_BUFFERHEADERTYPE *>(
+ msg.u.buffer_data.buffer);
+
+ bufferSource->codecBufferEmptied(buffer);
+ return;
+ }
}
mObserver->onMessage(msg);
@@ -682,6 +812,25 @@ void OMXNodeInstance::onGetHandleFailed() {
delete this;
}
+// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
+// Don't try to acquire mLock here -- in rare circumstances this will hang.
+void OMXNodeInstance::onEvent(
+ OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
+ const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
+
+ if (bufferSource != NULL && event == OMX_EventCmdComplete &&
+ arg1 == OMX_CommandStateSet) {
+ if (arg2 == OMX_StateExecuting) {
+ bufferSource->omxExecuting();
+ } else if (arg2 == OMX_StateLoaded) {
+ // Must be shutting down -- won't have a GraphicBufferSource
+ // on the way up.
+ bufferSource->omxLoaded();
+ setGraphicBufferSource(NULL);
+ }
+ }
+}
+
// static
OMX_ERRORTYPE OMXNodeInstance::OnEvent(
OMX_IN OMX_HANDLETYPE hComponent,