diff options
Diffstat (limited to 'videocodec/OMXVideoDecoderVP9Hybrid.cpp')
-rw-r--r-- | videocodec/OMXVideoDecoderVP9Hybrid.cpp | 277 |
1 files changed, 237 insertions, 40 deletions
diff --git a/videocodec/OMXVideoDecoderVP9Hybrid.cpp b/videocodec/OMXVideoDecoderVP9Hybrid.cpp index e1ff00d..1246b7b 100644 --- a/videocodec/OMXVideoDecoderVP9Hybrid.cpp +++ b/videocodec/OMXVideoDecoderVP9Hybrid.cpp @@ -39,6 +39,15 @@ OMXVideoDecoderVP9Hybrid::OMXVideoDecoderVP9Hybrid() { mDecoderDecode = NULL; mCheckBufferAvailable = NULL; mGetOutput = NULL; + mGetRawDataOutput = NULL; + mGetFrameResolution = NULL; + mDeinitDecoder = NULL; + mLastTimeStamp = 0; + mWorkingMode = RAWDATA_MODE; + mDecodedImageWidth = 0; + mDecodedImageHeight = 0; + mDecodedImageNewWidth = 0; + mDecodedImageNewHeight = 0; } OMXVideoDecoderVP9Hybrid::~OMXVideoDecoderVP9Hybrid() { @@ -57,15 +66,26 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::InitInputPortFormatSpecific( } OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorInit(void) { - unsigned int buff[MAX_GRAPHIC_BUFFER_NUM]; - unsigned int i; - int bufferSize = mGraphicBufferParam.graphicBufferStride * + uint32_t buff[MAX_GRAPHIC_BUFFER_NUM]; + uint32_t i, bufferCount; + bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE); + uint32_t bufferSize, bufferStride, bufferHeight; + if (!gralloc_mode) { + bufferSize = 1920 * 1088 * 1.5; + bufferStride = 1920; + bufferHeight = 1088; + bufferCount = 12; + } else { + bufferSize = mGraphicBufferParam.graphicBufferStride * mGraphicBufferParam.graphicBufferHeight * 1.5; - int bufferStride = mGraphicBufferParam.graphicBufferStride; + bufferStride = mGraphicBufferParam.graphicBufferStride; + bufferCount = mOMXBufferHeaderTypePtrNum; + bufferHeight = mGraphicBufferParam.graphicBufferHeight; - for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++ ) { - OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i]; - buff[i] = (unsigned int)(buf_hdr->pBuffer); + for (i = 0; i < bufferCount; i++ ) { + OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i]; + buff[i] = (uint32_t)(buf_hdr->pBuffer); + } } mLibHandle = dlopen("libDecoderVP9Hybrid.so", RTLD_NOW); @@ -82,10 +102,14 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorInit(void) { mDecoderDecode = (DecodeFunc)dlsym(mLibHandle, "Decoder_Decode"); mCheckBufferAvailable = (IsBufferAvailableFunc)dlsym(mLibHandle, "Decoder_IsBufferAvailable"); mGetOutput = (GetOutputFunc)dlsym(mLibHandle, "Decoder_GetOutput"); + mGetRawDataOutput = (GetRawDataOutputFunc)dlsym(mLibHandle, "Decoder_GetRawDataOutput"); + mGetFrameResolution = (GetFrameResolutionFunc)dlsym(mLibHandle, "Decoder_GetFrameResolution"); + mDeinitDecoder = (DeinitFunc)dlsym(mLibHandle, "Decoder_Deinit"); if (mOpenDecoder == NULL || mCloseDecoder == NULL || mInitDecoder == NULL || mSingalRenderDone == NULL || mDecoderDecode == NULL || mCheckBufferAvailable == NULL - || mGetOutput == NULL) { + || mGetOutput == NULL || mGetRawDataOutput == NULL + || mGetFrameResolution == NULL || mDeinitDecoder == NULL) { return OMX_ErrorBadParameter; } @@ -94,10 +118,58 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorInit(void) { return OMX_ErrorBadParameter; } - mInitDecoder(mHybridCtx,bufferSize,bufferStride,mOMXBufferHeaderTypePtrNum, buff); + mInitDecoder(mHybridCtx,bufferSize,bufferStride,bufferHeight,bufferCount,gralloc_mode, buff); return OMX_ErrorNone; } +OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorReset(void) +{ + uint32_t buff[MAX_GRAPHIC_BUFFER_NUM]; + uint32_t i, bufferCount; + bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE); + uint32_t bufferSize, bufferStride, bufferHeight; + if (!gralloc_mode) { + bufferSize = mDecodedImageWidth * mDecodedImageHeight * 1.5; + bufferStride = mDecodedImageWidth; + bufferHeight = mDecodedImageHeight; + bufferCount = 12; + } else { + bufferSize = mGraphicBufferParam.graphicBufferStride * + mGraphicBufferParam.graphicBufferHeight * 1.5; + bufferStride = mGraphicBufferParam.graphicBufferStride; + bufferCount = mOMXBufferHeaderTypePtrNum; + bufferHeight = mGraphicBufferParam.graphicBufferHeight; + + for (i = 0; i < bufferCount; i++ ) { + OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i]; + buff[i] = (uint32_t)(buf_hdr->pBuffer); + } + } + mInitDecoder(mHybridCtx,bufferSize,bufferStride,bufferHeight,bufferCount,gralloc_mode, buff); + + return OMX_ErrorNone; +} + +bool OMXVideoDecoderVP9Hybrid::isReallocateNeeded(const uint8_t * data,uint32_t data_sz) +{ + bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE); + uint32_t width, height; + bool ret = true; + if (gralloc_mode) { + ret = mGetFrameResolution(data,data_sz, &width, &height); + if (ret) { + ret = width > mGraphicBufferParam.graphicBufferWidth + || height > mGraphicBufferParam.graphicBufferHeight; + if (ret) { + mDecodedImageNewWidth = width; + mDecodedImageNewHeight = height; + return true; + } + } + } + return ret; +} + OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorDeinit(void) { mCloseDecoder(mCtx,mHybridCtx); mOMXBufferHeaderTypePtrNum = 0; @@ -112,7 +184,14 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorStop(void) { return OMXComponentCodecBase::ProcessorStop(); } -OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorFlush(OMX_U32) { +OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorFlush(OMX_U32 portIndex) { + if (portIndex == INPORT_INDEX || portIndex == OMX_ALL) { + // end the last frame + unsigned int width, height; + mDecoderDecode(mCtx,mHybridCtx,NULL,0,true); + mGetOutput(mCtx,mHybridCtx, &width, &height); + mLastTimeStamp = 0; + } return OMX_ErrorNone; } @@ -121,7 +200,7 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorPreFillBuffer(OMX_BUFFERHEADERT unsigned int i = 0; if (buffer->nOutputPortIndex == OUTPORT_INDEX){ - mSingalRenderDone(handle); + mSingalRenderDone(mHybridCtx,handle); } return OMX_ErrorNone; } @@ -134,6 +213,10 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorProcess( OMX_ERRORTYPE ret; OMX_BUFFERHEADERTYPE *inBuffer = *pBuffers[INPORT_INDEX]; OMX_BUFFERHEADERTYPE *outBuffer = *pBuffers[OUTPORT_INDEX]; + bool eos = (inBuffer->nFlags & OMX_BUFFERFLAG_EOS)? true:false; + OMX_BOOL isResolutionChange = OMX_FALSE; + + eos = eos && (inBuffer->nFilledLen == 0); if (inBuffer->pBuffer == NULL) { LOGE("Buffer to decode is empty."); @@ -148,22 +231,26 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorProcess( LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag."); } - if (inBuffer->nFlags & OMX_BUFFERFLAG_EOS) { - if (inBuffer->nFilledLen == 0) { - (*pBuffers[OUTPORT_INDEX])->nFilledLen = 0; - (*pBuffers[OUTPORT_INDEX])->nFlags = OMX_BUFFERFLAG_EOS; - return OMX_ErrorNone; - } - } - #if LOG_TIME == 1 struct timeval tv_start, tv_end; int32_t time_ms; gettimeofday(&tv_start,NULL); #endif - if (mDecoderDecode(mCtx,mHybridCtx,inBuffer->pBuffer + inBuffer->nOffset,inBuffer->nFilledLen) == false) { - LOGE("on2 decoder failed to decode frame."); - return OMX_ErrorBadParameter; + int res = mDecoderDecode(mCtx,mHybridCtx,inBuffer->pBuffer + inBuffer->nOffset,inBuffer->nFilledLen, eos); + if (res != 0) { + if (res == -2) { + if (isReallocateNeeded(inBuffer->pBuffer + inBuffer->nOffset,inBuffer->nFilledLen)) { + retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; + HandleFormatChange(); + return OMX_ErrorNone; + } + // drain the last frame, keep the current input buffer + res = mDecoderDecode(mCtx,mHybridCtx,NULL,0,true); + retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; + } else { + LOGE("on2 decoder failed to decode frame."); + return OMX_ErrorBadParameter; + } } #if LOG_TIME == 1 @@ -174,12 +261,17 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorProcess( ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], - ((*pBuffers[INPORT_INDEX]))->nFlags); + eos? OMX_BUFFERFLAG_EOS:0, + &isResolutionChange); if (ret == OMX_ErrorNone) { - (*pBuffers[OUTPORT_INDEX])->nTimeStamp = inBuffer->nTimeStamp; + (*pBuffers[OUTPORT_INDEX])->nTimeStamp = mLastTimeStamp; } + mLastTimeStamp = inBuffer->nTimeStamp; + if (isResolutionChange == OMX_TRUE) { + HandleFormatChange(); + } bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS); // if output port is not eos, retain the input buffer @@ -206,29 +298,51 @@ static int ALIGN(int x, int y) { OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer, buffer_retain_t *retain, - OMX_U32 inportBufferFlags) + OMX_U32 inportBufferFlags, + OMX_BOOL *isResolutionChange) { OMX_BUFFERHEADERTYPE *buffer = *pBuffer; OMX_BUFFERHEADERTYPE *buffer_orign = buffer; OMX_ERRORTYPE ret = OMX_ErrorNone; - if (mWorkingMode != GRAPHICBUFFER_MODE) { - LOGE("Working Mode is not GRAPHICBUFFER_MODE"); - ret = OMX_ErrorBadParameter; + int fb_index; + if (mWorkingMode == RAWDATA_MODE) { + const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput + = this->ports[OUTPORT_INDEX]->GetPortDefinition(); + int32_t stride = paramPortDefinitionOutput->format.video.nStride; + int32_t height = paramPortDefinitionOutput->format.video.nFrameHeight; + int32_t width = paramPortDefinitionOutput->format.video.nFrameWidth; + unsigned char *dst = buffer->pBuffer; + fb_index = mGetRawDataOutput(mCtx,mHybridCtx,dst,height,stride); + if (fb_index == -1) { + LOGV("vpx_codec_get_frame return NULL."); + return OMX_ErrorNotReady; + } + buffer->nOffset = 0; + buffer->nFilledLen = stride*height*3/2; + if (inportBufferFlags & OMX_BUFFERFLAG_EOS) { + buffer->nFlags = OMX_BUFFERFLAG_EOS; + } + return OMX_ErrorNone; } - int fb_index = mGetOutput(mCtx); + + fb_index = mGetOutput(mCtx,mHybridCtx, &mDecodedImageNewWidth, &mDecodedImageNewHeight); if (fb_index == -1) { - LOGE("vpx_codec_get_frame return NULL."); + LOGV("vpx_codec_get_frame return NULL."); return OMX_ErrorNotReady; } + if (mDecodedImageHeight == 0 && mDecodedImageWidth == 0) { + mDecodedImageWidth = mDecodedImageNewWidth; + mDecodedImageHeight = mDecodedImageNewHeight; + *isResolutionChange = OMX_TRUE; + } + if ((mDecodedImageNewWidth != mDecodedImageWidth) + || (mDecodedImageNewHeight!= mDecodedImageHeight)) { + *isResolutionChange = OMX_TRUE; + } buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[fb_index]; - - size_t dst_y_size = mGraphicBufferParam.graphicBufferStride * - mGraphicBufferParam.graphicBufferHeight; - size_t dst_c_stride = ALIGN(mGraphicBufferParam.graphicBufferStride / 2, 16); - size_t dst_c_size = dst_c_stride * mGraphicBufferParam.graphicBufferHeight / 2; buffer->nOffset = 0; buffer->nFilledLen = sizeof(OMX_U8*); if (inportBufferFlags & OMX_BUFFERFLAG_EOS) { @@ -268,6 +382,88 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::SetParamVideoVp9(OMX_PTR) { return OMX_ErrorNone; } +OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::HandleFormatChange(void) +{ + ALOGI("handle format change from %dx%d to %dx%d", + mDecodedImageWidth,mDecodedImageHeight,mDecodedImageNewWidth,mDecodedImageNewHeight); + mDecodedImageWidth = mDecodedImageNewWidth; + mDecodedImageHeight = mDecodedImageNewHeight; + // Sync port definition as it may change. + OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput; + + memcpy(¶mPortDefinitionInput, + this->ports[INPORT_INDEX]->GetPortDefinition(), + sizeof(paramPortDefinitionInput)); + + memcpy(¶mPortDefinitionOutput, + this->ports[OUTPORT_INDEX]->GetPortDefinition(), + sizeof(paramPortDefinitionOutput)); + + unsigned int width = mDecodedImageWidth; + unsigned int height = mDecodedImageHeight; + unsigned int stride = mDecodedImageWidth; + unsigned int sliceHeight = mDecodedImageHeight; + + unsigned int widthCropped = mDecodedImageWidth; + unsigned int heightCropped = mDecodedImageHeight; + unsigned int strideCropped = widthCropped; + unsigned int sliceHeightCropped = heightCropped; + + if (widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth && + heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) { + if (mWorkingMode == RAWDATA_MODE) { + LOGW("Change of portsetting is not reported as size is not changed."); + return OMX_ErrorNone; + } + } + + paramPortDefinitionInput.format.video.nFrameWidth = width; + paramPortDefinitionInput.format.video.nFrameHeight = height; + paramPortDefinitionInput.format.video.nStride = stride; + paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight; + + if (mWorkingMode == RAWDATA_MODE) { + paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped; + paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped; + paramPortDefinitionOutput.format.video.nStride = strideCropped; + paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped; + } else if (mWorkingMode == GRAPHICBUFFER_MODE) { + // when the width and height ES parse are not larger than allocated graphic buffer in outport, + // there is no need to reallocate graphic buffer,just report the crop info to omx client + if (width <= mGraphicBufferParam.graphicBufferWidth && + height <= mGraphicBufferParam.graphicBufferHeight) { + this->ports[INPORT_INDEX]->SetPortDefinition(¶mPortDefinitionInput, true); + this->ports[OUTPORT_INDEX]->ReportOutputCrop(); + return OMX_ErrorNone; + } + + if (width > mGraphicBufferParam.graphicBufferWidth || + height > mGraphicBufferParam.graphicBufferHeight) { + // update the real decoded resolution to outport instead of display resolution + // for graphic buffer reallocation + // when the width and height parsed from ES are larger than allocated graphic buffer in outport, + paramPortDefinitionOutput.format.video.nFrameWidth = width; + paramPortDefinitionOutput.format.video.nFrameHeight = (height + 0x1f) & ~0x1f; + paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat( + paramPortDefinitionOutput.format.video.nFrameWidth); + paramPortDefinitionOutput.format.video.nStride = stride; + paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight; + } + } + + paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false; + mOMXBufferHeaderTypePtrNum = 0; + memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam)); + mDeinitDecoder(mHybridCtx); + + this->ports[INPORT_INDEX]->SetPortDefinition(¶mPortDefinitionInput, true); + this->ports[OUTPORT_INDEX]->SetPortDefinition(¶mPortDefinitionOutput, true); + + this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged(); + return OMX_ErrorNone; +} + + OMX_COLOR_FORMATTYPE OMXVideoDecoderVP9Hybrid::GetOutputColorFormat(int) { LOGV("Output color format is HAL_PIXEL_FORMAT_YV12."); return (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12; @@ -301,7 +497,7 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetNativeBufferUsageSpecific(OMX_PTR pSt (android::GetAndroidNativeBufferUsageParams*)pStructure; CHECK_TYPE_HEADER(param); - param->nUsage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER \ + param->nUsage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_EXTERNAL_DISP); return OMX_ErrorNone; @@ -317,6 +513,7 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::SetNativeBufferModeSpecific(OMX_PTR pStr if (!param->enable) { mWorkingMode = RAWDATA_MODE; + LOGI("Raw data mode is used"); return OMX_ErrorNone; } mWorkingMode = GRAPHICBUFFER_MODE; @@ -325,13 +522,13 @@ OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::SetNativeBufferModeSpecific(OMX_PTR pStr OMX_PARAM_PORTDEFINITIONTYPE port_def; memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def)); - port_def.nBufferCountMin = mNativeBufferCount; + port_def.nBufferCountMin = mNativeBufferCount - 4; port_def.nBufferCountActual = mNativeBufferCount; port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE; - port_def.format.video.eColorFormat = (OMX_COLOR_FORMATTYPE)OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar; // add borders for libvpx decode need. - port_def.format.video.nFrameHeight += VPX_DECODE_BORDER * 2; port_def.format.video.nFrameWidth += VPX_DECODE_BORDER * 2; + mDecodedImageWidth = port_def.format.video.nFrameWidth; + mDecodedImageHeight = port_def.format.video.nFrameHeight; // make heigth 32bit align port_def.format.video.nFrameHeight = (port_def.format.video.nFrameHeight + 0x1f) & ~0x1f; port_def.format.video.eColorFormat = GetOutputColorFormat(port_def.format.video.nFrameWidth); @@ -354,7 +551,7 @@ bool OMXVideoDecoderVP9Hybrid::IsAllBufferAvailable(void) { if (!port_def->bEnabled) { return false; } - return mCheckBufferAvailable(); + return mCheckBufferAvailable(mHybridCtx); } DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.VP9.hybrid", "video_decoder.vp9", OMXVideoDecoderVP9Hybrid); |