From a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Wed, 24 Sep 2014 13:57:35 -0700 Subject: stagefright: misc fixes to software video encoders (and decoders) - move logic to set encoder parameters to common encoder class (similarly to what was done for decoders) - set compressed buffer size based on frame size and compression ratio, and codec-specific minimum size - set raw buffer size based on frame size and metadata mode - do not set stride and slice height on compressed ports - advertise only QCIF support for google H263 encoder - set large-enough input size for video decoders to support adaptive playback - do not change input buffer size on output port reconfiguration, as no input buffer reallocation takes place - do not return empty buffers with EOS after EOS has been signaled Bug: 18513091 Bug: 18639027 Change-Id: Ib13492ef66adf331aa4572c67d2b283ea020cb41 --- include/media/stagefright/foundation/AUtils.h | 6 + media/libstagefright/ACodec.cpp | 3 +- .../codecs/avc/enc/SoftAVCEncoder.cpp | 351 ++++---------------- .../libstagefright/codecs/avc/enc/SoftAVCEncoder.h | 7 - media/libstagefright/codecs/hevcdec/SoftHEVC.cpp | 11 +- .../codecs/m4v_h263/dec/SoftMPEG4.cpp | 13 +- .../libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h | 2 +- .../codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp | 361 ++++----------------- .../codecs/m4v_h263/enc/SoftMPEG4Encoder.h | 13 +- media/libstagefright/codecs/on2/dec/SoftVPX.cpp | 11 +- .../codecs/on2/enc/SoftVPXEncoder.cpp | 327 ++----------------- .../libstagefright/codecs/on2/enc/SoftVPXEncoder.h | 38 --- .../libstagefright/codecs/on2/h264dec/SoftAVC.cpp | 6 +- .../data/media_codecs_google_video.xml | 2 +- .../include/SoftVideoDecoderOMXComponent.h | 8 +- .../include/SoftVideoEncoderOMXComponent.h | 38 +++ .../omx/SoftVideoDecoderOMXComponent.cpp | 86 +++-- .../omx/SoftVideoEncoderOMXComponent.cpp | 307 +++++++++++++++++- media/libstagefright/tests/Utils_test.cpp | 7 + 19 files changed, 600 insertions(+), 997 deletions(-) diff --git a/include/media/stagefright/foundation/AUtils.h b/include/media/stagefright/foundation/AUtils.h index 3a73a39..d7ecf50 100644 --- a/include/media/stagefright/foundation/AUtils.h +++ b/include/media/stagefright/foundation/AUtils.h @@ -40,6 +40,12 @@ inline static const T divUp(const T &nom, const T &den) { } } +/* == ceil(nom / den) * den. T must be integer type, alignment must be positive power of 2 */ +template +inline static const T align(const T &nom, const U &den) { + return (nom + (T)(den - 1)) & (T)~(den - 1); +} + template inline static T abs(const T &a) { return a < 0 ? -a : a; diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 1a9b012..208f0d5 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -4240,7 +4240,8 @@ bool ACodec::BaseState::onOMXFillBufferDone( case RESUBMIT_BUFFERS: { - if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { + if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS) + || mCodec->mPortEOS[kPortIndexOutput])) { ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID); diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp index bb55871..24dfc29 100644 --- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp +++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp @@ -17,6 +17,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "SoftAVCEncoder" #include +#include #include "avcenc_api.h" #include "avcenc_int.h" @@ -25,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -51,31 +53,36 @@ static void InitOMXParams(T *params) { params->nVersion.s.nStep = 0; } +static const CodecProfileLevel kProfileLevels[] = { + { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2 }, +}; + typedef struct LevelConversion { OMX_U32 omxLevel; AVCLevel avcLevel; + uint32_t maxMacroBlocks; } LevelConcersion; static LevelConversion ConversionTable[] = { - { OMX_VIDEO_AVCLevel1, AVC_LEVEL1_B }, - { OMX_VIDEO_AVCLevel1b, AVC_LEVEL1 }, - { OMX_VIDEO_AVCLevel11, AVC_LEVEL1_1 }, - { OMX_VIDEO_AVCLevel12, AVC_LEVEL1_2 }, - { OMX_VIDEO_AVCLevel13, AVC_LEVEL1_3 }, - { OMX_VIDEO_AVCLevel2, AVC_LEVEL2 }, + { OMX_VIDEO_AVCLevel1, AVC_LEVEL1_B, 99 }, + { OMX_VIDEO_AVCLevel1b, AVC_LEVEL1, 99 }, + { OMX_VIDEO_AVCLevel11, AVC_LEVEL1_1, 396 }, + { OMX_VIDEO_AVCLevel12, AVC_LEVEL1_2, 396 }, + { OMX_VIDEO_AVCLevel13, AVC_LEVEL1_3, 396 }, + { OMX_VIDEO_AVCLevel2, AVC_LEVEL2, 396 }, #if 0 - // encoding speed is very poor if video - // resolution is higher than CIF - { OMX_VIDEO_AVCLevel21, AVC_LEVEL2_1 }, - { OMX_VIDEO_AVCLevel22, AVC_LEVEL2_2 }, - { OMX_VIDEO_AVCLevel3, AVC_LEVEL3 }, - { OMX_VIDEO_AVCLevel31, AVC_LEVEL3_1 }, - { OMX_VIDEO_AVCLevel32, AVC_LEVEL3_2 }, - { OMX_VIDEO_AVCLevel4, AVC_LEVEL4 }, - { OMX_VIDEO_AVCLevel41, AVC_LEVEL4_1 }, - { OMX_VIDEO_AVCLevel42, AVC_LEVEL4_2 }, - { OMX_VIDEO_AVCLevel5, AVC_LEVEL5 }, - { OMX_VIDEO_AVCLevel51, AVC_LEVEL5_1 }, + // encoding speed is very poor if video resolution + // is higher than CIF or if level is higher than 2 + { OMX_VIDEO_AVCLevel21, AVC_LEVEL2_1, 792 }, + { OMX_VIDEO_AVCLevel22, AVC_LEVEL2_2, 1620 }, + { OMX_VIDEO_AVCLevel3, AVC_LEVEL3, 1620 }, + { OMX_VIDEO_AVCLevel31, AVC_LEVEL3_1, 3600 }, + { OMX_VIDEO_AVCLevel32, AVC_LEVEL3_2, 5120 }, + { OMX_VIDEO_AVCLevel4, AVC_LEVEL4, 8192 }, + { OMX_VIDEO_AVCLevel41, AVC_LEVEL4_1, 8192 }, + { OMX_VIDEO_AVCLevel42, AVC_LEVEL4_2, 8704 }, + { OMX_VIDEO_AVCLevel5, AVC_LEVEL5, 22080 }, + { OMX_VIDEO_AVCLevel51, AVC_LEVEL5_1, 36864 }, #endif }; @@ -148,13 +155,11 @@ SoftAVCEncoder::SoftAVCEncoder( const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, OMX_COMPONENTTYPE **component) - : SoftVideoEncoderOMXComponent(name, callbacks, appData, component), - mVideoWidth(176), - mVideoHeight(144), - mVideoFrameRate(30), - mVideoBitRate(192000), - mVideoColorFormat(OMX_COLOR_FormatYUV420Planar), - mStoreMetaDataInBuffers(false), + : SoftVideoEncoderOMXComponent( + name, "video_encoder.avc", OMX_VIDEO_CodingAVC, + kProfileLevels, NELEM(kProfileLevels), + 176 /* width */, 144 /* height */, + callbacks, appData, component), mIDRFrameRefreshIntervalInSec(1), mAVCEncProfile(AVC_BASELINE), mAVCEncLevel(AVC_LEVEL2), @@ -168,7 +173,13 @@ SoftAVCEncoder::SoftAVCEncoder( mInputFrameData(NULL), mSliceGroup(NULL) { - initPorts(); + const size_t kOutputBufferSize = + 320 * ConversionTable[NELEM(ConversionTable) - 1].maxMacroBlocks; + + initPorts( + kNumBuffers, kNumBuffers, kOutputBufferSize, + MEDIA_MIMETYPE_VIDEO_AVC, 2 /* minCompressionRatio */); + ALOGI("Construct SoftAVCEncoder"); } @@ -230,30 +241,28 @@ OMX_ERRORTYPE SoftAVCEncoder::initEncParams() { mEncParams->use_overrun_buffer = AVC_OFF; - if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar - || mStoreMetaDataInBuffers) { + if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { // Color conversion is needed. free(mInputFrameData); mInputFrameData = - (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1); + (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1); CHECK(mInputFrameData != NULL); } // PV's AVC encoder requires the video dimension of multiple - if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) { + if (mWidth % 16 != 0 || mHeight % 16 != 0) { ALOGE("Video frame size %dx%d must be a multiple of 16", - mVideoWidth, mVideoHeight); + mWidth, mHeight); return OMX_ErrorBadParameter; } - mEncParams->width = mVideoWidth; - mEncParams->height = mVideoHeight; - mEncParams->bitrate = mVideoBitRate; - mEncParams->frame_rate = 1000 * mVideoFrameRate; // In frames/ms! - mEncParams->CPB_size = (uint32_t) (mVideoBitRate >> 1); + mEncParams->width = mWidth; + mEncParams->height = mHeight; + mEncParams->bitrate = mBitrate; + mEncParams->frame_rate = (1000 * mFramerate) >> 16; // In frames/ms!, mFramerate is in Q16 + mEncParams->CPB_size = (uint32_t) (mBitrate >> 1); - int32_t nMacroBlocks = ((((mVideoWidth + 15) >> 4) << 4) * - (((mVideoHeight + 15) >> 4) << 4)) >> 8; + int32_t nMacroBlocks = divUp(mWidth, 16) * divUp(mHeight, 16); CHECK(mSliceGroup == NULL); mSliceGroup = (uint32_t *) malloc(sizeof(uint32_t) * nMacroBlocks); CHECK(mSliceGroup != NULL); @@ -272,7 +281,7 @@ OMX_ERRORTYPE SoftAVCEncoder::initEncParams() { mEncParams->idr_period = 1; // All I frames } else { mEncParams->idr_period = - (mIDRFrameRefreshIntervalInSec * mVideoFrameRate); + (mIDRFrameRefreshIntervalInSec * mFramerate) >> 16; // mFramerate is in Q16 } // Set profile and level @@ -345,71 +354,9 @@ void SoftAVCEncoder::releaseOutputBuffers() { mOutputBuffers.clear(); } -void SoftAVCEncoder::initPorts() { - OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - - const size_t kInputBufferSize = (mVideoWidth * mVideoHeight * 3) >> 1; - - // 31584 is PV's magic number. Not sure why. - const size_t kOutputBufferSize = - (kInputBufferSize > 31584) ? kInputBufferSize: 31584; - - def.nPortIndex = 0; - def.eDir = OMX_DirInput; - def.nBufferCountMin = kNumBuffers; - def.nBufferCountActual = def.nBufferCountMin; - def.nBufferSize = kInputBufferSize; - def.bEnabled = OMX_TRUE; - def.bPopulated = OMX_FALSE; - def.eDomain = OMX_PortDomainVideo; - def.bBuffersContiguous = OMX_FALSE; - def.nBufferAlignment = 1; - - def.format.video.cMIMEType = const_cast("video/raw"); - def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; - def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; - def.format.video.xFramerate = (mVideoFrameRate << 16); // Q16 format - def.format.video.nBitrate = mVideoBitRate; - def.format.video.nFrameWidth = mVideoWidth; - def.format.video.nFrameHeight = mVideoHeight; - def.format.video.nStride = mVideoWidth; - def.format.video.nSliceHeight = mVideoHeight; - - addPort(def); - - def.nPortIndex = 1; - def.eDir = OMX_DirOutput; - def.nBufferCountMin = kNumBuffers; - def.nBufferCountActual = def.nBufferCountMin; - def.nBufferSize = kOutputBufferSize; - def.bEnabled = OMX_TRUE; - def.bPopulated = OMX_FALSE; - def.eDomain = OMX_PortDomainVideo; - def.bBuffersContiguous = OMX_FALSE; - def.nBufferAlignment = 2; - - def.format.video.cMIMEType = const_cast("video/avc"); - def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; - def.format.video.eColorFormat = OMX_COLOR_FormatUnused; - def.format.video.xFramerate = (0 << 16); // Q16 format - def.format.video.nBitrate = mVideoBitRate; - def.format.video.nFrameWidth = mVideoWidth; - def.format.video.nFrameHeight = mVideoHeight; - def.format.video.nStride = mVideoWidth; - def.format.video.nSliceHeight = mVideoHeight; - - addPort(def); -} - OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter( OMX_INDEXTYPE index, OMX_PTR params) { switch (index) { - case OMX_IndexParamVideoErrorCorrection: - { - return OMX_ErrorNotImplemented; - } - case OMX_IndexParamVideoBitrate: { OMX_VIDEO_PARAM_BITRATETYPE *bitRate = @@ -420,37 +367,7 @@ OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter( } bitRate->eControlRate = OMX_Video_ControlRateVariable; - bitRate->nTargetBitrate = mVideoBitRate; - return OMX_ErrorNone; - } - - case OMX_IndexParamVideoPortFormat: - { - OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = - (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; - - if (formatParams->nPortIndex > 1) { - return OMX_ErrorUndefined; - } - - if (formatParams->nIndex > 2) { - return OMX_ErrorNoMore; - } - - if (formatParams->nPortIndex == 0) { - formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused; - if (formatParams->nIndex == 0) { - formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar; - } else if (formatParams->nIndex == 1) { - formatParams->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - } else { - formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque; - } - } else { - formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC; - formatParams->eColorFormat = OMX_COLOR_FormatUnused; - } - + bitRate->nTargetBitrate = mBitrate; return OMX_ErrorNone; } @@ -487,30 +404,8 @@ OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter( return OMX_ErrorNone; } - case OMX_IndexParamVideoProfileLevelQuerySupported: - { - OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel = - (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)params; - - if (profileLevel->nPortIndex != 1) { - return OMX_ErrorUndefined; - } - - const size_t size = - sizeof(ConversionTable) / sizeof(ConversionTable[0]); - - if (profileLevel->nProfileIndex >= size) { - return OMX_ErrorNoMore; - } - - profileLevel->eProfile = OMX_VIDEO_AVCProfileBaseline; - profileLevel->eLevel = ConversionTable[profileLevel->nProfileIndex].omxLevel; - - return OMX_ErrorNone; - } - default: - return SimpleSoftOMXComponent::internalGetParameter(index, params); + return SoftVideoEncoderOMXComponent::internalGetParameter(index, params); } } @@ -519,11 +414,6 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter( int32_t indexFull = index; switch (indexFull) { - case OMX_IndexParamVideoErrorCorrection: - { - return OMX_ErrorNotImplemented; - } - case OMX_IndexParamVideoBitrate: { OMX_VIDEO_PARAM_BITRATETYPE *bitRate = @@ -534,109 +424,7 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter( return OMX_ErrorUndefined; } - mVideoBitRate = bitRate->nTargetBitrate; - return OMX_ErrorNone; - } - - case OMX_IndexParamPortDefinition: - { - OMX_PARAM_PORTDEFINITIONTYPE *def = - (OMX_PARAM_PORTDEFINITIONTYPE *)params; - if (def->nPortIndex > 1) { - return OMX_ErrorUndefined; - } - - 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_FormatAndroidOpaque)) { - return OMX_ErrorUndefined; - } - } else { - if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingAVC || - (def->format.video.eColorFormat != OMX_COLOR_FormatUnused)) { - return OMX_ErrorUndefined; - } - } - - OMX_ERRORTYPE err = SimpleSoftOMXComponent::internalSetParameter(index, params); - if (OMX_ErrorNone != err) { - return err; - } - - if (def->nPortIndex == 0) { - mVideoWidth = def->format.video.nFrameWidth; - mVideoHeight = def->format.video.nFrameHeight; - mVideoFrameRate = def->format.video.xFramerate >> 16; - mVideoColorFormat = def->format.video.eColorFormat; - - OMX_PARAM_PORTDEFINITIONTYPE *portDef = - &editPortInfo(0)->mDef; - portDef->format.video.nFrameWidth = mVideoWidth; - portDef->format.video.nFrameHeight = mVideoHeight; - portDef->format.video.nStride = portDef->format.video.nFrameWidth; - portDef->format.video.nSliceHeight = portDef->format.video.nFrameHeight; - portDef->format.video.xFramerate = def->format.video.xFramerate; - portDef->format.video.eColorFormat = - (OMX_COLOR_FORMATTYPE) mVideoColorFormat; - portDef->nBufferSize = - (portDef->format.video.nStride * portDef->format.video.nSliceHeight * 3) / 2; - portDef = &editPortInfo(1)->mDef; - portDef->format.video.nFrameWidth = mVideoWidth; - portDef->format.video.nFrameHeight = mVideoHeight; - } else { - mVideoBitRate = def->format.video.nBitrate; - } - - return OMX_ErrorNone; - } - - case OMX_IndexParamStandardComponentRole: - { - const OMX_PARAM_COMPONENTROLETYPE *roleParams = - (const OMX_PARAM_COMPONENTROLETYPE *)params; - - if (strncmp((const char *)roleParams->cRole, - "video_encoder.avc", - OMX_MAX_STRINGNAME_SIZE - 1)) { - return OMX_ErrorUndefined; - } - - return OMX_ErrorNone; - } - - case OMX_IndexParamVideoPortFormat: - { - const OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = - (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; - - if (formatParams->nPortIndex > 1) { - return OMX_ErrorUndefined; - } - - if (formatParams->nIndex > 2) { - return OMX_ErrorNoMore; - } - - if (formatParams->nPortIndex == 0) { - if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused || - ((formatParams->nIndex == 0 && - formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) || - (formatParams->nIndex == 1 && - formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) || - (formatParams->nIndex == 2 && - formatParams->eColorFormat != OMX_COLOR_FormatAndroidOpaque) )) { - return OMX_ErrorUndefined; - } - mVideoColorFormat = formatParams->eColorFormat; - } else { - if (formatParams->eCompressionFormat != OMX_VIDEO_CodingAVC || - formatParams->eColorFormat != OMX_COLOR_FormatUnused) { - return OMX_ErrorUndefined; - } - } - + mBitrate = bitRate->nTargetBitrate; return OMX_ErrorNone; } @@ -673,29 +461,8 @@ 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_FormatAndroidOpaque; - } - - return OMX_ErrorNone; - } - default: - return SimpleSoftOMXComponent::internalSetParameter(index, params); + return SoftVideoEncoderOMXComponent::internalSetParameter(index, params); } } @@ -789,11 +556,11 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 /* portIndex */) { if (inHeader->nFilledLen > 0) { AVCFrameIO videoInput; memset(&videoInput, 0, sizeof(videoInput)); - videoInput.height = ((mVideoHeight + 15) >> 4) << 4; - videoInput.pitch = ((mVideoWidth + 15) >> 4) << 4; + videoInput.height = align(mHeight, 16); + videoInput.pitch = align(mWidth, 16); videoInput.coding_timestamp = (inHeader->nTimeStamp + 500) / 1000; // in ms const uint8_t *inputData = NULL; - if (mStoreMetaDataInBuffers) { + if (mInputDataIsMeta) { if (inHeader->nFilledLen != 8) { ALOGE("MetaData buffer is wrong size! " "(got %u bytes, expected 8)", inHeader->nFilledLen); @@ -803,9 +570,9 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 /* portIndex */) { } inputData = extractGraphicBuffer( - mInputFrameData, (mVideoWidth * mVideoHeight * 3) >> 1, + mInputFrameData, (mWidth * mHeight * 3) >> 1, inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen, - mVideoWidth, mVideoHeight); + mWidth, mHeight); if (inputData == NULL) { ALOGE("Unable to extract gralloc buffer in metadata mode"); mSignalledError = true; @@ -815,9 +582,9 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 /* portIndex */) { // TODO: Verify/convert pixel format enum } else { inputData = (const uint8_t *)inHeader->pBuffer + inHeader->nOffset; - if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) { + if (mColorFormat != OMX_COLOR_FormatYUV420Planar) { ConvertYUV420SemiPlanarToYUV420Planar( - inputData, mInputFrameData, mVideoWidth, mVideoHeight); + inputData, mInputFrameData, mWidth, mHeight); inputData = mInputFrameData; } } diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h index 130593f..f31c1f4 100644 --- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h +++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h @@ -68,12 +68,6 @@ private: int32_t mFlags; } InputBufferInfo; - int32_t mVideoWidth; - int32_t mVideoHeight; - int32_t mVideoFrameRate; - int32_t mVideoBitRate; - int32_t mVideoColorFormat; - bool mStoreMetaDataInBuffers; int32_t mIDRFrameRefreshIntervalInSec; AVCProfile mAVCEncProfile; AVCLevel mAVCEncLevel; @@ -94,7 +88,6 @@ private: Vector mOutputBuffers; Vector mInputBufferInfoVec; - void initPorts(); OMX_ERRORTYPE initEncParams(); OMX_ERRORTYPE initEncoder(); OMX_ERRORTYPE releaseEncoder(); diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp index f4cba54..cddd176 100644 --- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp +++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp @@ -26,6 +26,7 @@ #include "SoftHEVC.h" #include +#include #include #include @@ -75,8 +76,12 @@ SoftHEVC::SoftHEVC( mNewWidth(mWidth), mNewHeight(mHeight), mChangingResolution(false) { - initPorts(kNumBuffers, INPUT_BUF_SIZE, kNumBuffers, - CODEC_MIME_TYPE); + const size_t kMinCompressionRatio = 4 /* compressionRatio (for Level 4+) */; + const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2; + // INPUT_BUF_SIZE is given by HEVC codec as minimum input size + initPorts( + kNumBuffers, max(kMaxOutputBufferSize / kMinCompressionRatio, (size_t)INPUT_BUF_SIZE), + kNumBuffers, CODEC_MIME_TYPE, kMinCompressionRatio); CHECK_EQ(initDecoder(), (status_t)OK); } @@ -644,7 +649,7 @@ void SoftHEVC::onQueueFilled(OMX_U32 portIndex) { // The decoder should be fixed so that |u4_error_code| instead of |status| returns // IHEVCD_UNSUPPORTED_DIMENSIONS. bool unsupportedDimensions = - ((IHEVCD_UNSUPPORTED_DIMENSIONS == status) + ((IHEVCD_UNSUPPORTED_DIMENSIONS == (IHEVCD_CXA_ERROR_CODES_T)status) || (IHEVCD_UNSUPPORTED_DIMENSIONS == s_dec_op.u4_error_code)); bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF)); diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp index 246069b..ede645c 100644 --- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp +++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp @@ -21,6 +21,7 @@ #include "SoftMPEG4.h" #include +#include #include #include #include @@ -70,7 +71,7 @@ SoftMPEG4::SoftMPEG4( mPvTime(0) { initPorts( kNumInputBuffers, - 8192 /* inputBufferSize */, + 352 * 288 * 3 / 2 /* minInputBufferSize */, kNumOutputBuffers, (mMode == MODE_MPEG4) ? MEDIA_MIMETYPE_VIDEO_MPEG4 : MEDIA_MIMETYPE_VIDEO_H263); @@ -353,14 +354,14 @@ void SoftMPEG4::onReset() { } } -void SoftMPEG4::updatePortDefinitions(bool updateCrop) { - SoftVideoDecoderOMXComponent::updatePortDefinitions(updateCrop); +void SoftMPEG4::updatePortDefinitions(bool updateCrop, bool updateInputSize) { + SoftVideoDecoderOMXComponent::updatePortDefinitions(updateCrop, updateInputSize); /* We have to align our width and height - this should affect stride! */ OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef; - def->nBufferSize = - (((def->format.video.nFrameWidth + 15) & -16) - * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2; + def->format.video.nStride = align(def->format.video.nStride, 16); + def->format.video.nSliceHeight = align(def->format.video.nSliceHeight, 16); + def->nBufferSize = (def->format.video.nStride * def->format.video.nSliceHeight * 3) / 2; } } // namespace android diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h index 31577e2..4114e7d 100644 --- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h +++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h @@ -66,7 +66,7 @@ private: status_t initDecoder(); - virtual void updatePortDefinitions(bool updateCrop = true); + virtual void updatePortDefinitions(bool updateCrop = true, bool updateInputSize = false); bool handlePortSettingsChange(); DISALLOW_EVIL_CONSTRUCTORS(SoftMPEG4); diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp index 400f320..fa3486c 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp @@ -17,6 +17,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "SoftMPEG4Encoder" #include +#include #include "mp4enc_api.h" #include "OMX_Video.h" @@ -24,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -46,19 +48,30 @@ static void InitOMXParams(T *params) { params->nVersion.s.nStep = 0; } +static const CodecProfileLevel kMPEG4ProfileLevels[] = { + { OMX_VIDEO_MPEG4ProfileCore, OMX_VIDEO_MPEG4Level2 }, +}; + +static const CodecProfileLevel kH263ProfileLevels[] = { + { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 }, +}; + SoftMPEG4Encoder::SoftMPEG4Encoder( const char *name, + const char *componentRole, + OMX_VIDEO_CODINGTYPE codingType, + const char *mime, + const CodecProfileLevel *profileLevels, + size_t numProfileLevels, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, OMX_COMPONENTTYPE **component) - : SoftVideoEncoderOMXComponent(name, callbacks, appData, component), + : SoftVideoEncoderOMXComponent( + name, componentRole, codingType, + profileLevels, numProfileLevels, + 176 /* width */, 144 /* height */, + callbacks, appData, component), mEncodeMode(COMBINE_MODE_WITH_ERR_RES), - mVideoWidth(176), - mVideoHeight(144), - mVideoFrameRate(30), - mVideoBitRate(192000), - mVideoColorFormat(OMX_COLOR_FormatYUV420Planar), - mStoreMetaDataInBuffers(false), mIDRFrameRefreshIntervalInSec(1), mNumInputFrames(-1), mStarted(false), @@ -68,13 +81,15 @@ SoftMPEG4Encoder::SoftMPEG4Encoder( mEncParams(new tagvideoEncOptions), mInputFrameData(NULL) { - if (!strcmp(name, "OMX.google.h263.encoder")) { + if (codingType == OMX_VIDEO_CodingH263) { mEncodeMode = H263_MODE; - } else { - CHECK(!strcmp(name, "OMX.google.mpeg4.encoder")); } - initPorts(); + // 256 * 1024 is a magic number for PV's encoder, not sure why + const size_t kOutputBufferSize = 256 * 1024; + + initPorts(kNumBuffers, kNumBuffers, kOutputBufferSize, mime); + ALOGI("Construct SoftMPEG4Encoder"); } @@ -98,9 +113,9 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() { return OMX_ErrorUndefined; } mEncParams->encMode = mEncodeMode; - mEncParams->encWidth[0] = mVideoWidth; - mEncParams->encHeight[0] = mVideoHeight; - mEncParams->encFrameRate[0] = mVideoFrameRate; + mEncParams->encWidth[0] = mWidth; + mEncParams->encHeight[0] = mHeight; + mEncParams->encFrameRate[0] = mFramerate >> 16; // mFramerate is in Q16 format mEncParams->rcType = VBR_1; mEncParams->vbvDelay = 5.0f; @@ -111,27 +126,26 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() { mEncParams->rvlcEnable = PV_OFF; mEncParams->numLayers = 1; mEncParams->timeIncRes = 1000; - mEncParams->tickPerSrc = mEncParams->timeIncRes / mVideoFrameRate; + mEncParams->tickPerSrc = ((int64_t)mEncParams->timeIncRes << 16) / mFramerate; - mEncParams->bitRate[0] = mVideoBitRate; + mEncParams->bitRate[0] = mBitrate; mEncParams->iQuant[0] = 15; mEncParams->pQuant[0] = 12; mEncParams->quantType[0] = 0; mEncParams->noFrameSkipped = PV_OFF; - if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar - || mStoreMetaDataInBuffers) { + if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { // Color conversion is needed. free(mInputFrameData); mInputFrameData = - (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1); + (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1); CHECK(mInputFrameData != NULL); } // PV's MPEG4 encoder requires the video dimension of multiple - if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) { + if (mWidth % 16 != 0 || mHeight % 16 != 0) { ALOGE("Video frame size %dx%d must be a multiple of 16", - mVideoWidth, mVideoHeight); + mWidth, mHeight); return OMX_ErrorBadParameter; } @@ -142,7 +156,7 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() { mEncParams->intraPeriod = 1; // All I frames } else { mEncParams->intraPeriod = - (mIDRFrameRefreshIntervalInSec * mVideoFrameRate); + (mIDRFrameRefreshIntervalInSec * mFramerate) >> 16; } mEncParams->numIntraMB = 0; @@ -201,81 +215,9 @@ OMX_ERRORTYPE SoftMPEG4Encoder::releaseEncoder() { return OMX_ErrorNone; } -void SoftMPEG4Encoder::initPorts() { - OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - - const size_t kInputBufferSize = (mVideoWidth * mVideoHeight * 3) >> 1; - - // 256 * 1024 is a magic number for PV's encoder, not sure why - const size_t kOutputBufferSize = - (kInputBufferSize > 256 * 1024) - ? kInputBufferSize: 256 * 1024; - - def.nPortIndex = 0; - def.eDir = OMX_DirInput; - def.nBufferCountMin = kNumBuffers; - def.nBufferCountActual = def.nBufferCountMin; - def.nBufferSize = kInputBufferSize; - def.bEnabled = OMX_TRUE; - def.bPopulated = OMX_FALSE; - def.eDomain = OMX_PortDomainVideo; - def.bBuffersContiguous = OMX_FALSE; - def.nBufferAlignment = 1; - - def.format.video.cMIMEType = const_cast("video/raw"); - - def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; - def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; - def.format.video.xFramerate = (mVideoFrameRate << 16); // Q16 format - def.format.video.nBitrate = mVideoBitRate; - def.format.video.nFrameWidth = mVideoWidth; - def.format.video.nFrameHeight = mVideoHeight; - def.format.video.nStride = mVideoWidth; - def.format.video.nSliceHeight = mVideoHeight; - - addPort(def); - - def.nPortIndex = 1; - def.eDir = OMX_DirOutput; - def.nBufferCountMin = kNumBuffers; - def.nBufferCountActual = def.nBufferCountMin; - def.nBufferSize = kOutputBufferSize; - def.bEnabled = OMX_TRUE; - def.bPopulated = OMX_FALSE; - def.eDomain = OMX_PortDomainVideo; - def.bBuffersContiguous = OMX_FALSE; - def.nBufferAlignment = 2; - - def.format.video.cMIMEType = - (mEncodeMode == COMBINE_MODE_WITH_ERR_RES) - ? const_cast(MEDIA_MIMETYPE_VIDEO_MPEG4) - : const_cast(MEDIA_MIMETYPE_VIDEO_H263); - - def.format.video.eCompressionFormat = - (mEncodeMode == COMBINE_MODE_WITH_ERR_RES) - ? OMX_VIDEO_CodingMPEG4 - : OMX_VIDEO_CodingH263; - - def.format.video.eColorFormat = OMX_COLOR_FormatUnused; - def.format.video.xFramerate = (0 << 16); // Q16 format - def.format.video.nBitrate = mVideoBitRate; - def.format.video.nFrameWidth = mVideoWidth; - def.format.video.nFrameHeight = mVideoHeight; - def.format.video.nStride = mVideoWidth; - def.format.video.nSliceHeight = mVideoHeight; - - addPort(def); -} - OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter( OMX_INDEXTYPE index, OMX_PTR params) { switch (index) { - case OMX_IndexParamVideoErrorCorrection: - { - return OMX_ErrorNotImplemented; - } - case OMX_IndexParamVideoBitrate: { OMX_VIDEO_PARAM_BITRATETYPE *bitRate = @@ -286,41 +228,7 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter( } bitRate->eControlRate = OMX_Video_ControlRateVariable; - bitRate->nTargetBitrate = mVideoBitRate; - return OMX_ErrorNone; - } - - case OMX_IndexParamVideoPortFormat: - { - OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = - (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; - - if (formatParams->nPortIndex > 1) { - return OMX_ErrorUndefined; - } - - if (formatParams->nIndex > 2) { - return OMX_ErrorNoMore; - } - - if (formatParams->nPortIndex == 0) { - formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused; - if (formatParams->nIndex == 0) { - formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar; - } else if (formatParams->nIndex == 1) { - formatParams->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - } else { - formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque; - } - } else { - formatParams->eCompressionFormat = - (mEncodeMode == COMBINE_MODE_WITH_ERR_RES) - ? OMX_VIDEO_CodingMPEG4 - : OMX_VIDEO_CodingH263; - - formatParams->eColorFormat = OMX_COLOR_FormatUnused; - } - + bitRate->nTargetBitrate = mBitrate; return OMX_ErrorNone; } @@ -369,32 +277,8 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter( return OMX_ErrorNone; } - case OMX_IndexParamVideoProfileLevelQuerySupported: - { - OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel = - (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)params; - - if (profileLevel->nPortIndex != 1) { - return OMX_ErrorUndefined; - } - - if (profileLevel->nProfileIndex > 0) { - return OMX_ErrorNoMore; - } - - if (mEncodeMode == H263_MODE) { - profileLevel->eProfile = OMX_VIDEO_H263ProfileBaseline; - profileLevel->eLevel = OMX_VIDEO_H263Level45; - } else { - profileLevel->eProfile = OMX_VIDEO_MPEG4ProfileCore; - profileLevel->eLevel = OMX_VIDEO_MPEG4Level2; - } - - return OMX_ErrorNone; - } - default: - return SimpleSoftOMXComponent::internalGetParameter(index, params); + return SoftVideoEncoderOMXComponent::internalGetParameter(index, params); } } @@ -403,11 +287,6 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter( int32_t indexFull = index; switch (indexFull) { - case OMX_IndexParamVideoErrorCorrection: - { - return OMX_ErrorNotImplemented; - } - case OMX_IndexParamVideoBitrate: { OMX_VIDEO_PARAM_BITRATETYPE *bitRate = @@ -418,116 +297,7 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter( return OMX_ErrorUndefined; } - mVideoBitRate = bitRate->nTargetBitrate; - return OMX_ErrorNone; - } - - case OMX_IndexParamPortDefinition: - { - OMX_PARAM_PORTDEFINITIONTYPE *def = - (OMX_PARAM_PORTDEFINITIONTYPE *)params; - if (def->nPortIndex > 1) { - return OMX_ErrorUndefined; - } - - 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_FormatAndroidOpaque)) { - return OMX_ErrorUndefined; - } - } else { - if ((mEncodeMode == COMBINE_MODE_WITH_ERR_RES && - def->format.video.eCompressionFormat != OMX_VIDEO_CodingMPEG4) || - (mEncodeMode == H263_MODE && - def->format.video.eCompressionFormat != OMX_VIDEO_CodingH263) || - (def->format.video.eColorFormat != OMX_COLOR_FormatUnused)) { - return OMX_ErrorUndefined; - } - } - - OMX_ERRORTYPE err = SimpleSoftOMXComponent::internalSetParameter(index, params); - if (OMX_ErrorNone != err) { - return err; - } - - if (def->nPortIndex == 0) { - mVideoWidth = def->format.video.nFrameWidth; - mVideoHeight = def->format.video.nFrameHeight; - mVideoFrameRate = def->format.video.xFramerate >> 16; - mVideoColorFormat = def->format.video.eColorFormat; - - OMX_PARAM_PORTDEFINITIONTYPE *portDef = - &editPortInfo(0)->mDef; - portDef->format.video.nFrameWidth = mVideoWidth; - portDef->format.video.nFrameHeight = mVideoHeight; - portDef->format.video.nStride = portDef->format.video.nFrameWidth; - portDef->format.video.nSliceHeight = portDef->format.video.nFrameHeight; - portDef->format.video.xFramerate = def->format.video.xFramerate; - portDef->format.video.eColorFormat = - (OMX_COLOR_FORMATTYPE) mVideoColorFormat; - portDef->nBufferSize = - (portDef->format.video.nStride * portDef->format.video.nSliceHeight * 3) / 2; - portDef = &editPortInfo(1)->mDef; - portDef->format.video.nFrameWidth = mVideoWidth; - portDef->format.video.nFrameHeight = mVideoHeight; - } else { - mVideoBitRate = def->format.video.nBitrate; - } - - return OMX_ErrorNone; - } - - case OMX_IndexParamStandardComponentRole: - { - const OMX_PARAM_COMPONENTROLETYPE *roleParams = - (const OMX_PARAM_COMPONENTROLETYPE *)params; - - if (strncmp((const char *)roleParams->cRole, - (mEncodeMode == H263_MODE) - ? "video_encoder.h263": "video_encoder.mpeg4", - OMX_MAX_STRINGNAME_SIZE - 1)) { - return OMX_ErrorUndefined; - } - - return OMX_ErrorNone; - } - - case OMX_IndexParamVideoPortFormat: - { - const OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = - (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; - - if (formatParams->nPortIndex > 1) { - return OMX_ErrorUndefined; - } - - if (formatParams->nIndex > 2) { - return OMX_ErrorNoMore; - } - - if (formatParams->nPortIndex == 0) { - if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused || - ((formatParams->nIndex == 0 && - formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) || - (formatParams->nIndex == 1 && - formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) || - (formatParams->nIndex == 2 && - formatParams->eColorFormat != OMX_COLOR_FormatAndroidOpaque) )) { - return OMX_ErrorUndefined; - } - mVideoColorFormat = formatParams->eColorFormat; - } else { - if ((mEncodeMode == H263_MODE && - formatParams->eCompressionFormat != OMX_VIDEO_CodingH263) || - (mEncodeMode == COMBINE_MODE_WITH_ERR_RES && - formatParams->eCompressionFormat != OMX_VIDEO_CodingMPEG4) || - formatParams->eColorFormat != OMX_COLOR_FormatUnused) { - return OMX_ErrorUndefined; - } - } - + mBitrate = bitRate->nTargetBitrate; return OMX_ErrorNone; } @@ -578,29 +348,8 @@ 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_FormatAndroidOpaque; - } - - return OMX_ErrorNone; - } - default: - return SimpleSoftOMXComponent::internalSetParameter(index, params); + return SoftVideoEncoderOMXComponent::internalSetParameter(index, params); } } @@ -663,7 +412,7 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) { if (inHeader->nFilledLen > 0) { const uint8_t *inputData = NULL; - if (mStoreMetaDataInBuffers) { + if (mInputDataIsMeta) { if (inHeader->nFilledLen != 8) { ALOGE("MetaData buffer is wrong size! " "(got %u bytes, expected 8)", inHeader->nFilledLen); @@ -673,9 +422,9 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) { } inputData = extractGraphicBuffer( - mInputFrameData, (mVideoWidth * mVideoHeight * 3) >> 1, + mInputFrameData, (mWidth * mHeight * 3) >> 1, inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen, - mVideoWidth, mVideoHeight); + mWidth, mHeight); if (inputData == NULL) { ALOGE("Unable to extract gralloc buffer in metadata mode"); mSignalledError = true; @@ -684,9 +433,9 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) { } } else { inputData = (const uint8_t *)inHeader->pBuffer + inHeader->nOffset; - if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) { + if (mColorFormat != OMX_COLOR_FormatYUV420Planar) { ConvertYUV420SemiPlanarToYUV420Planar( - inputData, mInputFrameData, mVideoWidth, mVideoHeight); + inputData, mInputFrameData, mWidth, mHeight); inputData = mInputFrameData; } } @@ -696,8 +445,8 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) { VideoEncFrameIO vin, vout; memset(&vin, 0, sizeof(vin)); memset(&vout, 0, sizeof(vout)); - vin.height = ((mVideoHeight + 15) >> 4) << 4; - vin.pitch = ((mVideoWidth + 15) >> 4) << 4; + vin.height = align(mHeight, 16); + vin.pitch = align(mWidth, 16); vin.timestamp = (inHeader->nTimeStamp + 500) / 1000; // in ms vin.yChan = (uint8_t *)inputData; vin.uChan = vin.yChan + vin.height * vin.pitch; @@ -745,5 +494,19 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) { android::SoftOMXComponent *createSoftOMXComponent( const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, OMX_COMPONENTTYPE **component) { - return new android::SoftMPEG4Encoder(name, callbacks, appData, component); + using namespace android; + if (!strcmp(name, "OMX.google.h263.encoder")) { + return new android::SoftMPEG4Encoder( + name, "video_encoder.h263", OMX_VIDEO_CodingH263, MEDIA_MIMETYPE_VIDEO_H263, + kH263ProfileLevels, NELEM(kH263ProfileLevels), + callbacks, appData, component); + } else if (!strcmp(name, "OMX.google.mpeg4.encoder")) { + return new android::SoftMPEG4Encoder( + name, "video_encoder.mpeg4", OMX_VIDEO_CodingMPEG4, MEDIA_MIMETYPE_VIDEO_MPEG4, + kMPEG4ProfileLevels, NELEM(kMPEG4ProfileLevels), + callbacks, appData, component); + } else { + CHECK(!"Unknown component"); + } + return NULL; } diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h index b0605b4..25ecdc9 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h +++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h @@ -25,11 +25,17 @@ namespace android { +struct CodecProfileLevel; struct MediaBuffer; struct SoftMPEG4Encoder : public SoftVideoEncoderOMXComponent { SoftMPEG4Encoder( const char *name, + const char *componentRole, + OMX_VIDEO_CODINGTYPE codingType, + const char *mime, + const CodecProfileLevel *profileLevels, + size_t numProfileLevels, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, OMX_COMPONENTTYPE **component); @@ -58,12 +64,6 @@ private: } InputBufferInfo; MP4EncodingMode mEncodeMode; - int32_t mVideoWidth; - int32_t mVideoHeight; - int32_t mVideoFrameRate; - int32_t mVideoBitRate; - int32_t mVideoColorFormat; - bool mStoreMetaDataInBuffers; int32_t mIDRFrameRefreshIntervalInSec; int64_t mNumInputFrames; @@ -76,7 +76,6 @@ private: uint8_t *mInputFrameData; Vector mInputBufferInfoVec; - void initPorts(); OMX_ERRORTYPE initEncParams(); OMX_ERRORTYPE initEncoder(); OMX_ERRORTYPE releaseEncoder(); diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp index 87d6961..8a95643 100644 --- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp +++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp @@ -40,10 +40,13 @@ SoftVPX::SoftVPX( mMode(codingType == OMX_VIDEO_CodingVP8 ? MODE_VP8 : MODE_VP9), mCtx(NULL), mImg(NULL) { - initPorts(kNumBuffers, 768 * 1024 /* inputBufferSize */, - kNumBuffers, - codingType == OMX_VIDEO_CodingVP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9); - + // arbitrary from avc/hevc as vpx does not specify a min compression ratio + const size_t kMinCompressionRatio = mMode == MODE_VP8 ? 2 : 4; + const char *mime = mMode == MODE_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9; + const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2; + initPorts( + kNumBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* inputBufferSize */, + kNumBuffers, mime, kMinCompressionRatio); CHECK_EQ(initDecoder(), (status_t)OK); } diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp index 0285feb..970acf3 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp @@ -19,6 +19,7 @@ #include "SoftVPXEncoder.h" #include +#include #include #include @@ -50,23 +51,29 @@ static int GetCPUCoreCount() { return cpuCoreCount; } +static const CodecProfileLevel kProfileLevels[] = { + { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version0 }, + { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version1 }, + { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version2 }, + { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version3 }, +}; + SoftVPXEncoder::SoftVPXEncoder(const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, OMX_COMPONENTTYPE **component) - : SoftVideoEncoderOMXComponent(name, callbacks, appData, component), + : SoftVideoEncoderOMXComponent( + name, "video_encoder.vp8", OMX_VIDEO_CodingVP8, + kProfileLevels, NELEM(kProfileLevels), + 176 /* width */, 144 /* height */, + callbacks, appData, component), mCodecContext(NULL), mCodecConfiguration(NULL), mCodecInterface(NULL), - mWidth(176), - mHeight(144), - mBitrate(192000), // in bps - mFramerate(30 << 16), // in Q16 format mBitrateUpdated(false), mBitrateControlMode(VPX_VBR), // variable bitrate mDCTPartitions(0), mErrorResilience(OMX_FALSE), - mColorFormat(OMX_COLOR_FormatYUV420Planar), mLevel(OMX_VIDEO_VP8Level_Version0), mKeyFrameInterval(0), mMinQuantizer(0), @@ -77,83 +84,22 @@ SoftVPXEncoder::SoftVPXEncoder(const char *name, mTemporalPatternIdx(0), mLastTimestamp(0x7FFFFFFFFFFFFFFFLL), mConversionBuffer(NULL), - mInputDataIsMeta(false), mKeyFrameRequested(false) { memset(mTemporalLayerBitrateRatio, 0, sizeof(mTemporalLayerBitrateRatio)); mTemporalLayerBitrateRatio[0] = 100; - initPorts(); -} + const size_t kMinOutputBufferSize = 1024 * 1024; // arbitrary -SoftVPXEncoder::~SoftVPXEncoder() { - releaseEncoder(); + initPorts( + kNumBuffers, kNumBuffers, kMinOutputBufferSize, + MEDIA_MIMETYPE_VIDEO_VP8, 2 /* minCompressionRatio */); } -void SoftVPXEncoder::initPorts() { - OMX_PARAM_PORTDEFINITIONTYPE inputPort; - OMX_PARAM_PORTDEFINITIONTYPE outputPort; - - InitOMXParams(&inputPort); - InitOMXParams(&outputPort); - - inputPort.nBufferCountMin = kNumBuffers; - inputPort.nBufferCountActual = inputPort.nBufferCountMin; - inputPort.bEnabled = OMX_TRUE; - inputPort.bPopulated = OMX_FALSE; - inputPort.eDomain = OMX_PortDomainVideo; - inputPort.bBuffersContiguous = OMX_FALSE; - inputPort.format.video.pNativeRender = NULL; - inputPort.format.video.nFrameWidth = mWidth; - inputPort.format.video.nFrameHeight = mHeight; - inputPort.format.video.nStride = inputPort.format.video.nFrameWidth; - inputPort.format.video.nSliceHeight = inputPort.format.video.nFrameHeight; - inputPort.format.video.nBitrate = 0; - // frameRate is in Q16 format. - inputPort.format.video.xFramerate = mFramerate; - inputPort.format.video.bFlagErrorConcealment = OMX_FALSE; - inputPort.nPortIndex = kInputPortIndex; - inputPort.eDir = OMX_DirInput; - inputPort.nBufferAlignment = kInputBufferAlignment; - inputPort.format.video.cMIMEType = - const_cast(MEDIA_MIMETYPE_VIDEO_RAW); - inputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; - inputPort.format.video.eColorFormat = mColorFormat; - inputPort.format.video.pNativeWindow = NULL; - inputPort.nBufferSize = - (inputPort.format.video.nStride * - inputPort.format.video.nSliceHeight * 3) / 2; - - addPort(inputPort); - - outputPort.nBufferCountMin = kNumBuffers; - outputPort.nBufferCountActual = outputPort.nBufferCountMin; - outputPort.bEnabled = OMX_TRUE; - outputPort.bPopulated = OMX_FALSE; - outputPort.eDomain = OMX_PortDomainVideo; - outputPort.bBuffersContiguous = OMX_FALSE; - outputPort.format.video.pNativeRender = NULL; - outputPort.format.video.nFrameWidth = mWidth; - outputPort.format.video.nFrameHeight = mHeight; - outputPort.format.video.nStride = outputPort.format.video.nFrameWidth; - outputPort.format.video.nSliceHeight = outputPort.format.video.nFrameHeight; - outputPort.format.video.nBitrate = mBitrate; - outputPort.format.video.xFramerate = 0; - outputPort.format.video.bFlagErrorConcealment = OMX_FALSE; - outputPort.nPortIndex = kOutputPortIndex; - outputPort.eDir = OMX_DirOutput; - outputPort.nBufferAlignment = kOutputBufferAlignment; - outputPort.format.video.cMIMEType = - const_cast(MEDIA_MIMETYPE_VIDEO_VP8); - outputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8; - outputPort.format.video.eColorFormat = OMX_COLOR_FormatUnused; - outputPort.format.video.pNativeWindow = NULL; - outputPort.nBufferSize = 1024 * 1024; // arbitrary - - addPort(outputPort); +SoftVPXEncoder::~SoftVPXEncoder() { + releaseEncoder(); } - status_t SoftVPXEncoder::initEncoder() { vpx_codec_err_t codec_return; @@ -409,38 +355,6 @@ OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index, const int32_t indexFull = index; switch (indexFull) { - case OMX_IndexParamVideoPortFormat: { - OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = - (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param; - - if (formatParams->nPortIndex == kInputPortIndex) { - if (formatParams->nIndex >= kNumberOfSupportedColorFormats) { - return OMX_ErrorNoMore; - } - - // Color formats, in order of preference - if (formatParams->nIndex == 0) { - formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar; - } else if (formatParams->nIndex == 1) { - formatParams->eColorFormat = - OMX_COLOR_FormatYUV420SemiPlanar; - } else { - formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque; - } - - formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused; - formatParams->xFramerate = mFramerate; - return OMX_ErrorNone; - } else if (formatParams->nPortIndex == kOutputPortIndex) { - formatParams->eCompressionFormat = OMX_VIDEO_CodingVP8; - formatParams->eColorFormat = OMX_COLOR_FormatUnused; - formatParams->xFramerate = 0; - return OMX_ErrorNone; - } else { - return OMX_ErrorBadPortIndex; - } - } - case OMX_IndexParamVideoBitrate: { OMX_VIDEO_PARAM_BITRATETYPE *bitrate = (OMX_VIDEO_PARAM_BITRATETYPE *)param; @@ -495,54 +409,8 @@ OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index, return OMX_ErrorNone; } - case OMX_IndexParamVideoProfileLevelQuerySupported: { - OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileAndLevel = - (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param; - - if (profileAndLevel->nPortIndex != kOutputPortIndex) { - return OMX_ErrorUnsupportedIndex; - } - - switch (profileAndLevel->nProfileIndex) { - case 0: - profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version0; - break; - - case 1: - profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version1; - break; - - case 2: - profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version2; - break; - - case 3: - profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version3; - break; - - default: - return OMX_ErrorNoMore; - } - - profileAndLevel->eProfile = OMX_VIDEO_VP8ProfileMain; - return OMX_ErrorNone; - } - - case OMX_IndexParamVideoProfileLevelCurrent: { - OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileAndLevel = - (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param; - - if (profileAndLevel->nPortIndex != kOutputPortIndex) { - return OMX_ErrorUnsupportedIndex; - } - - profileAndLevel->eLevel = mLevel; - profileAndLevel->eProfile = OMX_VIDEO_VP8ProfileMain; - return OMX_ErrorNone; - } - default: - return SimpleSoftOMXComponent::internalGetParameter(index, param); + return SoftVideoEncoderOMXComponent::internalGetParameter(index, param); } } @@ -553,30 +421,10 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index, const int32_t indexFull = index; switch (indexFull) { - case OMX_IndexParamStandardComponentRole: - return internalSetRoleParams( - (const OMX_PARAM_COMPONENTROLETYPE *)param); - case OMX_IndexParamVideoBitrate: return internalSetBitrateParams( (const OMX_VIDEO_PARAM_BITRATETYPE *)param); - case OMX_IndexParamPortDefinition: - { - OMX_ERRORTYPE err = internalSetPortParams( - (const OMX_PARAM_PORTDEFINITIONTYPE *)param); - - if (err != OMX_ErrorNone) { - return err; - } - - return SimpleSoftOMXComponent::internalSetParameter(index, param); - } - - case OMX_IndexParamVideoPortFormat: - return internalSetFormatParams( - (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param); - case OMX_IndexParamVideoVp8: return internalSetVp8Params( (const OMX_VIDEO_PARAM_VP8TYPE *)param); @@ -585,27 +433,8 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index, return internalSetAndroidVp8Params( (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param); - case OMX_IndexParamVideoProfileLevelCurrent: - return internalSetProfileLevel( - (const OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param); - - case kStoreMetaDataExtensionIndex: - { - // storeMetaDataInBuffers - const StoreMetaDataInBuffersParams *storeParam = - (const StoreMetaDataInBuffersParams *)param; - - if (storeParam->nPortIndex != kInputPortIndex) { - return OMX_ErrorBadPortIndex; - } - - mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE); - - return OMX_ErrorNone; - } - default: - return SimpleSoftOMXComponent::internalSetParameter(index, param); + return SoftVideoEncoderOMXComponent::internalSetParameter(index, param); } } @@ -646,29 +475,6 @@ OMX_ERRORTYPE SoftVPXEncoder::setConfig( } } -OMX_ERRORTYPE SoftVPXEncoder::internalSetProfileLevel( - const OMX_VIDEO_PARAM_PROFILELEVELTYPE* profileAndLevel) { - if (profileAndLevel->nPortIndex != kOutputPortIndex) { - return OMX_ErrorUnsupportedIndex; - } - - if (profileAndLevel->eProfile != OMX_VIDEO_VP8ProfileMain) { - return OMX_ErrorBadParameter; - } - - if (profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version0 || - profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version1 || - profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version2 || - profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version3) { - mLevel = (OMX_VIDEO_VP8LEVELTYPE)profileAndLevel->eLevel; - } else { - return OMX_ErrorBadParameter; - } - - return OMX_ErrorNone; -} - - OMX_ERRORTYPE SoftVPXEncoder::internalSetVp8Params( const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) { if (vp8Params->nPortIndex != kOutputPortIndex) { @@ -743,95 +549,6 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetAndroidVp8Params( return OMX_ErrorNone; } -OMX_ERRORTYPE SoftVPXEncoder::internalSetFormatParams( - const OMX_VIDEO_PARAM_PORTFORMATTYPE* format) { - if (format->nPortIndex == kInputPortIndex) { - if (format->eColorFormat == OMX_COLOR_FormatYUV420Planar || - format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar || - format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) { - mColorFormat = format->eColorFormat; - - OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef; - def->format.video.eColorFormat = mColorFormat; - - return OMX_ErrorNone; - } else { - ALOGE("Unsupported color format %i", format->eColorFormat); - return OMX_ErrorUnsupportedSetting; - } - } else if (format->nPortIndex == kOutputPortIndex) { - if (format->eCompressionFormat == OMX_VIDEO_CodingVP8) { - return OMX_ErrorNone; - } else { - return OMX_ErrorUnsupportedSetting; - } - } else { - return OMX_ErrorBadPortIndex; - } -} - - -OMX_ERRORTYPE SoftVPXEncoder::internalSetRoleParams( - const OMX_PARAM_COMPONENTROLETYPE* role) { - const char* roleText = (const char*)role->cRole; - const size_t roleTextMaxSize = OMX_MAX_STRINGNAME_SIZE - 1; - - if (strncmp(roleText, "video_encoder.vp8", roleTextMaxSize)) { - ALOGE("Unsupported component role"); - return OMX_ErrorBadParameter; - } - - return OMX_ErrorNone; -} - - -OMX_ERRORTYPE SoftVPXEncoder::internalSetPortParams( - const OMX_PARAM_PORTDEFINITIONTYPE* port) { - if (port->nPortIndex == kInputPortIndex) { - mWidth = port->format.video.nFrameWidth; - mHeight = port->format.video.nFrameHeight; - - // xFramerate comes in Q16 format, in frames per second unit - mFramerate = port->format.video.xFramerate; - - if (port->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar || - port->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar || - port->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) { - mColorFormat = port->format.video.eColorFormat; - } else { - return OMX_ErrorUnsupportedSetting; - } - - OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef; - def->format.video.nFrameWidth = mWidth; - def->format.video.nFrameHeight = mHeight; - def->format.video.nStride = def->format.video.nFrameWidth; - def->format.video.nSliceHeight = def->format.video.nFrameHeight; - def->format.video.xFramerate = mFramerate; - def->format.video.eColorFormat = mColorFormat; - def->nBufferSize = - (def->format.video.nStride * def->format.video.nSliceHeight * 3) / 2; - def = &editPortInfo(kOutputPortIndex)->mDef; - def->format.video.nFrameWidth = mWidth; - def->format.video.nFrameHeight = mHeight; - - return OMX_ErrorNone; - } else if (port->nPortIndex == kOutputPortIndex) { - mBitrate = port->format.video.nBitrate; - mWidth = port->format.video.nFrameWidth; - mHeight = port->format.video.nFrameHeight; - - OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef; - def->format.video.nFrameWidth = mWidth; - def->format.video.nFrameHeight = mHeight; - def->format.video.nBitrate = mBitrate; - return OMX_ErrorNone; - } else { - return OMX_ErrorBadPortIndex; - } -} - - OMX_ERRORTYPE SoftVPXEncoder::internalSetBitrateParams( const OMX_VIDEO_PARAM_BITRATETYPE* bitrate) { if (bitrate->nPortIndex != kOutputPortIndex) { @@ -920,7 +637,7 @@ vpx_enc_frame_flags_t SoftVPXEncoder::getEncodeFlags() { return flags; } -void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) { +void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) { // Initialize encoder if not already if (mCodecContext == NULL) { if (OK != initEncoder()) { diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h index f4c1564..cd0a0cf 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h @@ -155,18 +155,6 @@ private: // that specifies algorithm interface (e.g. vp8) vpx_codec_iface_t* mCodecInterface; - // Width of the input frames - int32_t mWidth; - - // Height of the input frames - int32_t mHeight; - - // Target bitrate set for the encoder, in bits per second. - uint32_t mBitrate; - - // Target framerate set for the encoder. - uint32_t mFramerate; - // If a request for a change it bitrate has been received. bool mBitrateUpdated; @@ -182,9 +170,6 @@ private: // is enabled in encoder OMX_BOOL mErrorResilience; - // Color format for the input port - OMX_COLOR_FORMATTYPE mColorFormat; - // Encoder profile corresponding to OMX level parameter // // The inconsistency in the naming is caused by @@ -229,14 +214,8 @@ private: // indeed YUV420SemiPlanar. uint8_t* mConversionBuffer; - bool mInputDataIsMeta; - bool mKeyFrameRequested; - // Initializes input and output OMX ports with sensible - // default values. - void initPorts(); - // Initializes vpx encoder with available settings. status_t initEncoder(); @@ -250,23 +229,10 @@ private: // Get current encode flags vpx_enc_frame_flags_t getEncodeFlags(); - // Handles port changes with respect to color formats - OMX_ERRORTYPE internalSetFormatParams( - const OMX_VIDEO_PARAM_PORTFORMATTYPE* format); - - // Verifies the component role tried to be set to this OMX component is - // strictly video_encoder.vp8 - OMX_ERRORTYPE internalSetRoleParams( - const OMX_PARAM_COMPONENTROLETYPE* role); - // Updates bitrate to reflect port settings. OMX_ERRORTYPE internalSetBitrateParams( const OMX_VIDEO_PARAM_BITRATETYPE* bitrate); - // Handles port definition changes. - OMX_ERRORTYPE internalSetPortParams( - const OMX_PARAM_PORTDEFINITIONTYPE* port); - // Handles vp8 specific parameters. OMX_ERRORTYPE internalSetVp8Params( const OMX_VIDEO_PARAM_VP8TYPE* vp8Params); @@ -275,10 +241,6 @@ private: OMX_ERRORTYPE internalSetAndroidVp8Params( const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams); - // Updates encoder profile - OMX_ERRORTYPE internalSetProfileLevel( - const OMX_VIDEO_PARAM_PROFILELEVELTYPE* profileAndLevel); - DISALLOW_EVIL_CONSTRUCTORS(SoftVPXEncoder); }; diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp index 168208f..6b8b395 100644 --- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp +++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp @@ -64,9 +64,11 @@ SoftAVC::SoftAVC( mHeadersDecoded(false), mEOSStatus(INPUT_DATA_AVAILABLE), mSignalledError(false) { + const size_t kMinCompressionRatio = 2; + const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2; initPorts( - kNumInputBuffers, 8192 /* inputBufferSize */, - kNumOutputBuffers, MEDIA_MIMETYPE_VIDEO_AVC); + kNumInputBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* minInputBufferSize */, + kNumOutputBuffers, MEDIA_MIMETYPE_VIDEO_AVC, kMinCompressionRatio); CHECK_EQ(initDecoder(), (status_t)OK); } diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml index 1cbef39..7e9fa18 100644 --- a/media/libstagefright/data/media_codecs_google_video.xml +++ b/media/libstagefright/data/media_codecs_google_video.xml @@ -73,7 +73,7 @@ - + diff --git a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h index 9e97ebd..4529007 100644 --- a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h +++ b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h @@ -61,9 +61,10 @@ protected: void initPorts(OMX_U32 numInputBuffers, OMX_U32 inputBufferSize, OMX_U32 numOutputBuffers, - const char *mimeType); + const char *mimeType, + OMX_U32 minCompressionRatio = 1u); - virtual void updatePortDefinitions(bool updateCrop = true); + virtual void updatePortDefinitions(bool updateCrop = true, bool updateInputSize = false); uint32_t outputBufferWidth(); uint32_t outputBufferHeight(); @@ -99,6 +100,9 @@ protected: } mOutputPortSettingsChange; private: + uint32_t mMinInputBufferSize; + uint32_t mMinCompressionRatio; + const char *mComponentRole; OMX_VIDEO_CODINGTYPE mCodingType; const CodecProfileLevel *mProfileLevels; diff --git a/media/libstagefright/include/SoftVideoEncoderOMXComponent.h b/media/libstagefright/include/SoftVideoEncoderOMXComponent.h index b3b810d..b43635d 100644 --- a/media/libstagefright/include/SoftVideoEncoderOMXComponent.h +++ b/media/libstagefright/include/SoftVideoEncoderOMXComponent.h @@ -18,6 +18,8 @@ #define SOFT_VIDEO_ENCODER_OMX_COMPONENT_H_ +#include + #include "SimpleSoftOMXComponent.h" #include @@ -28,11 +30,26 @@ namespace android { struct SoftVideoEncoderOMXComponent : public SimpleSoftOMXComponent { SoftVideoEncoderOMXComponent( const char *name, + const char *componentRole, + OMX_VIDEO_CODINGTYPE codingType, + const CodecProfileLevel *profileLevels, + size_t numProfileLevels, + int32_t width, + int32_t height, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, OMX_COMPONENTTYPE **component); + virtual OMX_ERRORTYPE internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR param); + virtual OMX_ERRORTYPE internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params); + protected: + void initPorts( + OMX_U32 numInputBuffers, OMX_U32 numOutputBuffers, OMX_U32 outputBufferSize, + const char *mime, OMX_U32 minCompressionRatio = 1); + + static void setRawVideoSize(OMX_PARAM_PORTDEFINITIONTYPE *def); + static void ConvertFlexYUVToPlanar( uint8_t *dst, size_t dstStride, size_t dstVStride, struct android_ycbcr *ycbcr, int32_t width, int32_t height); @@ -56,9 +73,30 @@ protected: kOutputPortIndex = 1, }; + bool mInputDataIsMeta; + int32_t mWidth; // width of the input frames + int32_t mHeight; // height of the input frames + uint32_t mBitrate; // target bitrate set for the encoder, in bits per second + uint32_t mFramerate; // target framerate set for the encoder, in Q16 format + OMX_COLOR_FORMATTYPE mColorFormat; // Color format for the input port + private: + void updatePortParams(); + OMX_ERRORTYPE internalSetPortParams(const OMX_PARAM_PORTDEFINITIONTYPE* port); + + static const uint32_t kInputBufferAlignment = 1; + static const uint32_t kOutputBufferAlignment = 2; + mutable const hw_module_t *mGrallocModule; + uint32_t mMinOutputBufferSize; + uint32_t mMinCompressionRatio; + + const char *mComponentRole; + OMX_VIDEO_CODINGTYPE mCodingType; + const CodecProfileLevel *mProfileLevels; + size_t mNumProfileLevels; + DISALLOW_EVIL_CONSTRUCTORS(SoftVideoEncoderOMXComponent); }; diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp index 2f83610..532cf2f 100644 --- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp +++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace android { @@ -61,6 +62,8 @@ SoftVideoDecoderOMXComponent::SoftVideoDecoderOMXComponent( mCropWidth(width), mCropHeight(height), mOutputPortSettingsChange(NONE), + mMinInputBufferSize(384), // arbitrary, using one uncompressed macroblock + mMinCompressionRatio(1), // max input size is normally the output size mComponentRole(componentRole), mCodingType(codingType), mProfileLevels(profileLevels), @@ -71,7 +74,11 @@ void SoftVideoDecoderOMXComponent::initPorts( OMX_U32 numInputBuffers, OMX_U32 inputBufferSize, OMX_U32 numOutputBuffers, - const char *mimeType) { + const char *mimeType, + OMX_U32 minCompressionRatio) { + mMinInputBufferSize = inputBufferSize; + mMinCompressionRatio = minCompressionRatio; + OMX_PARAM_PORTDEFINITIONTYPE def; InitOMXParams(&def); @@ -120,27 +127,30 @@ void SoftVideoDecoderOMXComponent::initPorts( addPort(def); - updatePortDefinitions(); + updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */); } -void SoftVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop) { - OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef; - def->format.video.nFrameWidth = mWidth; - def->format.video.nFrameHeight = mHeight; - def->format.video.nStride = def->format.video.nFrameWidth; - def->format.video.nSliceHeight = def->format.video.nFrameHeight; - - def->nBufferSize = def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2; - - def = &editPortInfo(kOutputPortIndex)->mDef; - def->format.video.nFrameWidth = outputBufferWidth(); - def->format.video.nFrameHeight = outputBufferHeight(); - def->format.video.nStride = def->format.video.nFrameWidth; - def->format.video.nSliceHeight = def->format.video.nFrameHeight; - - def->nBufferSize = - (def->format.video.nFrameWidth * - def->format.video.nFrameHeight * 3) / 2; +void SoftVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop, bool updateInputSize) { + OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef; + outDef->format.video.nFrameWidth = outputBufferWidth(); + outDef->format.video.nFrameHeight = outputBufferHeight(); + outDef->format.video.nStride = outDef->format.video.nFrameWidth; + outDef->format.video.nSliceHeight = outDef->format.video.nFrameHeight; + + outDef->nBufferSize = + (outDef->format.video.nStride * outDef->format.video.nSliceHeight * 3) / 2; + + OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef; + inDef->format.video.nFrameWidth = mWidth; + inDef->format.video.nFrameHeight = mHeight; + // input port is compressed, hence it has no stride + inDef->format.video.nStride = 0; + inDef->format.video.nSliceHeight = 0; + + // when output format changes, input buffer size does not actually change + if (updateInputSize) { + inDef->nBufferSize = max(outDef->nBufferSize / mMinCompressionRatio, mMinInputBufferSize); + } if (updateCrop) { mCropLeft = 0; @@ -169,7 +179,8 @@ void SoftVideoDecoderOMXComponent::handlePortSettingsChange( bool strideChanged = false; if (fakeStride) { OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef; - if (def->format.video.nStride != width || def->format.video.nSliceHeight != height) { + if (def->format.video.nStride != (OMX_S32)width + || def->format.video.nSliceHeight != (OMX_U32)height) { strideChanged = true; } } @@ -252,7 +263,7 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalGetParameter( (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; if (formatParams->nPortIndex > kMaxPortIndex) { - return OMX_ErrorUndefined; + return OMX_ErrorBadPortIndex; } if (formatParams->nIndex != 0) { @@ -324,13 +335,25 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter( (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; if (formatParams->nPortIndex > kMaxPortIndex) { - return OMX_ErrorUndefined; + return OMX_ErrorBadPortIndex; } if (formatParams->nIndex != 0) { return OMX_ErrorNoMore; } + if (formatParams->nPortIndex == kInputPortIndex) { + if (formatParams->eCompressionFormat != mCodingType + || formatParams->eColorFormat != OMX_COLOR_FormatUnused) { + return OMX_ErrorUnsupportedSetting; + } + } else { + if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused + || formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) { + return OMX_ErrorUnsupportedSetting; + } + } + return OMX_ErrorNone; } @@ -348,7 +371,7 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter( mAdaptiveMaxWidth = 0; mAdaptiveMaxHeight = 0; } - updatePortDefinitions(); + updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */); return OMX_ErrorNone; } @@ -369,11 +392,18 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter( (mIsAdaptive && outputPort) ? mAdaptiveMaxWidth : newWidth; def->format.video.nFrameHeight = (mIsAdaptive && outputPort) ? mAdaptiveMaxHeight : newHeight; - def->format.video.nStride = def->format.video.nFrameWidth; - def->format.video.nSliceHeight = def->format.video.nFrameHeight; - def->nBufferSize = - def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2; if (outputPort) { + def->format.video.nStride = def->format.video.nFrameWidth; + def->format.video.nSliceHeight = def->format.video.nFrameHeight; + def->nBufferSize = + def->format.video.nStride * def->format.video.nSliceHeight * 3 / 2; + + + OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef; + // increase input buffer size if required + inDef->nBufferSize = + max(def->nBufferSize / mMinCompressionRatio, inDef->nBufferSize); + mWidth = newWidth; mHeight = newHeight; mCropLeft = 0; diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp index 8bff142..b2d3623 100644 --- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp +++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp @@ -19,6 +19,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "SoftVideoEncoderOMXComponent" #include +#include #include "include/SoftVideoEncoderOMXComponent.h" @@ -27,6 +28,7 @@ #include #include #include +#include #include #include @@ -34,13 +36,316 @@ namespace android { +const static OMX_COLOR_FORMATTYPE kSupportedColorFormats[] = { + OMX_COLOR_FormatYUV420Planar, + OMX_COLOR_FormatYUV420SemiPlanar, + OMX_COLOR_FormatAndroidOpaque +}; + +template +static void InitOMXParams(T *params) { + params->nSize = sizeof(T); + params->nVersion.s.nVersionMajor = 1; + params->nVersion.s.nVersionMinor = 0; + params->nVersion.s.nRevision = 0; + params->nVersion.s.nStep = 0; +} + SoftVideoEncoderOMXComponent::SoftVideoEncoderOMXComponent( const char *name, + const char *componentRole, + OMX_VIDEO_CODINGTYPE codingType, + const CodecProfileLevel *profileLevels, + size_t numProfileLevels, + int32_t width, + int32_t height, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, OMX_COMPONENTTYPE **component) : SimpleSoftOMXComponent(name, callbacks, appData, component), - mGrallocModule(NULL) { + mInputDataIsMeta(false), + mWidth(width), + mHeight(height), + mBitrate(192000), + mFramerate(30 << 16), // Q16 format + mColorFormat(OMX_COLOR_FormatYUV420Planar), + mGrallocModule(NULL), + mMinOutputBufferSize(384), // arbitrary, using one uncompressed macroblock + mMinCompressionRatio(1), // max output size is normally the input size + mComponentRole(componentRole), + mCodingType(codingType), + mProfileLevels(profileLevels), + mNumProfileLevels(numProfileLevels) { +} + +void SoftVideoEncoderOMXComponent::initPorts( + OMX_U32 numInputBuffers, OMX_U32 numOutputBuffers, OMX_U32 outputBufferSize, + const char *mime, OMX_U32 minCompressionRatio) { + OMX_PARAM_PORTDEFINITIONTYPE def; + + mMinOutputBufferSize = outputBufferSize; + mMinCompressionRatio = minCompressionRatio; + + InitOMXParams(&def); + + def.nPortIndex = kInputPortIndex; + def.eDir = OMX_DirInput; + def.nBufferCountMin = numInputBuffers; + def.nBufferCountActual = def.nBufferCountMin; + def.bEnabled = OMX_TRUE; + def.bPopulated = OMX_FALSE; + def.eDomain = OMX_PortDomainVideo; + def.bBuffersContiguous = OMX_FALSE; + def.format.video.pNativeRender = NULL; + def.format.video.nFrameWidth = mWidth; + def.format.video.nFrameHeight = mHeight; + def.format.video.nStride = def.format.video.nFrameWidth; + def.format.video.nSliceHeight = def.format.video.nFrameHeight; + def.format.video.nBitrate = 0; + // frameRate is in Q16 format. + def.format.video.xFramerate = mFramerate; + def.format.video.bFlagErrorConcealment = OMX_FALSE; + def.nBufferAlignment = kInputBufferAlignment; + def.format.video.cMIMEType = const_cast("video/raw"); + def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + def.format.video.eColorFormat = mColorFormat; + def.format.video.pNativeWindow = NULL; + // buffersize set in updatePortParams + + addPort(def); + + InitOMXParams(&def); + + def.nPortIndex = kOutputPortIndex; + def.eDir = OMX_DirOutput; + def.nBufferCountMin = numOutputBuffers; + def.nBufferCountActual = def.nBufferCountMin; + def.bEnabled = OMX_TRUE; + def.bPopulated = OMX_FALSE; + def.eDomain = OMX_PortDomainVideo; + def.bBuffersContiguous = OMX_FALSE; + def.format.video.pNativeRender = NULL; + def.format.video.nFrameWidth = mWidth; + def.format.video.nFrameHeight = mHeight; + def.format.video.nStride = 0; + def.format.video.nSliceHeight = 0; + def.format.video.nBitrate = mBitrate; + def.format.video.xFramerate = 0 << 16; + def.format.video.bFlagErrorConcealment = OMX_FALSE; + def.nBufferAlignment = kOutputBufferAlignment; + def.format.video.cMIMEType = const_cast(mime); + def.format.video.eCompressionFormat = mCodingType; + def.format.video.eColorFormat = OMX_COLOR_FormatUnused; + def.format.video.pNativeWindow = NULL; + // buffersize set in updatePortParams + + addPort(def); + + updatePortParams(); +} + +void SoftVideoEncoderOMXComponent::updatePortParams() { + OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef; + inDef->format.video.nFrameWidth = mWidth; + inDef->format.video.nFrameHeight = mHeight; + inDef->format.video.nStride = inDef->format.video.nFrameWidth; + inDef->format.video.nSliceHeight = inDef->format.video.nFrameHeight; + inDef->format.video.xFramerate = mFramerate; + inDef->format.video.eColorFormat = mColorFormat; + uint32_t rawBufferSize = + inDef->format.video.nStride * inDef->format.video.nSliceHeight * 3 / 2; + if (inDef->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) { + inDef->nBufferSize = 4 + max(sizeof(buffer_handle_t), sizeof(GraphicBuffer *)); + } else { + inDef->nBufferSize = rawBufferSize; + } + + OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef; + outDef->format.video.nFrameWidth = mWidth; + outDef->format.video.nFrameHeight = mHeight; + outDef->format.video.nBitrate = mBitrate; + + outDef->nBufferSize = max(mMinOutputBufferSize, rawBufferSize / mMinCompressionRatio); +} + +OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetPortParams( + const OMX_PARAM_PORTDEFINITIONTYPE *port) { + if (port->nPortIndex == kInputPortIndex) { + mWidth = port->format.video.nFrameWidth; + mHeight = port->format.video.nFrameHeight; + + // xFramerate comes in Q16 format, in frames per second unit + mFramerate = port->format.video.xFramerate; + + if (port->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused + || (port->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar + && port->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar + && port->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) { + return OMX_ErrorUnsupportedSetting; + } + + mColorFormat = port->format.video.eColorFormat; + } else if (port->nPortIndex == kOutputPortIndex) { + if (port->format.video.eCompressionFormat != mCodingType + || port->format.video.eColorFormat != OMX_COLOR_FormatUnused) { + return OMX_ErrorUnsupportedSetting; + } + + mBitrate = port->format.video.nBitrate; + } else { + return OMX_ErrorBadPortIndex; + } + + updatePortParams(); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetParameter( + OMX_INDEXTYPE index, const OMX_PTR param) { + // can include extension index OMX_INDEXEXTTYPE + const int32_t indexFull = index; + + switch (indexFull) { + case OMX_IndexParamVideoErrorCorrection: + { + return OMX_ErrorNotImplemented; + } + + case OMX_IndexParamStandardComponentRole: + { + const OMX_PARAM_COMPONENTROLETYPE *roleParams = + (const OMX_PARAM_COMPONENTROLETYPE *)param; + + if (strncmp((const char *)roleParams->cRole, + mComponentRole, + OMX_MAX_STRINGNAME_SIZE - 1)) { + return OMX_ErrorUnsupportedSetting; + } + + return OMX_ErrorNone; + } + + case OMX_IndexParamPortDefinition: + { + OMX_ERRORTYPE err = internalSetPortParams((const OMX_PARAM_PORTDEFINITIONTYPE *)param); + + if (err != OMX_ErrorNone) { + return err; + } + + return SimpleSoftOMXComponent::internalSetParameter(index, param); + } + + case OMX_IndexParamVideoPortFormat: + { + const OMX_VIDEO_PARAM_PORTFORMATTYPE* format = + (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param; + + if (format->nPortIndex == kInputPortIndex) { + if (format->eColorFormat == OMX_COLOR_FormatYUV420Planar || + format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar || + format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) { + mColorFormat = format->eColorFormat; + + updatePortParams(); + return OMX_ErrorNone; + } else { + ALOGE("Unsupported color format %i", format->eColorFormat); + return OMX_ErrorUnsupportedSetting; + } + } else if (format->nPortIndex == kOutputPortIndex) { + if (format->eCompressionFormat == mCodingType) { + return OMX_ErrorNone; + } else { + return OMX_ErrorUnsupportedSetting; + } + } else { + return OMX_ErrorBadPortIndex; + } + } + + case kStoreMetaDataExtensionIndex: + { + // storeMetaDataInBuffers + const StoreMetaDataInBuffersParams *storeParam = + (const StoreMetaDataInBuffersParams *)param; + + if (storeParam->nPortIndex == kOutputPortIndex) { + return storeParam->bStoreMetaData ? OMX_ErrorUnsupportedSetting : OMX_ErrorNone; + } else if (storeParam->nPortIndex != kInputPortIndex) { + return OMX_ErrorBadPortIndex; + } + + mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE); + if (mInputDataIsMeta) { + mColorFormat = OMX_COLOR_FormatAndroidOpaque; + } else if (mColorFormat == OMX_COLOR_FormatAndroidOpaque) { + mColorFormat = OMX_COLOR_FormatYUV420Planar; + } + updatePortParams(); + return OMX_ErrorNone; + } + + default: + return SimpleSoftOMXComponent::internalSetParameter(index, param); + } +} + +OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalGetParameter( + OMX_INDEXTYPE index, OMX_PTR param) { + switch (index) { + case OMX_IndexParamVideoErrorCorrection: + { + return OMX_ErrorNotImplemented; + } + + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = + (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param; + + if (formatParams->nPortIndex == kInputPortIndex) { + if (formatParams->nIndex >= NELEM(kSupportedColorFormats)) { + return OMX_ErrorNoMore; + } + + // Color formats, in order of preference + formatParams->eColorFormat = kSupportedColorFormats[formatParams->nIndex]; + formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused; + formatParams->xFramerate = mFramerate; + return OMX_ErrorNone; + } else if (formatParams->nPortIndex == kOutputPortIndex) { + formatParams->eCompressionFormat = mCodingType; + formatParams->eColorFormat = OMX_COLOR_FormatUnused; + formatParams->xFramerate = 0; + return OMX_ErrorNone; + } else { + return OMX_ErrorBadPortIndex; + } + } + + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel = + (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) param; + + if (profileLevel->nPortIndex != kOutputPortIndex) { + ALOGE("Invalid port index: %u", profileLevel->nPortIndex); + return OMX_ErrorUnsupportedIndex; + } + + if (profileLevel->nProfileIndex >= mNumProfileLevels) { + return OMX_ErrorNoMore; + } + + profileLevel->eProfile = mProfileLevels[profileLevel->nProfileIndex].mProfile; + profileLevel->eLevel = mProfileLevels[profileLevel->nProfileIndex].mLevel; + return OMX_ErrorNone; + } + + default: + return SimpleSoftOMXComponent::internalGetParameter(index, param); + } } // static diff --git a/media/libstagefright/tests/Utils_test.cpp b/media/libstagefright/tests/Utils_test.cpp index 43e0269..5c323c1 100644 --- a/media/libstagefright/tests/Utils_test.cpp +++ b/media/libstagefright/tests/Utils_test.cpp @@ -172,6 +172,13 @@ TEST_F(UtilsTest, TestMathTemplates) { ASSERT_EQ(divUp(12, 4), 3); ASSERT_EQ(divUp(13, 4), 4); + ASSERT_EQ(align(11, 4), 12); + ASSERT_EQ(align(12, 4), 12); + ASSERT_EQ(align(13, 4), 16); + ASSERT_EQ(align(11, 8), 16); + ASSERT_EQ(align(11, 2), 12); + ASSERT_EQ(align(11, 1), 11); + ASSERT_EQ(abs(5L), 5L); ASSERT_EQ(abs(-25), 25); -- cgit v1.1