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
25static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
26
27VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
28    : VideoDecoderAVC(mimeType),
29      mNaluHeaderBuffer(NULL),
30      mSliceHeaderBuffer(NULL) {
31    setParserType(VBP_H264SECURE);
32}
33
34VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
35}
36
37Decode_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
63void 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
78Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
79    Decode_Status status;
80    int32_t sizeAccumulated = 0;
81    int32_t sliceHeaderSize = 0;
82    int32_t sizeLeft = 0;
83    int32_t sliceIdx = 0;
84    uint8_t naluType;
85    frame_info_t* pFrameInfo;
86
87    mFrameSize = 0;
88    if (buffer->flag & IS_SECURE_DATA) {
89        VTRACE("Decoding protected video ...");
90        mIsEncryptData = 1;
91    } else {
92        VTRACE("Decoding clear video ...");
93        mIsEncryptData = 0;
94        return VideoDecoderAVC::decode(buffer);
95    }
96
97    if (buffer->size != sizeof(frame_info_t)) {
98        ETRACE("Not enough data to read frame_info_t!");
99        return DECODE_INVALID_DATA;
100    }
101    pFrameInfo = (frame_info_t*) buffer->data;
102
103    mFrameSize = pFrameInfo->length;
104    VTRACE("mFrameSize = %d", mFrameSize);
105
106    memcpy(&mEncParam, pFrameInfo->pavp, sizeof(pavp_info_t));
107    for (int32_t i = 0; i < pFrameInfo->num_nalus; i++) {
108        naluType = pFrameInfo->nalus[i].type & NALU_TYPE_MASK;
109        if (naluType >= h264_NAL_UNIT_TYPE_SLICE && naluType <= h264_NAL_UNIT_TYPE_IDR) {
110            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
111                &sliceIdx,
112                sizeof(int32_t));
113            sliceHeaderSize += 4;
114
115            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
116                &pFrameInfo->data,
117                sizeof(uint8_t*));
118            sliceHeaderSize += sizeof(uint8_t*);
119
120            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
121                &pFrameInfo->nalus[i].offset,
122                sizeof(uint32_t));
123            sliceHeaderSize += sizeof(uint32_t);
124
125            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
126                &pFrameInfo->nalus[i].length,
127                sizeof(uint32_t));
128            sliceHeaderSize += sizeof(uint32_t);
129
130            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
131                pFrameInfo->nalus[i].slice_header,
132                sizeof(slice_header_t));
133            sliceHeaderSize += sizeof(slice_header_t);
134            if (pFrameInfo->nalus[i].type & 0x60) {
135                memcpy(mSliceHeaderBuffer+sliceHeaderSize, pFrameInfo->dec_ref_pic_marking, sizeof(dec_ref_pic_marking_t));
136            } else {
137                memset(mSliceHeaderBuffer+sliceHeaderSize, 0, sizeof(dec_ref_pic_marking_t));
138            }
139            sliceHeaderSize += sizeof(dec_ref_pic_marking_t);
140            sliceIdx++;
141        } else if (naluType >= h264_NAL_UNIT_TYPE_SEI && naluType <= h264_NAL_UNIT_TYPE_PPS) {
142            memcpy(mNaluHeaderBuffer + sizeAccumulated,
143                startcodePrefix,
144                STARTCODE_PREFIX_LEN);
145            sizeAccumulated += STARTCODE_PREFIX_LEN;
146            memcpy(mNaluHeaderBuffer + sizeAccumulated,
147                pFrameInfo->nalus[i].data,
148                pFrameInfo->nalus[i].length);
149            sizeAccumulated += pFrameInfo->nalus[i].length;
150        } else {
151            WTRACE("Failure: DECODE_FRAME_DROPPED");
152            return DECODE_FRAME_DROPPED;
153        }
154    }
155
156    vbp_data_h264 *data = NULL;
157    int new_sequence_to_handle = 0;
158
159    if (sizeAccumulated > 0) {
160        status =  VideoDecoderBase::parseBuffer(
161                mNaluHeaderBuffer,
162                sizeAccumulated,
163                false,
164                (void**)&data);
165        CHECK_STATUS("VideoDecoderBase::parseBuffer");
166
167        // [FIX DRC zoom issue] if one buffer contains more than one nalu
168        // for example SPS+PPS+IDR, new_sps/new_pps flags set in parseBuffer
169        // will be flushed in the following updateBuffer.
170        // So that handleNewSequence will not be handled in decodeFrame()
171        if (data->new_sps || data->new_pps) {
172            new_sequence_to_handle = 1;
173        }
174    }
175
176    if (sliceHeaderSize > 0) {
177        memset(mSliceHeaderBuffer + sliceHeaderSize, 0xFF, 4);
178        sliceHeaderSize += 4;
179        status =  VideoDecoderBase::updateBuffer(
180                mSliceHeaderBuffer,
181                sliceHeaderSize,
182                (void**)&data);
183        CHECK_STATUS("VideoDecoderBase::updateBuffer");
184
185        // in case the flags were flushed but indeed new sequence needed to be handled.
186        if ((1 == new_sequence_to_handle) &&
187            ((data->new_sps == 0) || (data->new_pps == 0))) {
188            data->new_sps = 1;
189            data->new_pps = 1;
190        }
191    }
192
193    if (data == NULL) {
194        ETRACE("Invalid data returned by parser!");
195        return DECODE_MEMORY_FAIL;
196    }
197
198    if (!mVAStarted) {
199         if (data->has_sps && data->has_pps) {
200            status = startVA(data);
201            CHECK_STATUS("startVA");
202        } else {
203            WTRACE("Can't start VA as either SPS or PPS is still not available.");
204            return DECODE_SUCCESS;
205        }
206    }
207    status = decodeFrame(buffer, data);
208    return status;
209}
210
211Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
212    Decode_Status status;
213    VAStatus vaStatus;
214    uint32_t bufferIDCount = 0;
215    // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
216    VABufferID bufferIDs[5];
217
218    vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
219    vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
220    VAPictureParameterBufferH264 *picParam = picData->pic_parms;
221    VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
222    VAEncryptionParameterBuffer encryptParam;
223
224    if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
225        // either condition indicates start of a new frame
226        if (sliceParam->first_mb_in_slice != 0) {
227            WTRACE("The first slice is lost.");
228            // TODO: handle the first slice lost
229        }
230        if (mDecodingFrame) {
231            // interlace content, complete decoding the first field
232            vaStatus = vaEndPicture(mVADisplay, mVAContext);
233            CHECK_VA_STATUS("vaEndPicture");
234
235            // for interlace content, top field may be valid only after the second field is parsed
236            mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
237        }
238
239        // Update  the reference frames and surface IDs for DPB and current frame
240        status = updateDPB(picParam);
241        CHECK_STATUS("updateDPB");
242
243        vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
244        CHECK_VA_STATUS("vaBeginPicture");
245
246        // start decoding a frame
247        mDecodingFrame = true;
248
249        vaStatus = vaCreateBuffer(
250            mVADisplay,
251            mVAContext,
252            VAPictureParameterBufferType,
253            sizeof(VAPictureParameterBufferH264),
254            1,
255            picParam,
256            &bufferIDs[bufferIDCount]);
257        CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
258        bufferIDCount++;
259
260        vaStatus = vaCreateBuffer(
261            mVADisplay,
262            mVAContext,
263            VAIQMatrixBufferType,
264            sizeof(VAIQMatrixBufferH264),
265            1,
266            data->IQ_matrix_buf,
267            &bufferIDs[bufferIDCount]);
268        CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
269        bufferIDCount++;
270
271        if (mIsEncryptData) {
272            memset(&encryptParam, 0, sizeof(VAEncryptionParameterBuffer));
273            encryptParam.pavpCounterMode = 4;
274            encryptParam.pavpEncryptionType = 2;
275            encryptParam.hostEncryptMode = 2;
276            encryptParam.pavpHasBeenEnabled = 1;
277            encryptParam.app_id = 0;
278            memcpy(encryptParam.pavpAesCounter, mEncParam.iv, 16);
279
280            vaStatus = vaCreateBuffer(
281                mVADisplay,
282                mVAContext,
283                (VABufferType)VAEncryptionParameterBufferType,
284                sizeof(VAEncryptionParameterBuffer),
285                1,
286                &encryptParam,
287                &bufferIDs[bufferIDCount]);
288            CHECK_VA_STATUS("vaCreateEncryptionParameterBuffer");
289            bufferIDCount++;
290        }
291
292        vaStatus = vaCreateBuffer(
293            mVADisplay,
294            mVAContext,
295            VASliceDataBufferType,
296            mFrameSize, //size
297            1,        //num_elements
298            sliceData->buffer_addr + sliceData->slice_offset,
299            &bufferIDs[bufferIDCount]);
300        CHECK_VA_STATUS("vaCreateSliceDataBuffer");
301        bufferIDCount++;
302
303    }
304
305    vaStatus = vaCreateBuffer(
306        mVADisplay,
307        mVAContext,
308        VASliceParameterBufferType,
309        sizeof(VASliceParameterBufferH264Base),
310        1,
311        sliceParam,
312        &bufferIDs[bufferIDCount]);
313
314    CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
315    bufferIDCount++;
316
317    vaStatus = vaRenderPicture(
318        mVADisplay,
319        mVAContext,
320        bufferIDs,
321        bufferIDCount);
322    CHECK_VA_STATUS("vaRenderPicture");
323
324    return DECODE_SUCCESS;
325}
326
327Decode_Status VideoDecoderAVCSecure::getCodecSpecificConfigs(
328    VAProfile profile, VAConfigID *config)
329{
330    VAStatus vaStatus;
331    VAConfigAttrib attrib[2];
332
333    if (config == NULL) {
334        ETRACE("Invalid parameter!");
335        return DECODE_FAIL;
336    }
337
338    attrib[0].type = VAConfigAttribRTFormat;
339    attrib[0].value = VA_RT_FORMAT_YUV420;
340    attrib[1].type = VAConfigAttribDecSliceMode;
341    attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
342
343    vaStatus = vaGetConfigAttributes(mVADisplay,profile,VAEntrypointVLD, &attrib[1], 1);
344
345    if (attrib[1].value & VA_DEC_SLICE_MODE_BASE)
346    {
347        ITRACE("AVC short format used");
348        attrib[1].value = VA_DEC_SLICE_MODE_BASE;
349    } else if (attrib[1].value & VA_DEC_SLICE_MODE_NORMAL) {
350        ITRACE("AVC long format ssed");
351        attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
352    } else {
353        ETRACE("Unsupported Decode Slice Mode!");
354        return DECODE_FAIL;
355    }
356
357    vaStatus = vaCreateConfig(
358            mVADisplay,
359            profile,
360            VAEntrypointVLD,
361            &attrib[0],
362            2,
363            config);
364    CHECK_VA_STATUS("vaCreateConfig");
365
366    return DECODE_SUCCESS;
367}
368