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