Home | History | Annotate | Download | only in cherrytrail
      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 
    158     if (sizeAccumulated > 0) {
    159         status =  VideoDecoderBase::parseBuffer(
    160                 mNaluHeaderBuffer,
    161                 sizeAccumulated,
    162                 false,
    163                 (void**)&data);
    164         CHECK_STATUS("VideoDecoderBase::parseBuffer");
    165     }
    166 
    167     if (sliceHeaderSize > 0) {
    168         memset(mSliceHeaderBuffer + sliceHeaderSize, 0xFF, 4);
    169         sliceHeaderSize += 4;
    170         status =  VideoDecoderBase::updateBuffer(
    171                 mSliceHeaderBuffer,
    172                 sliceHeaderSize,
    173                 (void**)&data);
    174         CHECK_STATUS("VideoDecoderBase::updateBuffer");
    175     }
    176 
    177     if (data == NULL) {
    178         ETRACE("Invalid data returned by parser!");
    179         return DECODE_MEMORY_FAIL;
    180     }
    181 
    182     if (!mVAStarted) {
    183          if (data->has_sps && data->has_pps) {
    184             status = startVA(data);
    185             CHECK_STATUS("startVA");
    186         } else {
    187             WTRACE("Can't start VA as either SPS or PPS is still not available.");
    188             return DECODE_SUCCESS;
    189         }
    190     }
    191     status = decodeFrame(buffer, data);
    192     return status;
    193 }
    194 
    195 Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
    196     Decode_Status status;
    197     VAStatus vaStatus;
    198     uint32_t bufferIDCount = 0;
    199     // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
    200     VABufferID bufferIDs[5];
    201 
    202     vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
    203     vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
    204     VAPictureParameterBufferH264 *picParam = picData->pic_parms;
    205     VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
    206     VAEncryptionParameterBuffer encryptParam;
    207 
    208     if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
    209         // either condition indicates start of a new frame
    210         if (sliceParam->first_mb_in_slice != 0) {
    211             WTRACE("The first slice is lost.");
    212             // TODO: handle the first slice lost
    213         }
    214         if (mDecodingFrame) {
    215             // interlace content, complete decoding the first field
    216             vaStatus = vaEndPicture(mVADisplay, mVAContext);
    217             CHECK_VA_STATUS("vaEndPicture");
    218 
    219             // for interlace content, top field may be valid only after the second field is parsed
    220             mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
    221         }
    222 
    223         // Update  the reference frames and surface IDs for DPB and current frame
    224         status = updateDPB(picParam);
    225         CHECK_STATUS("updateDPB");
    226 
    227         vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
    228         CHECK_VA_STATUS("vaBeginPicture");
    229 
    230         // start decoding a frame
    231         mDecodingFrame = true;
    232 
    233         vaStatus = vaCreateBuffer(
    234             mVADisplay,
    235             mVAContext,
    236             VAPictureParameterBufferType,
    237             sizeof(VAPictureParameterBufferH264),
    238             1,
    239             picParam,
    240             &bufferIDs[bufferIDCount]);
    241         CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
    242         bufferIDCount++;
    243 
    244         vaStatus = vaCreateBuffer(
    245             mVADisplay,
    246             mVAContext,
    247             VAIQMatrixBufferType,
    248             sizeof(VAIQMatrixBufferH264),
    249             1,
    250             data->IQ_matrix_buf,
    251             &bufferIDs[bufferIDCount]);
    252         CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
    253         bufferIDCount++;
    254 
    255         if (mIsEncryptData) {
    256             memset(&encryptParam, 0, sizeof(VAEncryptionParameterBuffer));
    257             encryptParam.pavpCounterMode = 4;
    258             encryptParam.pavpEncryptionType = 2;
    259             encryptParam.hostEncryptMode = 2;
    260             encryptParam.pavpHasBeenEnabled = 1;
    261             encryptParam.app_id = 0;
    262             memcpy(encryptParam.pavpAesCounter, mEncParam.iv, 16);
    263 
    264             vaStatus = vaCreateBuffer(
    265                 mVADisplay,
    266                 mVAContext,
    267                 (VABufferType)VAEncryptionParameterBufferType,
    268                 sizeof(VAEncryptionParameterBuffer),
    269                 1,
    270                 &encryptParam,
    271                 &bufferIDs[bufferIDCount]);
    272             CHECK_VA_STATUS("vaCreateEncryptionParameterBuffer");
    273             bufferIDCount++;
    274         }
    275 
    276         vaStatus = vaCreateBuffer(
    277             mVADisplay,
    278             mVAContext,
    279             VASliceDataBufferType,
    280             mFrameSize, //size
    281             1,        //num_elements
    282             sliceData->buffer_addr + sliceData->slice_offset,
    283             &bufferIDs[bufferIDCount]);
    284         CHECK_VA_STATUS("vaCreateSliceDataBuffer");
    285         bufferIDCount++;
    286 
    287     }
    288 
    289     vaStatus = vaCreateBuffer(
    290         mVADisplay,
    291         mVAContext,
    292         VASliceParameterBufferType,
    293         sizeof(VASliceParameterBufferH264Base),
    294         1,
    295         sliceParam,
    296         &bufferIDs[bufferIDCount]);
    297 
    298     CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
    299     bufferIDCount++;
    300 
    301     vaStatus = vaRenderPicture(
    302         mVADisplay,
    303         mVAContext,
    304         bufferIDs,
    305         bufferIDCount);
    306     CHECK_VA_STATUS("vaRenderPicture");
    307 
    308     return DECODE_SUCCESS;
    309 }
    310 
    311 Decode_Status VideoDecoderAVCSecure::getCodecSpecificConfigs(
    312     VAProfile profile, VAConfigID *config)
    313 {
    314     VAStatus vaStatus;
    315     VAConfigAttrib attrib[2];
    316 
    317     if (config == NULL) {
    318         ETRACE("Invalid parameter!");
    319         return DECODE_FAIL;
    320     }
    321 
    322     attrib[0].type = VAConfigAttribRTFormat;
    323     attrib[0].value = VA_RT_FORMAT_YUV420;
    324     attrib[1].type = VAConfigAttribDecSliceMode;
    325     attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
    326 
    327     vaStatus = vaGetConfigAttributes(mVADisplay,profile,VAEntrypointVLD, &attrib[1], 1);
    328 
    329     if (attrib[1].value & VA_DEC_SLICE_MODE_BASE)
    330     {
    331         ITRACE("AVC short format used");
    332         attrib[1].value = VA_DEC_SLICE_MODE_BASE;
    333     } else if (attrib[1].value & VA_DEC_SLICE_MODE_NORMAL) {
    334         ITRACE("AVC long format ssed");
    335         attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
    336     } else {
    337         ETRACE("Unsupported Decode Slice Mode!");
    338         return DECODE_FAIL;
    339     }
    340 
    341     vaStatus = vaCreateConfig(
    342             mVADisplay,
    343             profile,
    344             VAEntrypointVLD,
    345             &attrib[0],
    346             2,
    347             config);
    348     CHECK_VA_STATUS("vaCreateConfig");
    349 
    350     return DECODE_SUCCESS;
    351 }
    352