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 25static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01}; 26 27VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType) 28 : VideoDecoderAVC(mimeType), 29 mNaluHeaderBuffer(NULL), 30 mSliceHeaderBuffer(NULL) { 31 setParserType(VBP_H264SECURE); 32} 33 34VideoDecoderAVCSecure::~VideoDecoderAVCSecure() { 35} 36 37Decode_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 63void 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 78Decode_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 211Decode_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 327Decode_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