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
VideoDecoderAVCSecure(const char * mimeType)27 VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
28 : VideoDecoderAVC(mimeType),
29 mNaluHeaderBuffer(NULL),
30 mSliceHeaderBuffer(NULL) {
31 setParserType(VBP_H264SECURE);
32 }
33
~VideoDecoderAVCSecure()34 VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
35 }
36
start(VideoConfigBuffer * buffer)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
stop(void)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
decode(VideoDecodeBuffer * buffer)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
decodeSlice(vbp_data_h264 * data,uint32_t picIndex,uint32_t sliceIndex)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
getCodecSpecificConfigs(VAProfile profile,VAConfigID * config)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