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/codecs/m4v_h263/enc | |
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/codecs/m4v_h263/enc')
3 files changed, 124 insertions, 8 deletions
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); }; |