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 "VideoDecoderVP8.h"
     18 #include "VideoDecoderTrace.h"
     19 #include <string.h>
     20 
     21 VideoDecoderVP8::VideoDecoderVP8(const char *mimeType)
     22     : VideoDecoderBase(mimeType, VBP_VP8) {
     23     invalidateReferenceFrames(0);
     24     invalidateReferenceFrames(1);
     25 }
     26 
     27 VideoDecoderVP8::~VideoDecoderVP8() {
     28     stop();
     29 }
     30 
     31 void VideoDecoderVP8::invalidateReferenceFrames(int toggle) {
     32     ReferenceFrameBuffer *p = mRFBs[toggle];
     33     for (int i = 0; i < VP8_REF_SIZE; i++) {
     34         p->index = (uint32_t) -1;
     35         p->surfaceBuffer = NULL;
     36         p++;
     37     }
     38 }
     39 
     40 void VideoDecoderVP8::clearAsReference(int toggle, int ref_type) {
     41     ReferenceFrameBuffer ref = mRFBs[toggle][ref_type];
     42     if (ref.surfaceBuffer) {
     43         ref.surfaceBuffer->asReferernce = false;
     44     }
     45 }
     46 
     47 void VideoDecoderVP8::updateFormatInfo(vbp_data_vp8 *data) {
     48     uint32_t width = data->codec_data->frame_width;
     49     uint32_t height = data->codec_data->frame_height;
     50     ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
     51             mVideoFormatInfo.width, mVideoFormatInfo.height, width, height);
     52 
     53     if ((mVideoFormatInfo.width != width ||
     54             mVideoFormatInfo.height != height) &&
     55             width && height) {
     56         if ((VideoDecoderBase::alignMB(mVideoFormatInfo.width) != width) ||
     57             (VideoDecoderBase::alignMB(mVideoFormatInfo.height) != height)) {
     58             mSizeChanged = true;
     59             ITRACE("Video size is changed.");
     60         }
     61         mVideoFormatInfo.width = width;
     62         mVideoFormatInfo.height = height;
     63     }
     64 
     65     mVideoFormatInfo.cropLeft = data->codec_data->crop_left;
     66     mVideoFormatInfo.cropRight = data->codec_data->crop_right;
     67     mVideoFormatInfo.cropTop = data->codec_data->crop_top;
     68     mVideoFormatInfo.cropBottom = data->codec_data->crop_bottom;
     69     ITRACE("Cropping: left = %d, top = %d, right = %d, bottom = %d", data->codec_data->crop_left, data->codec_data->crop_top, data->codec_data->crop_right, data->codec_data->crop_bottom);
     70 
     71     mVideoFormatInfo.valid = true;
     72 
     73     setRenderRect();
     74 }
     75 
     76 Decode_Status VideoDecoderVP8::startVA(vbp_data_vp8 *data) {
     77     updateFormatInfo(data);
     78 
     79     VAProfile vaProfile = VAProfileVP8Version0_3;
     80     if (data->codec_data->version_num > 3) {
     81         return DECODE_PARSER_FAIL;
     82     }
     83 
     84     enableLowDelayMode(true);
     85 
     86     return VideoDecoderBase::setupVA(VP8_SURFACE_NUMBER + VP8_REF_SIZE, vaProfile);
     87 }
     88 
     89 Decode_Status VideoDecoderVP8::start(VideoConfigBuffer *buffer) {
     90     Decode_Status status;
     91 
     92     status = VideoDecoderBase::start(buffer);
     93     CHECK_STATUS("VideoDecoderBase::start");
     94 
     95     // We don't want base class to manage reference.
     96     VideoDecoderBase::ManageReference(false);
     97 
     98     if (buffer->data == NULL || buffer->size == 0) {
     99         WTRACE("No config data to start VA.");
    100         return DECODE_SUCCESS;
    101     }
    102 
    103     vbp_data_vp8 *data = NULL;
    104     status = VideoDecoderBase::parseBuffer(buffer->data, buffer->size, true, (void**)&data);
    105     CHECK_STATUS("VideoDecoderBase::parseBuffer");
    106 
    107     status = startVA(data);
    108     return status;
    109 }
    110 
    111 void VideoDecoderVP8::stop(void) {
    112     VideoDecoderBase::stop();
    113 
    114     invalidateReferenceFrames(0);
    115     invalidateReferenceFrames(1);
    116 }
    117 
    118 void VideoDecoderVP8::flush(void) {
    119     VideoDecoderBase::flush();
    120 
    121     invalidateReferenceFrames(0);
    122     invalidateReferenceFrames(1);
    123 }
    124 
    125 Decode_Status VideoDecoderVP8::decode(VideoDecodeBuffer *buffer) {
    126     Decode_Status status;
    127     vbp_data_vp8 *data = NULL;
    128     if (buffer == NULL) {
    129         ETRACE("VideoDecodeBuffer is NULL.");
    130         return DECODE_INVALID_DATA;
    131     }
    132 
    133     status = VideoDecoderBase::parseBuffer(
    134                  buffer->data,
    135                  buffer->size,
    136                  false,
    137                  (void**)&data);
    138     CHECK_STATUS("VideoDecoderBase::parseBuffer");
    139 
    140     mShowFrame = data->codec_data->show_frame;
    141 
    142     if (!mVAStarted) {
    143         status = startVA(data);
    144         CHECK_STATUS("startVA");
    145     }
    146 
    147     VideoDecoderBase::setRotationDegrees(buffer->rotationDegrees);
    148 
    149     status = decodeFrame(buffer, data);
    150 
    151     return status;
    152 }
    153 
    154 Decode_Status VideoDecoderVP8::decodeFrame(VideoDecodeBuffer* buffer, vbp_data_vp8 *data) {
    155     Decode_Status status;
    156     bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
    157     mCurrentPTS = buffer->timeStamp;
    158     if (0 == data->num_pictures || NULL == data->pic_data) {
    159         WTRACE("Number of pictures is 0.");
    160         return DECODE_SUCCESS;
    161     }
    162 
    163     if (VP8_KEY_FRAME == data->codec_data->frame_type) {
    164         if (mSizeChanged && !useGraphicbuffer){
    165             mSizeChanged = false;
    166             return DECODE_FORMAT_CHANGE;
    167         } else {
    168             updateFormatInfo(data);
    169             bool noNeedFlush = false;
    170             if (useGraphicbuffer) {
    171                 noNeedFlush = (mVideoFormatInfo.width <= mVideoFormatInfo.surfaceWidth)
    172                         && (mVideoFormatInfo.height <= mVideoFormatInfo.surfaceHeight);
    173             }
    174             if (mSizeChanged == true && !noNeedFlush) {
    175                 flushSurfaceBuffers();
    176                 mSizeChanged = false;
    177                 return DECODE_FORMAT_CHANGE;
    178             }
    179         }
    180     }
    181 
    182     if (data->codec_data->frame_type == VP8_SKIPPED_FRAME) {
    183         // Do nothing for skip frame as the last frame will be rendered agian by natively
    184         return DECODE_SUCCESS;
    185     }
    186 
    187     status = acquireSurfaceBuffer();
    188     CHECK_STATUS("acquireSurfaceBuffer");
    189 
    190     // set referenceFrame to true if frame decoded is I/P frame, false otherwise.
    191     int frameType = data->codec_data->frame_type;
    192     mAcquiredBuffer->referenceFrame = (frameType == VP8_KEY_FRAME || frameType == VP8_INTER_FRAME);
    193     // assume it is frame picture.
    194     mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
    195     mAcquiredBuffer->renderBuffer.timeStamp = buffer->timeStamp;
    196     mAcquiredBuffer->renderBuffer.flag = 0;
    197     if (buffer->flag & WANT_DECODE_ONLY) {
    198         mAcquiredBuffer->renderBuffer.flag |= WANT_DECODE_ONLY;
    199     }
    200     if (mSizeChanged) {
    201         mSizeChanged = false;
    202         mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
    203     }
    204 
    205     // Here data->num_pictures is always equal to 1
    206     for (uint32_t index = 0; index < data->num_pictures; index++) {
    207         status = decodePicture(data, index);
    208         if (status != DECODE_SUCCESS) {
    209             endDecodingFrame(true);
    210             return status;
    211         }
    212     }
    213 
    214     if (frameType != VP8_SKIPPED_FRAME) {
    215         updateReferenceFrames(data);
    216     }
    217 
    218     // if sample is successfully decoded, call outputSurfaceBuffer(); otherwise
    219     // call releaseSurfacebuffer();
    220     status = outputSurfaceBuffer();
    221     return status;
    222 }
    223 
    224 Decode_Status VideoDecoderVP8::decodePicture(vbp_data_vp8 *data, int32_t picIndex) {
    225     VAStatus vaStatus = VA_STATUS_SUCCESS;
    226     Decode_Status status;
    227     uint32_t bufferIDCount = 0;
    228     VABufferID bufferIDs[5];
    229 
    230     vbp_picture_data_vp8 *picData = &(data->pic_data[picIndex]);
    231     VAPictureParameterBufferVP8 *picParams = picData->pic_parms;
    232 
    233     status = setReference(picParams);
    234     CHECK_STATUS("setReference");
    235 
    236     vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
    237     CHECK_VA_STATUS("vaBeginPicture");
    238     // setting mDecodingFrame to true so vaEndPicture will be invoked to end the picture decoding.
    239     mDecodingFrame = true;
    240 
    241     vaStatus = vaCreateBuffer(
    242                    mVADisplay,
    243                    mVAContext,
    244                    VAPictureParameterBufferType,
    245                    sizeof(VAPictureParameterBufferVP8),
    246                    1,
    247                    picParams,
    248                    &bufferIDs[bufferIDCount]);
    249     CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
    250     bufferIDCount++;
    251 
    252     vaStatus = vaCreateBuffer(
    253                    mVADisplay,
    254                    mVAContext,
    255                    VAProbabilityBufferType,
    256                    sizeof(VAProbabilityDataBufferVP8),
    257                    1,
    258                    data->prob_data,
    259                    &bufferIDs[bufferIDCount]);
    260     CHECK_VA_STATUS("vaCreateProbabilityBuffer");
    261     bufferIDCount++;
    262 
    263     vaStatus = vaCreateBuffer(
    264                    mVADisplay,
    265                    mVAContext,
    266                    VAIQMatrixBufferType,
    267                    sizeof(VAIQMatrixBufferVP8),
    268                    1,
    269                    data->IQ_matrix_buf,
    270                    &bufferIDs[bufferIDCount]);
    271     CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
    272     bufferIDCount++;
    273 
    274     /* Here picData->num_slices is always equal to 1 */
    275     for (uint32_t i = 0; i < picData->num_slices; i++) {
    276         vaStatus = vaCreateBuffer(
    277                        mVADisplay,
    278                        mVAContext,
    279                        VASliceParameterBufferType,
    280                        sizeof(VASliceParameterBufferVP8),
    281                        1,
    282                        &(picData->slc_data[i].slc_parms),
    283                        &bufferIDs[bufferIDCount]);
    284         CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
    285         bufferIDCount++;
    286 
    287         vaStatus = vaCreateBuffer(
    288                        mVADisplay,
    289                        mVAContext,
    290                        VASliceDataBufferType,
    291                        picData->slc_data[i].slice_size, //size
    292                        1,        //num_elements
    293                        picData->slc_data[i].buffer_addr + picData->slc_data[i].slice_offset,
    294                        &bufferIDs[bufferIDCount]);
    295         CHECK_VA_STATUS("vaCreateSliceDataBuffer");
    296         bufferIDCount++;
    297     }
    298 
    299     vaStatus = vaRenderPicture(
    300                    mVADisplay,
    301                    mVAContext,
    302                    bufferIDs,
    303                    bufferIDCount);
    304     CHECK_VA_STATUS("vaRenderPicture");
    305 
    306     vaStatus = vaEndPicture(mVADisplay, mVAContext);
    307     mDecodingFrame = false;
    308     CHECK_VA_STATUS("vaEndPicture");
    309 
    310     return DECODE_SUCCESS;
    311 }
    312 
    313 Decode_Status VideoDecoderVP8::setReference(VAPictureParameterBufferVP8 *picParam) {
    314     int frameType = picParam->pic_fields.bits.key_frame;
    315     switch (frameType) {
    316     case VP8_KEY_FRAME:
    317         picParam->last_ref_frame = VA_INVALID_SURFACE;
    318         picParam->alt_ref_frame = VA_INVALID_SURFACE;
    319         picParam->golden_ref_frame = VA_INVALID_SURFACE;
    320         break;
    321     case VP8_INTER_FRAME:
    322         if (mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer   == NULL ||
    323                 mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer    == NULL ||
    324                 mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer == NULL) {
    325             mAcquiredBuffer->renderBuffer.errBuf.errorNumber = 1;
    326             mAcquiredBuffer->renderBuffer.errBuf.errorArray[0].type = DecodeRefMissing;
    327             return DECODE_NO_REFERENCE;
    328         }
    329         //mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer = mLastReference;
    330         picParam->last_ref_frame = mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer->renderBuffer.surface;
    331         picParam->alt_ref_frame = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer->renderBuffer.surface;
    332         picParam->golden_ref_frame = mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer->renderBuffer.surface;
    333         break;
    334     case VP8_SKIPPED_FRAME:
    335         // will never happen here
    336         break;
    337     default:
    338         return DECODE_PARSER_FAIL;
    339     }
    340 
    341     return DECODE_SUCCESS;
    342 }
    343 
    344 void VideoDecoderVP8::updateReferenceFrames(vbp_data_vp8 *data) {
    345     /* Refresh last frame reference buffer using the currently reconstructed frame */
    346     refreshLastReference(data);
    347 
    348     /* Refresh golden frame reference buffer using the currently reconstructed frame */
    349     refreshGoldenReference(data);
    350 
    351     /* Refresh alternative frame reference buffer using the currently reconstructed frame */
    352     refreshAltReference(data);
    353 
    354     /* Update reference frames */
    355     for (int i = 0; i < VP8_REF_SIZE; i++) {
    356         VideoSurfaceBuffer *p = mRFBs[1][i].surfaceBuffer;
    357         int j;
    358         for (j = 0; j < VP8_REF_SIZE; j++) {
    359             if (p == mRFBs[0][j].surfaceBuffer) {
    360                 break;
    361             }
    362         }
    363         if (j == VP8_REF_SIZE) {
    364             clearAsReference(1, i);
    365         }
    366     }
    367 }
    368 
    369 void VideoDecoderVP8::refreshLastReference(vbp_data_vp8 *data) {
    370     /* Save previous last reference */
    371     mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer = mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer;
    372     mRFBs[1][VP8_LAST_REF_PIC].index = mRFBs[0][VP8_LAST_REF_PIC].index;
    373 
    374     /* For key frame, this is always true */
    375     if (data->codec_data->refresh_last_frame) {
    376         mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer = mAcquiredBuffer;
    377         mRFBs[0][VP8_LAST_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
    378         mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer->asReferernce = true;
    379     }
    380 }
    381 
    382 void VideoDecoderVP8::refreshGoldenReference(vbp_data_vp8 *data) {
    383     /* Save previous golden reference */
    384     mRFBs[1][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer;
    385     mRFBs[1][VP8_GOLDEN_REF_PIC].index = mRFBs[0][VP8_GOLDEN_REF_PIC].index;
    386 
    387     if (data->codec_data->golden_copied != BufferCopied_NoneToGolden) {
    388         if (data->codec_data->golden_copied == BufferCopied_LastToGolden) {
    389             /* LastFrame is copied to GoldenFrame */
    390             mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer;
    391             mRFBs[0][VP8_GOLDEN_REF_PIC].index = mRFBs[1][VP8_LAST_REF_PIC].index;
    392         } else if (data->codec_data->golden_copied == BufferCopied_AltRefToGolden) {
    393             /* AltRefFrame is copied to GoldenFrame */
    394             mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer;
    395             mRFBs[0][VP8_GOLDEN_REF_PIC].index = mRFBs[0][VP8_ALT_REF_PIC].index;
    396         }
    397     }
    398 
    399     /* For key frame, this is always true */
    400     if (data->codec_data->refresh_golden_frame) {
    401         mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mAcquiredBuffer;
    402         mRFBs[0][VP8_GOLDEN_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
    403         mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer->asReferernce = true;
    404     }
    405 }
    406 
    407 void VideoDecoderVP8::refreshAltReference(vbp_data_vp8 *data) {
    408     /* Save previous alternative reference */
    409     mRFBs[1][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer;
    410     mRFBs[1][VP8_ALT_REF_PIC].index = mRFBs[0][VP8_ALT_REF_PIC].index;
    411 
    412     if (data->codec_data->altref_copied != BufferCopied_NoneToAltRef) {
    413         if (data->codec_data->altref_copied == BufferCopied_LastToAltRef) {
    414             /* LastFrame is copied to AltRefFrame */
    415             mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer;
    416             mRFBs[0][VP8_ALT_REF_PIC].index = mRFBs[1][VP8_LAST_REF_PIC].index;
    417         } else if (data->codec_data->altref_copied == BufferCopied_GoldenToAltRef) {
    418             /* GoldenFrame is copied to AltRefFrame */
    419             mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[1][VP8_GOLDEN_REF_PIC].surfaceBuffer;
    420             mRFBs[0][VP8_ALT_REF_PIC].index = mRFBs[1][VP8_GOLDEN_REF_PIC].index;
    421         }
    422     }
    423 
    424     /* For key frame, this is always true */
    425     if (data->codec_data->refresh_alt_frame) {
    426         mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mAcquiredBuffer;
    427         mRFBs[0][VP8_ALT_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
    428         mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer->asReferernce = true;
    429     }
    430 }
    431 
    432 
    433 Decode_Status VideoDecoderVP8::checkHardwareCapability() {
    434     VAStatus vaStatus;
    435     VAConfigAttrib cfgAttribs[2];
    436     cfgAttribs[0].type = VAConfigAttribMaxPictureWidth;
    437     cfgAttribs[1].type = VAConfigAttribMaxPictureHeight;
    438     vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileVP8Version0_3,
    439             VAEntrypointVLD, cfgAttribs, 2);
    440     CHECK_VA_STATUS("vaGetConfigAttributes");
    441     if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) {
    442         ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d",
    443                 cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height);
    444         return DECODE_DRIVER_FAIL;
    445     }
    446 
    447     return DECODE_SUCCESS;
    448 }
    449 
    450