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 "VideoDecoderAVCSecure.h"
18 #include "VideoDecoderTrace.h"
19 #include <string.h>
20
21
22 #define STARTCODE_00 0x00
23 #define STARTCODE_01 0x01
24 #define STARTCODE_PREFIX_LEN 3
25 #define NALU_TYPE_MASK 0x1F
26
27
28 // mask for little endian, to mast the second and fourth bytes in the byte stream
29 #define STARTCODE_MASK0 0xFF000000 //0x00FF0000
30 #define STARTCODE_MASK1 0x0000FF00 //0x000000FF
31
32
33 typedef enum {
34 NAL_UNIT_TYPE_unspecified0 = 0,
35 NAL_UNIT_TYPE_SLICE,
36 NAL_UNIT_TYPE_DPA,
37 NAL_UNIT_TYPE_DPB,
38 NAL_UNIT_TYPE_DPC,
39 NAL_UNIT_TYPE_IDR,
40 NAL_UNIT_TYPE_SEI,
41 NAL_UNIT_TYPE_SPS,
42 NAL_UNIT_TYPE_PPS,
43 NAL_UNIT_TYPE_Acc_unit_delimiter,
44 NAL_UNIT_TYPE_EOSeq,
45 NAL_UNIT_TYPE_EOstream,
46 NAL_UNIT_TYPE_filler_data,
47 NAL_UNIT_TYPE_SPS_extension,
48 NAL_UNIT_TYPE_Reserved14,
49 NAL_UNIT_TYPE_Reserved15,
50 NAL_UNIT_TYPE_Reserved16,
51 NAL_UNIT_TYPE_Reserved17,
52 NAL_UNIT_TYPE_Reserved18,
53 NAL_UNIT_TYPE_ACP,
54 NAL_UNIT_TYPE_Reserved20,
55 NAL_UNIT_TYPE_Reserved21,
56 NAL_UNIT_TYPE_Reserved22,
57 NAL_UNIT_TYPE_Reserved23,
58 NAL_UNIT_TYPE_unspecified24,
59 } NAL_UNIT_TYPE;
60
61 #ifndef min
62 #define min(X, Y) ((X) <(Y) ? (X) : (Y))
63 #endif
64
65
66 static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
67
68
VideoDecoderAVCSecure(const char * mimeType)69 VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
70 : VideoDecoderAVC(mimeType),
71 mNaluHeaderBuffer(NULL),
72 mInputBuffer(NULL) {
73
74 memset(&mMetadata, 0, sizeof(NaluMetadata));
75 memset(&mByteStream, 0, sizeof(NaluByteStream));
76 }
77
~VideoDecoderAVCSecure()78 VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
79 }
80
start(VideoConfigBuffer * buffer)81 Decode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
82 Decode_Status status = VideoDecoderAVC::start(buffer);
83 if (status != DECODE_SUCCESS) {
84 return status;
85 }
86
87 mMetadata.naluInfo = new NaluInfo [MAX_NALU_NUMBER];
88 mByteStream.byteStream = new uint8_t [MAX_NALU_HEADER_BUFFER];
89 mNaluHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
90
91 if (mMetadata.naluInfo == NULL ||
92 mByteStream.byteStream == NULL ||
93 mNaluHeaderBuffer == NULL) {
94 ETRACE("Failed to allocate memory.");
95 // TODO: release all allocated memory
96 return DECODE_MEMORY_FAIL;
97 }
98 return status;
99 }
100
stop(void)101 void VideoDecoderAVCSecure::stop(void) {
102 VideoDecoderAVC::stop();
103
104 if (mMetadata.naluInfo) {
105 delete [] mMetadata.naluInfo;
106 mMetadata.naluInfo = NULL;
107 }
108
109 if (mByteStream.byteStream) {
110 delete [] mByteStream.byteStream;
111 mByteStream.byteStream = NULL;
112 }
113
114 if (mNaluHeaderBuffer) {
115 delete [] mNaluHeaderBuffer;
116 mNaluHeaderBuffer = NULL;
117 }
118 }
119
decode(VideoDecodeBuffer * buffer)120 Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
121 Decode_Status status;
122 int32_t sizeAccumulated = 0;
123 int32_t sizeLeft = 0;
124 uint8_t *pByteStream = NULL;
125 NaluInfo *pNaluInfo = mMetadata.naluInfo;
126
127 if (buffer->flag & IS_SECURE_DATA) {
128 // NALU headers are appended to encrypted video bitstream
129 // |...encrypted video bitstream (16 bytes aligned)...| 4 bytes of header size |...NALU headers..|
130 pByteStream = buffer->data + buffer->size + 4;
131 sizeLeft = *(int32_t *)(buffer->data + buffer->size);
132 VTRACE("%s sizeLeft: %d buffer->size: %#x", __func__, sizeLeft, buffer->size);
133 mInputBuffer = buffer->data;
134 } else {
135 status = parseAnnexBStream(buffer->data, buffer->size, &mByteStream);
136 CHECK_STATUS("parseAnnexBStream");
137 pByteStream = mByteStream.byteStream;
138 sizeLeft = mByteStream.streamPos;
139 mInputBuffer = buffer->data;
140 }
141 if (sizeLeft < 4) {
142 ETRACE("Not enough data to read number of NALU.");
143 return DECODE_INVALID_DATA;
144 }
145
146 // read number of NALU
147 memcpy(&(mMetadata.naluNumber), pByteStream, sizeof(int32_t));
148 pByteStream += 4;
149 sizeLeft -= 4;
150
151 if (mMetadata.naluNumber == 0) {
152 WTRACE("Number of NALU is ZERO!");
153 return DECODE_SUCCESS;
154 }
155
156 for (int32_t i = 0; i < mMetadata.naluNumber; i++) {
157 if (sizeLeft < 12) {
158 ETRACE("Not enough data to parse NALU offset, size, header length for NALU %d, left = %d", i, sizeLeft);
159 return DECODE_INVALID_DATA;
160 }
161 sizeLeft -= 12;
162 // read NALU offset
163 memcpy(&(pNaluInfo->naluOffset), pByteStream, sizeof(int32_t));
164 pByteStream += 4;
165
166 // read NALU size
167 memcpy(&(pNaluInfo->naluLen), pByteStream, sizeof(int32_t));
168 pByteStream += 4;
169
170 // read NALU header length
171 memcpy(&(pNaluInfo->naluHeaderLen), pByteStream, sizeof(int32_t));
172 pByteStream += 4;
173
174
175 if (sizeLeft < pNaluInfo->naluHeaderLen) {
176 ETRACE("Not enough data to copy NALU header for %d, left = %d, header len = %d", i, sizeLeft, pNaluInfo->naluHeaderLen);
177 return DECODE_INVALID_DATA;
178 }
179
180 sizeLeft -= pNaluInfo->naluHeaderLen;
181
182 if (pNaluInfo->naluHeaderLen) {
183 // copy start code prefix to buffer
184 memcpy(mNaluHeaderBuffer + sizeAccumulated,
185 startcodePrefix,
186 STARTCODE_PREFIX_LEN);
187 sizeAccumulated += STARTCODE_PREFIX_LEN;
188
189 // copy NALU header
190 memcpy(mNaluHeaderBuffer + sizeAccumulated, pByteStream, pNaluInfo->naluHeaderLen);
191 pByteStream += pNaluInfo->naluHeaderLen;
192
193 sizeAccumulated += pNaluInfo->naluHeaderLen;
194 } else {
195 WTRACE("header len is zero for NALU %d", i);
196 }
197
198 // for next NALU
199 pNaluInfo++;
200 }
201
202 buffer->data = mNaluHeaderBuffer;
203 buffer->size = sizeAccumulated;
204
205 return VideoDecoderAVC::decode(buffer);
206 }
207
208
decodeSlice(vbp_data_h264 * data,uint32_t picIndex,uint32_t sliceIndex)209 Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
210
211 Decode_Status status;
212 VAStatus vaStatus;
213 uint32_t bufferIDCount = 0;
214 // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
215 VABufferID bufferIDs[4];
216
217 vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
218 vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
219 VAPictureParameterBufferH264 *picParam = picData->pic_parms;
220 VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
221
222 if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
223 // either condition indicates start of a new frame
224 if (sliceParam->first_mb_in_slice != 0) {
225 WTRACE("The first slice is lost.");
226 // TODO: handle the first slice lost
227 }
228 if (mDecodingFrame) {
229 // interlace content, complete decoding the first field
230 vaStatus = vaEndPicture(mVADisplay, mVAContext);
231 CHECK_VA_STATUS("vaEndPicture");
232
233 // for interlace content, top field may be valid only after the second field is parsed
234 mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
235 }
236
237 // Check there is no reference frame loss before decoding a frame
238
239 // Update the reference frames and surface IDs for DPB and current frame
240 status = updateDPB(picParam);
241 CHECK_STATUS("updateDPB");
242
243 //We have to provide a hacked DPB rather than complete DPB for libva as workaround
244 status = updateReferenceFrames(picData);
245 CHECK_STATUS("updateReferenceFrames");
246
247 vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
248 CHECK_VA_STATUS("vaBeginPicture");
249
250 // start decoding a frame
251 mDecodingFrame = true;
252
253 vaStatus = vaCreateBuffer(
254 mVADisplay,
255 mVAContext,
256 VAPictureParameterBufferType,
257 sizeof(VAPictureParameterBufferH264),
258 1,
259 picParam,
260 &bufferIDs[bufferIDCount]);
261 CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
262 bufferIDCount++;
263
264 vaStatus = vaCreateBuffer(
265 mVADisplay,
266 mVAContext,
267 VAIQMatrixBufferType,
268 sizeof(VAIQMatrixBufferH264),
269 1,
270 data->IQ_matrix_buf,
271 &bufferIDs[bufferIDCount]);
272 CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
273 bufferIDCount++;
274 }
275
276 status = setReference(sliceParam);
277 CHECK_STATUS("setReference");
278
279 // find which naluinfo is correlated to current slice
280 int naluIndex = 0;
281 uint32_t accumulatedHeaderLen = 0;
282 uint32_t headerLen = 0;
283 for (; naluIndex < mMetadata.naluNumber; naluIndex++) {
284 headerLen = mMetadata.naluInfo[naluIndex].naluHeaderLen;
285 if (headerLen == 0) {
286 WTRACE("lenght of current NAL unit is 0.");
287 continue;
288 }
289 accumulatedHeaderLen += STARTCODE_PREFIX_LEN;
290 if (accumulatedHeaderLen + headerLen > sliceData->slice_offset) {
291 break;
292 }
293 accumulatedHeaderLen += headerLen;
294 }
295
296 if (sliceData->slice_offset != accumulatedHeaderLen) {
297 WTRACE("unexpected slice offset %d, accumulatedHeaderLen = %d", sliceData->slice_offset, accumulatedHeaderLen);
298 }
299
300 sliceParam->slice_data_size = mMetadata.naluInfo[naluIndex].naluLen;
301 uint32_t sliceOffset = mMetadata.naluInfo[naluIndex].naluOffset;
302 uint32_t slice_offset_shift = sliceOffset % 16;
303 sliceParam->slice_data_offset += slice_offset_shift;
304 sliceData->slice_size = (sliceParam->slice_data_size + slice_offset_shift + 0xF) & ~0xF;
305
306 vaStatus = vaCreateBuffer(
307 mVADisplay,
308 mVAContext,
309 VASliceParameterBufferType,
310 sizeof(VASliceParameterBufferH264),
311 1,
312 sliceParam,
313 &bufferIDs[bufferIDCount]);
314 CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
315 bufferIDCount++;
316
317 // sliceData->slice_offset - accumulatedHeaderLen is the absolute offset to start codes of current NAL unit
318 // offset points to first byte of NAL unit
319
320 if (mInputBuffer != NULL) {
321 vaStatus = vaCreateBuffer(
322 mVADisplay,
323 mVAContext,
324 VASliceDataBufferType,
325 sliceData->slice_size, //Slice size
326 1, // num_elements
327 mInputBuffer + sliceOffset - slice_offset_shift,
328 &bufferIDs[bufferIDCount]);
329 } else {
330 vaStatus = vaCreateBuffer(
331 mVADisplay,
332 mVAContext,
333 VAProtectedSliceDataBufferType,
334 sliceData->slice_size, //size
335 1, //num_elements
336 (uint8_t*)sliceOffset, // IMR offset
337 &bufferIDs[bufferIDCount]);
338 }
339 CHECK_VA_STATUS("vaCreateSliceDataBuffer");
340 bufferIDCount++;
341
342 vaStatus = vaRenderPicture(
343 mVADisplay,
344 mVAContext,
345 bufferIDs,
346 bufferIDCount);
347 CHECK_VA_STATUS("vaRenderPicture");
348
349 return DECODE_SUCCESS;
350 }
351
352
353 // Parse byte string pattern "0x000001" (3 bytes) in the current buffer.
354 // Returns offset of position following the pattern in the buffer if pattern is found or -1 if not found.
findNalUnitOffset(uint8_t * stream,int32_t offset,int32_t length)355 int32_t VideoDecoderAVCSecure::findNalUnitOffset(uint8_t *stream, int32_t offset, int32_t length) {
356 uint8_t *ptr;
357 uint32_t left = 0, data = 0, phase = 0;
358 uint8_t mask1 = 0, mask2 = 0;
359
360 /* Meaning of phase:
361 0: initial status, "0x000001" bytes are not found so far;
362 1: one "0x00" byte is found;
363 2: two or more consecutive "0x00" bytes" are found;
364 3: "0x000001" patten is found ;
365 4: if there is one more byte after "0x000001";
366 */
367
368 left = length;
369 ptr = (uint8_t *) (stream + offset);
370 phase = 0;
371
372 // parse until there is more data and start code not found
373 while ((left > 0) && (phase < 3)) {
374 // Check if the address is 32-bit aligned & phase=0, if thats the case we can check 4 bytes instead of one byte at a time.
375 if (((((uint32_t)ptr) & 0x3) == 0) && (phase == 0)) {
376 while (left > 3) {
377 data = *((uint32_t *)ptr);
378 mask1 = (STARTCODE_00 != (data & STARTCODE_MASK0));
379 mask2 = (STARTCODE_00 != (data & STARTCODE_MASK1));
380 // If second byte and fourth byte are not zero's then we cannot have a start code here,
381 // as we need two consecutive zero bytes for a start code pattern.
382 if (mask1 && mask2) {
383 // skip 4 bytes and start over
384 ptr += 4;
385 left -=4;
386 continue;
387 } else {
388 break;
389 }
390 }
391 }
392
393 // At this point either data is not on a 32-bit boundary or phase > 0 so we look at one byte at a time
394 if (left > 0) {
395 if (*ptr == STARTCODE_00) {
396 phase++;
397 if (phase > 2) {
398 // more than 2 consecutive '0x00' bytes is found
399 phase = 2;
400 }
401 } else if ((*ptr == STARTCODE_01) && (phase == 2)) {
402 // start code is found
403 phase = 3;
404 } else {
405 // reset lookup
406 phase = 0;
407 }
408 ptr++;
409 left--;
410 }
411 }
412
413 if ((left > 0) && (phase == 3)) {
414 phase = 4;
415 // return offset of position following the pattern in the buffer which matches "0x000001" byte string
416 return (int32_t)(ptr - stream);
417 }
418 return -1;
419 }
420
421
copyNaluHeader(uint8_t * stream,NaluByteStream * naluStream)422 Decode_Status VideoDecoderAVCSecure::copyNaluHeader(uint8_t *stream, NaluByteStream *naluStream) {
423 uint8_t naluType;
424 int32_t naluHeaderLen;
425
426 naluType = *(uint8_t *)(stream + naluStream->naluOffset);
427 naluType &= NALU_TYPE_MASK;
428 // first update nalu header length based on nalu type
429 if (naluType >= NAL_UNIT_TYPE_SLICE && naluType <= NAL_UNIT_TYPE_IDR) {
430 // coded slice, return only up to MAX_SLICE_HEADER_SIZE bytes
431 naluHeaderLen = min(naluStream->naluLen, MAX_SLICE_HEADER_SIZE);
432 } else if (naluType >= NAL_UNIT_TYPE_SEI && naluType <= NAL_UNIT_TYPE_PPS) {
433 //sps, pps, sei, etc, return the entire NAL unit in clear
434 naluHeaderLen = naluStream->naluLen;
435 } else {
436 return DECODE_FRAME_DROPPED;
437 }
438
439 memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluOffset), sizeof(int32_t));
440 naluStream->streamPos += 4;
441
442 memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluLen), sizeof(int32_t));
443 naluStream->streamPos += 4;
444
445 memcpy(naluStream->byteStream + naluStream->streamPos, &naluHeaderLen, sizeof(int32_t));
446 naluStream->streamPos += 4;
447
448 if (naluHeaderLen) {
449 memcpy(naluStream->byteStream + naluStream->streamPos, (uint8_t*)(stream + naluStream->naluOffset), naluHeaderLen);
450 naluStream->streamPos += naluHeaderLen;
451 }
452 return DECODE_SUCCESS;
453 }
454
455
456 // parse start-code prefixed stream, also knowns as Annex B byte stream, commonly used in AVI, ES, MPEG2 TS container
parseAnnexBStream(uint8_t * stream,int32_t length,NaluByteStream * naluStream)457 Decode_Status VideoDecoderAVCSecure::parseAnnexBStream(uint8_t *stream, int32_t length, NaluByteStream *naluStream) {
458 int32_t naluOffset, offset, left;
459 NaluInfo *info;
460 uint32_t ret = DECODE_SUCCESS;
461
462 naluOffset = 0;
463 offset = 0;
464 left = length;
465
466 // leave 4 bytes to copy nalu count
467 naluStream->streamPos = 4;
468 naluStream->naluCount = 0;
469 memset(naluStream->byteStream, 0, MAX_NALU_HEADER_BUFFER);
470
471 for (; ;) {
472 naluOffset = findNalUnitOffset(stream, offset, left);
473 if (naluOffset == -1) {
474 break;
475 }
476
477 if (naluStream->naluCount == 0) {
478 naluStream->naluOffset = naluOffset;
479 } else {
480 naluStream->naluLen = naluOffset - naluStream->naluOffset - STARTCODE_PREFIX_LEN;
481 ret = copyNaluHeader(stream, naluStream);
482 if (ret != DECODE_SUCCESS && ret != DECODE_FRAME_DROPPED) {
483 LOGW("copyNaluHeader returned %d", ret);
484 return ret;
485 }
486 // starting position for next NALU
487 naluStream->naluOffset = naluOffset;
488 }
489
490 if (ret == DECODE_SUCCESS) {
491 naluStream->naluCount++;
492 }
493
494 // update next lookup position and length
495 offset = naluOffset + 1; // skip one byte of NAL unit type
496 left = length - offset;
497 }
498
499 if (naluStream->naluCount > 0) {
500 naluStream->naluLen = length - naluStream->naluOffset;
501 memcpy(naluStream->byteStream, &(naluStream->naluCount), sizeof(int32_t));
502 // ignore return value, either DECODE_SUCCESS or DECODE_FRAME_DROPPED
503 copyNaluHeader(stream, naluStream);
504 return DECODE_SUCCESS;
505 }
506
507 LOGW("number of valid NALU is 0!");
508 return DECODE_SUCCESS;
509 }
510
511