summaryrefslogtreecommitdiffstats
path: root/media/libstagefright
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2012-07-18 17:46:06 -0700
committerEino-Ville Talvala <etalvala@google.com>2012-07-24 16:59:21 -0700
commitbf5bea96f236adb5eef78c2f414ef82b3602a0f7 (patch)
treeec9dcb7ffdb2de6257fcee026583ffe998fef1d8 /media/libstagefright
parent7aa1b72252749c990c9a5efce3d8fe399261b88e (diff)
downloadframeworks_av-bf5bea96f236adb5eef78c2f414ef82b3602a0f7.zip
frameworks_av-bf5bea96f236adb5eef78c2f414ef82b3602a0f7.tar.gz
frameworks_av-bf5bea96f236adb5eef78c2f414ef82b3602a0f7.tar.bz2
Codecs: Add MetaDataMode support to software video encoders.
This support is needed to enable efficient video recording with emulator and camera HAL 2. - Update SoftAVCEncoder and SoftMPEG4Encoder to support MetaDataMode extension. - Allow CameraSource to handle opaque pixel formats, so that MetaDataMode can be used. - Remove hardware codec restriction for MetaDataMode Bug: 6243944 Change-Id: I970eb3d55542a413b6d75a78f76d3a8583155601
Diffstat (limited to 'media/libstagefright')
-rwxr-xr-xmedia/libstagefright/CameraSource.cpp4
-rwxr-xr-xmedia/libstagefright/OMXCodec.cpp3
-rw-r--r--media/libstagefright/codecs/avc/enc/Android.mk2
-rw-r--r--media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp120
-rw-r--r--media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h12
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/Android.mk2
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp117
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h13
8 files changed, 257 insertions, 16 deletions
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 3ddad93..a604c8f 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -111,6 +111,10 @@ static int32_t getColorFormat(const char* colorFormat) {
return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
}
+ if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE)) {
+ return OMX_COLOR_FormatAndroidOpaque;
+ }
+
ALOGE("Uknown color format (%s), please add it to "
"CameraSource::getColorFormat", colorFormat);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 1d4ab32..8fbcb8a 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -301,6 +301,9 @@ sp<MediaSource> OMXCodec::Create(
&matchingCodecs, &matchingCodecQuirks);
if (matchingCodecs.isEmpty()) {
+ ALOGV("No matching codecs! (mime: %s, createEncoder: %s, "
+ "matchComponentName: %s, flags: 0x%x)",
+ mime, createEncoder ? "true" : "false", matchComponentName, flags);
return NULL;
}
diff --git a/media/libstagefright/codecs/avc/enc/Android.mk b/media/libstagefright/codecs/avc/enc/Android.mk
index 48923cf..0aecfa8 100644
--- a/media/libstagefright/codecs/avc/enc/Android.mk
+++ b/media/libstagefright/codecs/avc/enc/Android.mk
@@ -42,6 +42,7 @@ LOCAL_SRC_FILES := \
LOCAL_C_INCLUDES := \
frameworks/av/media/libstagefright/include \
+ frameworks/native/include/media/hardware \
frameworks/native/include/media/openmax \
$(LOCAL_PATH)/src \
$(LOCAL_PATH)/include \
@@ -63,6 +64,7 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright_foundation \
libstagefright_omx \
libutils \
+ libui
LOCAL_MODULE := libstagefright_soft_h264enc
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
index c6f658d..117f3f1 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
@@ -22,11 +22,15 @@
#include "avcenc_int.h"
#include "OMX_Video.h"
+#include <HardwareAPI.h>
+#include <MetadataBufferType.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
+#include <ui/Rect.h>
+#include <ui/GraphicBufferMapper.h>
#include "SoftAVCEncoder.h"
@@ -171,6 +175,7 @@ SoftAVCEncoder::SoftAVCEncoder(
mVideoFrameRate(30),
mVideoBitRate(192000),
mVideoColorFormat(OMX_COLOR_FormatYUV420Planar),
+ mStoreMetaDataInBuffers(false),
mIDRFrameRefreshIntervalInSec(1),
mAVCEncProfile(AVC_BASELINE),
mAVCEncLevel(AVC_LEVEL2),
@@ -448,7 +453,7 @@ OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter(
return OMX_ErrorUndefined;
}
- if (formatParams->nIndex > 1) {
+ if (formatParams->nIndex > 2) {
return OMX_ErrorNoMore;
}
@@ -456,8 +461,10 @@ OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter(
formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
if (formatParams->nIndex == 0) {
formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
- } else {
+ } else if (formatParams->nIndex == 1) {
formatParams->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ } else {
+ formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
}
} else {
formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
@@ -529,7 +536,9 @@ OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter(
OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter(
OMX_INDEXTYPE index, const OMX_PTR params) {
- switch (index) {
+ int32_t indexFull = index;
+
+ switch (indexFull) {
case OMX_IndexParamVideoErrorCorrection:
{
return OMX_ErrorNotImplemented;
@@ -560,7 +569,8 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter(
if (def->nPortIndex == 0) {
if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused ||
(def->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar &&
- def->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar)) {
+ def->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar &&
+ def->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
return OMX_ErrorUndefined;
}
} else {
@@ -610,7 +620,7 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter(
return OMX_ErrorUndefined;
}
- if (formatParams->nIndex > 1) {
+ if (formatParams->nIndex > 2) {
return OMX_ErrorNoMore;
}
@@ -619,7 +629,9 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter(
((formatParams->nIndex == 0 &&
formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) ||
(formatParams->nIndex == 1 &&
- formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar))) {
+ formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) ||
+ (formatParams->nIndex == 2 &&
+ formatParams->eColorFormat != OMX_COLOR_FormatAndroidOpaque) )) {
return OMX_ErrorUndefined;
}
mVideoColorFormat = formatParams->eColorFormat;
@@ -666,6 +678,31 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter(
return OMX_ErrorNone;
}
+ case kStoreMetaDataExtensionIndex:
+ {
+ StoreMetaDataInBuffersParams *storeParams =
+ (StoreMetaDataInBuffersParams*)params;
+ if (storeParams->nPortIndex != 0) {
+ ALOGE("%s: StoreMetadataInBuffersParams.nPortIndex not zero!",
+ __FUNCTION__);
+ return OMX_ErrorUndefined;
+ }
+
+ mStoreMetaDataInBuffers = storeParams->bStoreMetaData;
+ ALOGV("StoreMetaDataInBuffers set to: %s",
+ mStoreMetaDataInBuffers ? " true" : "false");
+
+ if (mStoreMetaDataInBuffers) {
+ mVideoColorFormat == OMX_COLOR_FormatYUV420SemiPlanar;
+ if (mInputFrameData == NULL) {
+ mInputFrameData =
+ (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+ }
+ }
+
+ return OMX_ErrorNone;
+ }
+
default:
return SimpleSoftOMXComponent::internalSetParameter(index, params);
}
@@ -744,6 +781,8 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 portIndex) {
}
}
+ buffer_handle_t srcBuffer; // for MetaDataMode only
+
// Get next input video frame
if (mReadyForNextFrame) {
// Save the input buffer info so that it can be
@@ -764,8 +803,28 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 portIndex) {
videoInput.height = ((mVideoHeight + 15) >> 4) << 4;
videoInput.pitch = ((mVideoWidth + 15) >> 4) << 4;
videoInput.coding_timestamp = (inHeader->nTimeStamp + 500) / 1000; // in ms
- const void *inData = inHeader->pBuffer + inHeader->nOffset;
- uint8_t *inputData = (uint8_t *) inData;
+ uint8_t *inputData = NULL;
+ if (mStoreMetaDataInBuffers) {
+ if (inHeader->nFilledLen != 8) {
+ ALOGE("MetaData buffer is wrong size! "
+ "(got %lu bytes, expected 8)", inHeader->nFilledLen);
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return;
+ }
+ inputData =
+ extractGrallocData(inHeader->pBuffer + inHeader->nOffset,
+ &srcBuffer);
+ if (inputData == NULL) {
+ ALOGE("Unable to extract gralloc buffer in metadata mode");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return;
+ }
+ // TODO: Verify/convert pixel format enum
+ } else {
+ inputData = (uint8_t *)inHeader->pBuffer + inHeader->nOffset;
+ }
if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
ConvertYUV420SemiPlanarToYUV420Planar(
@@ -790,12 +849,14 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 portIndex) {
if (encoderStatus < AVCENC_SUCCESS) {
ALOGE("encoderStatus = %d at line %d", encoderStatus, __LINE__);
mSignalledError = true;
+ releaseGrallocData(srcBuffer);
notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
return;
} else {
ALOGV("encoderStatus = %d at line %d", encoderStatus, __LINE__);
inQueue.erase(inQueue.begin());
inInfo->mOwnedByUs = false;
+ releaseGrallocData(srcBuffer);
notifyEmptyBufferDone(inHeader);
return;
}
@@ -829,6 +890,7 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 portIndex) {
if (encoderStatus < AVCENC_SUCCESS) {
ALOGE("encoderStatus = %d at line %d", encoderStatus, __LINE__);
mSignalledError = true;
+ releaseGrallocData(srcBuffer);
notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
return;
}
@@ -838,6 +900,7 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 portIndex) {
inQueue.erase(inQueue.begin());
inInfo->mOwnedByUs = false;
+ releaseGrallocData(srcBuffer);
notifyEmptyBufferDone(inHeader);
outQueue.erase(outQueue.begin());
@@ -881,6 +944,47 @@ void SoftAVCEncoder::signalBufferReturned(MediaBuffer *buffer) {
ALOGV("signalBufferReturned: %p", buffer);
}
+OMX_ERRORTYPE SoftAVCEncoder::getExtensionIndex(
+ const char *name, OMX_INDEXTYPE *index) {
+ if (!strcmp(name, "OMX.google.android.index.storeMetaDataInBuffers")) {
+ *(int32_t*)index = kStoreMetaDataExtensionIndex;
+ return OMX_ErrorNone;
+ }
+ return OMX_ErrorUndefined;
+}
+
+uint8_t *SoftAVCEncoder::extractGrallocData(void *data, buffer_handle_t *buffer) {
+ OMX_U32 type = *(OMX_U32*)data;
+ status_t res;
+ if (type != kMetadataBufferTypeGrallocSource) {
+ ALOGE("Data passed in with metadata mode does not have type "
+ "kMetadataBufferTypeGrallocSource (%d), has type %ld instead",
+ kMetadataBufferTypeGrallocSource, type);
+ return NULL;
+ }
+ buffer_handle_t imgBuffer = *(buffer_handle_t*)((uint8_t*)data + 4);
+
+ const Rect rect(mVideoWidth, mVideoHeight);
+ uint8_t *img;
+ res = GraphicBufferMapper::get().lock(imgBuffer,
+ GRALLOC_USAGE_HW_VIDEO_ENCODER,
+ rect, (void**)&img);
+ if (res != OK) {
+ ALOGE("%s: Unable to lock image buffer %p for access", __FUNCTION__,
+ imgBuffer);
+ return NULL;
+ }
+
+ *buffer = imgBuffer;
+ return img;
+}
+
+void SoftAVCEncoder::releaseGrallocData(buffer_handle_t buffer) {
+ if (mStoreMetaDataInBuffers) {
+ GraphicBufferMapper::get().unlock(buffer);
+ }
+}
+
} // namespace android
android::SoftOMXComponent *createSoftOMXComponent(
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
index a2587c6..23d5ff1 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
@@ -45,6 +45,10 @@ struct SoftAVCEncoder : public MediaBufferObserver,
virtual void onQueueFilled(OMX_U32 portIndex);
+ // Override SoftOMXComponent methods
+
+ virtual OMX_ERRORTYPE getExtensionIndex(
+ const char *name, OMX_INDEXTYPE *index);
// Implement MediaBufferObserver
virtual void signalBufferReturned(MediaBuffer *buffer);
@@ -63,6 +67,10 @@ private:
kNumBuffers = 2,
};
+ enum {
+ kStoreMetaDataExtensionIndex = OMX_IndexVendorStartUnused + 1
+ };
+
// OMX input buffer's timestamp and flags
typedef struct {
int64_t mTimeUs;
@@ -74,6 +82,7 @@ private:
int32_t mVideoFrameRate;
int32_t mVideoBitRate;
int32_t mVideoColorFormat;
+ bool mStoreMetaDataInBuffers;
int32_t mIDRFrameRefreshIntervalInSec;
AVCProfile mAVCEncProfile;
AVCLevel mAVCEncLevel;
@@ -100,6 +109,9 @@ private:
OMX_ERRORTYPE releaseEncoder();
void releaseOutputBuffers();
+ uint8_t* extractGrallocData(void *data, buffer_handle_t *buffer);
+ void releaseGrallocData(buffer_handle_t buffer);
+
DISALLOW_EVIL_CONSTRUCTORS(SoftAVCEncoder);
};
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.mk b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
index 484180d..865cc9c 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
@@ -45,6 +45,7 @@ LOCAL_SRC_FILES := \
LOCAL_C_INCLUDES := \
frameworks/av/media/libstagefright/include \
frameworks/native/include/media/openmax \
+ frameworks/native/include/media/hardware \
$(LOCAL_PATH)/src \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/../common/include \
@@ -64,6 +65,7 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright_foundation \
libstagefright_omx \
libutils \
+ libui
LOCAL_MODULE := libstagefright_soft_mpeg4enc
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index a5a2332..8bc0275 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -21,11 +21,15 @@
#include "mp4enc_api.h"
#include "OMX_Video.h"
+#include <HardwareAPI.h>
+#include <MetadataBufferType.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
+#include <ui/Rect.h>
+#include <ui/GraphicBufferMapper.h>
#include "SoftMPEG4Encoder.h"
@@ -82,6 +86,7 @@ SoftMPEG4Encoder::SoftMPEG4Encoder(
mVideoFrameRate(30),
mVideoBitRate(192000),
mVideoColorFormat(OMX_COLOR_FormatYUV420Planar),
+ mStoreMetaDataInBuffers(false),
mIDRFrameRefreshIntervalInSec(1),
mNumInputFrames(-1),
mStarted(false),
@@ -321,7 +326,7 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter(
return OMX_ErrorUndefined;
}
- if (formatParams->nIndex > 1) {
+ if (formatParams->nIndex > 2) {
return OMX_ErrorNoMore;
}
@@ -329,8 +334,10 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter(
formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
if (formatParams->nIndex == 0) {
formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
- } else {
+ } else if (formatParams->nIndex == 1) {
formatParams->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ } else {
+ formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
}
} else {
formatParams->eCompressionFormat =
@@ -420,7 +427,9 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter(
OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter(
OMX_INDEXTYPE index, const OMX_PTR params) {
- switch (index) {
+ int32_t indexFull = index;
+
+ switch (indexFull) {
case OMX_IndexParamVideoErrorCorrection:
{
return OMX_ErrorNotImplemented;
@@ -451,7 +460,8 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter(
if (def->nPortIndex == 0) {
if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused ||
(def->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar &&
- def->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar)) {
+ def->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar &&
+ def->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
return OMX_ErrorUndefined;
}
} else {
@@ -505,7 +515,7 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter(
return OMX_ErrorUndefined;
}
- if (formatParams->nIndex > 1) {
+ if (formatParams->nIndex > 2) {
return OMX_ErrorNoMore;
}
@@ -514,7 +524,9 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter(
((formatParams->nIndex == 0 &&
formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) ||
(formatParams->nIndex == 1 &&
- formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar))) {
+ formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) ||
+ (formatParams->nIndex == 2 &&
+ formatParams->eColorFormat != OMX_COLOR_FormatAndroidOpaque) )) {
return OMX_ErrorUndefined;
}
mVideoColorFormat = formatParams->eColorFormat;
@@ -578,6 +590,31 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter(
return OMX_ErrorNone;
}
+ case kStoreMetaDataExtensionIndex:
+ {
+ StoreMetaDataInBuffersParams *storeParams =
+ (StoreMetaDataInBuffersParams*)params;
+ if (storeParams->nPortIndex != 0) {
+ ALOGE("%s: StoreMetadataInBuffersParams.nPortIndex not zero!",
+ __FUNCTION__);
+ return OMX_ErrorUndefined;
+ }
+
+ mStoreMetaDataInBuffers = storeParams->bStoreMetaData;
+ ALOGV("StoreMetaDataInBuffers set to: %s",
+ mStoreMetaDataInBuffers ? " true" : "false");
+
+ if (mStoreMetaDataInBuffers) {
+ mVideoColorFormat == OMX_COLOR_FormatYUV420SemiPlanar;
+ if (mInputFrameData == NULL) {
+ mInputFrameData =
+ (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+ }
+ }
+
+ return OMX_ErrorNone;
+ }
+
default:
return SimpleSoftOMXComponent::internalSetParameter(index, params);
}
@@ -640,9 +677,31 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 portIndex) {
mSawInputEOS = true;
}
+ buffer_handle_t srcBuffer; // for MetaDataMode only
if (inHeader->nFilledLen > 0) {
- const void *inData = inHeader->pBuffer + inHeader->nOffset;
- uint8_t *inputData = (uint8_t *) inData;
+ uint8_t *inputData = NULL;
+ if (mStoreMetaDataInBuffers) {
+ if (inHeader->nFilledLen != 8) {
+ ALOGE("MetaData buffer is wrong size! "
+ "(got %lu bytes, expected 8)", inHeader->nFilledLen);
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return;
+ }
+ inputData =
+ extractGrallocData(inHeader->pBuffer + inHeader->nOffset,
+ &srcBuffer);
+ if (inputData == NULL) {
+ ALOGE("Unable to extract gralloc buffer in metadata mode");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
+ return;
+ }
+ // TODO: Verify/convert pixel format enum
+ } else {
+ inputData = (uint8_t *)inHeader->pBuffer + inHeader->nOffset;
+ }
+
if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
ConvertYUV420SemiPlanarToYUV420Planar(
inputData, mInputFrameData, mVideoWidth, mVideoHeight);
@@ -683,6 +742,7 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 portIndex) {
inQueue.erase(inQueue.begin());
inInfo->mOwnedByUs = false;
+ releaseGrallocData(srcBuffer);
notifyEmptyBufferDone(inHeader);
outQueue.erase(outQueue.begin());
@@ -697,6 +757,47 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 portIndex) {
}
}
+OMX_ERRORTYPE SoftMPEG4Encoder::getExtensionIndex(
+ const char *name, OMX_INDEXTYPE *index) {
+ if (!strcmp(name, "OMX.google.android.index.storeMetaDataInBuffers")) {
+ *(int32_t*)index = kStoreMetaDataExtensionIndex;
+ return OMX_ErrorNone;
+ }
+ return OMX_ErrorUndefined;
+}
+
+uint8_t *SoftMPEG4Encoder::extractGrallocData(void *data, buffer_handle_t *buffer) {
+ OMX_U32 type = *(OMX_U32*)data;
+ status_t res;
+ if (type != kMetadataBufferTypeGrallocSource) {
+ ALOGE("Data passed in with metadata mode does not have type "
+ "kMetadataBufferTypeGrallocSource (%d), has type %ld instead",
+ kMetadataBufferTypeGrallocSource, type);
+ return NULL;
+ }
+ buffer_handle_t imgBuffer = *(buffer_handle_t*)((uint8_t*)data + 4);
+
+ const Rect rect(mVideoWidth, mVideoHeight);
+ uint8_t *img;
+ res = GraphicBufferMapper::get().lock(imgBuffer,
+ GRALLOC_USAGE_HW_VIDEO_ENCODER,
+ rect, (void**)&img);
+ if (res != OK) {
+ ALOGE("%s: Unable to lock image buffer %p for access", __FUNCTION__,
+ imgBuffer);
+ return NULL;
+ }
+
+ *buffer = imgBuffer;
+ return img;
+}
+
+void SoftMPEG4Encoder::releaseGrallocData(buffer_handle_t buffer) {
+ if (mStoreMetaDataInBuffers) {
+ GraphicBufferMapper::get().unlock(buffer);
+ }
+}
+
} // namespace android
android::SoftOMXComponent *createSoftOMXComponent(
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
index 3e90d54..cc4ea8f 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
@@ -43,6 +43,11 @@ struct SoftMPEG4Encoder : public SimpleSoftOMXComponent {
virtual void onQueueFilled(OMX_U32 portIndex);
+ // Override SoftOMXComponent methods
+
+ virtual OMX_ERRORTYPE getExtensionIndex(
+ const char *name, OMX_INDEXTYPE *index);
+
protected:
virtual ~SoftMPEG4Encoder();
@@ -51,6 +56,10 @@ private:
kNumBuffers = 2,
};
+ enum {
+ kStoreMetaDataExtensionIndex = OMX_IndexVendorStartUnused + 1
+ };
+
// OMX input buffer's timestamp and flags
typedef struct {
int64_t mTimeUs;
@@ -63,6 +72,7 @@ private:
int32_t mVideoFrameRate;
int32_t mVideoBitRate;
int32_t mVideoColorFormat;
+ bool mStoreMetaDataInBuffers;
int32_t mIDRFrameRefreshIntervalInSec;
int64_t mNumInputFrames;
@@ -80,6 +90,9 @@ private:
OMX_ERRORTYPE initEncoder();
OMX_ERRORTYPE releaseEncoder();
+ uint8_t* extractGrallocData(void *data, buffer_handle_t *buffer);
+ void releaseGrallocData(buffer_handle_t buffer);
+
DISALLOW_EVIL_CONSTRUCTORS(SoftMPEG4Encoder);
};