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 
158     if (sizeAccumulated > 0) {
159         status =  VideoDecoderBase::parseBuffer(
160                 mNaluHeaderBuffer,
161                 sizeAccumulated,
162                 false,
163                 (void**)&data);
164         CHECK_STATUS("VideoDecoderBase::parseBuffer");
165     }
166 
167     if (sliceHeaderSize > 0) {
168         memset(mSliceHeaderBuffer + sliceHeaderSize, 0xFF, 4);
169         sliceHeaderSize += 4;
170         status =  VideoDecoderBase::updateBuffer(
171                 mSliceHeaderBuffer,
172                 sliceHeaderSize,
173                 (void**)&data);
174         CHECK_STATUS("VideoDecoderBase::updateBuffer");
175     }
176 
177     if (data == NULL) {
178         ETRACE("Invalid data returned by parser!");
179         return DECODE_MEMORY_FAIL;
180     }
181 
182     if (!mVAStarted) {
183          if (data->has_sps && data->has_pps) {
184             status = startVA(data);
185             CHECK_STATUS("startVA");
186         } else {
187             WTRACE("Can't start VA as either SPS or PPS is still not available.");
188             return DECODE_SUCCESS;
189         }
190     }
191     status = decodeFrame(buffer, data);
192     return status;
193 }
194 
decodeSlice(vbp_data_h264 * data,uint32_t picIndex,uint32_t sliceIndex)195 Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
196     Decode_Status status;
197     VAStatus vaStatus;
198     uint32_t bufferIDCount = 0;
199     // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
200     VABufferID bufferIDs[5];
201 
202     vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
203     vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
204     VAPictureParameterBufferH264 *picParam = picData->pic_parms;
205     VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
206     VAEncryptionParameterBuffer encryptParam;
207 
208     if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
209         // either condition indicates start of a new frame
210         if (sliceParam->first_mb_in_slice != 0) {
211             WTRACE("The first slice is lost.");
212             // TODO: handle the first slice lost
213         }
214         if (mDecodingFrame) {
215             // interlace content, complete decoding the first field
216             vaStatus = vaEndPicture(mVADisplay, mVAContext);
217             CHECK_VA_STATUS("vaEndPicture");
218 
219             // for interlace content, top field may be valid only after the second field is parsed
220             mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
221         }
222 
223         // Update  the reference frames and surface IDs for DPB and current frame
224         status = updateDPB(picParam);
225         CHECK_STATUS("updateDPB");
226 
227         vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
228         CHECK_VA_STATUS("vaBeginPicture");
229 
230         // start decoding a frame
231         mDecodingFrame = true;
232 
233         vaStatus = vaCreateBuffer(
234             mVADisplay,
235             mVAContext,
236             VAPictureParameterBufferType,
237             sizeof(VAPictureParameterBufferH264),
238             1,
239             picParam,
240             &bufferIDs[bufferIDCount]);
241         CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
242         bufferIDCount++;
243 
244         vaStatus = vaCreateBuffer(
245             mVADisplay,
246             mVAContext,
247             VAIQMatrixBufferType,
248             sizeof(VAIQMatrixBufferH264),
249             1,
250             data->IQ_matrix_buf,
251             &bufferIDs[bufferIDCount]);
252         CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
253         bufferIDCount++;
254 
255         if (mIsEncryptData) {
256             memset(&encryptParam, 0, sizeof(VAEncryptionParameterBuffer));
257             encryptParam.pavpCounterMode = 4;
258             encryptParam.pavpEncryptionType = 2;
259             encryptParam.hostEncryptMode = 2;
260             encryptParam.pavpHasBeenEnabled = 1;
261             encryptParam.app_id = 0;
262             memcpy(encryptParam.pavpAesCounter, mEncParam.iv, 16);
263 
264             vaStatus = vaCreateBuffer(
265                 mVADisplay,
266                 mVAContext,
267                 (VABufferType)VAEncryptionParameterBufferType,
268                 sizeof(VAEncryptionParameterBuffer),
269                 1,
270                 &encryptParam,
271                 &bufferIDs[bufferIDCount]);
272             CHECK_VA_STATUS("vaCreateEncryptionParameterBuffer");
273             bufferIDCount++;
274         }
275 
276         vaStatus = vaCreateBuffer(
277             mVADisplay,
278             mVAContext,
279             VASliceDataBufferType,
280             mFrameSize, //size
281             1,        //num_elements
282             sliceData->buffer_addr + sliceData->slice_offset,
283             &bufferIDs[bufferIDCount]);
284         CHECK_VA_STATUS("vaCreateSliceDataBuffer");
285         bufferIDCount++;
286 
287     }
288 
289     vaStatus = vaCreateBuffer(
290         mVADisplay,
291         mVAContext,
292         VASliceParameterBufferType,
293         sizeof(VASliceParameterBufferH264Base),
294         1,
295         sliceParam,
296         &bufferIDs[bufferIDCount]);
297 
298     CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
299     bufferIDCount++;
300 
301     vaStatus = vaRenderPicture(
302         mVADisplay,
303         mVAContext,
304         bufferIDs,
305         bufferIDCount);
306     CHECK_VA_STATUS("vaRenderPicture");
307 
308     return DECODE_SUCCESS;
309 }
310 
getCodecSpecificConfigs(VAProfile profile,VAConfigID * config)311 Decode_Status VideoDecoderAVCSecure::getCodecSpecificConfigs(
312     VAProfile profile, VAConfigID *config)
313 {
314     VAStatus vaStatus;
315     VAConfigAttrib attrib[2];
316 
317     if (config == NULL) {
318         ETRACE("Invalid parameter!");
319         return DECODE_FAIL;
320     }
321 
322     attrib[0].type = VAConfigAttribRTFormat;
323     attrib[0].value = VA_RT_FORMAT_YUV420;
324     attrib[1].type = VAConfigAttribDecSliceMode;
325     attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
326 
327     vaStatus = vaGetConfigAttributes(mVADisplay,profile,VAEntrypointVLD, &attrib[1], 1);
328 
329     if (attrib[1].value & VA_DEC_SLICE_MODE_BASE)
330     {
331         ITRACE("AVC short format used");
332         attrib[1].value = VA_DEC_SLICE_MODE_BASE;
333     } else if (attrib[1].value & VA_DEC_SLICE_MODE_NORMAL) {
334         ITRACE("AVC long format ssed");
335         attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
336     } else {
337         ETRACE("Unsupported Decode Slice Mode!");
338         return DECODE_FAIL;
339     }
340 
341     vaStatus = vaCreateConfig(
342             mVADisplay,
343             profile,
344             VAEntrypointVLD,
345             &attrib[0],
346             2,
347             config);
348     CHECK_VA_STATUS("vaCreateConfig");
349 
350     return DECODE_SUCCESS;
351 }
352