Home | History | Annotate | Download | only in baytrail
      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 "va_private.h"
     18 #include "VideoDecoderAVCSecure.h"
     19 #include "VideoDecoderTrace.h"
     20 #include <string.h>
     21 
     22 #define STARTCODE_PREFIX_LEN        3
     23 #define NALU_TYPE_MASK              0x1F
     24 #define MAX_NALU_HEADER_BUFFER      8192
     25 static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
     26 
     27 VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
     28     : VideoDecoderAVC(mimeType),
     29       mNaluHeaderBuffer(NULL),
     30       mSliceHeaderBuffer(NULL) {
     31     setParserType(VBP_H264SECURE);
     32 }
     33 
     34 VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
     35 }
     36 
     37 Decode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
     38     Decode_Status status = VideoDecoderAVC::start(buffer);
     39     if (status != DECODE_SUCCESS) {
     40         return status;
     41     }
     42 
     43     mNaluHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
     44 
     45     if (mNaluHeaderBuffer == NULL) {
     46         ETRACE("Failed to allocate memory for mNaluHeaderBuffer");
     47         return DECODE_MEMORY_FAIL;
     48     }
     49 
     50     mSliceHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
     51     if (mSliceHeaderBuffer == NULL) {
     52         ETRACE("Failed to allocate memory for mSliceHeaderBuffer");
     53         if (mNaluHeaderBuffer) {
     54             delete [] mNaluHeaderBuffer;
     55             mNaluHeaderBuffer = NULL;
     56         }
     57         return DECODE_MEMORY_FAIL;
     58     }
     59 
     60     return status;
     61 }
     62 
     63 void VideoDecoderAVCSecure::stop(void) {
     64     VideoDecoderAVC::stop();
     65 
     66     if (mNaluHeaderBuffer) {
     67         delete [] mNaluHeaderBuffer;
     68         mNaluHeaderBuffer = NULL;
     69     }
     70 
     71     if (mSliceHeaderBuffer) {
     72         delete [] mSliceHeaderBuffer;
     73         mSliceHeaderBuffer = NULL;
     74     }
     75 
     76 }
     77 
     78 Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
     79     Decode_Status status;
     80     int32_t sizeAccumulated = 0;
     81     int32_t sliceHeaderSize = 0;
     82     int32_t sizeLeft = 0;
     83     int32_t sliceIdx = 0;
     84     uint8_t naluType;
     85     frame_info_t* pFrameInfo;
     86 
     87     mFrameSize = 0;
     88     if (buffer->flag & IS_SECURE_DATA) {
     89         VTRACE("Decoding protected video ...");
     90         mIsEncryptData = 1;
     91     } else {
     92         VTRACE("Decoding clear video ...");
     93         mIsEncryptData = 0;
     94         return VideoDecoderAVC::decode(buffer);
     95     }
     96 
     97     if (buffer->size != sizeof(frame_info_t)) {
     98         ETRACE("Not enough data to read frame_info_t!");
     99         return DECODE_INVALID_DATA;
    100     }
    101     pFrameInfo = (frame_info_t*) buffer->data;
    102 
    103     mFrameSize = pFrameInfo->length;
    104     VTRACE("mFrameSize = %d", mFrameSize);
    105 
    106     memcpy(&mEncParam, pFrameInfo->pavp, sizeof(pavp_info_t));
    107     for (int32_t i = 0; i < pFrameInfo->num_nalus; i++) {
    108         naluType = pFrameInfo->nalus[i].type & NALU_TYPE_MASK;
    109         if (naluType >= h264_NAL_UNIT_TYPE_SLICE && naluType <= h264_NAL_UNIT_TYPE_IDR) {
    110             memcpy(mSliceHeaderBuffer + sliceHeaderSize,
    111                 &sliceIdx,
    112                 sizeof(int32_t));
    113             sliceHeaderSize += 4;
    114 
    115             memcpy(mSliceHeaderBuffer + sliceHeaderSize,
    116                 &pFrameInfo->data,
    117                 sizeof(uint8_t*));
    118             sliceHeaderSize += sizeof(uint8_t*);
    119 
    120             memcpy(mSliceHeaderBuffer + sliceHeaderSize,
    121                 &pFrameInfo->nalus[i].offset,
    122                 sizeof(uint32_t));
    123             sliceHeaderSize += sizeof(uint32_t);
    124 
    125             memcpy(mSliceHeaderBuffer + sliceHeaderSize,
    126                 &pFrameInfo->nalus[i].length,
    127                 sizeof(uint32_t));
    128             sliceHeaderSize += sizeof(uint32_t);
    129 
    130             memcpy(mSliceHeaderBuffer + sliceHeaderSize,
    131                 pFrameInfo->nalus[i].slice_header,
    132                 sizeof(slice_header_t));
    133             sliceHeaderSize += sizeof(slice_header_t);
    134             if (pFrameInfo->nalus[i].type & 0x60) {
    135                 memcpy(mSliceHeaderBuffer+sliceHeaderSize, pFrameInfo->dec_ref_pic_marking, sizeof(dec_ref_pic_marking_t));
    136             } else {
    137                 memset(mSliceHeaderBuffer+sliceHeaderSize, 0, sizeof(dec_ref_pic_marking_t));
    138             }
    139             sliceHeaderSize += sizeof(dec_ref_pic_marking_t);
    140             sliceIdx++;
    141         } else if (naluType >= h264_NAL_UNIT_TYPE_SEI && naluType <= h264_NAL_UNIT_TYPE_PPS) {
    142             memcpy(mNaluHeaderBuffer + sizeAccumulated,
    143                 startcodePrefix,
    144                 STARTCODE_PREFIX_LEN);
    145             sizeAccumulated += STARTCODE_PREFIX_LEN;
    146             memcpy(mNaluHeaderBuffer + sizeAccumulated,
    147                 pFrameInfo->nalus[i].data,
    148                 pFrameInfo->nalus[i].length);
    149             sizeAccumulated += pFrameInfo->nalus[i].length;
    150         } else {
    151             WTRACE("Failure: DECODE_FRAME_DROPPED");
    152             return DECODE_FRAME_DROPPED;
    153         }
    154     }
    155 
    156     vbp_data_h264 *data = NULL;
    157     int new_sequence_to_handle = 0;
    158 
    159     if (sizeAccumulated > 0) {
    160         status =  VideoDecoderBase::parseBuffer(
    161                 mNaluHeaderBuffer,
    162                 sizeAccumulated,
    163                 false,
    164                 (void**)&data);
    165         CHECK_STATUS("VideoDecoderBase::parseBuffer");
    166 
    167         // [FIX DRC zoom issue] if one buffer contains more than one nalu
    168         // for example SPS+PPS+IDR, new_sps/new_pps flags set in parseBuffer
    169         // will be flushed in the following updateBuffer.
    170         // So that handleNewSequence will not be handled in decodeFrame()
    171         if (data->new_sps || data->new_pps) {
    172             new_sequence_to_handle = 1;
    173         }
    174     }
    175 
    176     if (sliceHeaderSize > 0) {
    177         memset(mSliceHeaderBuffer + sliceHeaderSize, 0xFF, 4);
    178         sliceHeaderSize += 4;
    179         status =  VideoDecoderBase::updateBuffer(
    180                 mSliceHeaderBuffer,
    181                 sliceHeaderSize,
    182                 (void**)&data);
    183         CHECK_STATUS("VideoDecoderBase::updateBuffer");
    184 
    185         // in case the flags were flushed but indeed new sequence needed to be handled.
    186         if ((1 == new_sequence_to_handle) &&
    187             ((data->new_sps == 0) || (data->new_pps == 0))) {
    188             data->new_sps = 1;
    189             data->new_pps = 1;
    190         }
    191     }
    192 
    193     if (data == NULL) {
    194         ETRACE("Invalid data returned by parser!");
    195         return DECODE_MEMORY_FAIL;
    196     }
    197 
    198     if (!mVAStarted) {
    199          if (data->has_sps && data->has_pps) {
    200             status = startVA(data);
    201             CHECK_STATUS("startVA");
    202         } else {
    203             WTRACE("Can't start VA as either SPS or PPS is still not available.");
    204             return DECODE_SUCCESS;
    205         }
    206     }
    207     status = decodeFrame(buffer, data);
    208     return status;
    209 }
    210 
    211 Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
    212     Decode_Status status;
    213     VAStatus vaStatus;
    214     uint32_t bufferIDCount = 0;
    215     // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
    216     VABufferID bufferIDs[5];
    217 
    218     vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
    219     vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
    220     VAPictureParameterBufferH264 *picParam = picData->pic_parms;
    221     VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
    222     VAEncryptionParameterBuffer encryptParam;
    223 
    224     if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
    225         // either condition indicates start of a new frame
    226         if (sliceParam->first_mb_in_slice != 0) {
    227             WTRACE("The first slice is lost.");
    228             // TODO: handle the first slice lost
    229         }
    230         if (mDecodingFrame) {
    231             // interlace content, complete decoding the first field
    232             vaStatus = vaEndPicture(mVADisplay, mVAContext);
    233             CHECK_VA_STATUS("vaEndPicture");
    234 
    235             // for interlace content, top field may be valid only after the second field is parsed
    236             mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
    237         }
    238 
    239         // Update  the reference frames and surface IDs for DPB and current frame
    240         status = updateDPB(picParam);
    241         CHECK_STATUS("updateDPB");
    242 
    243         vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
    244         CHECK_VA_STATUS("vaBeginPicture");
    245 
    246         // start decoding a frame
    247         mDecodingFrame = true;
    248 
    249         vaStatus = vaCreateBuffer(
    250             mVADisplay,
    251             mVAContext,
    252             VAPictureParameterBufferType,
    253             sizeof(VAPictureParameterBufferH264),
    254             1,
    255             picParam,
    256             &bufferIDs[bufferIDCount]);
    257         CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
    258         bufferIDCount++;
    259 
    260         vaStatus = vaCreateBuffer(
    261             mVADisplay,
    262             mVAContext,
    263             VAIQMatrixBufferType,
    264             sizeof(VAIQMatrixBufferH264),
    265             1,
    266             data->IQ_matrix_buf,
    267             &bufferIDs[bufferIDCount]);
    268         CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
    269         bufferIDCount++;
    270 
    271         if (mIsEncryptData) {
    272             memset(&encryptParam, 0, sizeof(VAEncryptionParameterBuffer));
    273             encryptParam.pavpCounterMode = 4;
    274             encryptParam.pavpEncryptionType = 2;
    275             encryptParam.hostEncryptMode = 2;
    276             encryptParam.pavpHasBeenEnabled = 1;
    277             encryptParam.app_id = 0;
    278             memcpy(encryptParam.pavpAesCounter, mEncParam.iv, 16);
    279 
    280             vaStatus = vaCreateBuffer(
    281                 mVADisplay,
    282                 mVAContext,
    283                 (VABufferType)VAEncryptionParameterBufferType,
    284                 sizeof(VAEncryptionParameterBuffer),
    285                 1,
    286                 &encryptParam,
    287                 &bufferIDs[bufferIDCount]);
    288             CHECK_VA_STATUS("vaCreateEncryptionParameterBuffer");
    289             bufferIDCount++;
    290         }
    291 
    292         vaStatus = vaCreateBuffer(
    293             mVADisplay,
    294             mVAContext,
    295             VASliceDataBufferType,
    296             mFrameSize, //size
    297             1,        //num_elements
    298             sliceData->buffer_addr + sliceData->slice_offset,
    299             &bufferIDs[bufferIDCount]);
    300         CHECK_VA_STATUS("vaCreateSliceDataBuffer");
    301         bufferIDCount++;
    302 
    303     }
    304 
    305     vaStatus = vaCreateBuffer(
    306         mVADisplay,
    307         mVAContext,
    308         VASliceParameterBufferType,
    309         sizeof(VASliceParameterBufferH264Base),
    310         1,
    311         sliceParam,
    312         &bufferIDs[bufferIDCount]);
    313 
    314     CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
    315     bufferIDCount++;
    316 
    317     vaStatus = vaRenderPicture(
    318         mVADisplay,
    319         mVAContext,
    320         bufferIDs,
    321         bufferIDCount);
    322     CHECK_VA_STATUS("vaRenderPicture");
    323 
    324     return DECODE_SUCCESS;
    325 }
    326 
    327 Decode_Status VideoDecoderAVCSecure::getCodecSpecificConfigs(
    328     VAProfile profile, VAConfigID *config)
    329 {
    330     VAStatus vaStatus;
    331     VAConfigAttrib attrib[2];
    332 
    333     if (config == NULL) {
    334         ETRACE("Invalid parameter!");
    335         return DECODE_FAIL;
    336     }
    337 
    338     attrib[0].type = VAConfigAttribRTFormat;
    339     attrib[0].value = VA_RT_FORMAT_YUV420;
    340     attrib[1].type = VAConfigAttribDecSliceMode;
    341     attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
    342 
    343     vaStatus = vaGetConfigAttributes(mVADisplay,profile,VAEntrypointVLD, &attrib[1], 1);
    344 
    345     if (attrib[1].value & VA_DEC_SLICE_MODE_BASE)
    346     {
    347         ITRACE("AVC short format used");
    348         attrib[1].value = VA_DEC_SLICE_MODE_BASE;
    349     } else if (attrib[1].value & VA_DEC_SLICE_MODE_NORMAL) {
    350         ITRACE("AVC long format ssed");
    351         attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
    352     } else {
    353         ETRACE("Unsupported Decode Slice Mode!");
    354         return DECODE_FAIL;
    355     }
    356 
    357     vaStatus = vaCreateConfig(
    358             mVADisplay,
    359             profile,
    360             VAEntrypointVLD,
    361             &attrib[0],
    362             2,
    363             config);
    364     CHECK_VA_STATUS("vaCreateConfig");
    365 
    366     return DECODE_SUCCESS;
    367 }
    368