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 
     18 #define LOG_NDEBUG 0
     19 #define LOG_TAG "OMXVideoDecoderVP9HWR"
     20 #include <wrs_omxil_core/log.h>
     21 #include "OMXVideoDecoderVP9HWR.h"
     22 
     23 #include <system/window.h>
     24 #include <ui/GraphicBufferMapper.h>
     25 #include <ui/Rect.h>
     26 #include <HardwareAPI.h>
     27 #include <hardware/hardware.h>
     28 #include <hardware/gralloc.h>
     29 #include <system/graphics.h>
     30 
     31 static const char* VP9_MIME_TYPE = "video/x-vnd.on2.vp9";
     32 
     33 static int GetCPUCoreCount()
     34 {
     35     int cpuCoreCount = 1;
     36 #if defined(_SC_NPROCESSORS_ONLN)
     37     cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
     38 #else
     39     // _SC_NPROC_ONLN must be defined...
     40     cpuCoreCount = sysconf(_SC_NPROC_ONLN);
     41 #endif
     42     if (cpuCoreCount < 1) {
     43         LOGW("Get CPU Core Count error.");
     44         cpuCoreCount = 1;
     45     }
     46     LOGV("Number of CPU cores: %d", cpuCoreCount);
     47     return cpuCoreCount;
     48 }
     49 
     50 
     51 OMXVideoDecoderVP9HWR::OMXVideoDecoderVP9HWR()
     52 {
     53     LOGV("OMXVideoDecoderVP9HWR is constructed.");
     54 
     55     mNumFrameBuffer = 0;
     56     mCtx = NULL;
     57 
     58     mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT;
     59     extUtilBufferCount = 0;
     60     extMappedNativeBufferCount = 0;
     61     BuildHandlerList();
     62 
     63     mDecodedImageWidth = 0;
     64     mDecodedImageHeight = 0;
     65     mDecodedImageNewWidth = 0;
     66     mDecodedImageNewHeight = 0;
     67 
     68 #ifdef DECODE_WITH_GRALLOC_BUFFER
     69     // setup va
     70     VAStatus vaStatus = VA_STATUS_SUCCESS;
     71     mDisplay = new Display;
     72     *mDisplay = ANDROID_DISPLAY_HANDLE;
     73 
     74     mVADisplay = vaGetDisplay(mDisplay);
     75     if (mVADisplay == NULL) {
     76         LOGE("vaGetDisplay failed.");
     77     }
     78 
     79     int majorVersion, minorVersion;
     80     vaStatus = vaInitialize(mVADisplay, &majorVersion, &minorVersion);
     81     if (vaStatus != VA_STATUS_SUCCESS) {
     82         LOGE("vaInitialize failed.");
     83     } else {
     84         LOGV("va majorVersion=%d, minorVersion=%d", majorVersion, minorVersion);
     85     }
     86 #endif
     87 }
     88 
     89 OMXVideoDecoderVP9HWR::~OMXVideoDecoderVP9HWR()
     90 {
     91     LOGV("OMXVideoDecoderVP9HWR is destructed.");
     92 
     93     unsigned int i = 0;
     94 
     95     if (mVADisplay) {
     96         vaTerminate(mVADisplay);
     97         mVADisplay = NULL;
     98     }
     99 }
    100 
    101 
    102 // Callback func for vpx decoder to get decode buffer
    103 // Now we map from the vaSurface to deploy gralloc buffer
    104 // as decode buffer
    105 int getVP9FrameBuffer(void *user_priv,
    106                           unsigned int new_size,
    107                           vpx_codec_frame_buffer_t *fb)
    108 {
    109     OMXVideoDecoderVP9HWR * p = (OMXVideoDecoderVP9HWR *)user_priv;
    110     if (fb == NULL) {
    111         return -1;
    112     }
    113 
    114     // TODO: Adaptive playback case needs to reconsider
    115     if (p->extNativeBufferSize < new_size) {
    116         LOGE("Provided frame buffer size < requesting min size.");
    117         return -1;
    118     }
    119 
    120     int i;
    121     for (i = 0; i < p->extMappedNativeBufferCount; i++ ) {
    122         if ((p->extMIDs[i]->m_render_done == true) &&
    123             (p->extMIDs[i]->m_released == true)) {
    124             fb->data = p->extMIDs[i]->m_usrAddr;
    125             fb->size = p->extNativeBufferSize;
    126             fb->fb_stride = p->extActualBufferStride;
    127             fb->fb_height_stride = p->extActualBufferHeightStride;
    128             fb->fb_index = i;
    129             p->extMIDs[i]->m_released = false;
    130             break;
    131         }
    132     }
    133 
    134     if (i == p->extMappedNativeBufferCount) {
    135         LOGE("No available frame buffer in pool.");
    136         return -1;
    137     }
    138     return 0;
    139 }
    140 
    141 // call back function from libvpx to inform frame buffer
    142 // not used anymore.
    143 int releaseVP9FrameBuffer(void *user_priv, vpx_codec_frame_buffer_t *fb)
    144 {
    145     int i;
    146     OMXVideoDecoderVP9HWR * p = (OMXVideoDecoderVP9HWR *)user_priv;
    147     if (fb == NULL) {
    148         return -1;
    149     }
    150     for (i = 0; i < p->extMappedNativeBufferCount; i++ ) {
    151         if (fb->data == p->extMIDs[i]->m_usrAddr) {
    152             p->extMIDs[i]->m_released = true;
    153             break;
    154         }
    155     }
    156 
    157     if (i == p->extMappedNativeBufferCount) {
    158         LOGE("Not found matching frame buffer in pool, libvpx's wrong?");
    159         return -1;
    160     }
    161     return 0;
    162 }
    163 
    164 
    165 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::initDecoder()
    166 {
    167     mCtx = new vpx_codec_ctx_t;
    168     vpx_codec_err_t vpx_err;
    169     vpx_codec_dec_cfg_t cfg;
    170     memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t));
    171     cfg.threads = GetCPUCoreCount();
    172     if ((vpx_err = vpx_codec_dec_init(
    173                 (vpx_codec_ctx_t *)mCtx,
    174                  &vpx_codec_vp9_dx_algo,
    175                  &cfg, 0))) {
    176         LOGE("on2 decoder failed to initialize. (%d)", vpx_err);
    177         return OMX_ErrorNotReady;
    178     }
    179 
    180     mNumFrameBuffer = OUTPORT_NATIVE_BUFFER_COUNT;
    181 
    182     if (vpx_codec_set_frame_buffer_functions((vpx_codec_ctx_t *)mCtx,
    183                                     getVP9FrameBuffer,
    184                                     releaseVP9FrameBuffer,
    185                                     this)) {
    186       LOGE("Failed to configure external frame buffers");
    187       return OMX_ErrorNotReady;
    188     }
    189 
    190     return OMX_ErrorNone;
    191 }
    192 
    193 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::destroyDecoder()
    194 {
    195     vpx_codec_destroy((vpx_codec_ctx_t *)mCtx);
    196     delete (vpx_codec_ctx_t *)mCtx;
    197     mCtx = NULL;
    198     return OMX_ErrorNone;
    199 }
    200 
    201 
    202 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::InitInputPortFormatSpecific(
    203     OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput)
    204 {
    205     paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
    206     paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
    207     paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE;
    208     paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)VP9_MIME_TYPE;
    209     paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingVP9;
    210 
    211     return OMX_ErrorNone;
    212 }
    213 
    214 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorInit(void)
    215 {
    216     unsigned int i = 0;
    217 
    218     for (i = 0; i < MAX_NATIVE_BUFFER_COUNT; i++) {
    219         extMIDs[i] = (vaapiMemId*)malloc(sizeof(vaapiMemId));
    220         extMIDs[i]->m_usrAddr = NULL;
    221         extMIDs[i]->m_surface = new VASurfaceID;
    222     }
    223 
    224     initDecoder();
    225 
    226     if (RAWDATA_MODE == mWorkingMode) {
    227         OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput;
    228 
    229         memcpy(&paramPortDefinitionInput,
    230                this->ports[INPORT_INDEX]->GetPortDefinition(),
    231                sizeof(paramPortDefinitionInput));
    232 
    233         extNativeBufferSize = INTERNAL_MAX_FRAME_WIDTH *
    234                               INTERNAL_MAX_FRAME_HEIGHT * 1.5;
    235         extActualBufferStride = INTERNAL_MAX_FRAME_WIDTH;
    236         extActualBufferHeightStride = INTERNAL_MAX_FRAME_HEIGHT;
    237 
    238         for (i = 0; i < OUTPORT_ACTUAL_BUFFER_COUNT; i++ ) {
    239             extMIDs[i]->m_usrAddr = (unsigned char*)malloc(sizeof(unsigned char) *
    240                                     extNativeBufferSize);
    241             extMIDs[i]->m_render_done = true;
    242             extMIDs[i]->m_released = true;
    243         }
    244         extMappedNativeBufferCount = OUTPORT_ACTUAL_BUFFER_COUNT;
    245         return OMX_ErrorNone;
    246     }
    247 
    248 #ifdef DECODE_WITH_GRALLOC_BUFFER
    249     if (mOMXBufferHeaderTypePtrNum > MAX_NATIVE_BUFFER_COUNT) {
    250         LOGE("Actual OMX outport buffer header type num (%d) > MAX_NATIVE_BUFFER_COUNT (%d)",
    251               mOMXBufferHeaderTypePtrNum, MAX_NATIVE_BUFFER_COUNT);
    252         return OMX_ErrorOverflow;
    253     }
    254 
    255     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput;
    256 
    257     memcpy(&paramPortDefinitionInput,
    258         this->ports[INPORT_INDEX]->GetPortDefinition(),
    259         sizeof(paramPortDefinitionInput));
    260 
    261     int surfaceWidth = mGraphicBufferParam.graphicBufferWidth;
    262     int surfaceHeight = mGraphicBufferParam.graphicBufferHeight;
    263     int surfaceStride = mGraphicBufferParam.graphicBufferStride;
    264     extNativeBufferSize = mGraphicBufferParam.graphicBufferStride *
    265                           mGraphicBufferParam.graphicBufferHeight * 1.5;
    266     extActualBufferStride = surfaceStride;
    267     extActualBufferHeightStride = surfaceHeight;
    268 
    269     for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
    270         OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i];
    271 
    272         extMIDs[i]->m_key = (unsigned int)(buf_hdr->pBuffer);
    273         extMIDs[i]->m_render_done = false;
    274         extMIDs[i]->m_released = true;
    275 
    276         VAStatus va_res;
    277         unsigned int buffer;
    278         VASurfaceAttrib attribs[2];
    279         VASurfaceAttribExternalBuffers* surfExtBuf = new VASurfaceAttribExternalBuffers;
    280         int32_t format = VA_RT_FORMAT_YUV420;
    281 
    282         surfExtBuf->buffers= (unsigned long *)&buffer;
    283         surfExtBuf->num_buffers = 1;
    284         surfExtBuf->pixel_format = VA_FOURCC_NV12;
    285         surfExtBuf->width = surfaceWidth;
    286         surfExtBuf->height = surfaceHeight;
    287         surfExtBuf->data_size = surfaceStride * surfaceHeight * 1.5;
    288         surfExtBuf->num_planes = 2;
    289         surfExtBuf->pitches[0] = surfaceStride;
    290         surfExtBuf->pitches[1] = surfaceStride;
    291         surfExtBuf->pitches[2] = 0;
    292         surfExtBuf->pitches[3] = 0;
    293         surfExtBuf->offsets[0] = 0;
    294         surfExtBuf->offsets[1] = surfaceStride * surfaceHeight;
    295         surfExtBuf->offsets[2] = 0;
    296         surfExtBuf->offsets[3] = 0;
    297         surfExtBuf->flags = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
    298 
    299         surfExtBuf->buffers[0] = (unsigned int)buf_hdr->pBuffer;
    300 
    301         attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType;
    302         attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
    303         attribs[0].value.type = VAGenericValueTypeInteger;
    304         attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
    305 
    306         attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
    307         attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
    308         attribs[1].value.type = VAGenericValueTypePointer;
    309         attribs[1].value.value.p = (void *)surfExtBuf;
    310 
    311         va_res = vaCreateSurfaces(mVADisplay,
    312                                   format,
    313                                   surfaceWidth,
    314                                   surfaceHeight,
    315                                   extMIDs[i]->m_surface,
    316                                   1,
    317                                   attribs,
    318                                   2);
    319 
    320         if (va_res != VA_STATUS_SUCCESS) {
    321             LOGE("Failed to create vaSurface!");
    322             return OMX_ErrorUndefined;
    323         }
    324 
    325         delete surfExtBuf;
    326 
    327         VAImage image;
    328         unsigned char* usrptr;
    329 
    330         va_res = vaDeriveImage(mVADisplay, *(extMIDs[i]->m_surface), &image);
    331         if (VA_STATUS_SUCCESS == va_res) {
    332             va_res = vaMapBuffer(mVADisplay, image.buf, (void **) &usrptr);
    333             if (VA_STATUS_SUCCESS == va_res) {
    334                 extMIDs[i]->m_usrAddr = usrptr;
    335                 vaUnmapBuffer(mVADisplay, image.buf);
    336             }
    337             vaDestroyImage(mVADisplay, image.image_id);
    338         }
    339         extMappedNativeBufferCount++;
    340     }
    341     return OMX_ErrorNone;
    342 #endif
    343 }
    344 
    345 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorDeinit(void)
    346 {
    347     destroyDecoder();
    348     unsigned int i = 0;
    349     if (mWorkingMode == GRAPHICBUFFER_MODE) {
    350         for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
    351             if (extMIDs[i]->m_surface != NULL) {
    352                 vaDestroySurfaces(mVADisplay, extMIDs[i]->m_surface, 1);
    353             }
    354         }
    355 
    356     } else if (mWorkingMode == RAWDATA_MODE) {
    357         for (i = 0; i < OUTPORT_ACTUAL_BUFFER_COUNT; i++ ) {
    358             if (extMIDs[i]->m_usrAddr != NULL) {
    359                 free(extMIDs[i]->m_usrAddr);
    360                 extMIDs[i]->m_usrAddr = NULL;
    361             }
    362         }
    363     }
    364     mOMXBufferHeaderTypePtrNum = 0;
    365     memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
    366     for (i = 0; i < MAX_NATIVE_BUFFER_COUNT; i++) {
    367         delete extMIDs[i]->m_surface;
    368         free(extMIDs[i]);
    369     }
    370     return OMXComponentCodecBase::ProcessorDeinit();
    371 }
    372 
    373 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorStop(void)
    374 {
    375     return OMXComponentCodecBase::ProcessorStop();
    376 }
    377 
    378 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorFlush(OMX_U32)
    379 {
    380     return OMX_ErrorNone;
    381 }
    382 
    383 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer)
    384 {
    385     unsigned int handle = (unsigned int)buffer->pBuffer;
    386     unsigned int i = 0;
    387 
    388     if (buffer->nOutputPortIndex == OUTPORT_INDEX){
    389         for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
    390             if (handle == extMIDs[i]->m_key) {
    391                 extMIDs[i]->m_render_done = true;
    392                 break;
    393             }
    394         }
    395     }
    396     return OMX_ErrorNone;
    397 }
    398 
    399 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorProcess(
    400         OMX_BUFFERHEADERTYPE ***pBuffers,
    401         buffer_retain_t *retains,
    402         OMX_U32)
    403 {
    404     OMX_ERRORTYPE ret;
    405     OMX_BUFFERHEADERTYPE *inBuffer = *pBuffers[INPORT_INDEX];
    406     OMX_BUFFERHEADERTYPE *outBuffer = *pBuffers[OUTPORT_INDEX];
    407     OMX_BOOL isResolutionChange = OMX_FALSE;
    408 
    409     if (inBuffer->pBuffer == NULL) {
    410         LOGE("Buffer to decode is empty.");
    411         return OMX_ErrorBadParameter;
    412     }
    413 
    414     if (inBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
    415         LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
    416     }
    417 
    418     if (inBuffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
    419         LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
    420     }
    421 
    422     if (inBuffer->nFlags & OMX_BUFFERFLAG_EOS) {
    423         if (inBuffer->nFilledLen == 0) {
    424             (*pBuffers[OUTPORT_INDEX])->nFilledLen = 0;
    425             (*pBuffers[OUTPORT_INDEX])->nFlags = OMX_BUFFERFLAG_EOS;
    426             return OMX_ErrorNone;
    427         }
    428     }
    429 
    430     if (vpx_codec_decode((vpx_codec_ctx_t *)mCtx,
    431                          inBuffer->pBuffer + inBuffer->nOffset,
    432                          inBuffer->nFilledLen,
    433                          NULL,
    434                          0)) {
    435         LOGE("on2 decoder failed to decode frame.");
    436         return OMX_ErrorBadParameter;
    437     }
    438 
    439     ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX],
    440                            &retains[OUTPORT_INDEX],
    441                            ((*pBuffers[INPORT_INDEX]))->nFlags,
    442                            &isResolutionChange);
    443 
    444     if (ret == OMX_ErrorNone) {
    445         (*pBuffers[OUTPORT_INDEX])->nTimeStamp = inBuffer->nTimeStamp;
    446     }
    447 
    448     if (isResolutionChange) {
    449         HandleFormatChange();
    450     }
    451 
    452     bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
    453     bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
    454     // if output port is not eos, retain the input buffer
    455     // until all the output buffers are drained.
    456     if (inputEoS && !outputEoS) {
    457         retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    458         // the input buffer is retained for draining purpose.
    459         // Set nFilledLen to 0 so buffer will not be decoded again.
    460         (*pBuffers[INPORT_INDEX])->nFilledLen = 0;
    461     }
    462 
    463     if (ret == OMX_ErrorNotReady) {
    464         retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    465         ret = OMX_ErrorNone;
    466     }
    467 
    468     return ret;
    469 }
    470 
    471 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorReset(void)
    472 {
    473     return OMX_ErrorNone;
    474 }
    475 
    476 static int ALIGN(int x, int y)
    477 {
    478     // y must be a power of 2.
    479     return (x + y - 1) & ~(y - 1);
    480 }
    481 
    482 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::HandleFormatChange(void)
    483 {
    484     mDecodedImageWidth = mDecodedImageNewWidth;
    485     mDecodedImageHeight = mDecodedImageNewHeight;
    486 
    487     // Sync port definition as it may change.
    488     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput;
    489 
    490     memcpy(&paramPortDefinitionInput,
    491         this->ports[INPORT_INDEX]->GetPortDefinition(),
    492         sizeof(paramPortDefinitionInput));
    493 
    494     memcpy(&paramPortDefinitionOutput,
    495         this->ports[OUTPORT_INDEX]->GetPortDefinition(),
    496         sizeof(paramPortDefinitionOutput));
    497 
    498     uint32_t width = mDecodedImageWidth;
    499     uint32_t height = mDecodedImageHeight;
    500     uint32_t stride = mDecodedImageWidth;
    501     uint32_t sliceHeight = mDecodedImageHeight;
    502 
    503     uint32_t widthCropped = mDecodedImageWidth;
    504     uint32_t heightCropped = mDecodedImageHeight;
    505     uint32_t strideCropped = widthCropped;
    506     uint32_t sliceHeightCropped = heightCropped;
    507 
    508     if (widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth &&
    509         heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) {
    510         if (mWorkingMode == RAWDATA_MODE) {
    511             LOGW("Change of portsetting is not reported as size is not changed.");
    512             return OMX_ErrorNone;
    513         }
    514     }
    515 
    516     paramPortDefinitionInput.format.video.nFrameWidth = width;
    517     paramPortDefinitionInput.format.video.nFrameHeight = height;
    518     paramPortDefinitionInput.format.video.nStride = stride;
    519     paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
    520 
    521     if (mWorkingMode == RAWDATA_MODE) {
    522         paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped;
    523         paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped;
    524         paramPortDefinitionOutput.format.video.nStride = strideCropped;
    525         paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped;
    526     } else if (mWorkingMode == GRAPHICBUFFER_MODE) {
    527         // when the width and height ES parse are not larger than allocated graphic buffer in outport,
    528         // there is no need to reallocate graphic buffer,just report the crop info to omx client
    529         if (width <= mGraphicBufferParam.graphicBufferWidth &&
    530             height <= mGraphicBufferParam.graphicBufferHeight) {
    531             this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
    532             this->ports[OUTPORT_INDEX]->ReportOutputCrop();
    533             return OMX_ErrorNone;
    534         }
    535 
    536         if (width > mGraphicBufferParam.graphicBufferWidth ||
    537             height > mGraphicBufferParam.graphicBufferHeight) {
    538             // update the real decoded resolution to outport instead of display resolution
    539             // for graphic buffer reallocation
    540             // when the width and height parsed from ES are larger than allocated graphic buffer in outport,
    541             paramPortDefinitionOutput.format.video.nFrameWidth = width;
    542             paramPortDefinitionOutput.format.video.nFrameHeight = (height + 0x1f) & ~0x1f;
    543             paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(
    544                     paramPortDefinitionOutput.format.video.nFrameWidth);
    545             paramPortDefinitionOutput.format.video.nStride = stride;
    546             paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
    547        }
    548     }
    549 
    550     paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
    551     mOMXBufferHeaderTypePtrNum = 0;
    552     memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
    553 
    554     this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
    555     this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
    556 
    557     this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
    558     return OMX_ErrorNone;
    559 }
    560 
    561 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer,
    562                                                       buffer_retain_t *retain,
    563                                                       OMX_U32 inportBufferFlags,
    564                                                       OMX_BOOL *isResolutionChange)
    565 {
    566     OMX_BUFFERHEADERTYPE *buffer = *pBuffer;
    567     OMX_BUFFERHEADERTYPE *buffer_orign = buffer;
    568 
    569     OMX_ERRORTYPE ret = OMX_ErrorNone;
    570 
    571     vpx_codec_iter_t iter = NULL;
    572     vpx_image_t *img = NULL;
    573     img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
    574 
    575     if (img != NULL) {
    576         if ((mDecodedImageWidth == 0) && (mDecodedImageHeight == 0)) { // init value
    577             mDecodedImageWidth = img->d_w;
    578             mDecodedImageHeight = img->d_h;
    579         }
    580         if ((mDecodedImageWidth != img->d_w) && (mDecodedImageHeight != img->d_h)) {
    581             mDecodedImageNewWidth = img->d_w;
    582             mDecodedImageNewHeight = img->d_h;
    583             *isResolutionChange = OMX_TRUE;
    584         }
    585     }
    586 
    587     if (mWorkingMode == RAWDATA_MODE) {
    588         if (img == NULL) {
    589             LOGE("vpx_codec_get_frame return NULL.");
    590             return OMX_ErrorNotReady;
    591         }
    592 
    593         // in Raw data mode, this flag should be always true
    594         extMIDs[img->fb_index]->m_render_done = true;
    595 
    596         void *dst = buffer->pBuffer;
    597         uint8_t *dst_y = (uint8_t *)dst;
    598         const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput
    599                                       = this->ports[INPORT_INDEX]->GetPortDefinition();
    600 
    601         size_t inBufferWidth = paramPortDefinitionInput->format.video.nFrameWidth;
    602         size_t inBufferHeight = paramPortDefinitionInput->format.video.nFrameHeight;
    603 
    604         const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput
    605                                       = this->ports[OUTPORT_INDEX]->GetPortDefinition();
    606 
    607         size_t dst_y_size = paramPortDefinitionOutput->format.video.nStride *
    608                             paramPortDefinitionOutput->format.video.nFrameHeight;
    609         size_t dst_c_stride = ALIGN(paramPortDefinitionOutput->format.video.nStride / 2, 16);
    610         size_t dst_c_size = dst_c_stride * paramPortDefinitionOutput->format.video.nFrameHeight / 2;
    611         uint8_t *dst_v = dst_y + dst_y_size;
    612         uint8_t *dst_u = dst_v + dst_c_size;
    613 
    614         //test border
    615         dst_y += VPX_DECODE_BORDER * paramPortDefinitionOutput->format.video.nStride + VPX_DECODE_BORDER;
    616         dst_v += (VPX_DECODE_BORDER/2) * dst_c_stride + (VPX_DECODE_BORDER/2);
    617         dst_u += (VPX_DECODE_BORDER/2) * dst_c_stride + (VPX_DECODE_BORDER/2);
    618 
    619         const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y];
    620 
    621         for (size_t i = 0; i < img->d_h; ++i) {
    622             memcpy(dst_y, srcLine, img->d_w);
    623 
    624             srcLine += img->stride[PLANE_Y];
    625             dst_y += paramPortDefinitionOutput->format.video.nStride;
    626         }
    627 
    628         srcLine = (const uint8_t *)img->planes[PLANE_U];
    629         for (size_t i = 0; i < img->d_h / 2; ++i) {
    630             memcpy(dst_u, srcLine, img->d_w / 2);
    631 
    632             srcLine += img->stride[PLANE_U];
    633             dst_u += dst_c_stride;
    634         }
    635 
    636         srcLine = (const uint8_t *)img->planes[PLANE_V];
    637         for (size_t i = 0; i < img->d_h / 2; ++i) {
    638             memcpy(dst_v, srcLine, img->d_w / 2);
    639 
    640             srcLine += img->stride[PLANE_V];
    641             dst_v += dst_c_stride;
    642         }
    643 
    644         buffer->nOffset = 0;
    645         buffer->nFilledLen = dst_y_size + dst_c_size * 2;
    646         if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
    647             buffer->nFlags = OMX_BUFFERFLAG_EOS;
    648         }
    649 
    650         if (buffer_orign != buffer) {
    651             *retain = BUFFER_RETAIN_OVERRIDDEN;
    652         }
    653         ret = OMX_ErrorNone;
    654 
    655         return ret;
    656 
    657     }
    658 
    659 #ifdef DECODE_WITH_GRALLOC_BUFFER
    660     if (NULL != img) {
    661         buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[img->fb_index];
    662 
    663         if ((unsigned int)(buffer->pBuffer) != extMIDs[img->fb_index]->m_key) {
    664             LOGE("There is gralloc handle mismatching between pool\
    665                   and mOMXBufferHeaderTypePtrArray.");
    666             return OMX_ErrorNotReady;
    667         }
    668 
    669         extMIDs[img->fb_index]->m_render_done = false;
    670 
    671         buffer->nOffset = 0;
    672 
    673         size_t dst_y_size = img->d_w * img->d_h;
    674 
    675         buffer->nFilledLen = dst_y_size * 1.5; // suport only 4:2:0 for now
    676 
    677         if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
    678             buffer->nFlags = OMX_BUFFERFLAG_EOS;
    679         }
    680 
    681         if (buffer_orign != buffer) {
    682             *retain = BUFFER_RETAIN_OVERRIDDEN;
    683         }
    684 
    685         return OMX_ErrorNone;
    686     } else {
    687         LOGE("vpx_codec_get_frame return NULL.");
    688         return OMX_ErrorNotReady;
    689     }
    690 #endif
    691 }
    692 
    693 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::PrepareConfigBuffer(VideoConfigBuffer *)
    694 {
    695     return OMX_ErrorNone;
    696 }
    697 
    698 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *,
    699                                                          buffer_retain_t *,
    700                                                          VideoDecodeBuffer *)
    701 {
    702     return OMX_ErrorNone;
    703 }
    704 
    705 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::BuildHandlerList(void)
    706 {
    707     OMXVideoDecoderBase::BuildHandlerList();
    708     return OMX_ErrorNone;
    709 }
    710 
    711 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::GetParamVideoVp9(OMX_PTR)
    712 {
    713     return OMX_ErrorNone;
    714 }
    715 
    716 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::SetParamVideoVp9(OMX_PTR)
    717 {
    718     return OMX_ErrorNone;
    719 }
    720 
    721 OMX_COLOR_FORMATTYPE OMXVideoDecoderVP9HWR::GetOutputColorFormat(int)
    722 {
    723     LOGV("Output color format is OMX_INTEL_COLOR_FormatHalYV12.");
    724     return (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12;
    725 }
    726 
    727 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::GetDecoderOutputCropSpecific(OMX_PTR pStructure)
    728 {
    729     OMX_ERRORTYPE ret = OMX_ErrorNone;
    730     OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure;
    731 
    732     CHECK_TYPE_HEADER(rectParams);
    733 
    734     if (rectParams->nPortIndex != OUTPORT_INDEX) {
    735         return OMX_ErrorUndefined;
    736     }
    737 
    738     const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput
    739                                       = this->ports[INPORT_INDEX]->GetPortDefinition();
    740 
    741     rectParams->nLeft = VPX_DECODE_BORDER;
    742     rectParams->nTop = VPX_DECODE_BORDER;
    743     rectParams->nWidth = paramPortDefinitionInput->format.video.nFrameWidth;
    744     rectParams->nHeight = paramPortDefinitionInput->format.video.nFrameHeight;
    745 
    746     return ret;
    747 }
    748 
    749 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::GetNativeBufferUsageSpecific(OMX_PTR pStructure)
    750 {
    751     OMX_ERRORTYPE ret;
    752     android::GetAndroidNativeBufferUsageParams *param =
    753         (android::GetAndroidNativeBufferUsageParams*)pStructure;
    754     CHECK_TYPE_HEADER(param);
    755 
    756     param->nUsage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER \
    757                      | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_EXTERNAL_DISP);
    758     return OMX_ErrorNone;
    759 
    760 }
    761 
    762 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::SetNativeBufferModeSpecific(OMX_PTR pStructure)
    763 {
    764     OMX_ERRORTYPE ret;
    765     EnableAndroidNativeBuffersParams *param =
    766         (EnableAndroidNativeBuffersParams*)pStructure;
    767 
    768     CHECK_TYPE_HEADER(param);
    769     CHECK_PORT_INDEX_RANGE(param);
    770     CHECK_SET_PARAM_STATE();
    771 
    772     if (!param->enable) {
    773         mWorkingMode = RAWDATA_MODE;
    774         return OMX_ErrorNone;
    775     }
    776     mWorkingMode = GRAPHICBUFFER_MODE;
    777     PortVideo *port = NULL;
    778     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
    779 
    780 
    781     OMX_PARAM_PORTDEFINITIONTYPE port_def;
    782     memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
    783     port_def.nBufferCountMin = mNativeBufferCount;
    784     port_def.nBufferCountActual = mNativeBufferCount;
    785     port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE;
    786     port_def.format.video.eColorFormat = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
    787 
    788     // add borders for libvpx decode need.
    789     port_def.format.video.nFrameHeight += VPX_DECODE_BORDER * 2;
    790     port_def.format.video.nFrameWidth += VPX_DECODE_BORDER * 2;
    791     // make heigth 32bit align
    792     port_def.format.video.nFrameHeight = (port_def.format.video.nFrameHeight + 0x1f) & ~0x1f;
    793     port_def.format.video.eColorFormat = GetOutputColorFormat(
    794                         port_def.format.video.nFrameWidth);
    795     port->SetPortDefinition(&port_def,true);
    796 
    797      return OMX_ErrorNone;
    798 }
    799 
    800 
    801 bool OMXVideoDecoderVP9HWR::IsAllBufferAvailable(void)
    802 {
    803     bool b = ComponentBase::IsAllBufferAvailable();
    804     if (b == false) {
    805         return false;
    806     }
    807 
    808     PortVideo *port = NULL;
    809     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
    810     const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition();
    811      // if output port is disabled, retain the input buffer
    812     if (!port_def->bEnabled) {
    813         return false;
    814     }
    815 
    816     unsigned int i = 0;
    817     int found = 0;
    818 
    819     if (RAWDATA_MODE == mWorkingMode) {
    820         for (i = 0; i < OUTPORT_ACTUAL_BUFFER_COUNT; i++) {
    821             if (extMIDs[i]->m_released == true) {
    822                found ++;
    823                if (found > 1) { //libvpx sometimes needs 2 buffer when calling decode once.
    824                    return true;
    825                }
    826             }
    827         }
    828     } else { // graphic buffer mode
    829         for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
    830             if ((extMIDs[i]->m_render_done == true) && (extMIDs[i]->m_released == true)) {
    831                found ++;
    832                if (found > 1) { //libvpx sometimes needs 2 buffer when calling decode once.
    833                    return true;
    834                }
    835             }
    836         }
    837     }
    838 
    839     b = false;
    840 
    841     return b;
    842 }
    843 
    844 DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.VP9.hwr", "video_decoder.vp9", OMXVideoDecoderVP9HWR);
    845 
    846