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 
     21 #include <hardware/gralloc.h>
     22 #include <va/va_android.h>
     23 
     24 #include "OMXVideoDecoderBase.h"
     25 #include "ProtectedDataBuffer.h"
     26 
     27 
     28 static const char* VA_RAW_MIME_TYPE = "video/x-raw-va";
     29 static const uint32_t VA_COLOR_FORMAT = 0x7FA00E00;
     30 
     31 OMXVideoDecoderBase::OMXVideoDecoderBase()
     32     : mRotationDegrees(0),
     33 #ifdef TARGET_HAS_ISV
     34       mVppBufferNum(0),
     35 #endif
     36       mCodecPriority(1),
     37       mOperatingRate(0),
     38       mVideoDecoder(NULL),
     39       mNativeBufferCount(OUTPORT_NATIVE_BUFFER_COUNT),
     40       mWorkingMode(RAWDATA_MODE),
     41       mErrorReportEnabled (false),
     42       mAPMode(LEGACY_MODE),
     43       mFlushMode(false),
     44       mFormatChanged(false) {
     45       mOMXBufferHeaderTypePtrNum = 0;
     46       mMetaDataBuffersNum = 0;
     47       memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
     48 }
     49 
     50 OMXVideoDecoderBase::~OMXVideoDecoderBase() {
     51     releaseVideoDecoder(mVideoDecoder);
     52 
     53     if (this->ports) {
     54         if (this->ports[INPORT_INDEX]) {
     55             delete this->ports[INPORT_INDEX];
     56             this->ports[INPORT_INDEX] = NULL;
     57         }
     58 
     59         if (this->ports[OUTPORT_INDEX]) {
     60             delete this->ports[OUTPORT_INDEX];
     61             this->ports[OUTPORT_INDEX] = NULL;
     62         }
     63     }
     64 }
     65 
     66 OMX_ERRORTYPE OMXVideoDecoderBase::InitInputPort(void) {
     67     this->ports[INPORT_INDEX] = new PortVideo;
     68     if (this->ports[INPORT_INDEX] == NULL) {
     69         return OMX_ErrorInsufficientResources;
     70     }
     71 
     72     PortVideo *port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
     73 
     74     // OMX_PARAM_PORTDEFINITIONTYPE
     75     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput;
     76     memset(&paramPortDefinitionInput, 0, sizeof(paramPortDefinitionInput));
     77     SetTypeHeader(&paramPortDefinitionInput, sizeof(paramPortDefinitionInput));
     78     paramPortDefinitionInput.nPortIndex = INPORT_INDEX;
     79     paramPortDefinitionInput.eDir = OMX_DirInput;
     80     paramPortDefinitionInput.nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
     81     paramPortDefinitionInput.nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
     82     paramPortDefinitionInput.nBufferSize = INPORT_BUFFER_SIZE;
     83     paramPortDefinitionInput.bEnabled = OMX_TRUE;
     84     paramPortDefinitionInput.bPopulated = OMX_FALSE;
     85     paramPortDefinitionInput.eDomain = OMX_PortDomainVideo;
     86     paramPortDefinitionInput.format.video.cMIMEType = NULL; // to be overridden
     87     paramPortDefinitionInput.format.video.pNativeRender = NULL;
     88     paramPortDefinitionInput.format.video.nFrameWidth = 176;
     89     paramPortDefinitionInput.format.video.nFrameHeight = 144;
     90     paramPortDefinitionInput.format.video.nStride = 0;
     91     paramPortDefinitionInput.format.video.nSliceHeight = 0;
     92     paramPortDefinitionInput.format.video.nBitrate = 64000;
     93     paramPortDefinitionInput.format.video.xFramerate = 15 << 16;
     94     // TODO: check if we need to set bFlagErrorConcealment  to OMX_TRUE
     95     paramPortDefinitionInput.format.video.bFlagErrorConcealment = OMX_FALSE;
     96     paramPortDefinitionInput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; // to be overridden
     97     paramPortDefinitionInput.format.video.eColorFormat = OMX_COLOR_FormatUnused;
     98     paramPortDefinitionInput.format.video.pNativeWindow = NULL;
     99     paramPortDefinitionInput.bBuffersContiguous = OMX_FALSE;
    100     paramPortDefinitionInput.nBufferAlignment = 0;
    101 
    102     // Derived class must implement this interface and override any field if needed.
    103     // eCompressionFormat and and cMIMEType must be overridden
    104     InitInputPortFormatSpecific(&paramPortDefinitionInput);
    105 
    106     port->SetPortDefinition(&paramPortDefinitionInput, true);
    107 
    108     // OMX_VIDEO_PARAM_PORTFORMATTYPE
    109     OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
    110     memset(&paramPortFormat, 0, sizeof(paramPortFormat));
    111     SetTypeHeader(&paramPortFormat, sizeof(paramPortFormat));
    112     paramPortFormat.nPortIndex = INPORT_INDEX;
    113     paramPortFormat.nIndex = 0;
    114     paramPortFormat.eCompressionFormat = paramPortDefinitionInput.format.video.eCompressionFormat;
    115     paramPortFormat.eColorFormat = paramPortDefinitionInput.format.video.eColorFormat;
    116     paramPortFormat.xFramerate = paramPortDefinitionInput.format.video.xFramerate;
    117 
    118     port->SetPortVideoParam(&paramPortFormat, true);
    119 
    120     return OMX_ErrorNone;
    121 }
    122 
    123 
    124 OMX_ERRORTYPE OMXVideoDecoderBase::InitOutputPort(void) {
    125     this->ports[OUTPORT_INDEX] = new PortVideo;
    126     if (this->ports[OUTPORT_INDEX] == NULL) {
    127         return OMX_ErrorInsufficientResources;
    128     }
    129 
    130     PortVideo *port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
    131 
    132     // OMX_PARAM_PORTDEFINITIONTYPE
    133     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionOutput;
    134 
    135     memset(&paramPortDefinitionOutput, 0, sizeof(paramPortDefinitionOutput));
    136     SetTypeHeader(&paramPortDefinitionOutput, sizeof(paramPortDefinitionOutput));
    137 
    138     paramPortDefinitionOutput.nPortIndex = OUTPORT_INDEX;
    139     paramPortDefinitionOutput.eDir = OMX_DirOutput;
    140     paramPortDefinitionOutput.nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT;
    141     paramPortDefinitionOutput.nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT;
    142     paramPortDefinitionOutput.nBufferSize = sizeof(VideoRenderBuffer);
    143 
    144     paramPortDefinitionOutput.bEnabled = OMX_TRUE;
    145     paramPortDefinitionOutput.bPopulated = OMX_FALSE;
    146     paramPortDefinitionOutput.eDomain = OMX_PortDomainVideo;
    147     paramPortDefinitionOutput.format.video.cMIMEType = (OMX_STRING)VA_RAW_MIME_TYPE;
    148     paramPortDefinitionOutput.format.video.pNativeRender = NULL;
    149     paramPortDefinitionOutput.format.video.nFrameWidth = 176;
    150     paramPortDefinitionOutput.format.video.nFrameHeight = 144;
    151     paramPortDefinitionOutput.format.video.nStride = 176;
    152     paramPortDefinitionOutput.format.video.nSliceHeight = 144;
    153     paramPortDefinitionOutput.format.video.nBitrate = 64000;
    154     paramPortDefinitionOutput.format.video.xFramerate = 15 << 16;
    155     paramPortDefinitionOutput.format.video.bFlagErrorConcealment = OMX_FALSE;
    156     paramPortDefinitionOutput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
    157     paramPortDefinitionOutput.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
    158     paramPortDefinitionOutput.format.video.pNativeWindow = NULL;
    159     paramPortDefinitionOutput.bBuffersContiguous = OMX_FALSE;
    160     paramPortDefinitionOutput.nBufferAlignment = 0;
    161 
    162     // no format specific to initialize output port
    163     InitOutputPortFormatSpecific(&paramPortDefinitionOutput);
    164 
    165     port->SetPortDefinition(&paramPortDefinitionOutput, true);
    166 
    167     // OMX_VIDEO_PARAM_PORTFORMATTYPE
    168     OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
    169     SetTypeHeader(&paramPortFormat, sizeof(paramPortFormat));
    170     paramPortFormat.nPortIndex = OUTPORT_INDEX;
    171     paramPortFormat.nIndex = 0;
    172     paramPortFormat.eCompressionFormat = paramPortDefinitionOutput.format.video.eCompressionFormat;
    173     paramPortFormat.eColorFormat = paramPortDefinitionOutput.format.video.eColorFormat;
    174     paramPortFormat.xFramerate = paramPortDefinitionOutput.format.video.xFramerate;
    175 
    176     port->SetPortVideoParam(&paramPortFormat, true);
    177 
    178     return OMX_ErrorNone;
    179 }
    180 
    181 OMX_ERRORTYPE OMXVideoDecoderBase::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *) {
    182     // no format specific to initialize output port
    183     return OMX_ErrorNone;
    184 }
    185 
    186 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorInit(void) {
    187     OMX_ERRORTYPE ret;
    188     ret = OMXComponentCodecBase::ProcessorInit();
    189     CHECK_RETURN_VALUE("OMXComponentCodecBase::ProcessorInit");
    190 
    191     if (mVideoDecoder == NULL) {
    192         LOGE("ProcessorInit: Video decoder is not created.");
    193         return OMX_ErrorDynamicResourcesUnavailable;
    194     }
    195 
    196     VideoConfigBuffer configBuffer;
    197     ret = PrepareConfigBuffer(&configBuffer);
    198     CHECK_RETURN_VALUE("PrepareConfigBuffer");
    199 
    200     //pthread_mutex_lock(&mSerializationLock);
    201     Decode_Status status = mVideoDecoder->start(&configBuffer);
    202     //pthread_mutex_unlock(&mSerializationLock);
    203 
    204     if (status != DECODE_SUCCESS) {
    205         return TranslateDecodeStatus(status);
    206     }
    207 
    208     return OMX_ErrorNone;
    209 }
    210 
    211 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorReset(void) {
    212     OMX_ERRORTYPE ret;
    213     VideoConfigBuffer configBuffer;
    214     // reset the configbuffer and set it to mix
    215     ret = PrepareConfigBuffer(&configBuffer);
    216     CHECK_RETURN_VALUE("PrepareConfigBuffer");
    217     mVideoDecoder->reset(&configBuffer);
    218     return OMX_ErrorNone;
    219 }
    220 
    221 
    222 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorDeinit(void) {
    223     if (mWorkingMode != GRAPHICBUFFER_MODE) {
    224         if (mVideoDecoder == NULL) {
    225             LOGE("ProcessorDeinit: Video decoder is not created.");
    226             return OMX_ErrorDynamicResourcesUnavailable;
    227         }
    228         mVideoDecoder->stop();
    229     }
    230     mOMXBufferHeaderTypePtrNum = 0;
    231     memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
    232     mRotationDegrees = 0;
    233 #ifdef TARGET_HAS_ISV
    234     mVppBufferNum = 0;
    235 #endif
    236     return OMXComponentCodecBase::ProcessorDeinit();
    237 }
    238 
    239 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorStart(void) {
    240     return OMXComponentCodecBase::ProcessorStart();
    241 }
    242 
    243 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorStop(void) {
    244     // There is no need to return all retained buffers as we don't accumulate buffer
    245     //this->ports[INPORT_INDEX]->ReturnAllRetainedBuffers();
    246 
    247     // TODO: this is new code
    248     ProcessorFlush(OMX_ALL);
    249     if (mWorkingMode == GRAPHICBUFFER_MODE) {
    250         // for GRAPHICBUFFER_MODE mode, va_destroySurface need to lock the graphicbuffer,
    251         // Make sure va_destroySurface is called(ExecutingToIdle) before graphicbuffer is freed(IdleToLoaded).
    252         if (mVideoDecoder == NULL) {
    253             LOGE("ProcessorStop: Video decoder is not created.");
    254             return OMX_ErrorDynamicResourcesUnavailable;
    255         }
    256         mVideoDecoder->stop();
    257     }
    258     return OMXComponentCodecBase::ProcessorStop();
    259 }
    260 
    261 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPause(void) {
    262     return OMXComponentCodecBase::ProcessorPause();
    263 }
    264 
    265 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorResume(void) {
    266     return OMXComponentCodecBase::ProcessorResume();
    267 }
    268 
    269 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorFlush(OMX_U32 portIndex) {
    270     LOGI("Flushing port# %u.", portIndex);
    271     if (mVideoDecoder == NULL) {
    272         LOGE("ProcessorFlush: Video decoder is not created.");
    273         return OMX_ErrorDynamicResourcesUnavailable;
    274     }
    275 
    276     // Portbase has returned all retained buffers.
    277     if (portIndex == INPORT_INDEX || portIndex == OMX_ALL) {
    278         //pthread_mutex_lock(&mSerializationLock);
    279         LOGW("Flushing video pipeline.");
    280         mVideoDecoder->flush();
    281         //pthread_mutex_unlock(&mSerializationLock);
    282     }
    283     // TODO: do we need to flush output port?
    284     return OMX_ErrorNone;
    285 }
    286 
    287 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPreFreeBuffer(OMX_U32 nPortIndex, OMX_BUFFERHEADERTYPE * pBuffer) {
    288     if (mWorkingMode == GRAPHICBUFFER_MODE)
    289         return OMX_ErrorNone;
    290 
    291     if (nPortIndex == OUTPORT_INDEX && pBuffer->pPlatformPrivate) {
    292         VideoRenderBuffer *p = (VideoRenderBuffer *)pBuffer->pPlatformPrivate;
    293         p->renderDone = true;
    294         pBuffer->pPlatformPrivate = NULL;
    295     }
    296     return OMX_ErrorNone;
    297 }
    298 
    299  OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer) {
    300     if (mWorkingMode == GRAPHICBUFFER_MODE && buffer->nOutputPortIndex == OUTPORT_INDEX){
    301         Decode_Status status;
    302         if(mVideoDecoder == NULL){
    303             LOGW("ProcessorPreFillBuffer: Video decoder is not created");
    304             return OMX_ErrorDynamicResourcesUnavailable;
    305         }
    306 
    307         if (mAPMode == METADATA_MODE) {
    308             bool found = false;
    309             if (mOMXBufferHeaderTypePtrNum < mMetaDataBuffersNum) {
    310                 for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
    311                     if (mOMXBufferHeaderTypePtrArray[i] == buffer) {
    312                         found = true;
    313                         break;
    314                     }
    315                 }
    316                 if (!found) {
    317                     mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum] = buffer;
    318                     mOMXBufferHeaderTypePtrNum++;
    319                 }
    320             }
    321 
    322             VideoDecoderOutputMetaData *metadata = (VideoDecoderOutputMetaData *)(buffer->pBuffer);
    323             status = mVideoDecoder->signalRenderDone((void *)(metadata->pHandle), !found);
    324         } else {
    325             status = mVideoDecoder->signalRenderDone(buffer->pBuffer);
    326         }
    327 
    328         if (status != DECODE_SUCCESS) {
    329             LOGW("ProcessorPreFillBuffer:: signalRenderDone return error");
    330             return TranslateDecodeStatus(status);
    331         }
    332     } else if (buffer->pPlatformPrivate && buffer->nOutputPortIndex == OUTPORT_INDEX){
    333         VideoRenderBuffer *p = (VideoRenderBuffer *)buffer->pPlatformPrivate;
    334         p->renderDone = true;
    335         buffer->pPlatformPrivate = NULL;
    336     }
    337     return OMX_ErrorNone;
    338 }
    339 
    340 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorProcess(
    341     OMX_BUFFERHEADERTYPE ***pBuffers,
    342     buffer_retain_t *retains,
    343     OMX_U32) {
    344 
    345     OMX_ERRORTYPE ret;
    346     Decode_Status status;
    347     OMX_BOOL isResolutionChange = OMX_FALSE;
    348     // fill render buffer without draining decoder output queue
    349     ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], 0, &isResolutionChange);
    350     if (ret == OMX_ErrorNone) {
    351         retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    352         if (isResolutionChange) {
    353             HandleFormatChange();
    354         }
    355 
    356         if (mFlushMode) {
    357             LOGI("in mFlushMode, do HandleFormatChange.");
    358             HandleFormatChange();
    359         } else {
    360             // Actually, if mAPMode is set, mWorkingMode should be GRAPHICBUFFER_MODE.
    361             if (((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) && mFormatChanged) {
    362                 if (((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS) || (mVideoDecoder->getOutputQueueLength() == 0)) {
    363                     // Format changed, set mFlushMode, clear eos
    364                     mFlushMode = true;
    365                     mFormatChanged = false;
    366                     (*pBuffers[OUTPORT_INDEX])->nFlags &= ~OMX_BUFFERFLAG_EOS;
    367                 }
    368             }
    369         }
    370 
    371         // TODO: continue decoding
    372         return ret;
    373     } else if (ret != OMX_ErrorNotReady) {
    374         return ret;
    375     }
    376 
    377     VideoDecodeBuffer decodeBuffer;
    378     // PrepareDecodeBuffer will set retain to either BUFFER_RETAIN_GETAGAIN or BUFFER_RETAIN_NOT_RETAIN
    379     ret = PrepareDecodeBuffer(*pBuffers[INPORT_INDEX], &retains[INPORT_INDEX], &decodeBuffer);
    380     if (ret == OMX_ErrorNotReady) {
    381         retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    382         return OMX_ErrorNone;
    383     } else if (ret != OMX_ErrorNone) {
    384         return ret;
    385     }
    386 
    387     if (decodeBuffer.size != 0) {
    388         //pthread_mutex_lock(&mSerializationLock);
    389         status = mVideoDecoder->decode(&decodeBuffer);
    390         //pthread_mutex_unlock(&mSerializationLock);
    391 
    392         if (status == DECODE_FORMAT_CHANGE) {
    393             if ((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) {
    394                 mFormatChanged = true;
    395                 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    396             } else {
    397                 ret = HandleFormatChange();
    398                 CHECK_RETURN_VALUE("HandleFormatChange");
    399                 ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0;
    400                 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    401                 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    402                 // real dynamic resolution change will be handled later
    403                 // Here is just a temporary workaround
    404                 // don't use the output buffer if format is changed.
    405                 return OMX_ErrorNone;
    406             }
    407         } else if (status == DECODE_NO_CONFIG) {
    408             LOGW("Decoder returns DECODE_NO_CONFIG.");
    409             retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    410             return OMX_ErrorNone;
    411         } else if (status == DECODE_NO_REFERENCE) {
    412             LOGW("Decoder returns DECODE_NO_REFERENCE.");
    413             //retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    414             //return OMX_ErrorNone;
    415         } else if (status == DECODE_MULTIPLE_FRAME){
    416             if (decodeBuffer.ext != NULL && decodeBuffer.ext->extType == PACKED_FRAME_TYPE && decodeBuffer.ext->extData != NULL) {
    417                 PackedFrameData* nextFrame = (PackedFrameData*)decodeBuffer.ext->extData;
    418                 (*pBuffers[INPORT_INDEX])->nOffset += nextFrame->offSet;
    419                 (*pBuffers[INPORT_INDEX])->nTimeStamp = nextFrame->timestamp;
    420                 (*pBuffers[INPORT_INDEX])->nFilledLen -= nextFrame->offSet;
    421                 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    422                 LOGW("Find multiple frames in a buffer, next frame offset = %d, timestamp = %lld", (*pBuffers[INPORT_INDEX])->nOffset, (*pBuffers[INPORT_INDEX])->nTimeStamp);
    423             }
    424         }
    425         else if (status != DECODE_SUCCESS && status != DECODE_FRAME_DROPPED) {
    426             if (checkFatalDecoderError(status)) {
    427                 return TranslateDecodeStatus(status);
    428             } else {
    429                 // For decoder errors that could be omitted,  not throw error and continue to decode.
    430                 TranslateDecodeStatus(status);
    431 
    432                 ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0;
    433 
    434                 // Do not return, and try to drain the output queue
    435                 // retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    436                 // return OMX_ErrorNone;
    437             }
    438         }
    439     }
    440     // drain the decoder output queue when in EOS state and fill the render buffer
    441     ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX],
    442             ((*pBuffers[INPORT_INDEX]))->nFlags,&isResolutionChange);
    443 
    444     if (isResolutionChange) {
    445         HandleFormatChange();
    446     }
    447 
    448     if (mFlushMode) {
    449         LOGI("in mFlushMode, do HandleFormatChange.");
    450         HandleFormatChange();
    451     } else {
    452         if (((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) && mFormatChanged) {
    453             if (((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS) || (mVideoDecoder->getOutputQueueLength() == 0)) {
    454                 // Format changed, set mFlushMode, clear eos.
    455                 mFlushMode = true;
    456                 mFormatChanged = false;
    457                 (*pBuffers[OUTPORT_INDEX])->nFlags &= ~OMX_BUFFERFLAG_EOS;
    458             }
    459         }
    460     }
    461 
    462     bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
    463     bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
    464     // if output port is not eos, retain the input buffer until all the output buffers are drained.
    465     if (inputEoS && !outputEoS) {
    466         retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    467         // the input buffer is retained for draining purpose. Set nFilledLen to 0 so buffer will not be decoded again.
    468         (*pBuffers[INPORT_INDEX])->nFilledLen = 0;
    469     }
    470 
    471     if (ret == OMX_ErrorNotReady) {
    472         retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    473         ret = OMX_ErrorNone;
    474     }
    475 
    476     return ret;
    477 }
    478 
    479 bool OMXVideoDecoderBase::IsAllBufferAvailable(void) {
    480     bool b = ComponentBase::IsAllBufferAvailable();
    481     if (b == false) {
    482         return false;
    483     }
    484 
    485     PortVideo *port = NULL;
    486     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
    487     const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition();
    488      // if output port is disabled, retain the input buffer
    489     if (!port_def->bEnabled) {
    490         return false;
    491     }
    492 
    493     if (mVideoDecoder) {
    494         return mVideoDecoder->checkBufferAvail();
    495     }
    496     return false;
    497 }
    498 
    499 OMX_ERRORTYPE OMXVideoDecoderBase::PrepareConfigBuffer(VideoConfigBuffer *p) {
    500     // default config buffer preparation
    501     memset(p, 0, sizeof(VideoConfigBuffer));
    502 
    503     const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput = this->ports[INPORT_INDEX]->GetPortDefinition();
    504     if (paramPortDefinitionInput == NULL) {
    505         return OMX_ErrorBadParameter;
    506     }
    507 
    508     if (mWorkingMode == GRAPHICBUFFER_MODE) {
    509         if (mAPMode == METADATA_MODE) {
    510             const OMX_PARAM_PORTDEFINITIONTYPE *def_output = this->ports[OUTPORT_INDEX]->GetPortDefinition();
    511             if (def_output == NULL) {
    512                 return OMX_ErrorBadParameter;
    513             }
    514 
    515             mMetaDataBuffersNum = def_output->nBufferCountActual;
    516             mOMXBufferHeaderTypePtrNum = 0;
    517 
    518             mGraphicBufferParam.graphicBufferColorFormat = def_output->format.video.eColorFormat;
    519             mGraphicBufferParam.graphicBufferHStride = getStride(def_output->format.video.nFrameWidth);
    520             mGraphicBufferParam.graphicBufferVStride = (def_output->format.video.nFrameHeight + 0x1f) & ~0x1f;
    521             mGraphicBufferParam.graphicBufferWidth = def_output->format.video.nFrameWidth;
    522             mGraphicBufferParam.graphicBufferHeight = def_output->format.video.nFrameHeight;
    523 
    524             p->surfaceNumber = mMetaDataBuffersNum;
    525             for (int i = 0; i < MAX_GRAPHIC_BUFFER_NUM; i++) {
    526                 p->graphicBufferHandler[i] = NULL;
    527             }
    528             p->flag |= WANT_STORE_META_DATA;
    529         } else {
    530             p->surfaceNumber = mOMXBufferHeaderTypePtrNum;
    531             for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++){
    532                 OMX_BUFFERHEADERTYPE *buffer_hdr = mOMXBufferHeaderTypePtrArray[i];
    533                 p->graphicBufferHandler[i] = buffer_hdr->pBuffer;
    534                 LOGV("PrepareConfigBuffer bufferid = %p, handle = %p", buffer_hdr, buffer_hdr->pBuffer);
    535             }
    536         }
    537         p->flag |= USE_NATIVE_GRAPHIC_BUFFER;
    538         p->graphicBufferHStride = mGraphicBufferParam.graphicBufferHStride;
    539         p->graphicBufferVStride = mGraphicBufferParam.graphicBufferVStride;
    540         p->graphicBufferWidth = mGraphicBufferParam.graphicBufferWidth;
    541         p->graphicBufferHeight = mGraphicBufferParam.graphicBufferHeight;
    542         p->graphicBufferColorFormat = mGraphicBufferParam.graphicBufferColorFormat;
    543         if (p->graphicBufferColorFormat == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled
    544 #ifdef USE_GEN_HW
    545             || p->graphicBufferColorFormat == HAL_PIXEL_FORMAT_NV12_X_TILED_INTEL
    546 #endif
    547         )
    548             p->flag |= USE_TILING_MEMORY;
    549 
    550         if (mEnableAdaptivePlayback)
    551             p->flag |= WANT_ADAPTIVE_PLAYBACK;
    552 
    553         PortVideo *port = NULL;
    554         port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
    555         OMX_PARAM_PORTDEFINITIONTYPE port_def;
    556         memcpy(&port_def, port->GetPortDefinition(), sizeof(port_def));
    557 
    558         if (port_def.format.video.pNativeWindow != NULL) {
    559             p->nativeWindow = port_def.format.video.pNativeWindow;
    560             LOGD("NativeWindow = %p", p->nativeWindow);
    561         }
    562 
    563     }
    564 
    565     p->rotationDegrees = mRotationDegrees;
    566 #ifdef TARGET_HAS_ISV
    567     p->vppBufferNum = mVppBufferNum;
    568 #endif
    569     p->width = paramPortDefinitionInput->format.video.nFrameWidth;
    570     p->height = paramPortDefinitionInput->format.video.nFrameHeight;
    571 
    572     return OMX_ErrorNone;
    573 }
    574 
    575 OMX_ERRORTYPE OMXVideoDecoderBase::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
    576     // default decode buffer preparation
    577     memset(p, 0, sizeof(VideoDecodeBuffer));
    578     if (buffer->nFilledLen == 0) {
    579         LOGW("Len of filled data to decode is 0.");
    580         return OMX_ErrorNone; //OMX_ErrorBadParameter;
    581     }
    582 
    583     if (buffer->pBuffer == NULL) {
    584         LOGE("Buffer to decode is empty.");
    585         return OMX_ErrorBadParameter;
    586     }
    587 
    588     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
    589         LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
    590     }
    591 
    592     if (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
    593         // TODO: Handle OMX_BUFFERFLAG_DECODEONLY : drop the decoded frame without rendering it.
    594         LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
    595     }
    596 
    597     p->data = buffer->pBuffer + buffer->nOffset;
    598     p->size = buffer->nFilledLen;
    599     p->timeStamp = buffer->nTimeStamp;
    600     if (buffer->nFlags & (OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS)) {
    601         // TODO: OMX_BUFFERFLAG_ENDOFFRAME can be used to indicate end of a NAL unit.
    602         // setting this flag may cause corruption if buffer does not contain end-of-frame data.
    603         p->flag = HAS_COMPLETE_FRAME;
    604     }
    605 
    606     if (buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) {
    607         p->flag |= IS_SYNC_FRAME;
    608     }
    609 
    610     if (buffer->pInputPortPrivate) {
    611         uint32_t degree = 0;
    612         memcpy ((void *) &degree, buffer->pInputPortPrivate, sizeof(uint32_t));
    613         p->rotationDegrees = degree;
    614         LOGV("rotationDegrees = %d", p->rotationDegrees);
    615     } else {
    616         p->rotationDegrees = mRotationDegrees;
    617     }
    618 
    619     *retain= BUFFER_RETAIN_NOT_RETAIN;
    620     return OMX_ErrorNone;
    621 }
    622 
    623 OMX_ERRORTYPE OMXVideoDecoderBase::PrepareDecodeNativeHandleBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
    624     // default decode buffer preparation
    625 
    626     memset(p, 0, sizeof(VideoDecodeBuffer));
    627     if (buffer->nFilledLen == 0) {
    628         LOGW("Len of filled data to decode is 0.");
    629         return OMX_ErrorNone; //OMX_ErrorBadParameter;
    630     }
    631 
    632     if (buffer->pBuffer == NULL) {
    633         LOGE("Buffer to decode is empty.");
    634         return OMX_ErrorBadParameter;
    635     }
    636 
    637     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
    638         LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
    639     }
    640 
    641     if (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
    642         // TODO: Handle OMX_BUFFERFLAG_DECODEONLY : drop the decoded frame without rendering it.
    643         LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
    644     }
    645     //Get data pointer from native_handle
    646     native_handle_t *native_handle = (native_handle_t *)buffer->pBuffer;
    647     ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *) native_handle->data[1];
    648     p->data =  dataBuffer->data + buffer->nOffset;
    649 
    650 
    651 
    652     p->size = buffer->nFilledLen;
    653     p->timeStamp = buffer->nTimeStamp;
    654     if (buffer->nFlags & (OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS)) {
    655         // TODO: OMX_BUFFERFLAG_ENDOFFRAME can be used to indicate end of a NAL unit.
    656         // setting this flag may cause corruption if buffer does not contain end-of-frame data.
    657         p->flag = HAS_COMPLETE_FRAME;
    658     }
    659 
    660     if (buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) {
    661         p->flag |= IS_SYNC_FRAME;
    662     }
    663 
    664     if (buffer->pInputPortPrivate) {
    665         uint32_t degree = 0;
    666         memcpy ((void *) &degree, buffer->pInputPortPrivate, sizeof(uint32_t));
    667         p->rotationDegrees = degree;
    668         LOGV("rotationDegrees = %d", p->rotationDegrees);
    669     } else {
    670         p->rotationDegrees = mRotationDegrees;
    671     }
    672 
    673     *retain= BUFFER_RETAIN_NOT_RETAIN;
    674     return OMX_ErrorNone;
    675 }
    676 
    677 
    678 OMX_ERRORTYPE OMXVideoDecoderBase::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer, buffer_retain_t *retain, OMX_U32 inportBufferFlags, OMX_BOOL *isResolutionChange) {
    679     OMX_BUFFERHEADERTYPE *buffer = *pBuffer;
    680     OMX_BUFFERHEADERTYPE *buffer_orign = buffer;
    681     VideoErrorBuffer *ErrBufPtr = NULL;
    682 
    683     if (mWorkingMode != GRAPHICBUFFER_MODE && buffer->pPlatformPrivate) {
    684         VideoRenderBuffer *p = (VideoRenderBuffer *)buffer->pPlatformPrivate;
    685         p->renderDone = true;
    686         buffer->pPlatformPrivate = NULL;
    687     }
    688 
    689     if (mWorkingMode == GRAPHICBUFFER_MODE && mErrorReportEnabled) {
    690         if (buffer->pOutputPortPrivate == NULL)
    691             LOGE("The App doesn't provide the output buffer for error reporting");
    692         else
    693             ErrBufPtr = (VideoErrorBuffer *)buffer->pOutputPortPrivate;
    694     }
    695 
    696     bool draining = (inportBufferFlags & OMX_BUFFERFLAG_EOS);
    697     //pthread_mutex_lock(&mSerializationLock);
    698     const VideoRenderBuffer *renderBuffer = NULL;
    699     //pthread_mutex_unlock(&mSerializationLock);
    700 
    701     // in mFlushMode, provide empty buffer.
    702     if (mFlushMode) {
    703         buffer->nFilledLen = 0;
    704         return OMX_ErrorNone;
    705     }
    706 
    707     if (((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) && mFormatChanged) {
    708          renderBuffer = mVideoDecoder->getOutput(true, ErrBufPtr);
    709     } else {
    710          renderBuffer = mVideoDecoder->getOutput(draining, ErrBufPtr);
    711     }
    712     if (renderBuffer == NULL) {
    713         buffer->nFilledLen = 0;
    714         if (draining) {
    715             LOGI("output EOS received");
    716             buffer->nFlags = OMX_BUFFERFLAG_EOS;
    717             return OMX_ErrorNone;
    718         }
    719         return OMX_ErrorNotReady;
    720     }
    721 
    722     if (mWorkingMode == GRAPHICBUFFER_MODE) {
    723         buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[renderBuffer->graphicBufferIndex];
    724      }
    725 
    726     buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
    727 #ifdef DEINTERLACE_EXT
    728     if (renderBuffer->scanFormat & (VA_TOP_FIELD | VA_BOTTOM_FIELD))
    729         buffer->nFlags |= OMX_BUFFERFLAG_TFF;
    730 #endif
    731     buffer->nTimeStamp = renderBuffer->timeStamp;
    732 
    733     if (renderBuffer->flag & IS_EOS) {
    734         buffer->nFlags |= OMX_BUFFERFLAG_EOS;
    735     }
    736     *isResolutionChange = (renderBuffer->flag & IS_RESOLUTION_CHANGE)? OMX_TRUE: OMX_FALSE;
    737 
    738     if (mWorkingMode == GRAPHICBUFFER_MODE) {
    739         if (buffer_orign != buffer) {
    740             VideoErrorBuffer *ErrBufOutPtr = NULL;
    741             ErrBufOutPtr = (VideoErrorBuffer *)buffer->pOutputPortPrivate;
    742             if (ErrBufPtr && ErrBufOutPtr) {
    743                 memcpy(ErrBufOutPtr, ErrBufPtr, sizeof(VideoErrorBuffer));
    744                 memset(ErrBufPtr, 0, sizeof(VideoErrorBuffer));
    745             }
    746             *retain = BUFFER_RETAIN_OVERRIDDEN;
    747         }
    748          buffer->nFilledLen = sizeof(OMX_U8*);
    749     } else {
    750         uint32_t size = 0;
    751         Decode_Status status = mVideoDecoder->getRawDataFromSurface(const_cast<VideoRenderBuffer *>(renderBuffer), buffer->pBuffer + buffer->nOffset, &size, false);
    752         if (status != DECODE_SUCCESS) {
    753             return TranslateDecodeStatus(status);
    754         }
    755         buffer->nFilledLen = size;
    756         buffer->pPlatformPrivate = (void *)renderBuffer;
    757     }
    758 
    759     return OMX_ErrorNone;
    760 }
    761 
    762 OMX_ERRORTYPE OMXVideoDecoderBase::HandleFormatChange(void) {
    763     LOGW("Video format is changed.");
    764     //pthread_mutex_lock(&mSerializationLock);
    765     const VideoFormatInfo *formatInfo = mVideoDecoder->getFormatInfo();
    766     //pthread_mutex_unlock(&mSerializationLock);
    767 
    768     // Sync port definition as it may change.
    769     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput;
    770 
    771     memcpy(&paramPortDefinitionInput,
    772         this->ports[INPORT_INDEX]->GetPortDefinition(),
    773         sizeof(paramPortDefinitionInput));
    774 
    775     memcpy(&paramPortDefinitionOutput,
    776         this->ports[OUTPORT_INDEX]->GetPortDefinition(),
    777         sizeof(paramPortDefinitionOutput));
    778 
    779     uint32_t width = formatInfo->width;
    780     uint32_t height = formatInfo->height;
    781     uint32_t stride = formatInfo->width;
    782     uint32_t sliceHeight = formatInfo->height;
    783 
    784     uint32_t widthCropped = formatInfo->width - formatInfo->cropLeft - formatInfo->cropRight;
    785     uint32_t heightCropped = formatInfo->height - formatInfo->cropTop - formatInfo->cropBottom;
    786     if (strcasecmp(formatInfo->mimeType,"video/avc") == 0 ||
    787         strcasecmp(formatInfo->mimeType,"video/avc-secure") == 0 ||
    788         strcasecmp(formatInfo->mimeType,"video/h264") == 0) {
    789         heightCropped = formatInfo->height;
    790         widthCropped = formatInfo->width;
    791     }
    792     uint32_t strideCropped = widthCropped;
    793     uint32_t sliceHeightCropped = heightCropped;
    794     int force_realloc = 0;
    795     bool isVP8 = false;
    796 
    797     if (mAPMode == METADATA_MODE && mWorkingMode == GRAPHICBUFFER_MODE) {
    798 #ifdef TARGET_HAS_ISV
    799         if (paramPortDefinitionOutput.nBufferCountActual - mVppBufferNum < formatInfo->actualBufferNeeded) {
    800 #else
    801         if (paramPortDefinitionOutput.nBufferCountActual < formatInfo->actualBufferNeeded) {
    802 #endif
    803             paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount = formatInfo->actualBufferNeeded;
    804             paramPortDefinitionOutput.nBufferCountMin = formatInfo->actualBufferNeeded - 4;
    805         }
    806         // input port
    807         paramPortDefinitionInput.format.video.nFrameWidth = width;
    808         paramPortDefinitionInput.format.video.nFrameHeight = height;
    809         paramPortDefinitionInput.format.video.nStride = stride;
    810         paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
    811         // output port
    812         paramPortDefinitionOutput.format.video.nFrameWidth = width;
    813         paramPortDefinitionOutput.format.video.nFrameHeight = height;
    814         paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(paramPortDefinitionOutput.format.video.nFrameWidth);
    815         paramPortDefinitionOutput.format.video.nStride = stride;
    816         paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
    817 
    818         paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
    819         mOMXBufferHeaderTypePtrNum = 0;
    820         memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
    821         mMetaDataBuffersNum = 0;
    822 
    823         this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
    824         this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
    825 
    826         ProcessorFlush(INPORT_INDEX);
    827 
    828         mVideoDecoder->freeSurfaceBuffers();
    829 
    830         this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
    831 
    832         mFlushMode = false;
    833         return OMX_ErrorNone;
    834     }
    835 
    836 #ifdef TARGET_HAS_ISV
    837     LOGI("============== mVppBufferNum = %d\n", mVppBufferNum);
    838     if (paramPortDefinitionOutput.nBufferCountActual - mVppBufferNum < formatInfo->actualBufferNeeded) {
    839 #else
    840     if (paramPortDefinitionOutput.nBufferCountActual < formatInfo->actualBufferNeeded) {
    841 #endif
    842         if (mWorkingMode == GRAPHICBUFFER_MODE) {
    843             LOGV("output port buffer number is not enough: %d to %d",
    844                  paramPortDefinitionOutput.nBufferCountActual,
    845                  formatInfo->actualBufferNeeded);
    846             paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount = formatInfo->actualBufferNeeded;
    847             paramPortDefinitionOutput.nBufferCountMin = mNativeBufferCount;
    848             force_realloc = 1;
    849         }
    850     }
    851 
    852     LOGV("Original size = %u x %u, new size = %d x %d, cropped size = %d x %d",
    853         paramPortDefinitionInput.format.video.nFrameWidth,
    854         paramPortDefinitionInput.format.video.nFrameHeight,
    855         width, height, widthCropped, heightCropped);
    856 
    857     if (paramPortDefinitionInput.format.video.eCompressionFormat == OMX_VIDEO_CodingVP8) {
    858         isVP8 = true;
    859     }
    860 
    861     if (!force_realloc &&
    862         widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth &&
    863         heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) {
    864         if (mWorkingMode == RAWDATA_MODE) {
    865             LOGW("Change of portsetting is not reported as size is not changed.");
    866             return OMX_ErrorNone;
    867         }
    868     }
    869 
    870     paramPortDefinitionInput.format.video.nFrameWidth = width;
    871     paramPortDefinitionInput.format.video.nFrameHeight = height;
    872     paramPortDefinitionInput.format.video.nStride = stride;
    873     paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
    874 
    875     if (mWorkingMode == RAWDATA_MODE) {
    876         paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped;
    877         paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped;
    878         paramPortDefinitionOutput.format.video.nStride = strideCropped;
    879         paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped;
    880     } else if (mWorkingMode == GRAPHICBUFFER_MODE) {
    881         // when the width and height ES parse are not larger than allocated graphic buffer in outport,
    882         // there is no need to reallocate graphic buffer,just report the crop info to omx client
    883         if (!force_realloc && width <= formatInfo->surfaceWidth && height <= formatInfo->surfaceHeight) {
    884             this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
    885             this->ports[OUTPORT_INDEX]->ReportOutputCrop();
    886             return OMX_ErrorNone;
    887         }
    888 
    889         if (isVP8 || width > formatInfo->surfaceWidth ||  height > formatInfo->surfaceHeight) {
    890             // update the real decoded resolution to outport instead of display resolution for graphic buffer reallocation
    891             // when the width and height parsed from ES are larger than allocated graphic buffer in outport,
    892             paramPortDefinitionOutput.format.video.nFrameWidth = width;
    893             paramPortDefinitionOutput.format.video.nFrameHeight = height;
    894             paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(
    895                     paramPortDefinitionOutput.format.video.nFrameWidth);
    896             paramPortDefinitionOutput.format.video.nStride = stride;
    897             paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
    898        }
    899     }
    900 
    901     paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
    902     mOMXBufferHeaderTypePtrNum = 0;
    903     memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
    904 
    905     this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
    906     this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
    907 
    908     if (mWorkingMode == GRAPHICBUFFER_MODE) {
    909         // Make sure va_destroySurface is called before graphicbuffer is freed in case of port setting changed
    910         mVideoDecoder->freeSurfaceBuffers();
    911 
    912         // Also make sure all the reference frames are flushed
    913         ProcessorFlush(INPORT_INDEX);
    914     }
    915     this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
    916     return OMX_ErrorNone;
    917 }
    918 
    919 OMX_ERRORTYPE OMXVideoDecoderBase::TranslateDecodeStatus(Decode_Status status) {
    920     switch (status) {
    921         case DECODE_NEED_RESTART:
    922             LOGE("Decoder returned DECODE_NEED_RESTART");
    923             return (OMX_ERRORTYPE)OMX_ErrorIntelVideoNotPermitted;
    924         case DECODE_NO_CONFIG:
    925             LOGE("Decoder returned DECODE_NO_CONFIG");
    926             return (OMX_ERRORTYPE)OMX_ErrorIntelMissingConfig;
    927         case DECODE_NO_SURFACE:
    928             LOGE("Decoder returned DECODE_NO_SURFACE");
    929             return OMX_ErrorDynamicResourcesUnavailable;
    930         case DECODE_NO_REFERENCE:
    931             LOGE("Decoder returned DECODE_NO_REFERENCE");
    932             return OMX_ErrorDynamicResourcesUnavailable; // TO DO
    933         case DECODE_NO_PARSER:
    934             LOGE("Decoder returned DECODE_NO_PARSER");
    935             return OMX_ErrorDynamicResourcesUnavailable;
    936         case DECODE_INVALID_DATA:
    937             LOGE("Decoder returned DECODE_INVALID_DATA");
    938             return OMX_ErrorBadParameter;
    939         case DECODE_DRIVER_FAIL:
    940             LOGE("Decoder returned DECODE_DRIVER_FAIL");
    941             return OMX_ErrorHardware;
    942         case DECODE_PARSER_FAIL:
    943             LOGE("Decoder returned DECODE_PARSER_FAIL");
    944             return (OMX_ERRORTYPE)OMX_ErrorIntelProcessStream; // OMX_ErrorStreamCorrupt
    945         case DECODE_MEMORY_FAIL:
    946             LOGE("Decoder returned DECODE_MEMORY_FAIL");
    947             return OMX_ErrorInsufficientResources;
    948         case DECODE_FAIL:
    949             LOGE("Decoder returned DECODE_FAIL");
    950             return OMX_ErrorUndefined;
    951         case DECODE_SUCCESS:
    952             return OMX_ErrorNone;
    953         case DECODE_FORMAT_CHANGE:
    954             LOGW("Decoder returned DECODE_FORMAT_CHANGE");
    955             return OMX_ErrorNone;
    956         case DECODE_FRAME_DROPPED:
    957             LOGI("Decoder returned DECODE_FRAME_DROPPED");
    958             return OMX_ErrorNone;
    959         default:
    960             LOGW("Decoder returned unknown error");
    961             return OMX_ErrorUndefined;
    962     }
    963 }
    964 
    965 OMX_ERRORTYPE OMXVideoDecoderBase::BuildHandlerList(void) {
    966     OMXComponentCodecBase::BuildHandlerList();
    967     AddHandler(OMX_IndexParamVideoPortFormat, GetParamVideoPortFormat, SetParamVideoPortFormat);
    968     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtGetNativeBufferUsage), GetNativeBufferUsage, SetNativeBufferUsage);
    969     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtUseNativeBuffer), GetNativeBuffer, SetNativeBuffer);
    970     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableNativeBuffer), GetNativeBufferMode, SetNativeBufferMode);
    971     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtRotationDegrees), GetDecoderRotation, SetDecoderRotation);
    972 #ifdef TARGET_HAS_ISV
    973     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtVppBufferNum), GetDecoderVppBufferNum, SetDecoderVppBufferNum);
    974 #endif
    975     AddHandler(OMX_IndexConfigCommonOutputCrop, GetDecoderOutputCrop, SetDecoderOutputCrop);
    976 #ifdef USE_META_DATA
    977     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexStoreMetaDataInBuffers), GetStoreMetaDataMode, SetStoreMetaDataMode);
    978 #endif
    979     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableErrorReport), GetErrorReportMode, SetErrorReportMode);
    980     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexConfigPriority), GetCodecPriority, SetCodecPriority);
    981     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexConfigOperatingRate), GetDecoderOperatingRate, SetDecoderOperatingRate);
    982 
    983     return OMX_ErrorNone;
    984 }
    985 
    986 OMX_ERRORTYPE OMXVideoDecoderBase::GetParamVideoPortFormat(OMX_PTR pStructure) {
    987     OMX_ERRORTYPE ret;
    988     OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
    989 
    990     CHECK_TYPE_HEADER(p);
    991     CHECK_PORT_INDEX_RANGE(p);
    992     CHECK_ENUMERATION_RANGE(p->nIndex, 1);
    993 
    994     PortVideo *port = NULL;
    995     port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
    996     memcpy(p, port->GetPortVideoParam(), sizeof(*p));
    997     return OMX_ErrorNone;
    998 }
    999 
   1000 OMX_ERRORTYPE OMXVideoDecoderBase::SetParamVideoPortFormat(OMX_PTR pStructure) {
   1001     OMX_ERRORTYPE ret;
   1002     OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
   1003 
   1004     CHECK_TYPE_HEADER(p);
   1005     CHECK_PORT_INDEX_RANGE(p);
   1006     CHECK_SET_PARAM_STATE();
   1007 
   1008     // TODO: do we need to check if port is enabled?
   1009     PortVideo *port = NULL;
   1010     port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
   1011     port->SetPortVideoParam(p, false);
   1012     return OMX_ErrorNone;
   1013 }
   1014 
   1015 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsageSpecific(OMX_PTR pStructure) {
   1016      OMX_ERRORTYPE ret;
   1017      GetAndroidNativeBufferUsageParams *param = (GetAndroidNativeBufferUsageParams*)pStructure;
   1018      CHECK_TYPE_HEADER(param);
   1019      // hardware usage: consumed by GLES and HWC
   1020      param->nUsage |= GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER;
   1021      // software usage: can be read/written by apps
   1022      param->nUsage |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY;
   1023      return OMX_ErrorNone;
   1024 }
   1025 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsageSpecific(OMX_PTR) {
   1026     CHECK_SET_PARAM_STATE();
   1027     return OMX_ErrorBadParameter;
   1028 }
   1029 
   1030 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsage(OMX_PTR pStructure) {
   1031     return this->GetNativeBufferUsageSpecific(pStructure);
   1032 }
   1033 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsage(OMX_PTR pStructure) {
   1034     return this->SetNativeBufferUsageSpecific(pStructure);
   1035 }
   1036 
   1037 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBuffer(OMX_PTR) {
   1038     return OMX_ErrorBadParameter;
   1039 }
   1040 
   1041 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBuffer(OMX_PTR pStructure) {
   1042     OMX_ERRORTYPE ret;
   1043     UseAndroidNativeBufferParams *param = (UseAndroidNativeBufferParams*)pStructure;
   1044     CHECK_TYPE_HEADER(param);
   1045     if (param->nPortIndex != OUTPORT_INDEX)
   1046         return OMX_ErrorBadParameter;
   1047     OMX_BUFFERHEADERTYPE **buf_hdr = NULL;
   1048 
   1049     mOMXBufferHeaderTypePtrNum++;
   1050     if (mOMXBufferHeaderTypePtrNum > MAX_GRAPHIC_BUFFER_NUM)
   1051         return OMX_ErrorOverflow;
   1052 
   1053     buf_hdr = &mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum-1];
   1054 
   1055     ret = this->ports[OUTPORT_INDEX]->UseBuffer(buf_hdr, OUTPORT_INDEX, param->pAppPrivate, sizeof(OMX_U8*),
   1056                                       const_cast<OMX_U8*>(reinterpret_cast<const OMX_U8*>(param->nativeBuffer->handle)));
   1057     if (ret != OMX_ErrorNone)
   1058         return ret;
   1059 
   1060     if (mOMXBufferHeaderTypePtrNum == 1) {
   1061          mGraphicBufferParam.graphicBufferColorFormat = param->nativeBuffer->format;
   1062          mGraphicBufferParam.graphicBufferHStride = param->nativeBuffer->stride;
   1063          // FIXME: use IMG_native_handle_t->aiVStride[0] instead..
   1064          mGraphicBufferParam.graphicBufferVStride = param->nativeBuffer->height;
   1065          mGraphicBufferParam.graphicBufferWidth = param->nativeBuffer->width;
   1066          mGraphicBufferParam.graphicBufferHeight = param->nativeBuffer->height;
   1067     }
   1068 
   1069     *(param->bufferHeader) = *buf_hdr;
   1070 
   1071     return OMX_ErrorNone;
   1072 }
   1073 
   1074 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferMode(OMX_PTR pStructure) {
   1075     return this->GetNativeBufferModeSpecific(pStructure);
   1076 }
   1077 
   1078 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferMode(OMX_PTR pStructure) {
   1079     return this->SetNativeBufferModeSpecific(pStructure);
   1080 }
   1081 
   1082 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferModeSpecific(OMX_PTR) {
   1083     LOGE("GetNativeBufferMode is not implemented");
   1084     return OMX_ErrorNotImplemented;
   1085 }
   1086 
   1087 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferModeSpecific(OMX_PTR pStructure) {
   1088     OMX_ERRORTYPE ret;
   1089     EnableAndroidNativeBuffersParams *param = (EnableAndroidNativeBuffersParams*)pStructure;
   1090 
   1091     CHECK_TYPE_HEADER(param);
   1092     CHECK_PORT_INDEX_RANGE(param);
   1093     CHECK_SET_PARAM_STATE();
   1094 
   1095     PortVideo *port = NULL;
   1096     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
   1097     OMX_PARAM_PORTDEFINITIONTYPE port_def;
   1098     memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
   1099 
   1100     if (!param->enable) {
   1101         mWorkingMode = RAWDATA_MODE;
   1102         // If it is fallback from native mode the color format has been
   1103         // already set to INTEL format.
   1104         // We need to set back the default color format and Native stuff.
   1105         port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
   1106         port_def.format.video.pNativeRender = NULL;
   1107         port_def.format.video.pNativeWindow = NULL;
   1108         port->SetPortDefinition(&port_def,true);
   1109         return OMX_ErrorNone;
   1110     }
   1111 
   1112     mWorkingMode = GRAPHICBUFFER_MODE;
   1113     port_def.nBufferCountMin = mNativeBufferCount;
   1114     if (mEnableAdaptivePlayback) {
   1115         SetMaxOutputBufferCount(&port_def);
   1116     } else {
   1117         port_def.nBufferCountActual = mNativeBufferCount;
   1118     }
   1119     port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE;
   1120     port_def.format.video.eColorFormat = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
   1121     port_def.format.video.nFrameHeight = port_def.format.video.nFrameHeight;
   1122 
   1123     port_def.format.video.eColorFormat = GetOutputColorFormat(
   1124                         port_def.format.video.nFrameWidth);
   1125     port->SetPortDefinition(&port_def,true);
   1126 
   1127     return OMX_ErrorNone;
   1128 }
   1129 
   1130 OMX_ERRORTYPE OMXVideoDecoderBase::GetStoreMetaDataMode(OMX_PTR) {
   1131     ALOGE("GetMetaDataMode is not implemented");
   1132     return OMX_ErrorNotImplemented;
   1133 }
   1134 
   1135 OMX_ERRORTYPE OMXVideoDecoderBase::SetStoreMetaDataMode(OMX_PTR pStructure) {
   1136 #ifndef USE_META_DATA
   1137     OMX_PARAM_PORTDEFINITIONTYPE defInput;
   1138     memcpy(&defInput,
   1139         this->ports[INPORT_INDEX]->GetPortDefinition(),
   1140         sizeof(defInput));
   1141     if (defInput.format.video.eCompressionFormat == OMX_VIDEO_CodingVP9) {
   1142         ALOGE("SetMetaDataMode for VP9 is not implemented");
   1143         return OMX_ErrorNotImplemented;
   1144     }
   1145 #endif
   1146     OMX_ERRORTYPE ret;
   1147     StoreMetaDataInBuffersParams *param = (StoreMetaDataInBuffersParams*)pStructure;
   1148 
   1149     CHECK_TYPE_HEADER(param);
   1150     CHECK_PORT_INDEX(param, OUTPORT_INDEX);
   1151     CHECK_SET_PARAM_STATE();
   1152 
   1153     if (!param->bStoreMetaData) {
   1154         mAPMode = LEGACY_MODE;
   1155         // Don't return error which otherwise may cause framework crash
   1156         return OMX_ErrorNone;
   1157     }
   1158     mAPMode = METADATA_MODE;
   1159     ALOGI("We are in meta data mode!!!");
   1160 
   1161     return OMX_ErrorNone;
   1162 }
   1163 
   1164 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderRotation(OMX_PTR) {
   1165     return OMX_ErrorBadParameter;
   1166 }
   1167 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderRotation(OMX_PTR pStructure) {
   1168     CHECK_SET_PARAM_STATE();
   1169     int32_t rotationDegrees = 0;
   1170 
   1171     if (pStructure) {
   1172         rotationDegrees = *(static_cast<int32_t*>(pStructure));
   1173         mRotationDegrees = rotationDegrees;
   1174         LOGI("Rotation Degree = %d", rotationDegrees);
   1175         return OMX_ErrorNone;
   1176     } else {
   1177         return OMX_ErrorBadParameter;
   1178     }
   1179 }
   1180 
   1181 #ifdef TARGET_HAS_ISV
   1182 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderVppBufferNum(OMX_PTR) {
   1183     return OMX_ErrorBadParameter;
   1184 }
   1185 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderVppBufferNum(OMX_PTR pStructure) {
   1186     CHECK_SET_PARAM_STATE();
   1187     int32_t num = 0;
   1188 
   1189     num = *(static_cast<int32_t*>(pStructure));
   1190     mVppBufferNum = num;
   1191 
   1192     return OMX_ErrorNone;
   1193 }
   1194 #endif
   1195 
   1196 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCropSpecific(OMX_PTR pStructure) {
   1197     OMX_ERRORTYPE ret;
   1198     OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure;
   1199 
   1200     CHECK_TYPE_HEADER(rectParams);
   1201 
   1202     if (rectParams->nPortIndex != OUTPORT_INDEX) {
   1203         return OMX_ErrorUndefined;
   1204     }
   1205 
   1206     PortVideo *port = NULL;
   1207     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
   1208     OMX_PARAM_PORTDEFINITIONTYPE port_def;
   1209     memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
   1210 
   1211     const VideoFormatInfo *formatInfo = mVideoDecoder->getFormatInfo();
   1212     if (formatInfo->valid == true) {
   1213         rectParams->nLeft =  formatInfo->cropLeft;
   1214         rectParams->nTop = formatInfo->cropTop;
   1215         rectParams->nWidth = formatInfo->width - formatInfo->cropLeft - formatInfo->cropRight;
   1216         rectParams->nHeight = formatInfo->height - formatInfo->cropTop - formatInfo->cropBottom;
   1217         if (strcasecmp(formatInfo->mimeType,"video/avc") == 0 ||
   1218             strcasecmp(formatInfo->mimeType,"video/avc-secure") == 0 ||
   1219             strcasecmp(formatInfo->mimeType,"video/h264") == 0) {
   1220             rectParams->nHeight = formatInfo->height;
   1221             rectParams->nWidth = formatInfo->width;
   1222         }
   1223 
   1224         // if port width parsed from extractor is not as same as from SPS/PPS nalu header,
   1225         // align it.
   1226         if (port_def.format.video.nFrameWidth != rectParams->nWidth) {
   1227             port_def.format.video.nFrameWidth = rectParams->nWidth;
   1228         }
   1229         port->SetPortDefinition(&port_def,true);
   1230         return OMX_ErrorNone;
   1231     } else {
   1232         return OMX_ErrorFormatNotDetected;
   1233     }
   1234 }
   1235 
   1236 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCropSpecific(OMX_PTR) {
   1237     return OMX_ErrorUnsupportedSetting;
   1238 }
   1239 
   1240 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCrop(OMX_PTR pStructure) {
   1241     return this->SetDecoderOutputCropSpecific(pStructure);
   1242 }
   1243 
   1244 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCrop(OMX_PTR pStructure) {
   1245     return this->GetDecoderOutputCropSpecific(pStructure);
   1246 }
   1247 
   1248 
   1249 OMX_ERRORTYPE OMXVideoDecoderBase::SetCodecPriority(OMX_PTR pStructure) {
   1250     OMX_ERRORTYPE ret;
   1251     OMX_PARAM_U32TYPE *priorityParam = (OMX_PARAM_U32TYPE *)pStructure;
   1252     mCodecPriority = priorityParam->nU32;
   1253     return OMX_ErrorNone;
   1254 }
   1255 
   1256 
   1257 OMX_ERRORTYPE OMXVideoDecoderBase::GetCodecPriority(OMX_PTR pStructure) {
   1258     OMX_ERRORTYPE ret;
   1259     OMX_PARAM_U32TYPE *priorityParam = (OMX_PARAM_U32TYPE *)pStructure;
   1260     CHECK_TYPE_HEADER(priorityParam);
   1261     priorityParam->nU32 = mCodecPriority;
   1262     return OMX_ErrorNone;
   1263 }
   1264 
   1265 
   1266 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOperatingRate(OMX_PTR pStructure) {
   1267     OMX_ERRORTYPE ret;
   1268     OMX_PARAM_U32TYPE *operatingRateParam = (OMX_PARAM_U32TYPE *)pStructure;
   1269     CHECK_TYPE_HEADER(operatingRateParam);
   1270     mOperatingRate = operatingRateParam->nU32;
   1271     return OMX_ErrorNone;
   1272 }
   1273 
   1274 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOperatingRate(OMX_PTR pStructure) {
   1275     OMX_ERRORTYPE ret;
   1276     OMX_PARAM_U32TYPE *operatingRateParam = (OMX_PARAM_U32TYPE *)pStructure;
   1277     CHECK_TYPE_HEADER(operatingRateParam);
   1278     operatingRateParam->nU32 = mOperatingRate;
   1279     return OMX_ErrorNone;
   1280 }
   1281 
   1282 OMX_ERRORTYPE OMXVideoDecoderBase::GetErrorReportMode(OMX_PTR) {
   1283     LOGE("GetErrorReportMode is not implemented");
   1284     return OMX_ErrorNotImplemented;
   1285 }
   1286 
   1287 OMX_ERRORTYPE OMXVideoDecoderBase::SetErrorReportMode(OMX_PTR pStructure) {
   1288     OMX_ERRORTYPE ret;
   1289 
   1290     OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *p = (OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *)pStructure;
   1291     CHECK_TYPE_HEADER(p);
   1292     CHECK_PORT_INDEX(p, OUTPORT_INDEX);
   1293 
   1294     mErrorReportEnabled = p->bEnable;
   1295     LOGD("Error reporting is %s", mErrorReportEnabled ? "enabled" : "disabled");
   1296 
   1297     mVideoDecoder->enableErrorReport(mErrorReportEnabled);
   1298     return OMX_ErrorNone;
   1299 }
   1300 
   1301 OMX_COLOR_FORMATTYPE OMXVideoDecoderBase::GetOutputColorFormat(int width) {
   1302 #ifndef VED_TILING
   1303     return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
   1304 #else
   1305     if (width > 1280 && width <= 2048) {
   1306         LOGI("HD Video and use tiled format");
   1307         return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled;
   1308     } else {
   1309         return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
   1310     }
   1311 #endif
   1312 }
   1313 
   1314 OMX_ERRORTYPE OMXVideoDecoderBase::SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE *) {
   1315     return OMX_ErrorNone;
   1316 }
   1317 
   1318 uint32_t OMXVideoDecoderBase::getStride(uint32_t width) {
   1319     uint32_t stride = 0;
   1320 
   1321     if (width <= 512)
   1322         stride = 512;
   1323     else if (width <= 1024)
   1324         stride = 1024;
   1325     else if (width <= 1280) {
   1326         stride = 1280;
   1327     } else if (width <= 2048)
   1328         stride = 2048;
   1329     else if (width <= 4096)
   1330         stride = 4096;
   1331     else
   1332         stride = (width + 0x3f) & ~0x3f;
   1333 
   1334     return stride;
   1335 }
   1336