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
33typedef 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
66static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
67
68
69VideoDecoderAVCSecure::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
78VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
79}
80
81Decode_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
101void 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
120Decode_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
209Decode_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.
355int32_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
422Decode_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
457Decode_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