Home | History | Annotate | Download | only in videocodec
      1 /*
      2 * Copyright (c) 2012 Intel Corporation.  All rights reserved.
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 * http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 
     17 #define LOG_TIME 0
     18 //#define LOG_NDEBUG 0
     19 #define LOG_TAG "OMXVideoDecoderVP9Hybrid"
     20 #include <wrs_omxil_core/log.h>
     21 #include "OMXVideoDecoderVP9Hybrid.h"
     22 
     23 #include <hardware/hardware.h>
     24 #include <hardware/gralloc.h>
     25 #include <system/graphics.h>
     26 
     27 #include <hal_public.h>
     28 
     29 #define VP9_YV12_ALIGN (128-1)
     30 static const char* VP9_MIME_TYPE = "video/x-vnd.on2.vp9";
     31 
     32 OMXVideoDecoderVP9Hybrid::OMXVideoDecoderVP9Hybrid() {
     33     LOGV("OMXVideoDecoderVP9Hybrid is constructed.");
     34     mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT;
     35     BuildHandlerList();
     36     mLibHandle = NULL;
     37     mOpenDecoder = NULL;
     38     mInitDecoder = NULL;
     39     mCloseDecoder = NULL;
     40     mSingalRenderDone = NULL;
     41     mDecoderDecode = NULL;
     42     mCheckBufferAvailable = NULL;
     43     mGetOutput = NULL;
     44     mGetRawDataOutput = NULL;
     45     mGetFrameResolution = NULL;
     46     mDeinitDecoder = NULL;
     47     mLastTimeStamp = 0;
     48     mWorkingMode = RAWDATA_MODE;
     49     mDecodedImageWidth = 0;
     50     mDecodedImageHeight = 0;
     51     mDecodedImageNewWidth = 0;
     52     mDecodedImageNewHeight = 0;
     53 }
     54 
     55 OMXVideoDecoderVP9Hybrid::~OMXVideoDecoderVP9Hybrid() {
     56     LOGV("OMXVideoDecoderVP9Hybrid is destructed.");
     57 }
     58 
     59 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::InitInputPortFormatSpecific(
     60     OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput) {
     61     // OMX_PARAM_PORTDEFINITIONTYPE
     62     paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
     63     paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
     64     paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE;
     65     paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)VP9_MIME_TYPE;
     66     paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingVP9;
     67     return OMX_ErrorNone;
     68 }
     69 
     70 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorInit(void) {
     71     uint32_t buff[MAX_GRAPHIC_BUFFER_NUM];
     72     uint32_t i, bufferCount;
     73     bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE);
     74     uint32_t bufferSize, bufferHStride, bufferHeight, bufferVStride, bufferWidth;
     75     if (!gralloc_mode) {
     76         bufferHStride = 1920;
     77         bufferVStride = 1088;
     78         bufferWidth = 1920;
     79         bufferHeight = 1080;
     80         bufferCount = 12;
     81     } else {
     82         if (mAPMode == METADATA_MODE) {
     83             const OMX_PARAM_PORTDEFINITIONTYPE *def_output = this->ports[OUTPORT_INDEX]->GetPortDefinition();
     84             if (def_output == NULL) {
     85                 return OMX_ErrorBadParameter;
     86             }
     87             bufferCount = mMetaDataBuffersNum = def_output->nBufferCountActual;
     88             mOMXBufferHeaderTypePtrNum = 0;
     89 
     90             mGraphicBufferParam.graphicBufferColorFormat = def_output->format.video.eColorFormat;
     91             mGraphicBufferParam.graphicBufferHStride = (def_output->format.video.nFrameWidth + VP9_YV12_ALIGN) & ~VP9_YV12_ALIGN;
     92             mGraphicBufferParam.graphicBufferVStride = (def_output->format.video.nFrameHeight + 0x1f) & ~0x1f;
     93             mGraphicBufferParam.graphicBufferWidth = def_output->format.video.nFrameWidth;
     94             mGraphicBufferParam.graphicBufferHeight = def_output->format.video.nFrameHeight;
     95             mDecodedImageWidth = def_output->format.video.nFrameWidth;
     96             mDecodedImageHeight = def_output->format.video.nFrameHeight;
     97         } else{
     98             bufferCount = mOMXBufferHeaderTypePtrNum;
     99 
    100             for (i = 0; i < bufferCount; i++ ) {
    101                 OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i];
    102                 buff[i] = (uint32_t)(buf_hdr->pBuffer);
    103             }
    104         }
    105 
    106         bufferHStride = mGraphicBufferParam.graphicBufferHStride;
    107         bufferVStride = mGraphicBufferParam.graphicBufferVStride;
    108         bufferWidth = mGraphicBufferParam.graphicBufferWidth;
    109         bufferHeight = mGraphicBufferParam.graphicBufferHeight;
    110     }
    111 
    112     bufferSize = bufferHStride * bufferVStride * 1.5;
    113 
    114     mLibHandle = dlopen("libDecoderVP9Hybrid.so", RTLD_NOW);
    115     if (mLibHandle == NULL) {
    116         LOGE("dlopen libDecoderVP9Hybrid.so fail\n");
    117         return OMX_ErrorBadParameter;
    118     } else {
    119         LOGI("dlopen libDecoderVP9Hybrid.so successfully\n");
    120     }
    121     mOpenDecoder = (OpenFunc)dlsym(mLibHandle, "Decoder_Open");
    122     mCloseDecoder = (CloseFunc)dlsym(mLibHandle, "Decoder_Close");
    123     mInitDecoder = (InitFunc)dlsym(mLibHandle, "Decoder_Init");
    124     mSingalRenderDone = (SingalRenderDoneFunc)dlsym(mLibHandle, "Decoder_SingalRenderDone");
    125     mDecoderDecode = (DecodeFunc)dlsym(mLibHandle, "Decoder_Decode");
    126     mCheckBufferAvailable = (IsBufferAvailableFunc)dlsym(mLibHandle, "Decoder_IsBufferAvailable");
    127     mGetOutput = (GetOutputFunc)dlsym(mLibHandle, "Decoder_GetOutput");
    128     mGetRawDataOutput = (GetRawDataOutputFunc)dlsym(mLibHandle, "Decoder_GetRawDataOutput");
    129     mGetFrameResolution = (GetFrameResolutionFunc)dlsym(mLibHandle, "Decoder_GetFrameResolution");
    130     mDeinitDecoder = (DeinitFunc)dlsym(mLibHandle, "Decoder_Deinit");
    131     if (mOpenDecoder == NULL || mCloseDecoder == NULL
    132         || mInitDecoder == NULL || mSingalRenderDone == NULL
    133         || mDecoderDecode == NULL || mCheckBufferAvailable == NULL
    134         || mGetOutput == NULL || mGetRawDataOutput == NULL
    135         || mGetFrameResolution == NULL || mDeinitDecoder == NULL) {
    136         return OMX_ErrorBadParameter;
    137     }
    138 
    139     if (mOpenDecoder(&mCtx,&mHybridCtx) == false) {
    140         LOGE("open hybrid Decoder fail\n");
    141         return OMX_ErrorBadParameter;
    142     }
    143 
    144     // FIXME: The proprietary part of the vp9hybrid decoder should be updated
    145     //        to take VStride as well as Height. For now it's convenient to
    146     //        use VStride as that was effectively what was done before..
    147     mInitDecoder(mHybridCtx, bufferSize, bufferHStride, bufferWidth,
    148         bufferHeight, bufferCount, gralloc_mode, buff, (uint32_t)mAPMode);
    149     return OMX_ErrorNone;
    150 }
    151 
    152 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorReset(void)
    153 {
    154     uint32_t buff[MAX_GRAPHIC_BUFFER_NUM];
    155     uint32_t i, bufferCount;
    156     bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE);
    157     uint32_t bufferSize, bufferHStride, bufferHeight, bufferVStride, bufferWidth;
    158     if (!gralloc_mode) {
    159         bufferHStride = mDecodedImageWidth;
    160         bufferVStride = mDecodedImageHeight;
    161         bufferWidth = mDecodedImageWidth;
    162         bufferHeight = mDecodedImageHeight;
    163         bufferSize = bufferHStride * bufferVStride * 1.5;
    164         bufferCount = 12;
    165     } else {
    166         if (mAPMode == METADATA_MODE) {
    167             const OMX_PARAM_PORTDEFINITIONTYPE *def_output = this->ports[OUTPORT_INDEX]->GetPortDefinition();
    168             if (def_output == NULL) {
    169                 return OMX_ErrorBadParameter;
    170             }
    171             bufferCount = mMetaDataBuffersNum = def_output->nBufferCountActual;
    172             mOMXBufferHeaderTypePtrNum = 0;
    173 
    174             mGraphicBufferParam.graphicBufferColorFormat = def_output->format.video.eColorFormat;
    175             mGraphicBufferParam.graphicBufferHStride = (def_output->format.video.nFrameWidth + VP9_YV12_ALIGN) & ~VP9_YV12_ALIGN;
    176             mGraphicBufferParam.graphicBufferVStride = (def_output->format.video.nFrameHeight + 0x1f) & ~0x1f;
    177             mGraphicBufferParam.graphicBufferWidth = def_output->format.video.nFrameWidth;
    178             mGraphicBufferParam.graphicBufferHeight = def_output->format.video.nFrameHeight;
    179         } else{
    180             bufferCount = mOMXBufferHeaderTypePtrNum;
    181 
    182             for (i = 0; i < bufferCount; i++ ) {
    183                 OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i];
    184                 buff[i] = (uint32_t)(buf_hdr->pBuffer);
    185             }
    186         }
    187         bufferHStride = mGraphicBufferParam.graphicBufferHStride;
    188         bufferVStride = mGraphicBufferParam.graphicBufferVStride;
    189         bufferWidth = mGraphicBufferParam.graphicBufferWidth;
    190         bufferHeight = mGraphicBufferParam.graphicBufferHeight;
    191     }
    192 
    193     bufferSize = bufferHStride * bufferVStride * 1.5;
    194 
    195     // FIXME: The proprietary part of the vp9hybrid decoder should be updated
    196     //        to take VStride as well as Height. For now it's convenient to
    197     //        use VStride as that was effectively what was done before..
    198     mInitDecoder(mHybridCtx, bufferSize, bufferHStride, bufferWidth,
    199         bufferHeight, bufferCount, gralloc_mode, buff, (uint32_t)mAPMode);
    200     mFormatChanged = false;
    201     return OMX_ErrorNone;
    202 }
    203 
    204 bool OMXVideoDecoderVP9Hybrid::isReallocateNeeded(const uint8_t * data,uint32_t data_sz)
    205 {
    206     bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE);
    207     uint32_t width, height;
    208     bool ret = true;
    209     if (gralloc_mode) {
    210         ret = mGetFrameResolution(data,data_sz, &width, &height);
    211         if (width == 0 || height == 0)
    212             return false;
    213 
    214         if (ret) {
    215             if (mAPMode == METADATA_MODE) {
    216                 ret = (width != mDecodedImageWidth)
    217                     || (height != mDecodedImageHeight);
    218             } else {
    219                 ret = width > mGraphicBufferParam.graphicBufferWidth
    220                     || height > mGraphicBufferParam.graphicBufferHeight;
    221             }
    222             if (ret) {
    223                 mDecodedImageNewWidth = width;
    224                 mDecodedImageNewHeight = height;
    225                 return true;
    226             }
    227         }
    228     }
    229 
    230     return ret;
    231 }
    232 
    233 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorDeinit(void) {
    234     mCloseDecoder(mCtx,mHybridCtx);
    235     mOMXBufferHeaderTypePtrNum = 0;
    236     if (mLibHandle != NULL) {
    237         dlclose(mLibHandle);
    238         mLibHandle = NULL;
    239     }
    240     return OMX_ErrorNone;
    241 }
    242 
    243 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorStop(void) {
    244     return OMXComponentCodecBase::ProcessorStop();
    245 }
    246 
    247 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorFlush(OMX_U32 portIndex) {
    248     if (portIndex == INPORT_INDEX || portIndex == OMX_ALL) {
    249         // end the last frame
    250         unsigned int width, height;
    251         mDecoderDecode(mCtx,mHybridCtx,NULL,0,true);
    252         mGetOutput(mCtx,mHybridCtx, &width, &height);
    253     }
    254     return OMX_ErrorNone;
    255 }
    256 
    257 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer) {
    258     if (buffer->nOutputPortIndex == OUTPORT_INDEX){
    259         unsigned int handle;
    260         if (mAPMode == METADATA_MODE) {
    261             bool found = false;
    262             if (mOMXBufferHeaderTypePtrNum < mMetaDataBuffersNum) {
    263                 for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
    264                     if (mOMXBufferHeaderTypePtrArray[i] == buffer) {
    265                         found = true;
    266                         break;
    267                     }
    268                 }
    269                 if (!found) {
    270                     mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum] = buffer;
    271                     mOMXBufferHeaderTypePtrNum++;
    272                 }
    273             } else {
    274                 found = true;
    275             }
    276 
    277             android::VideoGrallocMetadata *metadata = (android::VideoGrallocMetadata *)(buffer->pBuffer);
    278             handle = (unsigned int)metadata->pHandle;
    279             mSingalRenderDone(mHybridCtx, handle, !found);
    280         } else {
    281             handle = (unsigned int)buffer->pBuffer;
    282             mSingalRenderDone(mHybridCtx, handle, false);
    283         }
    284     }
    285     return OMX_ErrorNone;
    286 }
    287 
    288 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorProcess(
    289         OMX_BUFFERHEADERTYPE ***pBuffers,
    290         buffer_retain_t *retains,
    291         OMX_U32)
    292 {
    293     OMX_ERRORTYPE ret;
    294     OMX_BUFFERHEADERTYPE *inBuffer = *pBuffers[INPORT_INDEX];
    295     OMX_BUFFERHEADERTYPE *outBuffer = *pBuffers[OUTPORT_INDEX];
    296     OMX_BOOL isResolutionChange = OMX_FALSE;
    297     bool eos = (inBuffer->nFlags & OMX_BUFFERFLAG_EOS)? true : false;
    298     eos = eos && (inBuffer->nFilledLen == 0);
    299     static unsigned char *firstFrame = NULL;
    300     static uint32_t firstFrameSize = 0;
    301 
    302     if (inBuffer->pBuffer == NULL) {
    303         LOGE("Buffer to decode is empty.");
    304         return OMX_ErrorBadParameter;
    305     }
    306 
    307     if (inBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
    308         LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
    309     }
    310 
    311     if (inBuffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
    312         LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
    313     }
    314 
    315     if (firstFrameSize == 0 && inBuffer->nFilledLen != 0 && inBuffer->nTimeStamp != 0) {
    316         if (firstFrame != NULL) {
    317             free(firstFrame);
    318             firstFrame = NULL;
    319         }
    320 
    321         firstFrame = (unsigned char *)malloc(inBuffer->nFilledLen);
    322         memcpy(firstFrame, inBuffer->pBuffer + inBuffer->nOffset, inBuffer->nFilledLen);
    323         firstFrameSize = inBuffer->nFilledLen;
    324     }
    325 
    326     if ((mWorkingMode == GRAPHICBUFFER_MODE) && (mAPMode == METADATA_MODE) && (!mFormatChanged)) {
    327         bool mRet = mGetFrameResolution(inBuffer->pBuffer + inBuffer->nOffset, inBuffer->nFilledLen,
    328             &mDecodedImageNewWidth,&mDecodedImageNewHeight);
    329 
    330         if (mRet && ((mDecodedImageNewWidth != 0) && (mDecodedImageNewHeight != 0)) &&
    331             ((mDecodedImageWidth != 0) && (mDecodedImageHeight != 0)) &&
    332             ((mDecodedImageNewWidth != mDecodedImageWidth || mDecodedImageNewHeight != mDecodedImageHeight))) {
    333             if (mLastTimeStamp == 0) {
    334                 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    335                 HandleFormatChange();
    336                 return OMX_ErrorNone;
    337             } else {
    338                 // Detected format change in time.
    339                 // drain the last frame, keep the current input buffer
    340                 mDecoderDecode(mCtx, mHybridCtx, firstFrame, firstFrameSize, false);
    341                 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    342 
    343                 mFormatChanged = true;
    344 
    345                 ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX],
    346                     eos ? OMX_BUFFERFLAG_EOS : 0, &isResolutionChange);
    347 
    348                 if (ret == OMX_ErrorNone)
    349                     (*pBuffers[OUTPORT_INDEX])->nTimeStamp = mLastTimeStamp;
    350 
    351                 mLastTimeStamp = inBuffer->nTimeStamp;
    352 
    353                 free(firstFrame);
    354                 firstFrame = NULL;
    355                 firstFrameSize = 0;
    356                 return ret;
    357             }
    358         } else if (!mRet && (mDecodedImageNewWidth == 0 || mDecodedImageNewHeight == 0)) {
    359             retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
    360             return OMX_ErrorBadParameter;
    361         }
    362     }
    363 
    364 #if LOG_TIME == 1
    365     struct timeval tv_start, tv_end;
    366     int32_t time_ms;
    367     gettimeofday(&tv_start,NULL);
    368 #endif
    369     int res = mDecoderDecode(mCtx,mHybridCtx,inBuffer->pBuffer + inBuffer->nOffset,inBuffer->nFilledLen, eos);
    370     if (res != 0) {
    371         if (res == -2) {
    372             if (isReallocateNeeded(inBuffer->pBuffer + inBuffer->nOffset,inBuffer->nFilledLen)) {
    373                 if (mAPMode == METADATA_MODE) {
    374                     mFormatChanged = true;
    375                 } else {
    376                     retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    377                     HandleFormatChange();
    378                     return OMX_ErrorNone;
    379                 }
    380             }
    381             // drain the last frame, keep the current input buffer
    382             res = mDecoderDecode(mCtx,mHybridCtx,NULL,0,true);
    383             retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    384         } else if (res == -3) {
    385             LOGW("on2 decoder skipped to decode the frame.");
    386             (*pBuffers[OUTPORT_INDEX])->nOffset = 0;
    387             (*pBuffers[OUTPORT_INDEX])->nFilledLen = 0;
    388             return OMX_ErrorNone;
    389         } else {
    390             LOGE("on2 decoder failed to decode frame.");
    391             return OMX_ErrorBadParameter;
    392         }
    393     }
    394 
    395 #if LOG_TIME == 1
    396     gettimeofday(&tv_end,NULL);
    397     time_ms = (int32_t)(tv_end.tv_sec - tv_start.tv_sec) * 1000 + (int32_t)(tv_end.tv_usec - tv_start.tv_usec)/1000;
    398     LOGI("vpx_codec_decode: %d ms", time_ms);
    399 #endif
    400 
    401     ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX],
    402                            &retains[OUTPORT_INDEX],
    403                            eos? OMX_BUFFERFLAG_EOS:0,
    404                            &isResolutionChange);
    405 
    406     if (ret == OMX_ErrorNone) {
    407         (*pBuffers[OUTPORT_INDEX])->nTimeStamp = mLastTimeStamp;
    408     }
    409     mLastTimeStamp = inBuffer->nTimeStamp;
    410 
    411     if (isResolutionChange == OMX_TRUE) {
    412         HandleFormatChange();
    413     }
    414     bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
    415     bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
    416     // if output port is not eos, retain the input buffer
    417     // until all the output buffers are drained.
    418     if (inputEoS && !outputEoS && retains[INPORT_INDEX] != BUFFER_RETAIN_GETAGAIN) {
    419         retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    420         // the input buffer is retained for draining purpose.
    421         // Set nFilledLen to 0 so buffer will not be decoded again.
    422         (*pBuffers[INPORT_INDEX])->nFilledLen = 0;
    423     }
    424 
    425     if (ret == OMX_ErrorNotReady) {
    426         retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    427         ret = OMX_ErrorNone;
    428     }
    429 
    430     return ret;
    431 }
    432 
    433 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer,
    434                                                       buffer_retain_t *retain,
    435                                                       OMX_U32 inportBufferFlags,
    436                                                       OMX_BOOL *isResolutionChange)
    437 {
    438     OMX_BUFFERHEADERTYPE *buffer = *pBuffer;
    439     OMX_BUFFERHEADERTYPE *buffer_orign = buffer;
    440 
    441     OMX_ERRORTYPE ret = OMX_ErrorNone;
    442 
    443     int fb_index;
    444     if (mWorkingMode == RAWDATA_MODE) {
    445         const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput
    446                        = this->ports[OUTPORT_INDEX]->GetPortDefinition();
    447         int32_t stride = paramPortDefinitionOutput->format.video.nStride;
    448         int32_t height =  paramPortDefinitionOutput->format.video.nFrameHeight;
    449         int32_t width = paramPortDefinitionOutput->format.video.nFrameWidth;
    450         unsigned char *dst = buffer->pBuffer;
    451         fb_index = mGetRawDataOutput(mCtx,mHybridCtx,dst,height,stride);
    452         if (fb_index == -1) {
    453             if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
    454                 // eos frame is non-shown frame
    455                 buffer->nFlags = OMX_BUFFERFLAG_EOS;
    456                 buffer->nOffset = 0;
    457                 buffer->nFilledLen = 0;
    458                 return OMX_ErrorNone;
    459             }
    460             LOGV("vpx_codec_get_frame return NULL.");
    461             return OMX_ErrorNotReady;
    462         }
    463         buffer->nOffset = 0;
    464         buffer->nFilledLen = stride*height*3/2;
    465         if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
    466             buffer->nFlags = OMX_BUFFERFLAG_EOS;
    467         }
    468         return OMX_ErrorNone;
    469     }
    470 
    471     if (mFormatChanged && mAPMode == METADATA_MODE) {
    472         fb_index = mGetOutput(mCtx,mHybridCtx, &mDecodedImageWidth, &mDecodedImageHeight);
    473     } else {
    474         fb_index = mGetOutput(mCtx,mHybridCtx, &mDecodedImageNewWidth, &mDecodedImageNewHeight);
    475     }
    476     if (fb_index == -1) {
    477         if (mFormatChanged && mAPMode == METADATA_MODE) {
    478             *isResolutionChange = OMX_TRUE;
    479             return OMX_ErrorNone;
    480     }
    481 
    482         if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
    483             // eos frame is no-shown frame
    484             buffer->nFlags = OMX_BUFFERFLAG_EOS;
    485             buffer->nOffset = 0;
    486             buffer->nFilledLen = 0;
    487             return OMX_ErrorNone;
    488         }
    489         LOGV("vpx_codec_get_frame return NULL.");
    490         return OMX_ErrorNotReady;
    491     }
    492     if (mDecodedImageHeight == 0 && mDecodedImageWidth == 0) {
    493         mDecodedImageWidth = mDecodedImageNewWidth;
    494         mDecodedImageHeight = mDecodedImageNewHeight;
    495         if (mAPMode == LEGACY_MODE)
    496             *isResolutionChange = OMX_TRUE;
    497     }
    498 
    499     if (mAPMode == LEGACY_MODE) {
    500     if ((mDecodedImageNewWidth != mDecodedImageWidth)
    501         || (mDecodedImageNewHeight!= mDecodedImageHeight))
    502         *isResolutionChange = OMX_TRUE;
    503     } else {
    504         if (mFormatChanged && ((mDecodedImageNewWidth != mDecodedImageWidth)
    505             || (mDecodedImageNewHeight!= mDecodedImageHeight)))
    506             *isResolutionChange = OMX_TRUE;
    507     }
    508     buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[fb_index];
    509     buffer->nOffset = 0;
    510     buffer->nFilledLen = sizeof(OMX_U8*);
    511     if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
    512         buffer->nFlags = OMX_BUFFERFLAG_EOS;
    513     }
    514 
    515     if (buffer_orign != buffer) {
    516         *retain = BUFFER_RETAIN_OVERRIDDEN;
    517     }
    518 
    519     ret = OMX_ErrorNone;
    520 
    521     return ret;
    522 
    523 }
    524 
    525 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::PrepareConfigBuffer(VideoConfigBuffer *) {
    526     return OMX_ErrorNone;
    527 }
    528 
    529 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *,
    530                                                          buffer_retain_t *,
    531                                                          VideoDecodeBuffer *) {
    532     return OMX_ErrorNone;
    533 }
    534 
    535 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::BuildHandlerList(void) {
    536     OMXVideoDecoderBase::BuildHandlerList();
    537     return OMX_ErrorNone;
    538 }
    539 
    540 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetParamVideoVp9(OMX_PTR) {
    541     return OMX_ErrorNone;
    542 }
    543 
    544 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::SetParamVideoVp9(OMX_PTR) {
    545     return OMX_ErrorNone;
    546 }
    547 
    548 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::HandleFormatChange(void)
    549 {
    550     ALOGE("handle format change from %dx%d to %dx%d",
    551         mDecodedImageWidth,mDecodedImageHeight,mDecodedImageNewWidth,mDecodedImageNewHeight);
    552     mDecodedImageWidth = mDecodedImageNewWidth;
    553     mDecodedImageHeight = mDecodedImageNewHeight;
    554     // Sync port definition as it may change.
    555     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput;
    556 
    557     memcpy(&paramPortDefinitionInput,
    558         this->ports[INPORT_INDEX]->GetPortDefinition(),
    559         sizeof(paramPortDefinitionInput));
    560 
    561     memcpy(&paramPortDefinitionOutput,
    562         this->ports[OUTPORT_INDEX]->GetPortDefinition(),
    563         sizeof(paramPortDefinitionOutput));
    564 
    565     unsigned int width = mDecodedImageWidth;
    566     unsigned int height = mDecodedImageHeight;
    567     unsigned int stride = mDecodedImageWidth;
    568     unsigned int sliceHeight = mDecodedImageHeight;
    569 
    570     unsigned int widthCropped = mDecodedImageWidth;
    571     unsigned int heightCropped = mDecodedImageHeight;
    572     unsigned int strideCropped = widthCropped;
    573     unsigned int sliceHeightCropped = heightCropped;
    574 
    575     if (widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth &&
    576         heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) {
    577         if (mWorkingMode == RAWDATA_MODE) {
    578             LOGW("Change of portsetting is not reported as size is not changed.");
    579             return OMX_ErrorNone;
    580         }
    581     }
    582 
    583     if (mAPMode == METADATA_MODE) {
    584        paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount;
    585        paramPortDefinitionOutput.nBufferCountMin = mNativeBufferCount - 4;
    586     }
    587     paramPortDefinitionInput.format.video.nFrameWidth = width;
    588     paramPortDefinitionInput.format.video.nFrameHeight = height;
    589     paramPortDefinitionInput.format.video.nStride = stride;
    590     paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
    591 
    592     if (mWorkingMode == RAWDATA_MODE) {
    593         paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped;
    594         paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped;
    595         paramPortDefinitionOutput.format.video.nStride = strideCropped;
    596         paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped;
    597     } else if (mWorkingMode == GRAPHICBUFFER_MODE) {
    598         // when the width and height ES parse are not larger than allocated graphic buffer in outport,
    599         // there is no need to reallocate graphic buffer,just report the crop info to omx client
    600         if (mAPMode == LEGACY_MODE &&
    601             width <= mGraphicBufferParam.graphicBufferWidth &&
    602             height <= mGraphicBufferParam.graphicBufferHeight) {
    603             this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
    604             this->ports[OUTPORT_INDEX]->ReportOutputCrop();
    605             return OMX_ErrorNone;
    606         }
    607 
    608         if (mAPMode == METADATA_MODE ||
    609             width > mGraphicBufferParam.graphicBufferWidth ||
    610             height > mGraphicBufferParam.graphicBufferHeight) {
    611             // update the real decoded resolution to outport instead of display resolution
    612             // for graphic buffer reallocation
    613             // when the width and height parsed from ES are larger than allocated graphic buffer in outport,
    614             paramPortDefinitionOutput.format.video.nFrameWidth = width;
    615             paramPortDefinitionOutput.format.video.nFrameHeight = height;
    616             paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(
    617                     paramPortDefinitionOutput.format.video.nFrameWidth);
    618             paramPortDefinitionOutput.format.video.nStride = stride;
    619             paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
    620        }
    621     }
    622 
    623     paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
    624     mOMXBufferHeaderTypePtrNum = 0;
    625     mMetaDataBuffersNum = 0;
    626     memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
    627     mDeinitDecoder(mHybridCtx);
    628 
    629     this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
    630     this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
    631 
    632     this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
    633     return OMX_ErrorNone;
    634 }
    635 
    636 
    637 OMX_COLOR_FORMATTYPE OMXVideoDecoderVP9Hybrid::GetOutputColorFormat(int) {
    638     LOGV("Output color format is HAL_PIXEL_FORMAT_INTEL_YV12.");
    639     return (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_INTEL_YV12;
    640 }
    641 
    642 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetDecoderOutputCropSpecific(OMX_PTR pStructure) {
    643 
    644     OMX_ERRORTYPE ret = OMX_ErrorNone;
    645     OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure;
    646 
    647     CHECK_TYPE_HEADER(rectParams);
    648 
    649     if (rectParams->nPortIndex != OUTPORT_INDEX) {
    650         return OMX_ErrorUndefined;
    651     }
    652 
    653     const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput
    654                                       = this->ports[INPORT_INDEX]->GetPortDefinition();
    655 
    656     rectParams->nLeft = VPX_DECODE_BORDER;
    657     rectParams->nTop = VPX_DECODE_BORDER;
    658     rectParams->nWidth = paramPortDefinitionInput->format.video.nFrameWidth;
    659     rectParams->nHeight = paramPortDefinitionInput->format.video.nFrameHeight;
    660 
    661     return ret;
    662 }
    663 
    664 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetNativeBufferUsageSpecific(OMX_PTR pStructure) {
    665     OMX_ERRORTYPE ret;
    666     android::GetAndroidNativeBufferUsageParams *param =
    667         (android::GetAndroidNativeBufferUsageParams*)pStructure;
    668     CHECK_TYPE_HEADER(param);
    669 
    670     param->nUsage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN
    671                      | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_EXTERNAL_DISP);
    672     return OMX_ErrorNone;
    673 
    674 }
    675 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::SetNativeBufferModeSpecific(OMX_PTR pStructure) {
    676     OMX_ERRORTYPE ret;
    677     android::EnableAndroidNativeBuffersParams *param =
    678         (android::EnableAndroidNativeBuffersParams*)pStructure;
    679 
    680     CHECK_TYPE_HEADER(param);
    681     CHECK_PORT_INDEX_RANGE(param);
    682     CHECK_SET_PARAM_STATE();
    683 
    684     PortVideo *port = NULL;
    685     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
    686     OMX_PARAM_PORTDEFINITIONTYPE port_def;
    687     memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
    688 
    689     if (!param->enable) {
    690         mWorkingMode = RAWDATA_MODE;
    691         LOGI("Raw data mode is used");
    692         // If it is fallback from native mode the color format has been
    693         // already set to INTEL format.
    694         // We need to set back the default color format and Native stuff.
    695         port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
    696         port_def.format.video.pNativeRender = NULL;
    697         port_def.format.video.pNativeWindow = NULL;
    698         port->SetPortDefinition(&port_def,true);
    699         return OMX_ErrorNone;
    700     }
    701 
    702     mWorkingMode = GRAPHICBUFFER_MODE;
    703     port_def.nBufferCountMin = mNativeBufferCount - 4;
    704     port_def.nBufferCountActual = mNativeBufferCount;
    705     port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE;
    706     // add borders for libvpx decode need.
    707     port_def.format.video.nFrameWidth += VPX_DECODE_BORDER * 2;
    708     port_def.format.video.nFrameHeight += VPX_DECODE_BORDER * 2;
    709     mDecodedImageWidth = port_def.format.video.nFrameWidth;
    710     mDecodedImageHeight = port_def.format.video.nFrameHeight;
    711     port_def.format.video.eColorFormat = GetOutputColorFormat(port_def.format.video.nFrameWidth);
    712     port->SetPortDefinition(&port_def,true);
    713 
    714      return OMX_ErrorNone;
    715 }
    716 
    717 
    718 bool OMXVideoDecoderVP9Hybrid::IsAllBufferAvailable(void) {
    719     bool b = ComponentBase::IsAllBufferAvailable();
    720     if (b == false) {
    721         return false;
    722     }
    723 
    724     PortVideo *port = NULL;
    725     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
    726     const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition();
    727      // if output port is disabled, retain the input buffer
    728     if (!port_def->bEnabled) {
    729         return false;
    730     }
    731     return mCheckBufferAvailable(mHybridCtx);
    732 }
    733 
    734 DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.VP9.hybrid", "video_decoder.vp9", OMXVideoDecoderVP9Hybrid);
    735