Home | History | Annotate | Download | only in videodecoder
      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 #include "VideoDecoderMPEG4.h"
     18 #include "VideoDecoderTrace.h"
     19 #include <string.h>
     20 
     21 VideoDecoderMPEG4::VideoDecoderMPEG4(const char *mimeType)
     22     : VideoDecoderBase(mimeType, VBP_MPEG4),
     23       mLastVOPTimeIncrement(0),
     24       mExpectingNVOP(false),
     25       mSendIQMatrixBuf(false),
     26       mLastVOPCodingType(MP4_VOP_TYPE_I),
     27       mIsShortHeader(false) {
     28 }
     29 
     30 VideoDecoderMPEG4::~VideoDecoderMPEG4() {
     31     stop();
     32 }
     33 
     34 Decode_Status VideoDecoderMPEG4::start(VideoConfigBuffer *buffer) {
     35     Decode_Status status;
     36 
     37     status = VideoDecoderBase::start(buffer);
     38     CHECK_STATUS("VideoDecoderBase::start");
     39 
     40     if (buffer->data == NULL || buffer->size == 0) {
     41         WTRACE("No config data to start VA.");
     42         return DECODE_SUCCESS;
     43     }
     44 
     45     vbp_data_mp42 *data = NULL;
     46     status = VideoDecoderBase::parseBuffer(buffer->data, buffer->size, true, (void**)&data);
     47     CHECK_STATUS("VideoDecoderBase::parseBuffer");
     48 
     49     status = startVA(data);
     50     return status;
     51 }
     52 
     53 void VideoDecoderMPEG4::stop(void) {
     54     // drop the last frame and ignore return value
     55     endDecodingFrame(true);
     56     VideoDecoderBase::stop();
     57 
     58     mLastVOPTimeIncrement = 0;
     59     mExpectingNVOP = false;
     60     mLastVOPCodingType = MP4_VOP_TYPE_I;
     61 }
     62 
     63 Decode_Status VideoDecoderMPEG4::decode(VideoDecodeBuffer *buffer) {
     64     Decode_Status status;
     65     vbp_data_mp42 *data = NULL;
     66     bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
     67     if (buffer == NULL) {
     68         return DECODE_INVALID_DATA;
     69     }
     70     if (buffer->flag & IS_SYNC_FRAME) {
     71         mIsSyncFrame = true;
     72     } else {
     73         mIsSyncFrame = false;
     74     }
     75     buffer->ext = NULL;
     76     status =  VideoDecoderBase::parseBuffer(
     77             buffer->data,
     78             buffer->size,
     79             false,
     80             (void**)&data);
     81     CHECK_STATUS("VideoDecoderBase::parseBuffer");
     82 
     83     if (!mVAStarted) {
     84         status = startVA(data);
     85         CHECK_STATUS("startVA");
     86     }
     87 
     88     if (mSizeChanged && !useGraphicbuffer) {
     89         // some container has the incorrect width/height.
     90         // send the format change to OMX to update the crop info.
     91         mSizeChanged = false;
     92         ITRACE("Video size is changed during startVA");
     93         return DECODE_FORMAT_CHANGE;
     94     }
     95 
     96     if ((mVideoFormatInfo.width != (uint32_t)data->codec_data.video_object_layer_width ||
     97         mVideoFormatInfo.height != (uint32_t)data->codec_data.video_object_layer_height) &&
     98         data->codec_data.video_object_layer_width &&
     99         data->codec_data.video_object_layer_height) {
    100         // update  encoded image size
    101         ITRACE("Video size is changed. from %dx%d to %dx%d\n",mVideoFormatInfo.width,mVideoFormatInfo.height,
    102                 data->codec_data.video_object_layer_width,data->codec_data.video_object_layer_height);
    103         bool noNeedFlush = false;
    104         mVideoFormatInfo.width = data->codec_data.video_object_layer_width;
    105         mVideoFormatInfo.height = data->codec_data.video_object_layer_height;
    106         if (useGraphicbuffer) {
    107             noNeedFlush = (mVideoFormatInfo.width <= mVideoFormatInfo.surfaceWidth)
    108                     && (mVideoFormatInfo.height <= mVideoFormatInfo.surfaceHeight);
    109         }
    110         if (!noNeedFlush) {
    111             flushSurfaceBuffers();
    112             mSizeChanged = false;
    113             return DECODE_FORMAT_CHANGE;
    114         } else {
    115             mSizeChanged = true;
    116         }
    117 
    118         setRenderRect();
    119     }
    120 
    121     status = decodeFrame(buffer, data);
    122     CHECK_STATUS("decodeFrame");
    123 
    124     return status;
    125 }
    126 
    127 void VideoDecoderMPEG4::flush(void) {
    128     VideoDecoderBase::flush();
    129 
    130     mExpectingNVOP = false;
    131     mLastVOPTimeIncrement = 0;
    132     mLastVOPCodingType = MP4_VOP_TYPE_I;
    133 }
    134 
    135 Decode_Status VideoDecoderMPEG4::decodeFrame(VideoDecodeBuffer *buffer, vbp_data_mp42 *data) {
    136     Decode_Status status;
    137     // check if any slice is parsed, we may just receive configuration data
    138     if (data->number_picture_data == 0) {
    139         WTRACE("number_picture_data == 0");
    140         return DECODE_SUCCESS;
    141     }
    142 
    143     // When the MPEG4 parser gets the invaild parameters, add the check
    144     // and return error to OMX to avoid mediaserver crash.
    145     if (data->picture_data && (data->picture_data->picture_param.vop_width == 0
    146         || data->picture_data->picture_param.vop_height == 0)) {
    147         return DECODE_PARSER_FAIL;
    148     }
    149 
    150     uint64_t lastPTS = mCurrentPTS;
    151     mCurrentPTS = buffer->timeStamp;
    152 
    153     if (lastPTS != mCurrentPTS) {
    154         // finish decoding the last frame
    155         status = endDecodingFrame(false);
    156         CHECK_STATUS("endDecodingFrame");
    157 
    158         // start decoding a new frame
    159         status = beginDecodingFrame(data);
    160         if (status == DECODE_MULTIPLE_FRAME) {
    161             buffer->ext = &mExtensionBuffer;
    162             mExtensionBuffer.extType = PACKED_FRAME_TYPE;
    163             mExtensionBuffer.extSize = sizeof(mPackedFrame);
    164             mExtensionBuffer.extData = (uint8_t*)&mPackedFrame;
    165         } else if (status != DECODE_SUCCESS) {
    166             endDecodingFrame(true);
    167         }
    168         CHECK_STATUS("beginDecodingFrame");
    169     } else {
    170         status = continueDecodingFrame(data);
    171         if (status == DECODE_MULTIPLE_FRAME) {
    172             buffer->ext = &mExtensionBuffer;
    173             mExtensionBuffer.extType = PACKED_FRAME_TYPE;
    174             mExtensionBuffer.extSize = sizeof(mPackedFrame);
    175             mExtensionBuffer.extData = (uint8_t*)&mPackedFrame;
    176         } else if (status != DECODE_SUCCESS) {
    177             endDecodingFrame(true);
    178         }
    179         CHECK_STATUS("continueDecodingFrame");
    180     }
    181 
    182     if (buffer->flag & HAS_COMPLETE_FRAME) {
    183         // finish decoding current frame
    184         status = endDecodingFrame(false);
    185         CHECK_STATUS("endDecodingFrame");
    186     }
    187 
    188     return DECODE_SUCCESS;
    189 }
    190 
    191 Decode_Status VideoDecoderMPEG4::beginDecodingFrame(vbp_data_mp42 *data) {
    192 
    193     Decode_Status status = DECODE_SUCCESS;
    194     vbp_picture_data_mp42 *picData = data->picture_data;
    195     VAPictureParameterBufferMPEG4 *picParam = &(picData->picture_param);
    196     int codingType = picParam->vop_fields.bits.vop_coding_type;
    197 
    198     // start sanity checking
    199     if (mExpectingNVOP) {
    200         // if we are waiting for n-vop for packed frame, and the new frame is coded, the coding type
    201         // of this frame must be B
    202         // for example: {PB} B N P B B P...
    203         if (picData->vop_coded == 1 && codingType != MP4_VOP_TYPE_B) {
    204             WTRACE("Invalid coding type while waiting for n-vop for packed frame.");
    205             mExpectingNVOP = false;
    206         }
    207     }
    208 
    209     // handle N-VOP picuture, it could be a skipped frame or a simple placeholder of packed frame
    210     if (picData->vop_coded == 0) {
    211         if (mLastReference == NULL) {
    212             WTRACE("The last reference is unavailable to construct skipped frame.");
    213             flush();
    214             mExpectingNVOP = false;
    215             // TODO: handle this case
    216             return DECODE_SUCCESS;
    217         }
    218 
    219         if (mExpectingNVOP) {
    220             // P frame is already in queue, just need to update time stamp.
    221             mLastReference->renderBuffer.timeStamp = mCurrentPTS;
    222             mExpectingNVOP = false;
    223         }
    224         else {
    225             // Do nothing for skip frame as the last frame will be rendered agian by natively
    226             // No needs to handle reference frame neither
    227 #if 0
    228             // this is skipped frame, use the last reference frame as output
    229             status = acquireSurfaceBuffer();
    230             CHECK_STATUS("acquireSurfaceBuffer");
    231             mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS;
    232             mAcquiredBuffer->renderBuffer.flag = 0;
    233             mAcquiredBuffer->renderBuffer.scanFormat = mLastReference->renderBuffer.scanFormat;
    234             mAcquiredBuffer->renderBuffer.surface = mLastReference->renderBuffer.surface;
    235             // No need to update mappedData for HW decoding
    236             //mAcquiredBuffer->mappedData.data = mLastReference->mappedData.data;
    237             mAcquiredBuffer->referenceFrame = true;
    238             status = outputSurfaceBuffer();
    239             CHECK_STATUS("outputSurfaceBuffer");
    240 #endif
    241         }
    242 
    243         if (data->number_picture_data > 1) {
    244             WTRACE("Unexpected to have more picture data following a non-coded VOP.");
    245             //picture data is thrown away. No issue if picture data is for N-VOP. if picture data is for
    246             // coded picture, a frame is lost.
    247             // TODO: handle this case
    248             // return DECODE_FAIL;
    249         }
    250         return DECODE_SUCCESS;
    251     }
    252     else {
    253         // Check if we have reference frame(s)  for decoding
    254         if (codingType == MP4_VOP_TYPE_B)  {
    255             if (mForwardReference ==  NULL ||
    256                 mLastReference == NULL) {
    257                 if (mIsShortHeader) {
    258                     status = DECODE_SUCCESS;
    259                     VTRACE("%s: No reference frame but keep decoding", __FUNCTION__);
    260                 } else
    261                     return DECODE_NO_REFERENCE;
    262             }
    263         } else if (codingType == MP4_VOP_TYPE_P || codingType == MP4_VOP_TYPE_S) {
    264             if (mLastReference == NULL && mIsSyncFrame == false) {
    265                 if (mIsShortHeader) {
    266                     status = DECODE_SUCCESS;
    267                     VTRACE("%s: No reference frame but keep decoding", __FUNCTION__);
    268                 } else
    269                     return DECODE_NO_REFERENCE;
    270             }
    271         }
    272         // all sanity checks pass, continue decoding through continueDecodingFrame
    273         status = continueDecodingFrame(data);
    274     }
    275     return status;
    276 }
    277 
    278 Decode_Status VideoDecoderMPEG4::continueDecodingFrame(vbp_data_mp42 *data) {
    279     Decode_Status status = DECODE_SUCCESS;
    280     VAStatus vaStatus = VA_STATUS_SUCCESS;
    281     bool useGraphicBuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
    282 
    283     /*
    284          Packed Frame Assumption:
    285 
    286          1. In one packed frame, there's only one P or I frame and only one B frame.
    287          2. In packed frame, there's no skipped frame (vop_coded = 0)
    288          3. For one packed frame, there will be one N-VOP frame to follow the packed frame (may not immediately).
    289          4. N-VOP frame is the frame with vop_coded = 0.
    290          5. The timestamp of  N-VOP frame will be used for P or I frame in the packed frame
    291 
    292 
    293          I, P, {P, B}, B, N, P, N, I, ...
    294          I, P, {P, B}, N, P, N, I, ...
    295 
    296          The first N is placeholder for P frame in the packed frame
    297          The second N is a skipped frame
    298          */
    299 
    300     vbp_picture_data_mp42 *picData = data->picture_data;
    301     for (uint32_t i = 0; i < data->number_picture_data; i++, picData = picData->next_picture_data) {
    302         // each slice has its own picture data, video_packet_header following resync_marker may reset picture header, see MP4 spec
    303         VAPictureParameterBufferMPEG4 *picParam = &(picData->picture_param);
    304         int codingType = picParam->vop_fields.bits.vop_coding_type;
    305         if (codingType == MP4_VOP_TYPE_S && picParam->no_of_sprite_warping_points > 1) {
    306             WTRACE("Hardware only supports up to one warping point (stationary or translation)");
    307         }
    308 
    309         if (picData->vop_coded == 0) {
    310             ETRACE("Unexpected to have non-coded VOP.");
    311             return DECODE_FAIL;
    312         }
    313         if (picData->new_picture_flag == 1 || mDecodingFrame == false) {
    314             // either condition indicates start of a new frame
    315             if (picData->new_picture_flag == 0) {
    316                 WTRACE("First slice of picture is lost!");
    317                 // TODO: handle this case
    318             }
    319             if (mDecodingFrame) {
    320                 if (codingType == MP4_VOP_TYPE_B){
    321                     // this indicates the start of a new frame in the packed frame
    322                     // Update timestamp for P frame in the packed frame as timestamp here is for the B frame!
    323                     if (picParam->vop_time_increment_resolution){
    324                         uint64_t increment = mLastVOPTimeIncrement - picData->vop_time_increment +
    325                                 picParam->vop_time_increment_resolution;
    326                         increment = increment % picParam->vop_time_increment_resolution;
    327                         // convert to micro-second
    328                         // TODO: unit of time stamp varies on different frame work
    329                         increment = increment * 1e6 / picParam->vop_time_increment_resolution;
    330                         mAcquiredBuffer->renderBuffer.timeStamp += increment;
    331                         if (useGraphicBuffer){
    332                            mPackedFrame.timestamp = mCurrentPTS;
    333                            mCurrentPTS = mAcquiredBuffer->renderBuffer.timeStamp;
    334                         }
    335                     }
    336                 } else {
    337                     // this indicates the start of a new frame in the packed frame. no B frame int the packet
    338                     // Update the timestamp according the increment
    339                     if (picParam->vop_time_increment_resolution){
    340                         int64_t increment = picData->vop_time_increment - mLastVOPTimeIncrement + picParam->vop_time_increment_resolution;
    341                         increment = increment % picParam->vop_time_increment_resolution;
    342                         //convert to micro-second
    343                         increment = increment * 1e6 / picParam->vop_time_increment_resolution;
    344                         if (useGraphicBuffer) {
    345                             mPackedFrame.timestamp = mCurrentPTS + increment;
    346                         }
    347                         else {
    348                             mCurrentPTS += increment;
    349                         }
    350 
    351                     } else {
    352                         if (useGraphicBuffer) {
    353                             mPackedFrame.timestamp = mCurrentPTS + 30000;
    354                         }
    355                         else {
    356                             mCurrentPTS += 30000;
    357                         }
    358                     }
    359                 }
    360                 endDecodingFrame(false);
    361                 mExpectingNVOP = true;
    362                 if (codingType != MP4_VOP_TYPE_B) {
    363                     mExpectingNVOP = false;
    364                 }
    365                 if (useGraphicBuffer) {
    366                     int32_t count = i - 1;
    367                     if (count < 0) {
    368                         WTRACE("Shuld not be here!");
    369                         return DECODE_SUCCESS;
    370                     }
    371                     vbp_picture_data_mp42 *lastpic = data->picture_data;
    372                     for(int k = 0; k < count; k++ ) {
    373                         lastpic = lastpic->next_picture_data;
    374                     }
    375                     mPackedFrame.offSet = lastpic->slice_data.slice_offset + lastpic->slice_data.slice_size;
    376                     VTRACE("Report OMX to handle for Multiple frame offset=%d time=%lld",mPackedFrame.offSet,mPackedFrame.timestamp);
    377                     return DECODE_MULTIPLE_FRAME;
    378                 }
    379             }
    380 
    381             // acquire a new surface buffer
    382             status = acquireSurfaceBuffer();
    383             CHECK_STATUS("acquireSurfaceBuffer");
    384 
    385             // sprite is treated as P frame in the display order, so only B frame frame is not used as "reference"
    386             mAcquiredBuffer->referenceFrame = (codingType != MP4_VOP_TYPE_B);
    387             if (picData->picture_param.vol_fields.bits.interlaced) {
    388                 // only MPEG-4 studio profile can have field coding. All other profiles
    389                 // use frame coding only, i.e, there is no field VOP.  (see vop_structure in MP4 spec)
    390                 mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD | VA_TOP_FIELD;
    391             } else {
    392                 mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
    393             }
    394             // TODO:  set discontinuity flag
    395             mAcquiredBuffer->renderBuffer.flag = 0;
    396             mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS;
    397             if (mSizeChanged) {
    398                 mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
    399                 mSizeChanged = false;
    400             }
    401             if (codingType != MP4_VOP_TYPE_B) {
    402                 mLastVOPCodingType = codingType;
    403                 mLastVOPTimeIncrement = picData->vop_time_increment;
    404             }
    405 
    406             // start decoding a frame
    407             vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
    408             CHECK_VA_STATUS("vaBeginPicture");
    409 
    410             mDecodingFrame = true;
    411             mSendIQMatrixBuf = true;
    412         }
    413 
    414         status = decodeSlice(data, picData);
    415         CHECK_STATUS("decodeSlice");
    416     }
    417 
    418     return DECODE_SUCCESS;
    419 }
    420 
    421 
    422 Decode_Status VideoDecoderMPEG4::decodeSlice(vbp_data_mp42 *data, vbp_picture_data_mp42 *picData) {
    423     Decode_Status status;
    424     VAStatus vaStatus;
    425     uint32_t bufferIDCount = 0;
    426     // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
    427     VABufferID bufferIDs[4];
    428 
    429     VAPictureParameterBufferMPEG4 *picParam = &(picData->picture_param);
    430     vbp_slice_data_mp42 *sliceData = &(picData->slice_data);
    431     VASliceParameterBufferMPEG4 *sliceParam = &(sliceData->slice_param);
    432 
    433     // send picture parametre for each slice
    434     status = setReference(picParam);
    435     CHECK_STATUS("setReference");
    436 
    437     vaStatus = vaCreateBuffer(
    438         mVADisplay,
    439         mVAContext,
    440         VAPictureParameterBufferType,
    441         sizeof(VAPictureParameterBufferMPEG4),
    442         1,
    443         picParam,
    444         &bufferIDs[bufferIDCount]);
    445     CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
    446 
    447     bufferIDCount++;
    448     if (picParam->vol_fields.bits.quant_type && mSendIQMatrixBuf)
    449     {
    450         // only send IQ matrix for the first slice in the picture
    451         vaStatus = vaCreateBuffer(
    452             mVADisplay,
    453             mVAContext,
    454             VAIQMatrixBufferType,
    455             sizeof(VAIQMatrixBufferMPEG4),
    456             1,
    457             &(data->iq_matrix_buffer),
    458             &bufferIDs[bufferIDCount]);
    459         CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
    460 
    461         mSendIQMatrixBuf = false;
    462         bufferIDCount++;
    463     }
    464 
    465     vaStatus = vaCreateBuffer(
    466         mVADisplay,
    467         mVAContext,
    468         VASliceParameterBufferType,
    469         sizeof(VASliceParameterBufferMPEG4),
    470         1,
    471         sliceParam,
    472         &bufferIDs[bufferIDCount]);
    473     CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
    474 
    475     bufferIDCount++;
    476 
    477     //slice data buffer pointer
    478     //Note that this is the original data buffer ptr;
    479     // offset to the actual slice data is provided in
    480     // slice_data_offset in VASliceParameterBufferMP42
    481 
    482     vaStatus = vaCreateBuffer(
    483         mVADisplay,
    484         mVAContext,
    485         VASliceDataBufferType,
    486         sliceData->slice_size, //size
    487         1,        //num_elements
    488         sliceData->buffer_addr + sliceData->slice_offset,
    489         &bufferIDs[bufferIDCount]);
    490     CHECK_VA_STATUS("vaCreateSliceDataBuffer");
    491 
    492     bufferIDCount++;
    493 
    494     vaStatus = vaRenderPicture(
    495         mVADisplay,
    496         mVAContext,
    497         bufferIDs,
    498         bufferIDCount);
    499     CHECK_VA_STATUS("vaRenderPicture");
    500 
    501 
    502     return DECODE_SUCCESS;
    503 }
    504 
    505 Decode_Status VideoDecoderMPEG4::setReference(VAPictureParameterBufferMPEG4 *picParam) {
    506     switch (picParam->vop_fields.bits.vop_coding_type) {
    507         case MP4_VOP_TYPE_I:
    508             picParam->forward_reference_picture = VA_INVALID_SURFACE;
    509             picParam->backward_reference_picture = VA_INVALID_SURFACE;
    510             break;
    511         case MP4_VOP_TYPE_P:
    512             if (mLastReference == NULL && mIsSyncFrame == false && !mIsShortHeader) {
    513                 return DECODE_NO_REFERENCE;
    514             }
    515             if (mLastReference != NULL) {
    516                 picParam->forward_reference_picture = mLastReference->renderBuffer.surface;
    517             } else {
    518                 VTRACE("%s: no reference frame, but keep decoding", __FUNCTION__);
    519                 picParam->forward_reference_picture = VA_INVALID_SURFACE;
    520             }
    521             picParam->backward_reference_picture = VA_INVALID_SURFACE;
    522             break;
    523         case MP4_VOP_TYPE_B:
    524             picParam->vop_fields.bits.backward_reference_vop_coding_type = mLastVOPCodingType;
    525             // WEIRD, CHECK AGAIN !!!!!!!
    526             if (mIsShortHeader) {
    527                 if (mLastReference != NULL) {
    528                     picParam->forward_reference_picture = mLastReference->renderBuffer.surface;
    529                 } else {
    530                     VTRACE("%s: no forward reference frame, but keep decoding", __FUNCTION__);
    531                     picParam->forward_reference_picture = VA_INVALID_SURFACE;
    532                 }
    533                 if (mForwardReference != NULL) {
    534                     picParam->backward_reference_picture = mForwardReference->renderBuffer.surface;
    535                 } else {
    536                     VTRACE("%s: no backward reference frame, but keep decoding", __FUNCTION__);
    537                     picParam->backward_reference_picture = VA_INVALID_SURFACE;
    538                 }
    539             } else if (mLastReference == NULL || mForwardReference == NULL) {
    540                 return DECODE_NO_REFERENCE;
    541             } else {
    542                 picParam->forward_reference_picture = mLastReference->renderBuffer.surface;
    543                 picParam->backward_reference_picture = mForwardReference->renderBuffer.surface;
    544             }
    545             break;
    546         case MP4_VOP_TYPE_S:
    547             // WEIRD, CHECK AGAIN!!!! WAS using mForwardReference
    548             if (mLastReference == NULL) {
    549                 return DECODE_NO_REFERENCE;
    550             }
    551             picParam->forward_reference_picture = mLastReference->renderBuffer.surface;
    552             picParam->backward_reference_picture = VA_INVALID_SURFACE;
    553             break;
    554 
    555         default:
    556             // Will never reach here;
    557             return DECODE_PARSER_FAIL;
    558     }
    559     return DECODE_SUCCESS;
    560 }
    561 
    562 Decode_Status VideoDecoderMPEG4::startVA(vbp_data_mp42 *data) {
    563     updateFormatInfo(data);
    564 
    565     VAProfile vaProfile;
    566 
    567     if ((data->codec_data.profile_and_level_indication & 0xF8) == 0xF0) {
    568         vaProfile = VAProfileMPEG4AdvancedSimple;
    569     } else {
    570         vaProfile = VAProfileMPEG4Simple;
    571     }
    572 
    573     mIsShortHeader = data->codec_data.short_video_header;
    574 
    575     return VideoDecoderBase::setupVA(MP4_SURFACE_NUMBER, vaProfile);
    576 }
    577 
    578 void VideoDecoderMPEG4::updateFormatInfo(vbp_data_mp42 *data) {
    579     ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
    580         mVideoFormatInfo.width, mVideoFormatInfo.height,
    581         data->codec_data.video_object_layer_width,
    582         data->codec_data.video_object_layer_height);
    583 
    584     mVideoFormatInfo.cropBottom = data->codec_data.video_object_layer_height > mVideoFormatInfo.height ?
    585                                                                           data->codec_data.video_object_layer_height - mVideoFormatInfo.height : 0;
    586     mVideoFormatInfo.cropRight = data->codec_data.video_object_layer_width > mVideoFormatInfo.width ?
    587                                                                      data->codec_data.video_object_layer_width - mVideoFormatInfo.width : 0;
    588 
    589     if ((mVideoFormatInfo.width != (uint32_t)data->codec_data.video_object_layer_width ||
    590         mVideoFormatInfo.height != (uint32_t)data->codec_data.video_object_layer_height) &&
    591         data->codec_data.video_object_layer_width &&
    592         data->codec_data.video_object_layer_height) {
    593         // update  encoded image size
    594         mVideoFormatInfo.width = data->codec_data.video_object_layer_width;
    595         mVideoFormatInfo.height = data->codec_data.video_object_layer_height;
    596         mSizeChanged = true;
    597         ITRACE("Video size is changed.");
    598     }
    599 
    600     // video_range has default value of 0. Y ranges from 16 to 235.
    601     mVideoFormatInfo.videoRange = data->codec_data.video_range;
    602 
    603     switch (data->codec_data.matrix_coefficients) {
    604         case 1:
    605             mVideoFormatInfo.colorMatrix = VA_SRC_BT709;
    606             break;
    607 
    608         // ITU-R Recommendation BT.470-6 System B, G (MP4), same as
    609         // SMPTE 170M/BT601
    610         case 5:
    611         case 6:
    612             mVideoFormatInfo.colorMatrix = VA_SRC_BT601;
    613             break;
    614 
    615         default:
    616             // unknown color matrix, set to 0 so color space flag will not be set.
    617             mVideoFormatInfo.colorMatrix = 0;
    618             break;
    619     }
    620 
    621     mVideoFormatInfo.aspectX = data->codec_data.par_width;
    622     mVideoFormatInfo.aspectY = data->codec_data.par_height;
    623     //mVideoFormatInfo.bitrate = data->codec_data.bit_rate;
    624     mVideoFormatInfo.valid = true;
    625 
    626     setRenderRect();
    627 }
    628 
    629 Decode_Status VideoDecoderMPEG4::checkHardwareCapability() {
    630     VAStatus vaStatus;
    631     VAConfigAttrib cfgAttribs[2];
    632     cfgAttribs[0].type = VAConfigAttribMaxPictureWidth;
    633     cfgAttribs[1].type = VAConfigAttribMaxPictureHeight;
    634     vaStatus = vaGetConfigAttributes(mVADisplay,
    635             mIsShortHeader ? VAProfileH263Baseline : VAProfileMPEG4AdvancedSimple,
    636             VAEntrypointVLD, cfgAttribs, 2);
    637     CHECK_VA_STATUS("vaGetConfigAttributes");
    638     if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) {
    639         ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d",
    640                 cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height);
    641         return DECODE_DRIVER_FAIL;
    642     }
    643 
    644     return DECODE_SUCCESS;
    645 }
    646