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