Home | History | Annotate | Download | only in videocodec
      1 /*
      2 * Copyright (c) 2009-2011 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_NDEBUG 0
     18 #define LOG_TAG "OMXVideoDecoder"
     19 #include <wrs_omxil_core/log.h>
     20 #include "OMXVideoDecoderBase.h"
     21 #include <va/va_android.h>
     22 
     23 static const char* VA_RAW_MIME_TYPE = "video/x-raw-va";
     24 static const uint32_t VA_COLOR_FORMAT = 0x7FA00E00;
     25 
     26 OMXVideoDecoderBase::OMXVideoDecoderBase()
     27     : mRotationDegrees(0),
     28       mVideoDecoder(NULL),
     29       mNativeBufferCount(OUTPORT_NATIVE_BUFFER_COUNT),
     30 #ifdef TARGET_HAS_VPP
     31       mVppBufferNum(0),
     32 #endif
     33       mWorkingMode(RAWDATA_MODE),
     34       mErrorReportEnabled (false) {
     35       mOMXBufferHeaderTypePtrNum = 0;
     36       memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
     37 }
     38 
     39 OMXVideoDecoderBase::~OMXVideoDecoderBase() {
     40     releaseVideoDecoder(mVideoDecoder);
     41 
     42     if (this->ports) {
     43         if (this->ports[INPORT_INDEX]) {
     44             delete this->ports[INPORT_INDEX];
     45             this->ports[INPORT_INDEX] = NULL;
     46         }
     47 
     48         if (this->ports[OUTPORT_INDEX]) {
     49             delete this->ports[OUTPORT_INDEX];
     50             this->ports[OUTPORT_INDEX] = NULL;
     51         }
     52     }
     53 }
     54 
     55 OMX_ERRORTYPE OMXVideoDecoderBase::InitInputPort(void) {
     56     this->ports[INPORT_INDEX] = new PortVideo;
     57     if (this->ports[INPORT_INDEX] == NULL) {
     58         return OMX_ErrorInsufficientResources;
     59     }
     60 
     61     PortVideo *port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
     62 
     63     // OMX_PARAM_PORTDEFINITIONTYPE
     64     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput;
     65     memset(&paramPortDefinitionInput, 0, sizeof(paramPortDefinitionInput));
     66     SetTypeHeader(&paramPortDefinitionInput, sizeof(paramPortDefinitionInput));
     67     paramPortDefinitionInput.nPortIndex = INPORT_INDEX;
     68     paramPortDefinitionInput.eDir = OMX_DirInput;
     69     paramPortDefinitionInput.nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
     70     paramPortDefinitionInput.nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
     71     paramPortDefinitionInput.nBufferSize = INPORT_BUFFER_SIZE;
     72     paramPortDefinitionInput.bEnabled = OMX_TRUE;
     73     paramPortDefinitionInput.bPopulated = OMX_FALSE;
     74     paramPortDefinitionInput.eDomain = OMX_PortDomainVideo;
     75     paramPortDefinitionInput.format.video.cMIMEType = NULL; // to be overridden
     76     paramPortDefinitionInput.format.video.pNativeRender = NULL;
     77     paramPortDefinitionInput.format.video.nFrameWidth = 176;
     78     paramPortDefinitionInput.format.video.nFrameHeight = 144;
     79     paramPortDefinitionInput.format.video.nStride = 0;
     80     paramPortDefinitionInput.format.video.nSliceHeight = 0;
     81     paramPortDefinitionInput.format.video.nBitrate = 64000;
     82     paramPortDefinitionInput.format.video.xFramerate = 15 << 16;
     83     // TODO: check if we need to set bFlagErrorConcealment  to OMX_TRUE
     84     paramPortDefinitionInput.format.video.bFlagErrorConcealment = OMX_FALSE;
     85     paramPortDefinitionInput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; // to be overridden
     86     paramPortDefinitionInput.format.video.eColorFormat = OMX_COLOR_FormatUnused;
     87     paramPortDefinitionInput.format.video.pNativeWindow = NULL;
     88     paramPortDefinitionInput.bBuffersContiguous = OMX_FALSE;
     89     paramPortDefinitionInput.nBufferAlignment = 0;
     90 
     91     // Derived class must implement this interface and override any field if needed.
     92     // eCompressionFormat and and cMIMEType must be overridden
     93     InitInputPortFormatSpecific(&paramPortDefinitionInput);
     94 
     95     port->SetPortDefinition(&paramPortDefinitionInput, true);
     96 
     97     // OMX_VIDEO_PARAM_PORTFORMATTYPE
     98     OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
     99     memset(&paramPortFormat, 0, sizeof(paramPortFormat));
    100     SetTypeHeader(&paramPortFormat, sizeof(paramPortFormat));
    101     paramPortFormat.nPortIndex = INPORT_INDEX;
    102     paramPortFormat.nIndex = 0;
    103     paramPortFormat.eCompressionFormat = paramPortDefinitionInput.format.video.eCompressionFormat;
    104     paramPortFormat.eColorFormat = paramPortDefinitionInput.format.video.eColorFormat;
    105     paramPortFormat.xFramerate = paramPortDefinitionInput.format.video.xFramerate;
    106 
    107     port->SetPortVideoParam(&paramPortFormat, true);
    108 
    109     return OMX_ErrorNone;
    110 }
    111 
    112 
    113 OMX_ERRORTYPE OMXVideoDecoderBase::InitOutputPort(void) {
    114     this->ports[OUTPORT_INDEX] = new PortVideo;
    115     if (this->ports[OUTPORT_INDEX] == NULL) {
    116         return OMX_ErrorInsufficientResources;
    117     }
    118 
    119     PortVideo *port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
    120 
    121     // OMX_PARAM_PORTDEFINITIONTYPE
    122     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionOutput;
    123 
    124     memset(&paramPortDefinitionOutput, 0, sizeof(paramPortDefinitionOutput));
    125     SetTypeHeader(&paramPortDefinitionOutput, sizeof(paramPortDefinitionOutput));
    126 
    127     paramPortDefinitionOutput.nPortIndex = OUTPORT_INDEX;
    128     paramPortDefinitionOutput.eDir = OMX_DirOutput;
    129     paramPortDefinitionOutput.nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT;
    130     paramPortDefinitionOutput.nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT;
    131     paramPortDefinitionOutput.nBufferSize = sizeof(VideoRenderBuffer);
    132 
    133     paramPortDefinitionOutput.bEnabled = OMX_TRUE;
    134     paramPortDefinitionOutput.bPopulated = OMX_FALSE;
    135     paramPortDefinitionOutput.eDomain = OMX_PortDomainVideo;
    136     paramPortDefinitionOutput.format.video.cMIMEType = (OMX_STRING)VA_RAW_MIME_TYPE;
    137     paramPortDefinitionOutput.format.video.pNativeRender = NULL;
    138     paramPortDefinitionOutput.format.video.nFrameWidth = 176;
    139     paramPortDefinitionOutput.format.video.nFrameHeight = 144;
    140     paramPortDefinitionOutput.format.video.nStride = 176;
    141     paramPortDefinitionOutput.format.video.nSliceHeight = 144;
    142     paramPortDefinitionOutput.format.video.nBitrate = 64000;
    143     paramPortDefinitionOutput.format.video.xFramerate = 15 << 16;
    144     paramPortDefinitionOutput.format.video.bFlagErrorConcealment = OMX_FALSE;
    145     paramPortDefinitionOutput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
    146     paramPortDefinitionOutput.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
    147     paramPortDefinitionOutput.format.video.pNativeWindow = NULL;
    148     paramPortDefinitionOutput.bBuffersContiguous = OMX_FALSE;
    149     paramPortDefinitionOutput.nBufferAlignment = 0;
    150 
    151     // no format specific to initialize output port
    152     InitOutputPortFormatSpecific(&paramPortDefinitionOutput);
    153 
    154     port->SetPortDefinition(&paramPortDefinitionOutput, true);
    155 
    156     // OMX_VIDEO_PARAM_PORTFORMATTYPE
    157     OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
    158     SetTypeHeader(&paramPortFormat, sizeof(paramPortFormat));
    159     paramPortFormat.nPortIndex = OUTPORT_INDEX;
    160     paramPortFormat.nIndex = 0;
    161     paramPortFormat.eCompressionFormat = paramPortDefinitionOutput.format.video.eCompressionFormat;
    162     paramPortFormat.eColorFormat = paramPortDefinitionOutput.format.video.eColorFormat;
    163     paramPortFormat.xFramerate = paramPortDefinitionOutput.format.video.xFramerate;
    164 
    165     port->SetPortVideoParam(&paramPortFormat, true);
    166 
    167     return OMX_ErrorNone;
    168 }
    169 
    170 OMX_ERRORTYPE OMXVideoDecoderBase::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *) {
    171     // no format specific to initialize output port
    172     return OMX_ErrorNone;
    173 }
    174 
    175 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorInit(void) {
    176     OMX_ERRORTYPE ret;
    177     ret = OMXComponentCodecBase::ProcessorInit();
    178     CHECK_RETURN_VALUE("OMXComponentCodecBase::ProcessorInit");
    179 
    180     if (mVideoDecoder == NULL) {
    181         LOGE("ProcessorInit: Video decoder is not created.");
    182         return OMX_ErrorDynamicResourcesUnavailable;
    183     }
    184 
    185     VideoConfigBuffer configBuffer;
    186     ret = PrepareConfigBuffer(&configBuffer);
    187     CHECK_RETURN_VALUE("PrepareConfigBuffer");
    188 
    189     //pthread_mutex_lock(&mSerializationLock);
    190     Decode_Status status = mVideoDecoder->start(&configBuffer);
    191     //pthread_mutex_unlock(&mSerializationLock);
    192 
    193     if (status != DECODE_SUCCESS) {
    194         return TranslateDecodeStatus(status);
    195     }
    196 
    197     return OMX_ErrorNone;
    198 }
    199 
    200 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorReset(void) {
    201     OMX_ERRORTYPE ret;
    202     VideoConfigBuffer configBuffer;
    203     // reset the configbuffer and set it to mix
    204     ret = PrepareConfigBuffer(&configBuffer);
    205     CHECK_RETURN_VALUE("PrepareConfigBuffer");
    206     mVideoDecoder->reset(&configBuffer);
    207     return OMX_ErrorNone;
    208 }
    209 
    210 
    211 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorDeinit(void) {
    212     if (mWorkingMode != GRAPHICBUFFER_MODE) {
    213         if (mVideoDecoder == NULL) {
    214             LOGE("ProcessorDeinit: Video decoder is not created.");
    215             return OMX_ErrorDynamicResourcesUnavailable;
    216         }
    217         mVideoDecoder->stop();
    218     }
    219     mOMXBufferHeaderTypePtrNum = 0;
    220     memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
    221     mRotationDegrees = 0;
    222 #ifdef TARGET_HAS_VPP
    223     mVppBufferNum = 0;
    224 #endif
    225     return OMXComponentCodecBase::ProcessorDeinit();
    226 }
    227 
    228 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorStart(void) {
    229     return OMXComponentCodecBase::ProcessorStart();
    230 }
    231 
    232 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorStop(void) {
    233     // There is no need to return all retained buffers as we don't accumulate buffer
    234     //this->ports[INPORT_INDEX]->ReturnAllRetainedBuffers();
    235 
    236     // TODO: this is new code
    237     ProcessorFlush(OMX_ALL);
    238     if (mWorkingMode == GRAPHICBUFFER_MODE) {
    239         // for GRAPHICBUFFER_MODE mode, va_destroySurface need to lock the graphicbuffer,
    240         // Make sure va_destroySurface is called(ExecutingToIdle) before graphicbuffer is freed(IdleToLoaded).
    241         if (mVideoDecoder == NULL) {
    242             LOGE("ProcessorStop: Video decoder is not created.");
    243             return OMX_ErrorDynamicResourcesUnavailable;
    244         }
    245         mVideoDecoder->stop();
    246     }
    247     return OMXComponentCodecBase::ProcessorStop();
    248 }
    249 
    250 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPause(void) {
    251     return OMXComponentCodecBase::ProcessorPause();
    252 }
    253 
    254 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorResume(void) {
    255     return OMXComponentCodecBase::ProcessorResume();
    256 }
    257 
    258 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorFlush(OMX_U32 portIndex) {
    259     LOGI("Flushing port# %u.", portIndex);
    260     if (mVideoDecoder == NULL) {
    261         LOGE("ProcessorFlush: Video decoder is not created.");
    262         return OMX_ErrorDynamicResourcesUnavailable;
    263     }
    264 
    265     // Portbase has returned all retained buffers.
    266     if (portIndex == INPORT_INDEX || portIndex == OMX_ALL) {
    267         //pthread_mutex_lock(&mSerializationLock);
    268         LOGW("Flushing video pipeline.");
    269         mVideoDecoder->flush();
    270         //pthread_mutex_unlock(&mSerializationLock);
    271     }
    272     // TODO: do we need to flush output port?
    273     return OMX_ErrorNone;
    274 }
    275 
    276 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPreFreeBuffer(OMX_U32 nPortIndex, OMX_BUFFERHEADERTYPE * pBuffer) {
    277     if (mWorkingMode == GRAPHICBUFFER_MODE)
    278         return OMX_ErrorNone;
    279 
    280     if (nPortIndex == OUTPORT_INDEX && pBuffer->pPlatformPrivate) {
    281         VideoRenderBuffer *p = (VideoRenderBuffer *)pBuffer->pPlatformPrivate;
    282         p->renderDone = true;
    283         pBuffer->pPlatformPrivate = NULL;
    284     }
    285     return OMX_ErrorNone;
    286 }
    287 
    288  OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer) {
    289     if (mWorkingMode == GRAPHICBUFFER_MODE && buffer->nOutputPortIndex == OUTPORT_INDEX){
    290         Decode_Status status;
    291         if(mVideoDecoder == NULL){
    292             LOGW("ProcessorPreFillBuffer: Video decoder is not created");
    293             return OMX_ErrorDynamicResourcesUnavailable;
    294         }
    295         status = mVideoDecoder->signalRenderDone(buffer->pBuffer);
    296 
    297         if (status != DECODE_SUCCESS) {
    298             LOGW("ProcessorPreFillBuffer:: signalRenderDone return error");
    299             return TranslateDecodeStatus(status);
    300         }
    301     } else if (buffer->pPlatformPrivate && buffer->nOutputPortIndex == OUTPORT_INDEX){
    302         VideoRenderBuffer *p = (VideoRenderBuffer *)buffer->pPlatformPrivate;
    303         p->renderDone = true;
    304         buffer->pPlatformPrivate = NULL;
    305     }
    306     return OMX_ErrorNone;
    307 }
    308 
    309 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorProcess(
    310     OMX_BUFFERHEADERTYPE ***pBuffers,
    311     buffer_retain_t *retains,
    312     OMX_U32) {
    313 
    314     OMX_ERRORTYPE ret;
    315     Decode_Status status;
    316     OMX_BOOL isResolutionChange = OMX_FALSE;
    317     // fill render buffer without draining decoder output queue
    318     ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], 0, &isResolutionChange);
    319     if (ret == OMX_ErrorNone) {
    320         retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    321         if (isResolutionChange) {
    322             HandleFormatChange();
    323         }
    324         // TODO: continue decoding
    325         return ret;
    326     } else if (ret != OMX_ErrorNotReady) {
    327         return ret;
    328     }
    329 
    330     VideoDecodeBuffer decodeBuffer;
    331     // PrepareDecodeBuffer will set retain to either BUFFER_RETAIN_GETAGAIN or BUFFER_RETAIN_NOT_RETAIN
    332     ret = PrepareDecodeBuffer(*pBuffers[INPORT_INDEX], &retains[INPORT_INDEX], &decodeBuffer);
    333     if (ret == OMX_ErrorNotReady) {
    334         retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    335         return OMX_ErrorNone;
    336     } else if (ret != OMX_ErrorNone) {
    337         return ret;
    338     }
    339 
    340     if (decodeBuffer.size != 0) {
    341         //pthread_mutex_lock(&mSerializationLock);
    342         status = mVideoDecoder->decode(&decodeBuffer);
    343         //pthread_mutex_unlock(&mSerializationLock);
    344 
    345         if (status == DECODE_FORMAT_CHANGE) {
    346             ret = HandleFormatChange();
    347             CHECK_RETURN_VALUE("HandleFormatChange");
    348             ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0;
    349             retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    350             retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    351             // real dynamic resolution change will be handled later
    352             // Here is just a temporary workaround
    353             // don't use the output buffer if format is changed.
    354             return OMX_ErrorNone;
    355         } else if (status == DECODE_NO_CONFIG) {
    356             LOGW("Decoder returns DECODE_NO_CONFIG.");
    357             retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    358             return OMX_ErrorNone;
    359         } else if (status == DECODE_NO_REFERENCE) {
    360             LOGW("Decoder returns DECODE_NO_REFERENCE.");
    361             //retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    362             //return OMX_ErrorNone;
    363         } else if (status == DECODE_MULTIPLE_FRAME){
    364             if (decodeBuffer.ext != NULL && decodeBuffer.ext->extType == PACKED_FRAME_TYPE && decodeBuffer.ext->extData != NULL) {
    365                 PackedFrameData* nextFrame = (PackedFrameData*)decodeBuffer.ext->extData;
    366                 (*pBuffers[INPORT_INDEX])->nOffset += nextFrame->offSet;
    367                 (*pBuffers[INPORT_INDEX])->nTimeStamp = nextFrame->timestamp;
    368                 (*pBuffers[INPORT_INDEX])->nFilledLen -= nextFrame->offSet;
    369                 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    370                 LOGW("Find multiple frames in a buffer, next frame offset = %d, timestamp = %lld", (*pBuffers[INPORT_INDEX])->nOffset, (*pBuffers[INPORT_INDEX])->nTimeStamp);
    371             }
    372         }
    373         else if (status != DECODE_SUCCESS && status != DECODE_FRAME_DROPPED) {
    374             if (checkFatalDecoderError(status)) {
    375                 return TranslateDecodeStatus(status);
    376             } else {
    377                 // For decoder errors that could be omitted,  not throw error and continue to decode.
    378                 TranslateDecodeStatus(status);
    379 
    380                 ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0;
    381 
    382                 // Do not return, and try to drain the output queue
    383                 // retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    384                 // return OMX_ErrorNone;
    385             }
    386         }
    387     }
    388     // drain the decoder output queue when in EOS state and fill the render buffer
    389     ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX],
    390             ((*pBuffers[INPORT_INDEX]))->nFlags,&isResolutionChange);
    391 
    392     if (isResolutionChange) {
    393         HandleFormatChange();
    394     }
    395 
    396     bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
    397     bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
    398     // if output port is not eos, retain the input buffer until all the output buffers are drained.
    399     if (inputEoS && !outputEoS) {
    400         retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    401         // the input buffer is retained for draining purpose. Set nFilledLen to 0 so buffer will not be decoded again.
    402         (*pBuffers[INPORT_INDEX])->nFilledLen = 0;
    403     }
    404 
    405     if (ret == OMX_ErrorNotReady) {
    406         retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    407         ret = OMX_ErrorNone;
    408     }
    409 
    410     return ret;
    411 }
    412 
    413 bool OMXVideoDecoderBase::IsAllBufferAvailable(void) {
    414     bool b = ComponentBase::IsAllBufferAvailable();
    415     if (b == false) {
    416         return false;
    417     }
    418 
    419     PortVideo *port = NULL;
    420     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
    421     const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition();
    422      // if output port is disabled, retain the input buffer
    423     if (!port_def->bEnabled) {
    424         return false;
    425     }
    426 
    427     if (mVideoDecoder) {
    428         return mVideoDecoder->checkBufferAvail();
    429     }
    430     return false;
    431 }
    432 
    433 OMX_ERRORTYPE OMXVideoDecoderBase::PrepareConfigBuffer(VideoConfigBuffer *p) {
    434     // default config buffer preparation
    435     memset(p, 0, sizeof(VideoConfigBuffer));
    436 
    437     const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput = this->ports[INPORT_INDEX]->GetPortDefinition();
    438     if (paramPortDefinitionInput == NULL) {
    439         return OMX_ErrorBadParameter;
    440     }
    441 
    442     if (mWorkingMode == GRAPHICBUFFER_MODE) {
    443         p->surfaceNumber = mOMXBufferHeaderTypePtrNum;
    444         for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++){
    445             OMX_BUFFERHEADERTYPE *buffer_hdr = mOMXBufferHeaderTypePtrArray[i];
    446             p->graphicBufferHandler[i] = buffer_hdr->pBuffer;
    447             LOGV("PrepareConfigBuffer bufferid = %p, handle = %p", buffer_hdr, buffer_hdr->pBuffer);
    448         }
    449         p->flag |= USE_NATIVE_GRAPHIC_BUFFER;
    450         p->graphicBufferStride = mGraphicBufferParam.graphicBufferStride;
    451         p->graphicBufferColorFormat = mGraphicBufferParam.graphicBufferColorFormat;
    452         p->graphicBufferWidth = mGraphicBufferParam.graphicBufferWidth;
    453         p->graphicBufferHeight = mGraphicBufferParam.graphicBufferHeight;
    454         if (p->graphicBufferColorFormat == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled
    455 #ifdef USE_GEN_HW
    456             || p->graphicBufferColorFormat == HAL_PIXEL_FORMAT_NV12_X_TILED_INTEL
    457 #endif
    458         )
    459             p->flag |= USE_TILING_MEMORY;
    460 
    461         if (mEnableAdaptivePlayback)
    462             p->flag |= WANT_ADAPTIVE_PLAYBACK;
    463 
    464         PortVideo *port = NULL;
    465         port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
    466         OMX_PARAM_PORTDEFINITIONTYPE port_def;
    467         memcpy(&port_def, port->GetPortDefinition(), sizeof(port_def));
    468 
    469         if (port_def.format.video.pNativeWindow != NULL) {
    470             p->nativeWindow = port_def.format.video.pNativeWindow;
    471             LOGD("NativeWindow = %p", p->nativeWindow);
    472         }
    473 
    474     }
    475 
    476     p->rotationDegrees = mRotationDegrees;
    477 #ifdef TARGET_HAS_VPP
    478     p->vppBufferNum = mVppBufferNum;
    479 #endif
    480     p->width = paramPortDefinitionInput->format.video.nFrameWidth;
    481     p->height = paramPortDefinitionInput->format.video.nFrameHeight;
    482 
    483     return OMX_ErrorNone;
    484 }
    485 
    486 OMX_ERRORTYPE OMXVideoDecoderBase::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
    487     // default decode buffer preparation
    488     memset(p, 0, sizeof(VideoDecodeBuffer));
    489     if (buffer->nFilledLen == 0) {
    490         LOGW("Len of filled data to decode is 0.");
    491         return OMX_ErrorNone; //OMX_ErrorBadParameter;
    492     }
    493 
    494     if (buffer->pBuffer == NULL) {
    495         LOGE("Buffer to decode is empty.");
    496         return OMX_ErrorBadParameter;
    497     }
    498 
    499     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
    500         LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
    501     }
    502 
    503     if (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
    504         // TODO: Handle OMX_BUFFERFLAG_DECODEONLY : drop the decoded frame without rendering it.
    505         LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
    506     }
    507 
    508     p->data = buffer->pBuffer + buffer->nOffset;
    509     p->size = buffer->nFilledLen;
    510     p->timeStamp = buffer->nTimeStamp;
    511     if (buffer->nFlags & (OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS)) {
    512         // TODO: OMX_BUFFERFLAG_ENDOFFRAME can be used to indicate end of a NAL unit.
    513         // setting this flag may cause corruption if buffer does not contain end-of-frame data.
    514         p->flag = HAS_COMPLETE_FRAME;
    515     }
    516 
    517     if (buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) {
    518         p->flag |= IS_SYNC_FRAME;
    519     }
    520 
    521     if (buffer->pInputPortPrivate) {
    522         uint32_t degree = 0;
    523         memcpy ((void *) &degree, buffer->pInputPortPrivate, sizeof(uint32_t));
    524         p->rotationDegrees = degree;
    525         LOGV("rotationDegrees = %d", p->rotationDegrees);
    526     } else {
    527         p->rotationDegrees = mRotationDegrees;
    528     }
    529 
    530     *retain= BUFFER_RETAIN_NOT_RETAIN;
    531     return OMX_ErrorNone;
    532 }
    533 
    534 OMX_ERRORTYPE OMXVideoDecoderBase::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer, buffer_retain_t *retain,
    535     OMX_U32 inportBufferFlags, OMX_BOOL *isResolutionChange) {
    536     OMX_BUFFERHEADERTYPE *buffer = *pBuffer;
    537     OMX_BUFFERHEADERTYPE *buffer_orign = buffer;
    538     VideoErrorBuffer *ErrBufPtr = NULL;
    539 
    540     if (mWorkingMode != GRAPHICBUFFER_MODE && buffer->pPlatformPrivate) {
    541         VideoRenderBuffer *p = (VideoRenderBuffer *)buffer->pPlatformPrivate;
    542         p->renderDone = true;
    543         buffer->pPlatformPrivate = NULL;
    544     }
    545 
    546     if (mWorkingMode == GRAPHICBUFFER_MODE && mErrorReportEnabled) {
    547         if (buffer->pOutputPortPrivate == NULL)
    548             LOGE("The App doesn't provide the output buffer for error reporting");
    549         else
    550             ErrBufPtr = (VideoErrorBuffer *)buffer->pOutputPortPrivate;
    551     }
    552 
    553     bool draining = (inportBufferFlags & OMX_BUFFERFLAG_EOS);
    554     //pthread_mutex_lock(&mSerializationLock);
    555     const VideoRenderBuffer *renderBuffer = mVideoDecoder->getOutput(draining, ErrBufPtr);
    556     //pthread_mutex_unlock(&mSerializationLock);
    557     if (renderBuffer == NULL) {
    558         buffer->nFilledLen = 0;
    559         if (draining) {
    560             LOGI("output EOS received");
    561             buffer->nFlags = OMX_BUFFERFLAG_EOS;
    562             return OMX_ErrorNone;
    563         }
    564         return OMX_ErrorNotReady;
    565     }
    566 
    567     if (mWorkingMode == GRAPHICBUFFER_MODE) {
    568         buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[renderBuffer->graphicBufferIndex];
    569      }
    570 
    571     buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
    572 #ifdef DEINTERLACE_EXT
    573     if (renderBuffer->scanFormat & (VA_TOP_FIELD | VA_BOTTOM_FIELD))
    574         buffer->nFlags |= OMX_BUFFERFLAG_TFF;
    575 #endif
    576     buffer->nTimeStamp = renderBuffer->timeStamp;
    577 
    578     if (renderBuffer->flag & IS_EOS) {
    579         buffer->nFlags |= OMX_BUFFERFLAG_EOS;
    580     }
    581     *isResolutionChange = (renderBuffer->flag & IS_RESOLUTION_CHANGE)? OMX_TRUE: OMX_FALSE;
    582 
    583     if (mWorkingMode == GRAPHICBUFFER_MODE) {
    584         if (buffer_orign != buffer) {
    585             VideoErrorBuffer *ErrBufOutPtr = NULL;
    586             ErrBufOutPtr = (VideoErrorBuffer *)buffer->pOutputPortPrivate;
    587             if (ErrBufPtr && ErrBufOutPtr) {
    588                 memcpy(ErrBufOutPtr, ErrBufPtr, sizeof(VideoErrorBuffer));
    589                 memset(ErrBufPtr, 0, sizeof(VideoErrorBuffer));
    590             }
    591             *retain = BUFFER_RETAIN_OVERRIDDEN;
    592         }
    593          buffer->nFilledLen = sizeof(OMX_U8*);
    594     } else {
    595         uint32_t size = 0;
    596         Decode_Status status = mVideoDecoder->getRawDataFromSurface(const_cast<VideoRenderBuffer *>(renderBuffer), buffer->pBuffer + buffer->nOffset, &size, false);
    597         if (status != DECODE_SUCCESS) {
    598             return TranslateDecodeStatus(status);
    599         }
    600         buffer->nFilledLen = size;
    601         buffer->pPlatformPrivate = (void *)renderBuffer;
    602     }
    603 
    604     return OMX_ErrorNone;
    605 }
    606 
    607 OMX_ERRORTYPE OMXVideoDecoderBase::HandleFormatChange(void) {
    608     LOGW("Video format is changed.");
    609     //pthread_mutex_lock(&mSerializationLock);
    610     const VideoFormatInfo *formatInfo = mVideoDecoder->getFormatInfo();
    611     //pthread_mutex_unlock(&mSerializationLock);
    612 
    613     // Sync port definition as it may change.
    614     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput;
    615 
    616     memcpy(&paramPortDefinitionInput,
    617         this->ports[INPORT_INDEX]->GetPortDefinition(),
    618         sizeof(paramPortDefinitionInput));
    619 
    620     memcpy(&paramPortDefinitionOutput,
    621         this->ports[OUTPORT_INDEX]->GetPortDefinition(),
    622         sizeof(paramPortDefinitionOutput));
    623 
    624     uint32_t width = formatInfo->width;
    625     uint32_t height = formatInfo->height;
    626     uint32_t stride = formatInfo->width;
    627     uint32_t sliceHeight = formatInfo->height;
    628 
    629     uint32_t widthCropped = formatInfo->width - formatInfo->cropLeft - formatInfo->cropRight;
    630     uint32_t heightCropped = formatInfo->height - formatInfo->cropTop - formatInfo->cropBottom;
    631     uint32_t strideCropped = widthCropped;
    632     uint32_t sliceHeightCropped = heightCropped;
    633     int force_realloc = 0;
    634 
    635 #ifdef TARGET_HAS_VPP
    636     LOGI("============== mVppBufferNum = %d\n", mVppBufferNum);
    637     if (paramPortDefinitionOutput.nBufferCountActual - mVppBufferNum < formatInfo->actualBufferNeeded) {
    638 #else
    639     if (paramPortDefinitionOutput.nBufferCountActual < formatInfo->actualBufferNeeded) {
    640 #endif
    641         if (mWorkingMode == GRAPHICBUFFER_MODE) {
    642             LOGV("output port buffer number is not enough: %d to %d",
    643                  paramPortDefinitionOutput.nBufferCountActual,
    644                  formatInfo->actualBufferNeeded);
    645             paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount = formatInfo->actualBufferNeeded;
    646             paramPortDefinitionOutput.nBufferCountMin = mNativeBufferCount;
    647             force_realloc = 1;
    648         }
    649     }
    650 
    651     LOGV("Original size = %u x %u, new size = %d x %d, cropped size = %d x %d",
    652         paramPortDefinitionInput.format.video.nFrameWidth,
    653         paramPortDefinitionInput.format.video.nFrameHeight,
    654         width, height, widthCropped, heightCropped);
    655 
    656     if (!force_realloc &&
    657         widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth &&
    658         heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) {
    659         if (mWorkingMode == RAWDATA_MODE) {
    660             LOGW("Change of portsetting is not reported as size is not changed.");
    661             return OMX_ErrorNone;
    662         }
    663     }
    664 
    665     paramPortDefinitionInput.format.video.nFrameWidth = width;
    666     paramPortDefinitionInput.format.video.nFrameHeight = height;
    667     paramPortDefinitionInput.format.video.nStride = stride;
    668     paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
    669 
    670     if (mWorkingMode == RAWDATA_MODE) {
    671         paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped;
    672         paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped;
    673         paramPortDefinitionOutput.format.video.nStride = strideCropped;
    674         paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped;
    675     } else if (mWorkingMode == GRAPHICBUFFER_MODE) {
    676         // when the width and height ES parse are not larger than allocated graphic buffer in outport,
    677         // there is no need to reallocate graphic buffer,just report the crop info to omx client
    678         if (!force_realloc && width <= formatInfo->surfaceWidth && height <= formatInfo->surfaceHeight) {
    679             this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
    680             this->ports[OUTPORT_INDEX]->ReportOutputCrop();
    681             return OMX_ErrorNone;
    682         }
    683 
    684         if (width > formatInfo->surfaceWidth ||  height > formatInfo->surfaceHeight) {
    685             // update the real decoded resolution to outport instead of display resolution for graphic buffer reallocation
    686             // when the width and height parsed from ES are larger than allocated graphic buffer in outport,
    687             paramPortDefinitionOutput.format.video.nFrameWidth = width;
    688             paramPortDefinitionOutput.format.video.nFrameHeight = (height + 0x1f) & ~0x1f;
    689             paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(
    690                     paramPortDefinitionOutput.format.video.nFrameWidth);
    691             paramPortDefinitionOutput.format.video.nStride = stride;
    692             paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
    693        }
    694     }
    695 
    696     paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
    697     mOMXBufferHeaderTypePtrNum = 0;
    698     memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
    699 
    700     this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
    701     this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
    702 
    703     if (mWorkingMode == GRAPHICBUFFER_MODE) {
    704         // Make sure va_destroySurface is called before graphicbuffer is freed in case of port setting changed
    705         mVideoDecoder->freeSurfaceBuffers();
    706     }
    707     this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
    708     return OMX_ErrorNone;
    709 }
    710 
    711 OMX_ERRORTYPE OMXVideoDecoderBase::TranslateDecodeStatus(Decode_Status status) {
    712     switch (status) {
    713         case DECODE_NEED_RESTART:
    714             LOGE("Decoder returned DECODE_NEED_RESTART");
    715             return (OMX_ERRORTYPE)OMX_ErrorIntelVideoNotPermitted;
    716         case DECODE_NO_CONFIG:
    717             LOGE("Decoder returned DECODE_NO_CONFIG");
    718             return (OMX_ERRORTYPE)OMX_ErrorIntelMissingConfig;
    719         case DECODE_NO_SURFACE:
    720             LOGE("Decoder returned DECODE_NO_SURFACE");
    721             return OMX_ErrorDynamicResourcesUnavailable;
    722         case DECODE_NO_REFERENCE:
    723             LOGE("Decoder returned DECODE_NO_REFERENCE");
    724             return OMX_ErrorDynamicResourcesUnavailable; // TO DO
    725         case DECODE_NO_PARSER:
    726             LOGE("Decoder returned DECODE_NO_PARSER");
    727             return OMX_ErrorDynamicResourcesUnavailable;
    728         case DECODE_INVALID_DATA:
    729             LOGE("Decoder returned DECODE_INVALID_DATA");
    730             return OMX_ErrorBadParameter;
    731         case DECODE_DRIVER_FAIL:
    732             LOGE("Decoder returned DECODE_DRIVER_FAIL");
    733             return OMX_ErrorHardware;
    734         case DECODE_PARSER_FAIL:
    735             LOGE("Decoder returned DECODE_PARSER_FAIL");
    736             return (OMX_ERRORTYPE)OMX_ErrorIntelProcessStream; // OMX_ErrorStreamCorrupt
    737         case DECODE_MEMORY_FAIL:
    738             LOGE("Decoder returned DECODE_MEMORY_FAIL");
    739             return OMX_ErrorInsufficientResources;
    740         case DECODE_FAIL:
    741             LOGE("Decoder returned DECODE_FAIL");
    742             return OMX_ErrorUndefined;
    743         case DECODE_SUCCESS:
    744             return OMX_ErrorNone;
    745         case DECODE_FORMAT_CHANGE:
    746             LOGW("Decoder returned DECODE_FORMAT_CHANGE");
    747             return OMX_ErrorNone;
    748         case DECODE_FRAME_DROPPED:
    749             LOGI("Decoder returned DECODE_FRAME_DROPPED");
    750             return OMX_ErrorNone;
    751         default:
    752             LOGW("Decoder returned unknown error");
    753             return OMX_ErrorUndefined;
    754     }
    755 }
    756 
    757 OMX_ERRORTYPE OMXVideoDecoderBase::BuildHandlerList(void) {
    758     OMXComponentCodecBase::BuildHandlerList();
    759     AddHandler(OMX_IndexParamVideoPortFormat, GetParamVideoPortFormat, SetParamVideoPortFormat);
    760     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtGetNativeBufferUsage), GetNativeBufferUsage, SetNativeBufferUsage);
    761     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtUseNativeBuffer), GetNativeBuffer, SetNativeBuffer);
    762     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableNativeBuffer), GetNativeBufferMode, SetNativeBufferMode);
    763     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtRotationDegrees), GetDecoderRotation, SetDecoderRotation);
    764 #ifdef TARGET_HAS_VPP
    765     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtVppBufferNum), GetDecoderVppBufferNum, SetDecoderVppBufferNum);
    766 #endif
    767     AddHandler(OMX_IndexConfigCommonOutputCrop, GetDecoderOutputCrop, SetDecoderOutputCrop);
    768     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableErrorReport), GetErrorReportMode, SetErrorReportMode);
    769 
    770     return OMX_ErrorNone;
    771 }
    772 
    773 OMX_ERRORTYPE OMXVideoDecoderBase::GetParamVideoPortFormat(OMX_PTR pStructure) {
    774     OMX_ERRORTYPE ret;
    775     OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
    776 
    777     CHECK_TYPE_HEADER(p);
    778     CHECK_PORT_INDEX_RANGE(p);
    779     CHECK_ENUMERATION_RANGE(p->nIndex, 1);
    780 
    781     PortVideo *port = NULL;
    782     port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
    783     memcpy(p, port->GetPortVideoParam(), sizeof(*p));
    784     return OMX_ErrorNone;
    785 }
    786 
    787 OMX_ERRORTYPE OMXVideoDecoderBase::SetParamVideoPortFormat(OMX_PTR pStructure) {
    788     OMX_ERRORTYPE ret;
    789     OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
    790 
    791     CHECK_TYPE_HEADER(p);
    792     CHECK_PORT_INDEX_RANGE(p);
    793     CHECK_SET_PARAM_STATE();
    794 
    795     // TODO: do we need to check if port is enabled?
    796     PortVideo *port = NULL;
    797     port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
    798     port->SetPortVideoParam(p, false);
    799     return OMX_ErrorNone;
    800 }
    801 
    802 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsageSpecific(OMX_PTR pStructure) {
    803      OMX_ERRORTYPE ret;
    804      GetAndroidNativeBufferUsageParams *param = (GetAndroidNativeBufferUsageParams*)pStructure;
    805      CHECK_TYPE_HEADER(param);
    806      param->nUsage |= GRALLOC_USAGE_HW_TEXTURE;
    807      return OMX_ErrorNone;
    808 }
    809 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsageSpecific(OMX_PTR) {
    810     CHECK_SET_PARAM_STATE();
    811     return OMX_ErrorBadParameter;
    812 }
    813 
    814 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsage(OMX_PTR pStructure) {
    815     return this->GetNativeBufferUsageSpecific(pStructure);
    816 }
    817 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsage(OMX_PTR pStructure) {
    818     return this->SetNativeBufferUsageSpecific(pStructure);
    819 }
    820 
    821 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBuffer(OMX_PTR) {
    822     return OMX_ErrorBadParameter;
    823 }
    824 
    825 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBuffer(OMX_PTR pStructure) {
    826     OMX_ERRORTYPE ret;
    827     UseAndroidNativeBufferParams *param = (UseAndroidNativeBufferParams*)pStructure;
    828     CHECK_TYPE_HEADER(param);
    829     if (param->nPortIndex != OUTPORT_INDEX)
    830         return OMX_ErrorBadParameter;
    831     OMX_BUFFERHEADERTYPE **buf_hdr = NULL;
    832 
    833     mOMXBufferHeaderTypePtrNum++;
    834     if (mOMXBufferHeaderTypePtrNum > MAX_GRAPHIC_BUFFER_NUM)
    835         return OMX_ErrorOverflow;
    836 
    837     buf_hdr = &mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum-1];
    838 
    839     ret = this->ports[OUTPORT_INDEX]->UseBuffer(buf_hdr, OUTPORT_INDEX, param->pAppPrivate, sizeof(OMX_U8*),
    840                                       const_cast<OMX_U8*>(reinterpret_cast<const OMX_U8*>(param->nativeBuffer->handle)));
    841     if (ret != OMX_ErrorNone)
    842         return ret;
    843 
    844     if (mOMXBufferHeaderTypePtrNum == 1) {
    845          mGraphicBufferParam.graphicBufferColorFormat = param->nativeBuffer->format;
    846          mGraphicBufferParam.graphicBufferStride = param->nativeBuffer->stride;
    847          mGraphicBufferParam.graphicBufferWidth = param->nativeBuffer->width;
    848          mGraphicBufferParam.graphicBufferHeight = param->nativeBuffer->height;
    849     }
    850 
    851     *(param->bufferHeader) = *buf_hdr;
    852 
    853     return OMX_ErrorNone;
    854 }
    855 
    856 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferMode(OMX_PTR pStructure) {
    857     return this->GetNativeBufferModeSpecific(pStructure);
    858 }
    859 
    860 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferMode(OMX_PTR pStructure) {
    861     return this->SetNativeBufferModeSpecific(pStructure);
    862 }
    863 
    864 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferModeSpecific(OMX_PTR) {
    865     LOGE("GetNativeBufferMode is not implemented");
    866     return OMX_ErrorNotImplemented;
    867 }
    868 
    869 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferModeSpecific(OMX_PTR pStructure) {
    870     OMX_ERRORTYPE ret;
    871     EnableAndroidNativeBuffersParams *param = (EnableAndroidNativeBuffersParams*)pStructure;
    872 
    873     CHECK_TYPE_HEADER(param);
    874     CHECK_PORT_INDEX_RANGE(param);
    875     CHECK_SET_PARAM_STATE();
    876     if (!param->enable) {
    877         mWorkingMode = RAWDATA_MODE;
    878         return OMX_ErrorNone;
    879     }
    880     mWorkingMode = GRAPHICBUFFER_MODE;
    881     PortVideo *port = NULL;
    882     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
    883 
    884     OMX_PARAM_PORTDEFINITIONTYPE port_def;
    885     memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
    886     port_def.nBufferCountMin = mNativeBufferCount;
    887     if (mEnableAdaptivePlayback) {
    888         SetMaxOutputBufferCount(&port_def);
    889     } else {
    890         port_def.nBufferCountActual = mNativeBufferCount;
    891     }
    892     port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE;
    893     port_def.format.video.eColorFormat = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
    894     port_def.format.video.nFrameHeight = (port_def.format.video.nFrameHeight + 0x1f) & ~0x1f;
    895     port_def.format.video.eColorFormat = GetOutputColorFormat(
    896                         port_def.format.video.nFrameWidth);
    897     port->SetPortDefinition(&port_def,true);
    898 
    899     return OMX_ErrorNone;
    900 }
    901 
    902 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderRotation(OMX_PTR) {
    903     return OMX_ErrorBadParameter;
    904 }
    905 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderRotation(OMX_PTR pStructure) {
    906     CHECK_SET_PARAM_STATE();
    907     int32_t rotationDegrees = 0;
    908 
    909     if (pStructure) {
    910         rotationDegrees = *(static_cast<int32_t*>(pStructure));
    911         mRotationDegrees = rotationDegrees;
    912         LOGI("Rotation Degree = %d", rotationDegrees);
    913         return OMX_ErrorNone;
    914     } else {
    915         return OMX_ErrorBadParameter;
    916     }
    917 }
    918 
    919 #ifdef TARGET_HAS_VPP
    920 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderVppBufferNum(OMX_PTR pStructure) {
    921     return OMX_ErrorBadParameter;
    922 }
    923 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderVppBufferNum(OMX_PTR pStructure) {
    924     CHECK_SET_PARAM_STATE();
    925     int32_t num = 0;
    926 
    927     num = *(static_cast<int32_t*>(pStructure));
    928     mVppBufferNum = num;
    929 
    930     return OMX_ErrorNone;
    931 }
    932 #endif
    933 
    934 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCropSpecific(OMX_PTR pStructure) {
    935     OMX_ERRORTYPE ret;
    936     OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure;
    937 
    938     CHECK_TYPE_HEADER(rectParams);
    939 
    940     if (rectParams->nPortIndex != OUTPORT_INDEX) {
    941         return OMX_ErrorUndefined;
    942     }
    943     const VideoFormatInfo *formatInfo = mVideoDecoder->getFormatInfo();
    944     if (formatInfo->valid == true) {
    945         rectParams->nLeft =  formatInfo->cropLeft;
    946         rectParams->nTop = formatInfo->cropTop;
    947         rectParams->nWidth = formatInfo->width - formatInfo->cropLeft - formatInfo->cropRight;
    948         rectParams->nHeight = formatInfo->height - formatInfo->cropTop - formatInfo->cropBottom;
    949         return OMX_ErrorNone;
    950     } else {
    951         return OMX_ErrorFormatNotDetected;
    952     }
    953 }
    954 
    955 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCropSpecific(OMX_PTR) {
    956     return OMX_ErrorUnsupportedSetting;
    957 }
    958 
    959 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCrop(OMX_PTR pStructure) {
    960     return this->SetDecoderOutputCropSpecific(pStructure);
    961 }
    962 
    963 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCrop(OMX_PTR pStructure) {
    964     return this->GetDecoderOutputCropSpecific(pStructure);
    965 }
    966 
    967 OMX_ERRORTYPE OMXVideoDecoderBase::GetErrorReportMode(OMX_PTR) {
    968     LOGE("GetErrorReportMode is not implemented");
    969     return OMX_ErrorNotImplemented;
    970 }
    971 
    972 OMX_ERRORTYPE OMXVideoDecoderBase::SetErrorReportMode(OMX_PTR pStructure) {
    973     OMX_ERRORTYPE ret;
    974 
    975     OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *p = (OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *)pStructure;
    976     CHECK_TYPE_HEADER(p);
    977     CHECK_PORT_INDEX(p, OUTPORT_INDEX);
    978 
    979     mErrorReportEnabled = p->bEnable;
    980     LOGD("Error reporting is %s", mErrorReportEnabled ? "enabled" : "disabled");
    981 
    982     mVideoDecoder->enableErrorReport(mErrorReportEnabled);
    983     return OMX_ErrorNone;
    984 }
    985 
    986 OMX_COLOR_FORMATTYPE OMXVideoDecoderBase::GetOutputColorFormat(int width) {
    987 #ifndef VED_TILING
    988     return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
    989 #else
    990     if (width > 1280 && width <= 2048) {
    991         LOGI("HD Video and use tiled format");
    992         return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled;
    993     } else {
    994         return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
    995     }
    996 #endif
    997 }
    998 
    999 OMX_ERRORTYPE OMXVideoDecoderBase::SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE *) {
   1000     return OMX_ErrorNone;
   1001 }
   1002