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