1 /*
2 * Copyright (c) 2009-2011 Intel Corporation.  All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 #include "va_private.h"
18 #include "VideoDecoderAVCSecure.h"
19 #include "VideoDecoderTrace.h"
20 #include <string.h>
21 
22 #define STARTCODE_PREFIX_LEN        3
23 #define NALU_TYPE_MASK              0x1F
24 #define MAX_NALU_HEADER_BUFFER      8192
25 static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
26 
VideoDecoderAVCSecure(const char * mimeType)27 VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
28     : VideoDecoderAVC(mimeType),
29       mNaluHeaderBuffer(NULL),
30       mSliceHeaderBuffer(NULL) {
31     setParserType(VBP_H264SECURE);
32 }
33 
~VideoDecoderAVCSecure()34 VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
35 }
36 
start(VideoConfigBuffer * buffer)37 Decode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
38     Decode_Status status = VideoDecoderAVC::start(buffer);
39     if (status != DECODE_SUCCESS) {
40         return status;
41     }
42 
43     mNaluHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
44 
45     if (mNaluHeaderBuffer == NULL) {
46         ETRACE("Failed to allocate memory for mNaluHeaderBuffer");
47         return DECODE_MEMORY_FAIL;
48     }
49 
50     mSliceHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
51     if (mSliceHeaderBuffer == NULL) {
52         ETRACE("Failed to allocate memory for mSliceHeaderBuffer");
53         if (mNaluHeaderBuffer) {
54             delete [] mNaluHeaderBuffer;
55             mNaluHeaderBuffer = NULL;
56         }
57         return DECODE_MEMORY_FAIL;
58     }
59 
60     return status;
61 }
62 
stop(void)63 void VideoDecoderAVCSecure::stop(void) {
64     VideoDecoderAVC::stop();
65 
66     if (mNaluHeaderBuffer) {
67         delete [] mNaluHeaderBuffer;
68         mNaluHeaderBuffer = NULL;
69     }
70 
71     if (mSliceHeaderBuffer) {
72         delete [] mSliceHeaderBuffer;
73         mSliceHeaderBuffer = NULL;
74     }
75 
76 }
77 
decode(VideoDecodeBuffer * buffer)78 Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
79     Decode_Status status;
80     int32_t sizeAccumulated = 0;
81     int32_t sliceHeaderSize = 0;
82     int32_t sizeLeft = 0;
83     int32_t sliceIdx = 0;
84     uint8_t naluType;
85     frame_info_t* pFrameInfo;
86 
87     mFrameSize = 0;
88     if (buffer->flag & IS_SECURE_DATA) {
89         VTRACE("Decoding protected video ...");
90         mIsEncryptData = 1;
91     } else {
92         VTRACE("Decoding clear video ...");
93         mIsEncryptData = 0;
94         return VideoDecoderAVC::decode(buffer);
95     }
96 
97     if (buffer->size != sizeof(frame_info_t)) {
98         ETRACE("Not enough data to read frame_info_t!");
99         return DECODE_INVALID_DATA;
100     }
101     pFrameInfo = (frame_info_t*) buffer->data;
102 
103     mFrameSize = pFrameInfo->length;
104     VTRACE("mFrameSize = %d", mFrameSize);
105 
106     memcpy(&mEncParam, pFrameInfo->pavp, sizeof(pavp_info_t));
107     for (int32_t i = 0; i < pFrameInfo->num_nalus; i++) {
108         naluType = pFrameInfo->nalus[i].type & NALU_TYPE_MASK;
109         if (naluType >= h264_NAL_UNIT_TYPE_SLICE && naluType <= h264_NAL_UNIT_TYPE_IDR) {
110             memcpy(mSliceHeaderBuffer + sliceHeaderSize,
111                 &sliceIdx,
112                 sizeof(int32_t));
113             sliceHeaderSize += 4;
114 
115             memcpy(mSliceHeaderBuffer + sliceHeaderSize,
116                 &pFrameInfo->data,
117                 sizeof(uint8_t*));
118             sliceHeaderSize += sizeof(uint8_t*);
119 
120             memcpy(mSliceHeaderBuffer + sliceHeaderSize,
121                 &pFrameInfo->nalus[i].offset,
122                 sizeof(uint32_t));
123             sliceHeaderSize += sizeof(uint32_t);
124 
125             memcpy(mSliceHeaderBuffer + sliceHeaderSize,
126                 &pFrameInfo->nalus[i].length,
127                 sizeof(uint32_t));
128             sliceHeaderSize += sizeof(uint32_t);
129 
130             memcpy(mSliceHeaderBuffer + sliceHeaderSize,
131                 pFrameInfo->nalus[i].slice_header,
132                 sizeof(slice_header_t));
133             sliceHeaderSize += sizeof(slice_header_t);
134             if (pFrameInfo->nalus[i].type & 0x60) {
135                 memcpy(mSliceHeaderBuffer+sliceHeaderSize, pFrameInfo->dec_ref_pic_marking, sizeof(dec_ref_pic_marking_t));
136             } else {
137                 memset(mSliceHeaderBuffer+sliceHeaderSize, 0, sizeof(dec_ref_pic_marking_t));
138             }
139             sliceHeaderSize += sizeof(dec_ref_pic_marking_t);
140             sliceIdx++;
141         } else if (naluType >= h264_NAL_UNIT_TYPE_SEI && naluType <= h264_NAL_UNIT_TYPE_PPS) {
142             memcpy(mNaluHeaderBuffer + sizeAccumulated,
143                 startcodePrefix,
144                 STARTCODE_PREFIX_LEN);
145             sizeAccumulated += STARTCODE_PREFIX_LEN;
146             memcpy(mNaluHeaderBuffer + sizeAccumulated,
147                 pFrameInfo->nalus[i].data,
148                 pFrameInfo->nalus[i].length);
149             sizeAccumulated += pFrameInfo->nalus[i].length;
150         } else {
151             WTRACE("Failure: DECODE_FRAME_DROPPED");
152             return DECODE_FRAME_DROPPED;
153         }
154     }
155 
156     vbp_data_h264 *data = NULL;
157     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 
decodeSlice(vbp_data_h264 * data,uint32_t picIndex,uint32_t sliceIndex)211 Decode_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 
getCodecSpecificConfigs(VAProfile profile,VAConfigID * config)327 Decode_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