182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON/*
282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON* Copyright (c) 2009-2011 Intel Corporation.  All rights reserved.
382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON*
482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON* Licensed under the Apache License, Version 2.0 (the "License");
582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON* you may not use this file except in compliance with the License.
682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON* You may obtain a copy of the License at
782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON*
882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON* http://www.apache.org/licenses/LICENSE-2.0
982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON*
1082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON* Unless required by applicable law or agreed to in writing, software
1182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON* distributed under the License is distributed on an "AS IS" BASIS,
1282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON* See the License for the specific language governing permissions and
1482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON* limitations under the License.
1582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON*/
1682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
1782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#include "VideoDecoderAVCSecure.h"
1882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#include "VideoDecoderTrace.h"
1982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#include <string.h>
2082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
2182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
2282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#define STARTCODE_00                0x00
2382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#define STARTCODE_01                0x01
2482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#define STARTCODE_PREFIX_LEN        3
2582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#define NALU_TYPE_MASK              0x1F
2682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
2782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
2882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON// mask for little endian, to mast the second and fourth bytes in the byte stream
2982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#define STARTCODE_MASK0             0xFF000000 //0x00FF0000
3082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#define STARTCODE_MASK1             0x0000FF00  //0x000000FF
3182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
3282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
3382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTONtypedef enum {
3482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_unspecified0 = 0,
3582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_SLICE,
3682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_DPA,
3782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_DPB,
3882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_DPC,
3982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_IDR,
4082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_SEI,
4182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_SPS,
4282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_PPS,
4382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_Acc_unit_delimiter,
4482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_EOSeq,
4582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_EOstream,
4682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_filler_data,
4782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_SPS_extension,
4882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_Reserved14,
4982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_Reserved15,
5082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_Reserved16,
5182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_Reserved17,
5282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_Reserved18,
5382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_ACP,
5482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_Reserved20,
5582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_Reserved21,
5682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_Reserved22,
5782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_Reserved23,
5882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NAL_UNIT_TYPE_unspecified24,
5982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON} NAL_UNIT_TYPE;
6082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
6182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#ifndef min
6282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#define min(X, Y)  ((X) <(Y) ? (X) : (Y))
6382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON#endif
6482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
6582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
6682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTONstatic const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
6782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
6882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
6982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTONVideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
7082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    : VideoDecoderAVC(mimeType),
7182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON      mNaluHeaderBuffer(NULL),
7282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON      mInputBuffer(NULL) {
7382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
7482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    memset(&mMetadata, 0, sizeof(NaluMetadata));
7582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    memset(&mByteStream, 0, sizeof(NaluByteStream));
7682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON}
7782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
7882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTONVideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
7982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON}
8082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
8182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTONDecode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
8282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    Decode_Status status = VideoDecoderAVC::start(buffer);
8382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (status != DECODE_SUCCESS) {
8482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        return status;
8582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
8682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
8782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    mMetadata.naluInfo = new NaluInfo [MAX_NALU_NUMBER];
8882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    mByteStream.byteStream = new uint8_t [MAX_NALU_HEADER_BUFFER];
8982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    mNaluHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
9082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
9182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (mMetadata.naluInfo == NULL ||
9282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mByteStream.byteStream == NULL ||
9382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mNaluHeaderBuffer == NULL) {
9482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        ETRACE("Failed to allocate memory.");
9582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // TODO: release all allocated memory
9682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        return DECODE_MEMORY_FAIL;
9782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
9882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    return status;
9982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON}
10082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
10182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTONvoid VideoDecoderAVCSecure::stop(void) {
10282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    VideoDecoderAVC::stop();
10382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
10482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (mMetadata.naluInfo) {
10582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        delete [] mMetadata.naluInfo;
10682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mMetadata.naluInfo = NULL;
10782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
10882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
10982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (mByteStream.byteStream) {
11082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        delete [] mByteStream.byteStream;
11182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mByteStream.byteStream = NULL;
11282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
11382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
11482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (mNaluHeaderBuffer) {
11582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        delete [] mNaluHeaderBuffer;
11682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mNaluHeaderBuffer = NULL;
11782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
11882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON}
11982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
12082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTONDecode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
12182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    Decode_Status status;
12282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    int32_t sizeAccumulated = 0;
12382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    int32_t sizeLeft = 0;
12482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    uint8_t *pByteStream = NULL;
12582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NaluInfo *pNaluInfo = mMetadata.naluInfo;
12682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
12782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (buffer->flag & IS_SECURE_DATA) {
12882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        pByteStream = buffer->data;
12982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        sizeLeft = buffer->size;
13082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mInputBuffer = NULL;
13182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    } else {
13282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        status = parseAnnexBStream(buffer->data, buffer->size, &mByteStream);
13382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        CHECK_STATUS("parseAnnexBStream");
13482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        pByteStream = mByteStream.byteStream;
13582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        sizeLeft = mByteStream.streamPos;
13682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mInputBuffer = buffer->data;
13782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
13882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (sizeLeft < 4) {
13982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        ETRACE("Not enough data to read number of NALU.");
14082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        return DECODE_INVALID_DATA;
14182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
14282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
14382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    // read number of NALU
14482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    memcpy(&(mMetadata.naluNumber), pByteStream, sizeof(int32_t));
14582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    pByteStream += 4;
14682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    sizeLeft -= 4;
14782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
14882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (mMetadata.naluNumber == 0) {
14982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        WTRACE("Number of NALU is ZERO!");
15082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        return DECODE_SUCCESS;
15182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
15282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
15382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    for (int32_t i = 0; i < mMetadata.naluNumber; i++) {
15482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (sizeLeft < 12) {
15582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            ETRACE("Not enough data to parse NALU offset, size, header length for NALU %d, left = %d", i, sizeLeft);
15682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            return DECODE_INVALID_DATA;
15782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
15882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        sizeLeft -= 12;
15982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // read NALU offset
16082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        memcpy(&(pNaluInfo->naluOffset), pByteStream, sizeof(int32_t));
16182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        pByteStream += 4;
16282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
16382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // read NALU size
16482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        memcpy(&(pNaluInfo->naluLen), pByteStream, sizeof(int32_t));
16582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        pByteStream += 4;
16682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
16782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // read NALU header length
16882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        memcpy(&(pNaluInfo->naluHeaderLen), pByteStream, sizeof(int32_t));
16982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        pByteStream += 4;
17082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
17182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (sizeLeft < pNaluInfo->naluHeaderLen) {
17282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            ETRACE("Not enough data to copy NALU header for %d, left = %d, header len = %d", i, sizeLeft, pNaluInfo->naluHeaderLen);
17382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            return DECODE_INVALID_DATA;
17482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
17582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
17682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        sizeLeft -=  pNaluInfo->naluHeaderLen;
17782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
17882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (pNaluInfo->naluHeaderLen) {
17982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            // copy start code prefix to buffer
18082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            memcpy(mNaluHeaderBuffer + sizeAccumulated,
18182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                startcodePrefix,
18282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                STARTCODE_PREFIX_LEN);
18382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            sizeAccumulated += STARTCODE_PREFIX_LEN;
18482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
18582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            // copy NALU header
18682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            memcpy(mNaluHeaderBuffer + sizeAccumulated, pByteStream, pNaluInfo->naluHeaderLen);
18782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            pByteStream += pNaluInfo->naluHeaderLen;
18882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
18982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            sizeAccumulated += pNaluInfo->naluHeaderLen;
19082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        } else {
19182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            WTRACE("header len is zero for NALU %d", i);
19282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
19382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
19482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // for next NALU
19582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        pNaluInfo++;
19682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
19782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
19882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    buffer->data = mNaluHeaderBuffer;
19982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    buffer->size = sizeAccumulated;
20082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
20182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    return VideoDecoderAVC::decode(buffer);
20282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON}
20382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
20482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
20582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTONDecode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
20682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
20782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    Decode_Status status;
20882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    VAStatus vaStatus;
20982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    uint32_t bufferIDCount = 0;
21082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
21182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    VABufferID bufferIDs[4];
21282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
21382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
21482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
21582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    VAPictureParameterBufferH264 *picParam = picData->pic_parms;
21682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
21782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
21882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
21982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // either condition indicates start of a new frame
22082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (sliceParam->first_mb_in_slice != 0) {
22182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            WTRACE("The first slice is lost.");
22282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            // TODO: handle the first slice lost
22382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
22482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (mDecodingFrame) {
22582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            // interlace content, complete decoding the first field
22682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            vaStatus = vaEndPicture(mVADisplay, mVAContext);
22782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            CHECK_VA_STATUS("vaEndPicture");
22882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
22982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            // for interlace content, top field may be valid only after the second field is parsed
23082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
23182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
23282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
23382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // Check there is no reference frame loss before decoding a frame
23482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
23582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // Update  the reference frames and surface IDs for DPB and current frame
23682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        status = updateDPB(picParam);
23782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        CHECK_STATUS("updateDPB");
23882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
23982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        //We have to provide a hacked DPB rather than complete DPB for libva as workaround
24082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        status = updateReferenceFrames(picData);
24182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        CHECK_STATUS("updateReferenceFrames");
24282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
24382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
24482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        CHECK_VA_STATUS("vaBeginPicture");
24582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
24682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // start decoding a frame
24782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mDecodingFrame = true;
24882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
24982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        vaStatus = vaCreateBuffer(
25082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            mVADisplay,
25182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            mVAContext,
25282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            VAPictureParameterBufferType,
25382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            sizeof(VAPictureParameterBufferH264),
25482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            1,
25582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            picParam,
25682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            &bufferIDs[bufferIDCount]);
25782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
25882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        bufferIDCount++;
25982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
26082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        vaStatus = vaCreateBuffer(
26182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            mVADisplay,
26282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            mVAContext,
26382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            VAIQMatrixBufferType,
26482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            sizeof(VAIQMatrixBufferH264),
26582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            1,
26682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            data->IQ_matrix_buf,
26782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            &bufferIDs[bufferIDCount]);
26882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
26982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        bufferIDCount++;
27082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
27182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
27282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    status = setReference(sliceParam);
27382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    CHECK_STATUS("setReference");
27482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
27582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    // find which naluinfo is correlated to current slice
27682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    int naluIndex = 0;
27782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    uint32_t accumulatedHeaderLen = 0;
27882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    uint32_t headerLen = 0;
27982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    for (; naluIndex < mMetadata.naluNumber; naluIndex++)  {
28082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        headerLen = mMetadata.naluInfo[naluIndex].naluHeaderLen;
28182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (headerLen == 0) {
28282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            WTRACE("lenght of current NAL unit is 0.");
28382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            continue;
28482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
28582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        accumulatedHeaderLen += STARTCODE_PREFIX_LEN;
28682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (accumulatedHeaderLen + headerLen > sliceData->slice_offset) {
28782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            break;
28882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
28982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        accumulatedHeaderLen += headerLen;
29082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
29182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
29282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (sliceData->slice_offset != accumulatedHeaderLen) {
29382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        WTRACE("unexpected slice offset %d, accumulatedHeaderLen = %d", sliceData->slice_offset, accumulatedHeaderLen);
29482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
29582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
29682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    sliceParam->slice_data_size = mMetadata.naluInfo[naluIndex].naluLen;
29782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    sliceData->slice_size = sliceParam->slice_data_size;
29882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
29982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    // no need to update:
30082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    // sliceParam->slice_data_offset - 0 always
30182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    // sliceParam->slice_data_bit_offset - relative to  sliceData->slice_offset
30282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
30382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    vaStatus = vaCreateBuffer(
30482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mVADisplay,
30582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mVAContext,
30682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        VASliceParameterBufferType,
30782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        sizeof(VASliceParameterBufferH264),
30882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        1,
30982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        sliceParam,
31082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        &bufferIDs[bufferIDCount]);
31182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
31282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    bufferIDCount++;
31382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
31482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    // sliceData->slice_offset - accumulatedHeaderLen is the absolute offset to start codes of current NAL unit
31582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    // offset points to first byte of NAL unit
31682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    uint32_t sliceOffset = mMetadata.naluInfo[naluIndex].naluOffset;
31782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (mInputBuffer != NULL) {
31882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        vaStatus = vaCreateBuffer(
31982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            mVADisplay,
32082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            mVAContext,
32182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            VASliceDataBufferType,
32282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            sliceData->slice_size, //size
32382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            1,        //num_elements
32482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            mInputBuffer  + sliceOffset,
32582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            &bufferIDs[bufferIDCount]);
32682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    } else {
32782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        vaStatus = vaCreateBuffer(
32882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            mVADisplay,
32982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            mVAContext,
33082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            VAProtectedSliceDataBufferType,
33182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            sliceData->slice_size, //size
33282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            1,        //num_elements
33382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            (uint8_t*)sliceOffset, // IMR offset
33482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            &bufferIDs[bufferIDCount]);
33582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
33682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    CHECK_VA_STATUS("vaCreateSliceDataBuffer");
33782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    bufferIDCount++;
33882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
33982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    vaStatus = vaRenderPicture(
34082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mVADisplay,
34182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        mVAContext,
34282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        bufferIDs,
34382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        bufferIDCount);
34482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    CHECK_VA_STATUS("vaRenderPicture");
34582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
34682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    return DECODE_SUCCESS;
34782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON}
34882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
34982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
35082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON// Parse byte string pattern "0x000001" (3 bytes)  in the current buffer.
35182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON// Returns offset of position following  the pattern in the buffer if pattern is found or -1 if not found.
35282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTONint32_t VideoDecoderAVCSecure::findNalUnitOffset(uint8_t *stream, int32_t offset, int32_t length) {
35382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    uint8_t *ptr;
35482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    uint32_t left = 0, data = 0, phase = 0;
35582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    uint8_t mask1 = 0, mask2 = 0;
35682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
35782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    /* Meaning of phase:
35882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        0: initial status, "0x000001" bytes are not found so far;
35982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        1: one "0x00" byte is found;
36082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        2: two or more consecutive "0x00" bytes" are found;
36182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        3: "0x000001" patten is found ;
36282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        4: if there is one more byte after "0x000001";
36382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON       */
36482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
36582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    left = length;
36682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    ptr = (uint8_t *) (stream + offset);
36782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    phase = 0;
36882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
36982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    // parse until there is more data and start code not found
37082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    while ((left > 0) && (phase < 3)) {
37182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // 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.
37282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (((((uint32_t)ptr) & 0x3) == 0) && (phase == 0)) {
37382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            while (left > 3) {
37482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                data = *((uint32_t *)ptr);
37582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                mask1 = (STARTCODE_00 != (data & STARTCODE_MASK0));
37682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                mask2 = (STARTCODE_00 != (data & STARTCODE_MASK1));
37782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                // If second byte and fourth byte are not zero's then we cannot have a start code here,
37882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                //  as we need two consecutive zero bytes for a start code pattern.
37982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                if (mask1 && mask2) {
38082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                    // skip 4 bytes and start over
38182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                    ptr += 4;
38282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                    left -=4;
38382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                    continue;
38482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                } else {
38582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                    break;
38682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                }
38782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            }
38882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
38982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
39082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // At this point either data is not on a 32-bit boundary or phase > 0 so we look at one byte at a time
39182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (left > 0) {
39282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            if (*ptr == STARTCODE_00) {
39382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                phase++;
39482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                if (phase > 2) {
39582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                    // more than 2 consecutive '0x00' bytes is found
39682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                    phase = 2;
39782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                }
39882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            } else if ((*ptr == STARTCODE_01) && (phase == 2)) {
39982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                // start code is found
40082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                phase = 3;
40182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            } else {
40282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                // reset lookup
40382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                phase = 0;
40482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            }
40582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            ptr++;
40682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            left--;
40782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
40882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
40982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
41082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if ((left > 0) && (phase == 3)) {
41182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        phase = 4;
41282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // return offset of position following the pattern in the buffer which matches "0x000001" byte string
41382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        return (int32_t)(ptr - stream);
41482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
41582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    return -1;
41682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON}
41782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
41882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
41982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTONDecode_Status VideoDecoderAVCSecure::copyNaluHeader(uint8_t *stream, NaluByteStream *naluStream) {
42082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    uint8_t naluType;
42182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    int32_t naluHeaderLen;
42282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
42382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    naluType = *(uint8_t *)(stream + naluStream->naluOffset);
42482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    naluType &= NALU_TYPE_MASK;
42582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    // first update nalu header length based on nalu type
42682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (naluType >= NAL_UNIT_TYPE_SLICE && naluType <= NAL_UNIT_TYPE_IDR) {
42782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // coded slice, return only up to MAX_SLICE_HEADER_SIZE bytes
42882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        naluHeaderLen = min(naluStream->naluLen, MAX_SLICE_HEADER_SIZE);
42982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    } else if (naluType >= NAL_UNIT_TYPE_SEI && naluType <= NAL_UNIT_TYPE_PPS) {
43082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        //sps, pps, sei, etc, return the entire NAL unit in clear
43182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        naluHeaderLen = naluStream->naluLen;
43282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    } else {
43382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        return DECODE_FRAME_DROPPED;
43482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
43582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
43682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluOffset), sizeof(int32_t));
43782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    naluStream->streamPos += 4;
43882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
43982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluLen), sizeof(int32_t));
44082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    naluStream->streamPos += 4;
44182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
44282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    memcpy(naluStream->byteStream + naluStream->streamPos, &naluHeaderLen, sizeof(int32_t));
44382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    naluStream->streamPos += 4;
44482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
44582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (naluHeaderLen) {
44682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        memcpy(naluStream->byteStream + naluStream->streamPos, (uint8_t*)(stream + naluStream->naluOffset), naluHeaderLen);
44782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        naluStream->streamPos += naluHeaderLen;
44882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
44982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    return DECODE_SUCCESS;
45082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON}
45182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
45282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
45382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON// parse start-code prefixed stream, also knowns as Annex B byte stream, commonly used in AVI, ES, MPEG2 TS container
45482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTONDecode_Status VideoDecoderAVCSecure::parseAnnexBStream(uint8_t *stream, int32_t length, NaluByteStream *naluStream) {
45582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    int32_t naluOffset, offset, left;
45682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    NaluInfo *info;
45782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    uint32_t ret = DECODE_SUCCESS;
45882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
45982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    naluOffset = 0;
46082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    offset = 0;
46182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    left = length;
46282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
46382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    // leave 4 bytes to copy nalu count
46482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    naluStream->streamPos = 4;
46582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    naluStream->naluCount = 0;
46682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    memset(naluStream->byteStream, 0, MAX_NALU_HEADER_BUFFER);
46782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
46882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    for (; ;) {
46982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        naluOffset = findNalUnitOffset(stream, offset, left);
47082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (naluOffset == -1) {
47182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            break;
47282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
47382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
47482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (naluStream->naluCount == 0) {
47582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            naluStream->naluOffset = naluOffset;
47682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        } else {
47782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            naluStream->naluLen = naluOffset - naluStream->naluOffset - STARTCODE_PREFIX_LEN;
47882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            ret = copyNaluHeader(stream, naluStream);
47982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            if (ret != DECODE_SUCCESS && ret != DECODE_FRAME_DROPPED) {
48082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                LOGW("copyNaluHeader returned %d", ret);
48182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON                return ret;
48282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            }
48382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            // starting position for next NALU
48482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            naluStream->naluOffset = naluOffset;
48582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
48682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
48782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        if (ret == DECODE_SUCCESS) {
48882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON            naluStream->naluCount++;
48982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        }
49082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
49182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // update next lookup position and length
49282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        offset = naluOffset + 1; // skip one byte of NAL unit type
49382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        left = length - offset;
49482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
49582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
49682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    if (naluStream->naluCount > 0) {
49782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        naluStream->naluLen = length - naluStream->naluOffset;
49882b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        memcpy(naluStream->byteStream, &(naluStream->naluCount), sizeof(int32_t));
49982b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        // ignore return value, either DECODE_SUCCESS or DECODE_FRAME_DROPPED
50082b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        copyNaluHeader(stream, naluStream);
50182b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON        return DECODE_SUCCESS;
50282b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    }
50382b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
50482b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    LOGW("number of valid NALU is 0!");
50582b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON    return DECODE_SUCCESS;
50682b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON}
50782b428e49a70ddc051a36d2b3a25d90db79770dcGuilhem IMBERTON
508