diff options
author | Eino-Ville Talvala <etalvala@google.com> | 2012-07-18 17:46:06 -0700 |
---|---|---|
committer | Eino-Ville Talvala <etalvala@google.com> | 2012-07-24 16:59:21 -0700 |
commit | bf5bea96f236adb5eef78c2f414ef82b3602a0f7 (patch) | |
tree | ec9dcb7ffdb2de6257fcee026583ffe998fef1d8 /media/libstagefright | |
parent | 7aa1b72252749c990c9a5efce3d8fe399261b88e (diff) | |
download | frameworks_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-x | media/libstagefright/CameraSource.cpp | 4 | ||||
-rwxr-xr-x | media/libstagefright/OMXCodec.cpp | 3 | ||||
-rw-r--r-- | media/libstagefright/codecs/avc/enc/Android.mk | 2 | ||||
-rw-r--r-- | media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp | 120 | ||||
-rw-r--r-- | media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h | 12 | ||||
-rw-r--r-- | media/libstagefright/codecs/m4v_h263/enc/Android.mk | 2 | ||||
-rw-r--r-- | media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp | 117 | ||||
-rw-r--r-- | media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h | 13 |
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); }; |