aboutsummaryrefslogtreecommitdiffstats
path: root/videocodec/OMXVideoDecoderVP9Hybrid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'videocodec/OMXVideoDecoderVP9Hybrid.cpp')
-rw-r--r--videocodec/OMXVideoDecoderVP9Hybrid.cpp277
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(&paramPortDefinitionInput,
+ this->ports[INPORT_INDEX]->GetPortDefinition(),
+ sizeof(paramPortDefinitionInput));
+
+ memcpy(&paramPortDefinitionOutput,
+ 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(&paramPortDefinitionInput, 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(&paramPortDefinitionInput, true);
+ this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, 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);