You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
734 lines
29 KiB
734 lines
29 KiB
/* |
|
* Copyright (c) 2012 Intel Corporation. All rights reserved. |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
#define LOG_TIME 0 |
|
//#define LOG_NDEBUG 0 |
|
#define LOG_TAG "OMXVideoDecoderVP9Hybrid" |
|
#include <wrs_omxil_core/log.h> |
|
#include "OMXVideoDecoderVP9Hybrid.h" |
|
|
|
#include <hardware/hardware.h> |
|
#include <hardware/gralloc.h> |
|
#include <system/graphics.h> |
|
|
|
#include <hal_public.h> |
|
|
|
#define VP9_YV12_ALIGN (128-1) |
|
static const char* VP9_MIME_TYPE = "video/x-vnd.on2.vp9"; |
|
|
|
OMXVideoDecoderVP9Hybrid::OMXVideoDecoderVP9Hybrid() { |
|
LOGV("OMXVideoDecoderVP9Hybrid is constructed."); |
|
mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT; |
|
BuildHandlerList(); |
|
mLibHandle = NULL; |
|
mOpenDecoder = NULL; |
|
mInitDecoder = NULL; |
|
mCloseDecoder = NULL; |
|
mSingalRenderDone = NULL; |
|
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() { |
|
LOGV("OMXVideoDecoderVP9Hybrid is destructed."); |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::InitInputPortFormatSpecific( |
|
OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput) { |
|
// OMX_PARAM_PORTDEFINITIONTYPE |
|
paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT; |
|
paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT; |
|
paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE; |
|
paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)VP9_MIME_TYPE; |
|
paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingVP9; |
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorInit(void) { |
|
uint32_t buff[MAX_GRAPHIC_BUFFER_NUM]; |
|
uint32_t i, bufferCount; |
|
bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE); |
|
uint32_t bufferSize, bufferHStride, bufferHeight, bufferVStride, bufferWidth; |
|
if (!gralloc_mode) { |
|
bufferHStride = 1920; |
|
bufferVStride = 1088; |
|
bufferWidth = 1920; |
|
bufferHeight = 1080; |
|
bufferCount = 12; |
|
} else { |
|
if (mAPMode == METADATA_MODE) { |
|
const OMX_PARAM_PORTDEFINITIONTYPE *def_output = this->ports[OUTPORT_INDEX]->GetPortDefinition(); |
|
if (def_output == NULL) { |
|
return OMX_ErrorBadParameter; |
|
} |
|
bufferCount = mMetaDataBuffersNum = def_output->nBufferCountActual; |
|
mOMXBufferHeaderTypePtrNum = 0; |
|
|
|
mGraphicBufferParam.graphicBufferColorFormat = def_output->format.video.eColorFormat; |
|
mGraphicBufferParam.graphicBufferHStride = (def_output->format.video.nFrameWidth + VP9_YV12_ALIGN) & ~VP9_YV12_ALIGN; |
|
mGraphicBufferParam.graphicBufferVStride = (def_output->format.video.nFrameHeight + 0x1f) & ~0x1f; |
|
mGraphicBufferParam.graphicBufferWidth = def_output->format.video.nFrameWidth; |
|
mGraphicBufferParam.graphicBufferHeight = def_output->format.video.nFrameHeight; |
|
mDecodedImageWidth = def_output->format.video.nFrameWidth; |
|
mDecodedImageHeight = def_output->format.video.nFrameHeight; |
|
} else{ |
|
bufferCount = mOMXBufferHeaderTypePtrNum; |
|
|
|
for (i = 0; i < bufferCount; i++ ) { |
|
OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i]; |
|
buff[i] = (uint32_t)(buf_hdr->pBuffer); |
|
} |
|
} |
|
|
|
bufferHStride = mGraphicBufferParam.graphicBufferHStride; |
|
bufferVStride = mGraphicBufferParam.graphicBufferVStride; |
|
bufferWidth = mGraphicBufferParam.graphicBufferWidth; |
|
bufferHeight = mGraphicBufferParam.graphicBufferHeight; |
|
} |
|
|
|
bufferSize = bufferHStride * bufferVStride * 1.5; |
|
|
|
mLibHandle = dlopen("libDecoderVP9Hybrid.so", RTLD_NOW); |
|
if (mLibHandle == NULL) { |
|
LOGE("dlopen libDecoderVP9Hybrid.so fail\n"); |
|
return OMX_ErrorBadParameter; |
|
} else { |
|
LOGI("dlopen libDecoderVP9Hybrid.so successfully\n"); |
|
} |
|
mOpenDecoder = (OpenFunc)dlsym(mLibHandle, "Decoder_Open"); |
|
mCloseDecoder = (CloseFunc)dlsym(mLibHandle, "Decoder_Close"); |
|
mInitDecoder = (InitFunc)dlsym(mLibHandle, "Decoder_Init"); |
|
mSingalRenderDone = (SingalRenderDoneFunc)dlsym(mLibHandle, "Decoder_SingalRenderDone"); |
|
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 || mGetRawDataOutput == NULL |
|
|| mGetFrameResolution == NULL || mDeinitDecoder == NULL) { |
|
return OMX_ErrorBadParameter; |
|
} |
|
|
|
if (mOpenDecoder(&mCtx,&mHybridCtx) == false) { |
|
LOGE("open hybrid Decoder fail\n"); |
|
return OMX_ErrorBadParameter; |
|
} |
|
|
|
// FIXME: The proprietary part of the vp9hybrid decoder should be updated |
|
// to take VStride as well as Height. For now it's convenient to |
|
// use VStride as that was effectively what was done before.. |
|
mInitDecoder(mHybridCtx, bufferSize, bufferHStride, bufferWidth, |
|
bufferHeight, bufferCount, gralloc_mode, buff, (uint32_t)mAPMode); |
|
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, bufferHStride, bufferHeight, bufferVStride, bufferWidth; |
|
if (!gralloc_mode) { |
|
bufferHStride = mDecodedImageWidth; |
|
bufferVStride = mDecodedImageHeight; |
|
bufferWidth = mDecodedImageWidth; |
|
bufferHeight = mDecodedImageHeight; |
|
bufferSize = bufferHStride * bufferVStride * 1.5; |
|
bufferCount = 12; |
|
} else { |
|
if (mAPMode == METADATA_MODE) { |
|
const OMX_PARAM_PORTDEFINITIONTYPE *def_output = this->ports[OUTPORT_INDEX]->GetPortDefinition(); |
|
if (def_output == NULL) { |
|
return OMX_ErrorBadParameter; |
|
} |
|
bufferCount = mMetaDataBuffersNum = def_output->nBufferCountActual; |
|
mOMXBufferHeaderTypePtrNum = 0; |
|
|
|
mGraphicBufferParam.graphicBufferColorFormat = def_output->format.video.eColorFormat; |
|
mGraphicBufferParam.graphicBufferHStride = (def_output->format.video.nFrameWidth + VP9_YV12_ALIGN) & ~VP9_YV12_ALIGN; |
|
mGraphicBufferParam.graphicBufferVStride = (def_output->format.video.nFrameHeight + 0x1f) & ~0x1f; |
|
mGraphicBufferParam.graphicBufferWidth = def_output->format.video.nFrameWidth; |
|
mGraphicBufferParam.graphicBufferHeight = def_output->format.video.nFrameHeight; |
|
} else{ |
|
bufferCount = mOMXBufferHeaderTypePtrNum; |
|
|
|
for (i = 0; i < bufferCount; i++ ) { |
|
OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i]; |
|
buff[i] = (uint32_t)(buf_hdr->pBuffer); |
|
} |
|
} |
|
bufferHStride = mGraphicBufferParam.graphicBufferHStride; |
|
bufferVStride = mGraphicBufferParam.graphicBufferVStride; |
|
bufferWidth = mGraphicBufferParam.graphicBufferWidth; |
|
bufferHeight = mGraphicBufferParam.graphicBufferHeight; |
|
} |
|
|
|
bufferSize = bufferHStride * bufferVStride * 1.5; |
|
|
|
// FIXME: The proprietary part of the vp9hybrid decoder should be updated |
|
// to take VStride as well as Height. For now it's convenient to |
|
// use VStride as that was effectively what was done before.. |
|
mInitDecoder(mHybridCtx, bufferSize, bufferHStride, bufferWidth, |
|
bufferHeight, bufferCount, gralloc_mode, buff, (uint32_t)mAPMode); |
|
mFormatChanged = false; |
|
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 (width == 0 || height == 0) |
|
return false; |
|
|
|
if (ret) { |
|
if (mAPMode == METADATA_MODE) { |
|
ret = (width != mDecodedImageWidth) |
|
|| (height != mDecodedImageHeight); |
|
} else { |
|
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; |
|
if (mLibHandle != NULL) { |
|
dlclose(mLibHandle); |
|
mLibHandle = NULL; |
|
} |
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorStop(void) { |
|
return OMXComponentCodecBase::ProcessorStop(); |
|
} |
|
|
|
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); |
|
} |
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer) { |
|
if (buffer->nOutputPortIndex == OUTPORT_INDEX){ |
|
unsigned int handle; |
|
if (mAPMode == METADATA_MODE) { |
|
bool found = false; |
|
if (mOMXBufferHeaderTypePtrNum < mMetaDataBuffersNum) { |
|
for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++) { |
|
if (mOMXBufferHeaderTypePtrArray[i] == buffer) { |
|
found = true; |
|
break; |
|
} |
|
} |
|
if (!found) { |
|
mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum] = buffer; |
|
mOMXBufferHeaderTypePtrNum++; |
|
} |
|
} else { |
|
found = true; |
|
} |
|
|
|
android::VideoGrallocMetadata *metadata = (android::VideoGrallocMetadata *)(buffer->pBuffer); |
|
handle = (unsigned int)metadata->pHandle; |
|
mSingalRenderDone(mHybridCtx, handle, !found); |
|
} else { |
|
handle = (unsigned int)buffer->pBuffer; |
|
mSingalRenderDone(mHybridCtx, handle, false); |
|
} |
|
} |
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorProcess( |
|
OMX_BUFFERHEADERTYPE ***pBuffers, |
|
buffer_retain_t *retains, |
|
OMX_U32) |
|
{ |
|
OMX_ERRORTYPE ret; |
|
OMX_BUFFERHEADERTYPE *inBuffer = *pBuffers[INPORT_INDEX]; |
|
OMX_BUFFERHEADERTYPE *outBuffer = *pBuffers[OUTPORT_INDEX]; |
|
OMX_BOOL isResolutionChange = OMX_FALSE; |
|
bool eos = (inBuffer->nFlags & OMX_BUFFERFLAG_EOS)? true : false; |
|
eos = eos && (inBuffer->nFilledLen == 0); |
|
static unsigned char *firstFrame = NULL; |
|
static uint32_t firstFrameSize = 0; |
|
|
|
if (inBuffer->pBuffer == NULL) { |
|
LOGE("Buffer to decode is empty."); |
|
return OMX_ErrorBadParameter; |
|
} |
|
|
|
if (inBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { |
|
LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag."); |
|
} |
|
|
|
if (inBuffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) { |
|
LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag."); |
|
} |
|
|
|
if (firstFrameSize == 0 && inBuffer->nFilledLen != 0 && inBuffer->nTimeStamp != 0) { |
|
if (firstFrame != NULL) { |
|
free(firstFrame); |
|
firstFrame = NULL; |
|
} |
|
|
|
firstFrame = (unsigned char *)malloc(inBuffer->nFilledLen); |
|
memcpy(firstFrame, inBuffer->pBuffer + inBuffer->nOffset, inBuffer->nFilledLen); |
|
firstFrameSize = inBuffer->nFilledLen; |
|
} |
|
|
|
if ((mWorkingMode == GRAPHICBUFFER_MODE) && (mAPMode == METADATA_MODE) && (!mFormatChanged)) { |
|
bool mRet = mGetFrameResolution(inBuffer->pBuffer + inBuffer->nOffset, inBuffer->nFilledLen, |
|
&mDecodedImageNewWidth,&mDecodedImageNewHeight); |
|
|
|
if (mRet && ((mDecodedImageNewWidth != 0) && (mDecodedImageNewHeight != 0)) && |
|
((mDecodedImageWidth != 0) && (mDecodedImageHeight != 0)) && |
|
((mDecodedImageNewWidth != mDecodedImageWidth || mDecodedImageNewHeight != mDecodedImageHeight))) { |
|
if (mLastTimeStamp == 0) { |
|
retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; |
|
HandleFormatChange(); |
|
return OMX_ErrorNone; |
|
} else { |
|
// Detected format change in time. |
|
// drain the last frame, keep the current input buffer |
|
mDecoderDecode(mCtx, mHybridCtx, firstFrame, firstFrameSize, false); |
|
retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; |
|
|
|
mFormatChanged = true; |
|
|
|
ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], |
|
eos ? OMX_BUFFERFLAG_EOS : 0, &isResolutionChange); |
|
|
|
if (ret == OMX_ErrorNone) |
|
(*pBuffers[OUTPORT_INDEX])->nTimeStamp = mLastTimeStamp; |
|
|
|
mLastTimeStamp = inBuffer->nTimeStamp; |
|
|
|
free(firstFrame); |
|
firstFrame = NULL; |
|
firstFrameSize = 0; |
|
return ret; |
|
} |
|
} else if (!mRet && (mDecodedImageNewWidth == 0 || mDecodedImageNewHeight == 0)) { |
|
retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; |
|
return OMX_ErrorBadParameter; |
|
} |
|
} |
|
|
|
#if LOG_TIME == 1 |
|
struct timeval tv_start, tv_end; |
|
int32_t time_ms; |
|
gettimeofday(&tv_start,NULL); |
|
#endif |
|
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)) { |
|
if (mAPMode == METADATA_MODE) { |
|
mFormatChanged = true; |
|
} else { |
|
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 if (res == -3) { |
|
LOGW("on2 decoder skipped to decode the frame."); |
|
(*pBuffers[OUTPORT_INDEX])->nOffset = 0; |
|
(*pBuffers[OUTPORT_INDEX])->nFilledLen = 0; |
|
return OMX_ErrorNone; |
|
} else { |
|
LOGE("on2 decoder failed to decode frame."); |
|
return OMX_ErrorBadParameter; |
|
} |
|
} |
|
|
|
#if LOG_TIME == 1 |
|
gettimeofday(&tv_end,NULL); |
|
time_ms = (int32_t)(tv_end.tv_sec - tv_start.tv_sec) * 1000 + (int32_t)(tv_end.tv_usec - tv_start.tv_usec)/1000; |
|
LOGI("vpx_codec_decode: %d ms", time_ms); |
|
#endif |
|
|
|
ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], |
|
&retains[OUTPORT_INDEX], |
|
eos? OMX_BUFFERFLAG_EOS:0, |
|
&isResolutionChange); |
|
|
|
if (ret == OMX_ErrorNone) { |
|
(*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 |
|
// until all the output buffers are drained. |
|
if (inputEoS && !outputEoS && retains[INPORT_INDEX] != BUFFER_RETAIN_GETAGAIN) { |
|
retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; |
|
// the input buffer is retained for draining purpose. |
|
// Set nFilledLen to 0 so buffer will not be decoded again. |
|
(*pBuffers[INPORT_INDEX])->nFilledLen = 0; |
|
} |
|
|
|
if (ret == OMX_ErrorNotReady) { |
|
retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; |
|
ret = OMX_ErrorNone; |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer, |
|
buffer_retain_t *retain, |
|
OMX_U32 inportBufferFlags, |
|
OMX_BOOL *isResolutionChange) |
|
{ |
|
OMX_BUFFERHEADERTYPE *buffer = *pBuffer; |
|
OMX_BUFFERHEADERTYPE *buffer_orign = buffer; |
|
|
|
OMX_ERRORTYPE ret = OMX_ErrorNone; |
|
|
|
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) { |
|
if (inportBufferFlags & OMX_BUFFERFLAG_EOS) { |
|
// eos frame is non-shown frame |
|
buffer->nFlags = OMX_BUFFERFLAG_EOS; |
|
buffer->nOffset = 0; |
|
buffer->nFilledLen = 0; |
|
return OMX_ErrorNone; |
|
} |
|
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; |
|
} |
|
|
|
if (mFormatChanged && mAPMode == METADATA_MODE) { |
|
fb_index = mGetOutput(mCtx,mHybridCtx, &mDecodedImageWidth, &mDecodedImageHeight); |
|
} else { |
|
fb_index = mGetOutput(mCtx,mHybridCtx, &mDecodedImageNewWidth, &mDecodedImageNewHeight); |
|
} |
|
if (fb_index == -1) { |
|
if (mFormatChanged && mAPMode == METADATA_MODE) { |
|
*isResolutionChange = OMX_TRUE; |
|
return OMX_ErrorNone; |
|
} |
|
|
|
if (inportBufferFlags & OMX_BUFFERFLAG_EOS) { |
|
// eos frame is no-shown frame |
|
buffer->nFlags = OMX_BUFFERFLAG_EOS; |
|
buffer->nOffset = 0; |
|
buffer->nFilledLen = 0; |
|
return OMX_ErrorNone; |
|
} |
|
LOGV("vpx_codec_get_frame return NULL."); |
|
return OMX_ErrorNotReady; |
|
} |
|
if (mDecodedImageHeight == 0 && mDecodedImageWidth == 0) { |
|
mDecodedImageWidth = mDecodedImageNewWidth; |
|
mDecodedImageHeight = mDecodedImageNewHeight; |
|
if (mAPMode == LEGACY_MODE) |
|
*isResolutionChange = OMX_TRUE; |
|
} |
|
|
|
if (mAPMode == LEGACY_MODE) { |
|
if ((mDecodedImageNewWidth != mDecodedImageWidth) |
|
|| (mDecodedImageNewHeight!= mDecodedImageHeight)) |
|
*isResolutionChange = OMX_TRUE; |
|
} else { |
|
if (mFormatChanged && ((mDecodedImageNewWidth != mDecodedImageWidth) |
|
|| (mDecodedImageNewHeight!= mDecodedImageHeight))) |
|
*isResolutionChange = OMX_TRUE; |
|
} |
|
buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[fb_index]; |
|
buffer->nOffset = 0; |
|
buffer->nFilledLen = sizeof(OMX_U8*); |
|
if (inportBufferFlags & OMX_BUFFERFLAG_EOS) { |
|
buffer->nFlags = OMX_BUFFERFLAG_EOS; |
|
} |
|
|
|
if (buffer_orign != buffer) { |
|
*retain = BUFFER_RETAIN_OVERRIDDEN; |
|
} |
|
|
|
ret = OMX_ErrorNone; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::PrepareConfigBuffer(VideoConfigBuffer *) { |
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *, |
|
buffer_retain_t *, |
|
VideoDecodeBuffer *) { |
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::BuildHandlerList(void) { |
|
OMXVideoDecoderBase::BuildHandlerList(); |
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetParamVideoVp9(OMX_PTR) { |
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::SetParamVideoVp9(OMX_PTR) { |
|
return OMX_ErrorNone; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::HandleFormatChange(void) |
|
{ |
|
ALOGE("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; |
|
} |
|
} |
|
|
|
if (mAPMode == METADATA_MODE) { |
|
paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount; |
|
paramPortDefinitionOutput.nBufferCountMin = mNativeBufferCount - 4; |
|
} |
|
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 (mAPMode == LEGACY_MODE && |
|
width <= mGraphicBufferParam.graphicBufferWidth && |
|
height <= mGraphicBufferParam.graphicBufferHeight) { |
|
this->ports[INPORT_INDEX]->SetPortDefinition(¶mPortDefinitionInput, true); |
|
this->ports[OUTPORT_INDEX]->ReportOutputCrop(); |
|
return OMX_ErrorNone; |
|
} |
|
|
|
if (mAPMode == METADATA_MODE || |
|
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; |
|
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; |
|
mMetaDataBuffersNum = 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_INTEL_YV12."); |
|
return (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_INTEL_YV12; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetDecoderOutputCropSpecific(OMX_PTR pStructure) { |
|
|
|
OMX_ERRORTYPE ret = OMX_ErrorNone; |
|
OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure; |
|
|
|
CHECK_TYPE_HEADER(rectParams); |
|
|
|
if (rectParams->nPortIndex != OUTPORT_INDEX) { |
|
return OMX_ErrorUndefined; |
|
} |
|
|
|
const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput |
|
= this->ports[INPORT_INDEX]->GetPortDefinition(); |
|
|
|
rectParams->nLeft = VPX_DECODE_BORDER; |
|
rectParams->nTop = VPX_DECODE_BORDER; |
|
rectParams->nWidth = paramPortDefinitionInput->format.video.nFrameWidth; |
|
rectParams->nHeight = paramPortDefinitionInput->format.video.nFrameHeight; |
|
|
|
return ret; |
|
} |
|
|
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetNativeBufferUsageSpecific(OMX_PTR pStructure) { |
|
OMX_ERRORTYPE ret; |
|
android::GetAndroidNativeBufferUsageParams *param = |
|
(android::GetAndroidNativeBufferUsageParams*)pStructure; |
|
CHECK_TYPE_HEADER(param); |
|
|
|
param->nUsage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN |
|
| GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_EXTERNAL_DISP); |
|
return OMX_ErrorNone; |
|
|
|
} |
|
OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::SetNativeBufferModeSpecific(OMX_PTR pStructure) { |
|
OMX_ERRORTYPE ret; |
|
android::EnableAndroidNativeBuffersParams *param = |
|
(android::EnableAndroidNativeBuffersParams*)pStructure; |
|
|
|
CHECK_TYPE_HEADER(param); |
|
CHECK_PORT_INDEX_RANGE(param); |
|
CHECK_SET_PARAM_STATE(); |
|
|
|
PortVideo *port = NULL; |
|
port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]); |
|
OMX_PARAM_PORTDEFINITIONTYPE port_def; |
|
memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def)); |
|
|
|
if (!param->enable) { |
|
mWorkingMode = RAWDATA_MODE; |
|
LOGI("Raw data mode is used"); |
|
// If it is fallback from native mode the color format has been |
|
// already set to INTEL format. |
|
// We need to set back the default color format and Native stuff. |
|
port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; |
|
port_def.format.video.pNativeRender = NULL; |
|
port_def.format.video.pNativeWindow = NULL; |
|
port->SetPortDefinition(&port_def,true); |
|
return OMX_ErrorNone; |
|
} |
|
|
|
mWorkingMode = GRAPHICBUFFER_MODE; |
|
port_def.nBufferCountMin = mNativeBufferCount - 4; |
|
port_def.nBufferCountActual = mNativeBufferCount; |
|
port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE; |
|
// add borders for libvpx decode need. |
|
port_def.format.video.nFrameWidth += VPX_DECODE_BORDER * 2; |
|
port_def.format.video.nFrameHeight += VPX_DECODE_BORDER * 2; |
|
mDecodedImageWidth = port_def.format.video.nFrameWidth; |
|
mDecodedImageHeight = port_def.format.video.nFrameHeight; |
|
port_def.format.video.eColorFormat = GetOutputColorFormat(port_def.format.video.nFrameWidth); |
|
port->SetPortDefinition(&port_def,true); |
|
|
|
return OMX_ErrorNone; |
|
} |
|
|
|
|
|
bool OMXVideoDecoderVP9Hybrid::IsAllBufferAvailable(void) { |
|
bool b = ComponentBase::IsAllBufferAvailable(); |
|
if (b == false) { |
|
return false; |
|
} |
|
|
|
PortVideo *port = NULL; |
|
port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]); |
|
const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition(); |
|
// if output port is disabled, retain the input buffer |
|
if (!port_def->bEnabled) { |
|
return false; |
|
} |
|
return mCheckBufferAvailable(mHybridCtx); |
|
} |
|
|
|
DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.VP9.hybrid", "video_decoder.vp9", OMXVideoDecoderVP9Hybrid);
|
|
|