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