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
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
decodeSlice(vbp_data_h264 * data,uint32_t picIndex,uint32_t sliceIndex)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
getCodecSpecificConfigs(VAProfile profile,VAConfigID * config)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