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