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 "VideoDecoderWMV.h"
     18 #include "VideoDecoderTrace.h"
     19 #include <string.h>
     20 
     21 VideoDecoderWMV::VideoDecoderWMV(const char *mimeType)
     22     : VideoDecoderBase(mimeType, VBP_VC1),
     23       mBufferIDs(NULL),
     24       mNumBufferIDs(0),
     25       mConfigDataParsed(false),
     26       mRangeMapped(false),
     27       mDeblockedCurrPicIndex(0),
     28       mDeblockedLastPicIndex(1),
     29       mDeblockedForwardPicIndex(2) {
     30 }
     31 
     32 
     33 VideoDecoderWMV::~VideoDecoderWMV() {
     34     stop();
     35 }
     36 
     37 Decode_Status VideoDecoderWMV::start(VideoConfigBuffer *buffer) {
     38     Decode_Status status;
     39 
     40     status = VideoDecoderBase::start(buffer);
     41     CHECK_STATUS("VideoDecoderBase::start");
     42 
     43     if (buffer->data == NULL || buffer->size == 0) {
     44         WTRACE("No config data to start VA.");
     45         return DECODE_SUCCESS;
     46     }
     47 
     48     vbp_data_vc1 *data = NULL;
     49     status = parseBuffer(buffer->data, buffer->size, &data);
     50     CHECK_STATUS("parseBuffer");
     51 
     52     status = startVA(data);
     53     return status;
     54 }
     55 
     56 void VideoDecoderWMV::stop(void) {
     57     if (mBufferIDs) {
     58         delete [] mBufferIDs;
     59         mBufferIDs = NULL;
     60     }
     61     mNumBufferIDs = 0;
     62     mConfigDataParsed = false;
     63     mRangeMapped = false;
     64 
     65     mDeblockedCurrPicIndex = 0;
     66     mDeblockedLastPicIndex = 1;
     67     mDeblockedForwardPicIndex = 2;
     68 
     69     VideoDecoderBase::stop();
     70 }
     71 
     72 void VideoDecoderWMV::flush(void) {
     73     VideoDecoderBase::flush();
     74 
     75     mRangeMapped = false;
     76     mDeblockedCurrPicIndex = 0;
     77     mDeblockedLastPicIndex = 1;
     78     mDeblockedForwardPicIndex = 2;
     79 }
     80 
     81 Decode_Status VideoDecoderWMV::decode(VideoDecodeBuffer *buffer) {
     82     Decode_Status status;
     83     vbp_data_vc1 *data = NULL;
     84     bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
     85     if (buffer == NULL) {
     86         return DECODE_INVALID_DATA;
     87     }
     88 
     89     status = parseBuffer(buffer->data, buffer->size, &data);
     90     CHECK_STATUS("parseBuffer");
     91 
     92     if (!mVAStarted) {
     93         status = startVA(data);
     94         CHECK_STATUS("startVA");
     95     }
     96 
     97     if (mSizeChanged && !useGraphicbuffer) {
     98         mSizeChanged = false;
     99         return DECODE_FORMAT_CHANGE;
    100     }
    101 
    102     if ((mVideoFormatInfo.width != data->se_data->CODED_WIDTH ||
    103         mVideoFormatInfo.height != data->se_data->CODED_HEIGHT) &&
    104         data->se_data->CODED_WIDTH &&
    105         data->se_data->CODED_HEIGHT) {
    106         ITRACE("video size is changed from %dx%d to %dx%d", mVideoFormatInfo.width, mVideoFormatInfo.height,
    107                 data->se_data->CODED_WIDTH, data->se_data->CODED_HEIGHT);
    108         mVideoFormatInfo.width = data->se_data->CODED_WIDTH;
    109         mVideoFormatInfo.height = data->se_data->CODED_HEIGHT;
    110         bool noNeedFlush = false;
    111         if (useGraphicbuffer) {
    112             noNeedFlush = (mVideoFormatInfo.width <= mVideoFormatInfo.surfaceWidth)
    113                     && (mVideoFormatInfo.height <= mVideoFormatInfo.surfaceHeight);
    114         }
    115 
    116         setRenderRect();
    117 
    118         if (noNeedFlush) {
    119             mSizeChanged = true;
    120         } else {
    121             flushSurfaceBuffers();
    122             mSizeChanged = false;
    123             return DECODE_FORMAT_CHANGE;
    124         }
    125     }
    126 
    127     status = decodeFrame(buffer, data);
    128     CHECK_STATUS("decodeFrame");
    129     return status;
    130 }
    131 
    132 Decode_Status VideoDecoderWMV::decodeFrame(VideoDecodeBuffer* buffer, vbp_data_vc1 *data) {
    133     Decode_Status status;
    134     mCurrentPTS = buffer->timeStamp;
    135     if (0 == data->num_pictures || NULL == data->pic_data) {
    136         WTRACE("Number of pictures is 0, buffer contains configuration data only?");
    137         return DECODE_SUCCESS;
    138     }
    139 
    140     if (data->pic_data[0].picture_is_skipped == VC1_PTYPE_SKIPPED) {
    141 
    142         // Do nothing for skip frame as the last frame will be rendered agian by natively
    143         // No needs to handle reference frame neither
    144         return DECODE_SUCCESS;
    145 #if 0
    146         //use the last P or I frame surface for skipped frame and treat it as P frame
    147         if (mLastReference == NULL) {
    148             // TODO: handle this case
    149             WTRACE("The last reference is unavailable to construct skipped frame.");
    150             return DECODE_SUCCESS;
    151         }
    152 
    153         status = acquireSurfaceBuffer();
    154         CHECK_STATUS("acquireSurfaceBuffer");
    155         mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS;
    156         mAcquiredBuffer->renderBuffer.flag = 0;
    157         mAcquiredBuffer->renderBuffer.scanFormat = mLastReference->renderBuffer.scanFormat;
    158         mAcquiredBuffer->renderBuffer.surface = mLastReference->renderBuffer.surface;
    159         // No need to update mappedData for HW decoding
    160         //mAcquiredBuffer->mappedData.data = mLastReference->mappedData.data;
    161         mAcquiredBuffer->referenceFrame = true;
    162         // let outputSurfaceBuffer handle "asReference" for VC1
    163         status = outputSurfaceBuffer();
    164         return status;
    165 #endif
    166     }
    167 
    168     status = acquireSurfaceBuffer();
    169     CHECK_STATUS("acquireSurfaceBuffer");
    170 
    171     mAcquiredBuffer->renderBuffer.timeStamp = buffer->timeStamp;
    172     if (buffer->flag & HAS_DISCONTINUITY) {
    173         mAcquiredBuffer->renderBuffer.flag |= HAS_DISCONTINUITY;
    174     }
    175     if (buffer->flag & WANT_DECODE_ONLY) {
    176         mAcquiredBuffer->renderBuffer.flag |= WANT_DECODE_ONLY;
    177     }
    178     if (mSizeChanged) {
    179         mSizeChanged = false;
    180         mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
    181     }
    182 
    183     if (data->num_pictures > 1) {
    184         if (data->pic_data[0].pic_parms->picture_fields.bits.is_first_field) {
    185             mAcquiredBuffer->renderBuffer.scanFormat = VA_TOP_FIELD;
    186         } else {
    187             mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD;
    188         }
    189     } else {
    190         mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
    191     }
    192 
    193     mRangeMapped = (data->se_data->RANGE_MAPY_FLAG || data->se_data->RANGE_MAPUV_FLAG || data->se_data->RANGERED);
    194 
    195     int frameType = data->pic_data[0].pic_parms->picture_fields.bits.picture_type;
    196     mAcquiredBuffer->referenceFrame = (frameType == VC1_PTYPE_I || frameType == VC1_PTYPE_P);
    197 
    198     // TODO: handle multiple frames parsed from a sample buffer
    199     int numPictures = (data->num_pictures > 1) ? 2 : 1;
    200 
    201     for (int index = 0; index < numPictures; index++) {
    202         status = decodePicture(data, index);
    203         if (status != DECODE_SUCCESS) {
    204             endDecodingFrame(true);
    205             return status;
    206         }
    207     }
    208 
    209     if (mRangeMapped) {
    210         updateDeblockedPicIndexes(frameType);
    211     }
    212 
    213     // let outputSurfaceBuffer handle "asReference" for VC1
    214     status = outputSurfaceBuffer();
    215     return status;
    216 }
    217 
    218 
    219 Decode_Status VideoDecoderWMV::decodePicture(vbp_data_vc1 *data, int32_t picIndex) {
    220     VAStatus vaStatus = VA_STATUS_SUCCESS;
    221     Decode_Status status;
    222     int32_t bufferIDCount = 0;
    223     vbp_picture_data_vc1 *picData = &(data->pic_data[picIndex]);
    224     VAPictureParameterBufferVC1 *picParams = picData->pic_parms;
    225 
    226     if (picParams == NULL) {
    227         return DECODE_PARSER_FAIL;
    228     }
    229 
    230     status = allocateVABufferIDs(picData->num_slices * 2 + 2);
    231     CHECK_STATUS("allocateVABufferIDs");
    232 
    233     status = setReference(picParams, picIndex, mAcquiredBuffer->renderBuffer.surface);
    234     CHECK_STATUS("setReference");
    235 
    236     if (mRangeMapped) {
    237         // keep the destination surface for the picture after decoding and in-loop filtering
    238         picParams->inloop_decoded_picture = mExtraSurfaces[mDeblockedCurrPicIndex];
    239     } else {
    240         picParams->inloop_decoded_picture = VA_INVALID_SURFACE;
    241     }
    242 
    243     vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
    244     CHECK_VA_STATUS("vaBeginPicture");
    245     // setting mDecodingFrame to true so vaEndPicture will be invoked to end the picture decoding.
    246     mDecodingFrame = true;
    247 
    248     vaStatus = vaCreateBuffer(
    249             mVADisplay,
    250             mVAContext,
    251             VAPictureParameterBufferType,
    252             sizeof(VAPictureParameterBufferVC1),
    253             1,
    254             picParams,
    255             &mBufferIDs[bufferIDCount]);
    256     CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
    257     bufferIDCount++;
    258 
    259     if (picParams->bitplane_present.value) {
    260         vaStatus = vaCreateBuffer(
    261                 mVADisplay,
    262                 mVAContext,
    263                 VABitPlaneBufferType,
    264                 picData->size_bitplanes,
    265                 1,
    266                 picData->packed_bitplanes,
    267                 &mBufferIDs[bufferIDCount]);
    268         CHECK_VA_STATUS("vaCreateBitPlaneBuffer");
    269         bufferIDCount++;
    270     }
    271 
    272     for (uint32_t i = 0; i < picData->num_slices; i++) {
    273         vaStatus = vaCreateBuffer(
    274                 mVADisplay,
    275                 mVAContext,
    276                 VASliceParameterBufferType,
    277                 sizeof(VASliceParameterBufferVC1),
    278                 1,
    279                 &(picData->slc_data[i].slc_parms),
    280                 &mBufferIDs[bufferIDCount]);
    281         CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
    282         bufferIDCount++;
    283 
    284         vaStatus = vaCreateBuffer(
    285                 mVADisplay,
    286                 mVAContext,
    287                 VASliceDataBufferType,
    288                 //size
    289                 picData->slc_data[i].slice_size,
    290                 //num_elements
    291                 1,
    292                 //slice data buffer pointer
    293                 //Note that this is the original data buffer ptr;
    294                 // offset to the actual slice data is provided in
    295                 // slice_data_offset in VASliceParameterBufferVC1
    296                 picData->slc_data[i].buffer_addr + picData->slc_data[i].slice_offset,
    297                 &mBufferIDs[bufferIDCount]);
    298         CHECK_VA_STATUS("vaCreateSliceDataBuffer");
    299         bufferIDCount++;
    300     }
    301 
    302     vaStatus = vaRenderPicture(
    303             mVADisplay,
    304             mVAContext,
    305             mBufferIDs,
    306             bufferIDCount);
    307     CHECK_VA_STATUS("vaRenderPicture");
    308 
    309     vaStatus = vaEndPicture(mVADisplay, mVAContext);
    310     mDecodingFrame = false;
    311     CHECK_VA_STATUS("vaRenderPicture");
    312 
    313     return DECODE_SUCCESS;
    314 }
    315 
    316 
    317 Decode_Status VideoDecoderWMV::setReference(
    318         VAPictureParameterBufferVC1 *params,
    319         int32_t picIndex,
    320         VASurfaceID current) {
    321     int frameType = params->picture_fields.bits.picture_type;
    322     switch (frameType) {
    323         case VC1_PTYPE_I:
    324             params->forward_reference_picture = current;
    325             params->backward_reference_picture = current;
    326             break;
    327         case VC1_PTYPE_P:
    328             // check REFDIST in the picture parameter buffer
    329             if (0 != params->reference_fields.bits.reference_distance_flag &&
    330                 0 != params->reference_fields.bits.reference_distance) {
    331                 /* The previous decoded frame (distance is up to 16 but not 0) is used
    332                             for reference. Not supported here.
    333                             */
    334                 return DECODE_NO_REFERENCE;
    335             }
    336             if (1 == picIndex) {
    337                 // handle interlace field coding case
    338                 if (1 == params->reference_fields.bits.num_reference_pictures ||
    339                     1 == params->reference_fields.bits.reference_field_pic_indicator) {
    340                     /*
    341                                     two reference fields or the second closest I/P field is used for
    342                                     prediction. Set forward reference picture to INVALID so it will be
    343                                     updated to a valid previous reconstructed reference frame later.
    344                                     */
    345                     params->forward_reference_picture = VA_INVALID_SURFACE;
    346                 } else {
    347                    /* the closest I/P is used for reference so it must be the
    348                                   complementary field in the same surface.
    349                                  */
    350                     params->forward_reference_picture = current;
    351                 }
    352             }
    353             if (VA_INVALID_SURFACE == params->forward_reference_picture) {
    354                 if (mLastReference == NULL) {
    355                     return DECODE_NO_REFERENCE;
    356                 }
    357                 params->forward_reference_picture = mLastReference->renderBuffer.surface;
    358             }
    359             params->backward_reference_picture = VA_INVALID_SURFACE;
    360             break;
    361         case VC1_PTYPE_B:
    362             if (mForwardReference == NULL || mLastReference == NULL) {
    363                 return DECODE_NO_REFERENCE;
    364             }
    365             params->forward_reference_picture = mForwardReference->renderBuffer.surface;
    366             params->backward_reference_picture = mLastReference->renderBuffer.surface;
    367             break;
    368         case VC1_PTYPE_BI:
    369             params->forward_reference_picture = VA_INVALID_SURFACE;
    370             params->backward_reference_picture = VA_INVALID_SURFACE;
    371             break;
    372         case VC1_PTYPE_SKIPPED:
    373             //Will never happen here
    374             break;
    375         default:
    376             break;
    377     }
    378     return DECODE_SUCCESS;
    379 }
    380 
    381 void VideoDecoderWMV::updateDeblockedPicIndexes(int frameType) {
    382     int32_t curPicIndex = mDeblockedCurrPicIndex;
    383 
    384     /* Out Loop (range map) buffers */
    385     if (frameType != VC1_PTYPE_SKIPPED) {
    386         if ((frameType == VC1_PTYPE_I) || (frameType == VC1_PTYPE_P)) {
    387             mDeblockedCurrPicIndex = mDeblockedLastPicIndex;
    388             mDeblockedLastPicIndex = curPicIndex;
    389         } else {
    390             mDeblockedCurrPicIndex = mDeblockedForwardPicIndex;
    391             mDeblockedForwardPicIndex = curPicIndex;
    392         }
    393     }
    394 }
    395 
    396 Decode_Status VideoDecoderWMV::updateConfigData(
    397         uint8_t *configData,
    398         int32_t configDataLen,
    399         uint8_t **newConfigData,
    400         int32_t* newConfigDataLen) {
    401     int32_t i = 0;
    402     uint8_t *p = configData;
    403 
    404     /* Check for start codes.  If one exist, then this is VC-1 and not WMV. */
    405     while (i < configDataLen - 2) {
    406         if ((p[i] == 0) &&
    407             (p[i + 1] == 0) &&
    408             (p[i + 2] == 1)) {
    409             *newConfigData = NULL;
    410             *newConfigDataLen = 0;
    411             return DECODE_SUCCESS;
    412         }
    413         i++;
    414     }
    415 
    416     *newConfigDataLen = configDataLen + 9;
    417     p = *newConfigData = new uint8_t [*newConfigDataLen];
    418     if (!p) {
    419        return DECODE_MEMORY_FAIL;
    420     }
    421 
    422     /* If we get here we have 4+ bytes of codec data that must be formatted */
    423     /* to pass through as an RCV sequence header. */
    424     p[0] = 0;
    425     p[1] = 0;
    426     p[2] = 1;
    427     p[3] = 0x0f;  /* Start code. */
    428     p[4] = (mVideoFormatInfo.width >> 8) & 0x0ff;
    429     p[5] = mVideoFormatInfo.width & 0x0ff;
    430     p[6] = (mVideoFormatInfo.height >> 8) & 0x0ff;
    431     p[7] = mVideoFormatInfo.height & 0x0ff;
    432 
    433     memcpy(p + 8, configData, configDataLen);
    434     *(p + configDataLen + 8) = 0x80;
    435 
    436     return DECODE_SUCCESS;
    437 }
    438 
    439 Decode_Status VideoDecoderWMV::startVA(vbp_data_vc1 *data) {
    440     updateFormatInfo(data);
    441 
    442     VAProfile vaProfile;
    443     switch (data->se_data->PROFILE) {
    444         case 0:
    445         vaProfile = VAProfileVC1Simple;
    446         break;
    447         case 1:
    448         vaProfile = VAProfileVC1Main;
    449         break;
    450         default:
    451         vaProfile = VAProfileVC1Advanced;
    452         break;
    453     }
    454 
    455     return VideoDecoderBase::setupVA(VC1_SURFACE_NUMBER, vaProfile, VC1_EXTRA_SURFACE_NUMBER);
    456 }
    457 
    458 void VideoDecoderWMV::updateFormatInfo(vbp_data_vc1 *data) {
    459     ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
    460         mVideoFormatInfo.width, mVideoFormatInfo.height,
    461         data->se_data->CODED_WIDTH, data->se_data->CODED_HEIGHT);
    462 
    463     mVideoFormatInfo.cropBottom = data->se_data->CODED_HEIGHT > mVideoFormatInfo.height ?
    464                                                                            data->se_data->CODED_HEIGHT - mVideoFormatInfo.height : 0;
    465     mVideoFormatInfo.cropRight = data->se_data->CODED_WIDTH > mVideoFormatInfo.width ?
    466                                                                       data->se_data->CODED_WIDTH - mVideoFormatInfo.width : 0;
    467 
    468      if ((mVideoFormatInfo.width != data->se_data->CODED_WIDTH ||
    469         mVideoFormatInfo.height != data->se_data->CODED_HEIGHT) &&
    470         data->se_data->CODED_WIDTH &&
    471         data->se_data->CODED_HEIGHT) {
    472         // encoded image size
    473         mVideoFormatInfo.width = data->se_data->CODED_WIDTH;
    474         mVideoFormatInfo.height = data->se_data->CODED_HEIGHT;
    475         mSizeChanged = true;
    476         ITRACE("Video size is changed.");
    477     }
    478 
    479     // scaling has been performed on the decoded image.
    480     mVideoFormatInfo.videoRange = 1;
    481 
    482     switch (data->se_data->MATRIX_COEF) {
    483         case 1:
    484             mVideoFormatInfo.colorMatrix = VA_SRC_BT709;
    485             break;
    486         // ITU-R BT.1700, ITU-R BT.601-5, and SMPTE 293M-1996.
    487         case 6:
    488             mVideoFormatInfo.colorMatrix = VA_SRC_BT601;
    489             break;
    490         default:
    491             // unknown color matrix, set to 0 so color space flag will not be set.
    492             mVideoFormatInfo.colorMatrix = 0;
    493             break;
    494     }
    495 
    496     mVideoFormatInfo.aspectX = data->se_data->ASPECT_HORIZ_SIZE;
    497     mVideoFormatInfo.aspectY = data->se_data->ASPECT_VERT_SIZE;
    498     mVideoFormatInfo.bitrate = 0; //data->se_data->bitrate;
    499     mVideoFormatInfo.valid = true;
    500 
    501     setRenderRect();
    502 }
    503 
    504 Decode_Status VideoDecoderWMV::allocateVABufferIDs(int32_t number) {
    505     if (mNumBufferIDs > number) {
    506         return DECODE_SUCCESS;
    507     }
    508     if (mBufferIDs) {
    509         delete [] mBufferIDs;
    510     }
    511     mBufferIDs = NULL;
    512     mNumBufferIDs = 0;
    513     mBufferIDs = new VABufferID [number];
    514     if (mBufferIDs == NULL) {
    515         return DECODE_MEMORY_FAIL;
    516     }
    517     mNumBufferIDs = number;
    518     return DECODE_SUCCESS;
    519 }
    520 
    521 Decode_Status VideoDecoderWMV::parseBuffer(uint8_t *data, int32_t size, vbp_data_vc1 **vbpData) {
    522     Decode_Status status;
    523 
    524     if (data == NULL || size == 0) {
    525         return DECODE_INVALID_DATA;
    526     }
    527 
    528     if (mConfigDataParsed) {
    529         status = VideoDecoderBase::parseBuffer(data, size, false, (void**)vbpData);
    530         CHECK_STATUS("VideoDecoderBase::parseBuffer");
    531     } else {
    532         uint8_t *newData = NULL;
    533         int32_t newSize = 0;
    534         status = updateConfigData(data, size, &newData, &newSize);
    535         CHECK_STATUS("updateConfigData");
    536 
    537         if (newSize) {
    538             status = VideoDecoderBase::parseBuffer(newData, newSize, true, (void**)vbpData);
    539             delete [] newData;
    540         } else {
    541             status = VideoDecoderBase::parseBuffer(data, size, true, (void**)vbpData);
    542         }
    543         CHECK_STATUS("VideoDecoderBase::parseBuffer");
    544         mConfigDataParsed = true;
    545     }
    546     return DECODE_SUCCESS;
    547 }
    548 
    549 
    550 Decode_Status VideoDecoderWMV::checkHardwareCapability() {
    551 #ifndef USE_GEN_HW
    552     VAStatus vaStatus;
    553     VAConfigAttrib cfgAttribs[2];
    554     cfgAttribs[0].type = VAConfigAttribMaxPictureWidth;
    555     cfgAttribs[1].type = VAConfigAttribMaxPictureHeight;
    556     vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileVC1Advanced,
    557             VAEntrypointVLD, cfgAttribs, 2);
    558     CHECK_VA_STATUS("vaGetConfigAttributes");
    559     if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) {
    560         ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d",
    561                 cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height);
    562         return DECODE_DRIVER_FAIL;
    563     }
    564 #endif
    565     return DECODE_SUCCESS;
    566 }
    567 
    568 
    569