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; if (updateCrop) { mCropLeft = 0; mCropTop = 0; mCropWidth = mWidth; mCropHeight = mHeight; } }
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, max(mMinInputBufferSize, inDef->nBufferSize)); } if (updateCrop) { mCropLeft = 0; mCropTop = 0; mCropWidth = mWidth; mCropHeight = mHeight; } }
void SoftVideoDecoderOMXComponent::handlePortSettingsChange( bool *portWillReset, uint32_t width, uint32_t height, CropSettingsMode cropSettingsMode, bool fakeStride) { *portWillReset = false; bool sizeChanged = (width != mWidth || height != mHeight); bool updateCrop = (cropSettingsMode == kCropUnSet); bool cropChanged = (cropSettingsMode == kCropChanged); bool strideChanged = false; if (fakeStride) { OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef; if (def->format.video.nStride != (OMX_S32)width || def->format.video.nSliceHeight != (OMX_U32)height) { strideChanged = true; } } if (sizeChanged || cropChanged || strideChanged) { mWidth = width; mHeight = height; if ((sizeChanged && !mIsAdaptive) || width > mAdaptiveMaxWidth || height > mAdaptiveMaxHeight) { if (mIsAdaptive) { if (width > mAdaptiveMaxWidth) { mAdaptiveMaxWidth = width; } if (height > mAdaptiveMaxHeight) { mAdaptiveMaxHeight = height; } } updatePortDefinitions(updateCrop); notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 0, NULL); mOutputPortSettingsChange = AWAITING_DISABLED; *portWillReset = true; } else { updatePortDefinitions(updateCrop); if (fakeStride) { // MAJOR HACK that is not pretty, it's just to fool the renderer to read the correct // data. // Some software decoders (e.g. SoftMPEG4) fill decoded frame directly to output // buffer without considering the output buffer stride and slice height. So this is // used to signal how the buffer is arranged. The alternative is to re-arrange the // output buffer in SoftMPEG4, but that results in memcopies. OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef; def->format.video.nStride = mWidth; def->format.video.nSliceHeight = mHeight; } notify(OMX_EventPortSettingsChanged, kOutputPortIndex, OMX_IndexConfigCommonOutputCrop, NULL); } } }
void SoftAVC::updatePortDefinitions() { OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->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 = &editPortInfo(1)->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; }
void SoftMPEG4::updatePortDefinitions() { SoftVideoDecoderOMXComponent::updatePortDefinitions(); /* 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; }
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->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; }
void SoftFFmpegVideo::updatePortDefinitions() { OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->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; def = &editPortInfo(1)->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; #if 0 def->nBufferSize = (def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3) / 2; #else def->nBufferSize = (((def->format.video.nFrameWidth + 15) & -16) * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2; #endif }
void SoftMPEG4::onQueueFilled(OMX_U32 portIndex) { if (mSignalledError || mOutputPortSettingsChange != NONE) { return; } List<BufferInfo *> &inQueue = getPortQueue(0); List<BufferInfo *> &outQueue = getPortQueue(1); while (!inQueue.empty() && outQueue.size() == kNumOutputBuffers) { BufferInfo *inInfo = *inQueue.begin(); OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; PortInfo *port = editPortInfo(1); OMX_BUFFERHEADERTYPE *outHeader = port->mBuffers.editItemAt(mNumSamplesOutput & 1).mHeader; if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) { inQueue.erase(inQueue.begin()); inInfo->mOwnedByUs = false; notifyEmptyBufferDone(inHeader); ++mInputBufferCount; outHeader->nFilledLen = 0; outHeader->nFlags = OMX_BUFFERFLAG_EOS; List<BufferInfo *>::iterator it = outQueue.begin(); while ((*it)->mHeader != outHeader) { ++it; } BufferInfo *outInfo = *it; outInfo->mOwnedByUs = false; outQueue.erase(it); outInfo = NULL; notifyFillBufferDone(outHeader); outHeader = NULL; return; } uint8_t *bitstream = inHeader->pBuffer + inHeader->nOffset; if (!mInitialized) { uint8_t *vol_data[1]; int32_t vol_size = 0; vol_data[0] = NULL; if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { vol_data[0] = bitstream; vol_size = inHeader->nFilledLen; } MP4DecodingMode mode = (mMode == MODE_MPEG4) ? MPEG4_MODE : H263_MODE; Bool success = PVInitVideoDecoder( mHandle, vol_data, &vol_size, 1, mWidth, mHeight, mode); if (!success) { ALOGW("PVInitVideoDecoder failed. Unsupported content?"); notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; return; } MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle); if (mode != actualMode) { notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; return; } PVSetPostProcType((VideoDecControls *) mHandle, 0); if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { inInfo->mOwnedByUs = false; inQueue.erase(inQueue.begin()); inInfo = NULL; notifyEmptyBufferDone(inHeader); inHeader = NULL; } mInitialized = true; if (mode == MPEG4_MODE && portSettingsChanged()) { return; } continue; } if (!mFramesConfigured) { PortInfo *port = editPortInfo(1); OMX_BUFFERHEADERTYPE *outHeader = port->mBuffers.editItemAt(1).mHeader; PVSetReferenceYUV(mHandle, outHeader->pBuffer); mFramesConfigured = true; } uint32_t useExtTimestamp = (inHeader->nOffset == 0); // decoder deals in ms (int32_t), OMX in us (int64_t) // so use fake timestamp instead uint32_t timestamp = 0xFFFFFFFF; if (useExtTimestamp) { mPvToOmxTimeMap.add(mPvTime, inHeader->nTimeStamp); timestamp = mPvTime; mPvTime++; } int32_t bufferSize = inHeader->nFilledLen; int32_t tmp = bufferSize; // The PV decoder is lying to us, sometimes it'll claim to only have // consumed a subset of the buffer when it clearly consumed all of it. // ignore whatever it says... if (PVDecodeVideoFrame( mHandle, &bitstream, ×tamp, &tmp, &useExtTimestamp, outHeader->pBuffer) != PV_TRUE) { ALOGE("failed to decode video frame."); notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; return; } if (portSettingsChanged()) { return; } // decoder deals in ms, OMX in us. outHeader->nTimeStamp = mPvToOmxTimeMap.valueFor(timestamp); mPvToOmxTimeMap.removeItem(timestamp); inHeader->nOffset += bufferSize; inHeader->nFilledLen = 0; if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { outHeader->nFlags = OMX_BUFFERFLAG_EOS; } else { outHeader->nFlags = 0; } if (inHeader->nFilledLen == 0) { inInfo->mOwnedByUs = false; inQueue.erase(inQueue.begin()); inInfo = NULL; notifyEmptyBufferDone(inHeader); inHeader = NULL; } ++mInputBufferCount; outHeader->nOffset = 0; outHeader->nFilledLen = (mWidth * mHeight * 3) / 2; List<BufferInfo *>::iterator it = outQueue.begin(); while ((*it)->mHeader != outHeader) { ++it; } BufferInfo *outInfo = *it; outInfo->mOwnedByUs = false; outQueue.erase(it); outInfo = NULL; notifyFillBufferDone(outHeader); outHeader = NULL; ++mNumSamplesOutput; } }
OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter( OMX_INDEXTYPE index, const OMX_PTR params) { // Include extension index OMX_INDEXEXTTYPE. const int32_t indexFull = index; switch (indexFull) { case OMX_IndexParamStandardComponentRole: { const OMX_PARAM_COMPONENTROLETYPE *roleParams = (const OMX_PARAM_COMPONENTROLETYPE *)params; if (strncmp((const char *)roleParams->cRole, mComponentRole, OMX_MAX_STRINGNAME_SIZE - 1)) { return OMX_ErrorUndefined; } return OMX_ErrorNone; } case OMX_IndexParamVideoPortFormat: { OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; if (formatParams->nPortIndex > kMaxPortIndex) { return OMX_ErrorUndefined; } if (formatParams->nIndex != 0) { return OMX_ErrorNoMore; } return OMX_ErrorNone; } case kPrepareForAdaptivePlaybackIndex: { const PrepareForAdaptivePlaybackParams* adaptivePlaybackParams = (const PrepareForAdaptivePlaybackParams *)params; mIsAdaptive = adaptivePlaybackParams->bEnable; if (mIsAdaptive) { mAdaptiveMaxWidth = adaptivePlaybackParams->nMaxFrameWidth; mAdaptiveMaxHeight = adaptivePlaybackParams->nMaxFrameHeight; mWidth = mAdaptiveMaxWidth; mHeight = mAdaptiveMaxHeight; } else { mAdaptiveMaxWidth = 0; mAdaptiveMaxHeight = 0; } updatePortDefinitions(); return OMX_ErrorNone; } case OMX_IndexParamPortDefinition: { OMX_PARAM_PORTDEFINITIONTYPE *newParams = (OMX_PARAM_PORTDEFINITIONTYPE *)params; OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &newParams->format.video; OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(newParams->nPortIndex)->mDef; uint32_t oldWidth = def->format.video.nFrameWidth; uint32_t oldHeight = def->format.video.nFrameHeight; uint32_t newWidth = video_def->nFrameWidth; uint32_t newHeight = video_def->nFrameHeight; if (newWidth != oldWidth || newHeight != oldHeight) { bool outputPort = (newParams->nPortIndex == kOutputPortIndex); def->format.video.nFrameWidth = (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) { mWidth = newWidth; mHeight = newHeight; mCropLeft = 0; mCropTop = 0; mCropWidth = newWidth; mCropHeight = newHeight; } newParams->nBufferSize = def->nBufferSize; } return SimpleSoftOMXComponent::internalSetParameter(index, params); } default: return SimpleSoftOMXComponent::internalSetParameter(index, params); } }
void SoftMPEG4::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError || mOutputPortSettingsChange != NONE) { return; } List<BufferInfo *> &inQueue = getPortQueue(0); List<BufferInfo *> &outQueue = getPortQueue(1); while (!inQueue.empty() && outQueue.size() == kNumOutputBuffers) { BufferInfo *inInfo = *inQueue.begin(); OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; if (inHeader == NULL) { inQueue.erase(inQueue.begin()); inInfo->mOwnedByUs = false; continue; } PortInfo *port = editPortInfo(1); OMX_BUFFERHEADERTYPE *outHeader = port->mBuffers.editItemAt(mNumSamplesOutput & 1).mHeader; if (inHeader->nFilledLen == 0) { inQueue.erase(inQueue.begin()); inInfo->mOwnedByUs = false; notifyEmptyBufferDone(inHeader); ++mInputBufferCount; if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { outHeader->nFilledLen = 0; outHeader->nFlags = OMX_BUFFERFLAG_EOS; List<BufferInfo *>::iterator it = outQueue.begin(); while ((*it)->mHeader != outHeader) { ++it; } BufferInfo *outInfo = *it; outInfo->mOwnedByUs = false; outQueue.erase(it); outInfo = NULL; notifyFillBufferDone(outHeader); outHeader = NULL; } return; } uint8_t *bitstream = inHeader->pBuffer + inHeader->nOffset; uint32_t *start_code = (uint32_t *)bitstream; bool volHeader = *start_code == 0xB0010000; if (volHeader) { PVCleanUpVideoDecoder(mHandle); mInitialized = false; } if (!mInitialized) { uint8_t *vol_data[1]; int32_t vol_size = 0; vol_data[0] = NULL; if ((inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) || volHeader) { vol_data[0] = bitstream; vol_size = inHeader->nFilledLen; } MP4DecodingMode mode = (mMode == MODE_MPEG4) ? MPEG4_MODE : H263_MODE; Bool success = PVInitVideoDecoder( mHandle, vol_data, &vol_size, 1, outputBufferWidth(), outputBufferHeight(), mode); if (!success) { ALOGW("PVInitVideoDecoder failed. Unsupported content?"); notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; return; } MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle); if (mode != actualMode) { notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; return; } PVSetPostProcType((VideoDecControls *) mHandle, 0); bool hasFrameData = false; if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { inInfo->mOwnedByUs = false; inQueue.erase(inQueue.begin()); inInfo = NULL; notifyEmptyBufferDone(inHeader); inHeader = NULL; } else if (volHeader) { hasFrameData = true; } mInitialized = true; if (mode == MPEG4_MODE && handlePortSettingsChange()) { return; } if (!hasFrameData) { continue; } } if (!mFramesConfigured) { PortInfo *port = editPortInfo(1); OMX_BUFFERHEADERTYPE *outHeader = port->mBuffers.editItemAt(1).mHeader; OMX_U32 yFrameSize = sizeof(uint8) * mHandle->size; if ((outHeader->nAllocLen < yFrameSize) || (outHeader->nAllocLen - yFrameSize < yFrameSize / 2)) { ALOGE("Too small output buffer for reference frame: %lu bytes", (unsigned long)outHeader->nAllocLen); android_errorWriteLog(0x534e4554, "30033990"); notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; return; } PVSetReferenceYUV(mHandle, outHeader->pBuffer); mFramesConfigured = true; } uint32_t useExtTimestamp = (inHeader->nOffset == 0); // decoder deals in ms (int32_t), OMX in us (int64_t) // so use fake timestamp instead uint32_t timestamp = 0xFFFFFFFF; if (useExtTimestamp) { mPvToOmxTimeMap.add(mPvTime, inHeader->nTimeStamp); timestamp = mPvTime; mPvTime++; } int32_t bufferSize = inHeader->nFilledLen; int32_t tmp = bufferSize; OMX_U32 frameSize; OMX_U64 yFrameSize = (OMX_U64)mWidth * (OMX_U64)mHeight; if (yFrameSize > ((OMX_U64)UINT32_MAX / 3) * 2) { ALOGE("Frame size too large"); notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; return; } frameSize = (OMX_U32)(yFrameSize + (yFrameSize / 2)); if (outHeader->nAllocLen < frameSize) { android_errorWriteLog(0x534e4554, "27833616"); ALOGE("Insufficient output buffer size"); notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; return; } // The PV decoder is lying to us, sometimes it'll claim to only have // consumed a subset of the buffer when it clearly consumed all of it. // ignore whatever it says... if (PVDecodeVideoFrame( mHandle, &bitstream, ×tamp, &tmp, &useExtTimestamp, outHeader->pBuffer) != PV_TRUE) { ALOGE("failed to decode video frame."); notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; return; } // H263 doesn't have VOL header, the frame size information is in short header, i.e. the // decoder may detect size change after PVDecodeVideoFrame. if (handlePortSettingsChange()) { return; } // decoder deals in ms, OMX in us. outHeader->nTimeStamp = mPvToOmxTimeMap.valueFor(timestamp); mPvToOmxTimeMap.removeItem(timestamp); inHeader->nOffset += bufferSize; inHeader->nFilledLen = 0; if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { outHeader->nFlags = OMX_BUFFERFLAG_EOS; } else { outHeader->nFlags = 0; } if (inHeader->nFilledLen == 0) { inInfo->mOwnedByUs = false; inQueue.erase(inQueue.begin()); inInfo = NULL; notifyEmptyBufferDone(inHeader); inHeader = NULL; } ++mInputBufferCount; outHeader->nOffset = 0; outHeader->nFilledLen = frameSize; List<BufferInfo *>::iterator it = outQueue.begin(); while ((*it)->mHeader != outHeader) { ++it; } BufferInfo *outInfo = *it; outInfo->mOwnedByUs = false; outQueue.erase(it); outInfo = NULL; notifyFillBufferDone(outHeader); outHeader = NULL; ++mNumSamplesOutput; } }
OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter( OMX_INDEXTYPE index, const OMX_PTR params) { // Include extension index OMX_INDEXEXTTYPE. const int32_t indexFull = index; switch (indexFull) { case OMX_IndexParamStandardComponentRole: { const OMX_PARAM_COMPONENTROLETYPE *roleParams = (const OMX_PARAM_COMPONENTROLETYPE *)params; if (strncmp((const char *)roleParams->cRole, mComponentRole, OMX_MAX_STRINGNAME_SIZE - 1)) { return OMX_ErrorUndefined; } return OMX_ErrorNone; } case OMX_IndexParamVideoPortFormat: { OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; if (formatParams->nPortIndex > kMaxPortIndex) { 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; } case kPrepareForAdaptivePlaybackIndex: { const PrepareForAdaptivePlaybackParams* adaptivePlaybackParams = (const PrepareForAdaptivePlaybackParams *)params; mIsAdaptive = adaptivePlaybackParams->bEnable; if (mIsAdaptive) { mAdaptiveMaxWidth = adaptivePlaybackParams->nMaxFrameWidth; mAdaptiveMaxHeight = adaptivePlaybackParams->nMaxFrameHeight; mWidth = mAdaptiveMaxWidth; mHeight = mAdaptiveMaxHeight; } else { mAdaptiveMaxWidth = 0; mAdaptiveMaxHeight = 0; } updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */); return OMX_ErrorNone; } case OMX_IndexParamPortDefinition: { OMX_PARAM_PORTDEFINITIONTYPE *newParams = (OMX_PARAM_PORTDEFINITIONTYPE *)params; OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &newParams->format.video; OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(newParams->nPortIndex)->mDef; uint32_t oldWidth = def->format.video.nFrameWidth; uint32_t oldHeight = def->format.video.nFrameHeight; uint32_t newWidth = video_def->nFrameWidth; uint32_t newHeight = video_def->nFrameHeight; if (newWidth != oldWidth || newHeight != oldHeight) { bool outputPort = (newParams->nPortIndex == kOutputPortIndex); if (outputPort) { // only update (essentially crop) if size changes mWidth = newWidth; mHeight = newHeight; updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */); // reset buffer size based on frame size newParams->nBufferSize = def->nBufferSize; } else { // For input port, we only set nFrameWidth and nFrameHeight. Buffer size // is updated when configuring the output port using the max-frame-size, // though client can still request a larger size. def->format.video.nFrameWidth = newWidth; def->format.video.nFrameHeight = newHeight; } } return SimpleSoftOMXComponent::internalSetParameter(index, params); } default: return SimpleSoftOMXComponent::internalSetParameter(index, params); } }