1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 #include "oscl_types.h"
19 #include "avc_dec.h"
20 #include "avcdec_int.h"
21
22
23 /*************************************/
24 /* functions needed for video engine */
25 /*************************************/
26
27 /* These two functions are for callback functions of AvcHandle */
CBAVC_Malloc_OMX(void * aUserData,int32 aSize,int32 aAttribute)28 int32 CBAVC_Malloc_OMX(void* aUserData, int32 aSize, int32 aAttribute)
29 {
30 OSCL_UNUSED_ARG(aUserData);
31 OSCL_UNUSED_ARG(aAttribute);
32 void* pPtr;
33
34 pPtr = oscl_malloc(aSize);
35 return (int32) pPtr;
36 }
37
CBAVC_Free_OMX(void * aUserData,int32 aMem)38 void CBAVC_Free_OMX(void* aUserData, int32 aMem)
39 {
40 OSCL_UNUSED_ARG(aUserData);
41 oscl_free((uint8*) aMem);
42 }
43
44
CBAVCDec_GetData_OMX(void * aUserData,uint8 ** aBuffer,uint * aSize)45 AVCDec_Status CBAVCDec_GetData_OMX(void* aUserData, uint8** aBuffer, uint* aSize)
46 {
47 OSCL_UNUSED_ARG(aUserData);
48 OSCL_UNUSED_ARG(aBuffer);
49 OSCL_UNUSED_ARG(aSize);
50 return AVCDEC_FAIL; /* nothing for now */
51 }
52
AllocateBuffer_OMX(void * aUserData,int32 i,uint8 ** aYuvBuffer)53 int32 AvcDecoder_OMX::AllocateBuffer_OMX(void* aUserData, int32 i, uint8** aYuvBuffer)
54 {
55 AvcDecoder_OMX* pAvcDecoder_OMX = (AvcDecoder_OMX*)aUserData;
56
57 if (NULL == pAvcDecoder_OMX)
58 {
59 return 0;
60 }
61
62 *aYuvBuffer = pAvcDecoder_OMX->pDpbBuffer + i * pAvcDecoder_OMX->FrameSize;
63 //Store the input timestamp at the correct index
64 pAvcDecoder_OMX->DisplayTimestampArray[i] = pAvcDecoder_OMX->CurrInputTimestamp;
65 return 1;
66 }
67
68
UnbindBuffer_OMX(void * aUserData,int32 i)69 void UnbindBuffer_OMX(void* aUserData, int32 i)
70 {
71 OSCL_UNUSED_ARG(aUserData);
72 OSCL_UNUSED_ARG(i);
73 return;
74 }
75
ActivateSPS_OMX(void * aUserData,uint aSizeInMbs,uint aNumBuffers)76 int32 AvcDecoder_OMX::ActivateSPS_OMX(void* aUserData, uint aSizeInMbs, uint aNumBuffers)
77 {
78 AvcDecoder_OMX* pAvcDecoder_OMX = (AvcDecoder_OMX*)aUserData;
79
80 if (NULL == pAvcDecoder_OMX)
81 {
82 return 0;
83 }
84
85 PVAVCDecGetSeqInfo(&(pAvcDecoder_OMX->AvcHandle), &(pAvcDecoder_OMX->SeqInfo));
86
87 if (pAvcDecoder_OMX->pDpbBuffer)
88 {
89 oscl_free(pAvcDecoder_OMX->pDpbBuffer);
90 pAvcDecoder_OMX->pDpbBuffer = NULL;
91 }
92
93 pAvcDecoder_OMX->FrameSize = (aSizeInMbs << 7) * 3;
94 pAvcDecoder_OMX->pDpbBuffer = (uint8*) oscl_malloc(aNumBuffers * (pAvcDecoder_OMX->FrameSize));
95
96 return 1;
97 }
98
99 /* initialize video decoder */
InitializeVideoDecode_OMX()100 OMX_BOOL AvcDecoder_OMX::InitializeVideoDecode_OMX()
101 {
102 /* Initialize AvcHandle */
103 AvcHandle.AVCObject = NULL;
104 AvcHandle.userData = (void*)this;
105 AvcHandle.CBAVC_DPBAlloc = ActivateSPS_OMX;
106 AvcHandle.CBAVC_FrameBind = AllocateBuffer_OMX;
107 AvcHandle.CBAVC_FrameUnbind = UnbindBuffer_OMX;
108 AvcHandle.CBAVC_Malloc = CBAVC_Malloc_OMX;
109 AvcHandle.CBAVC_Free = CBAVC_Free_OMX;
110
111 return OMX_TRUE;
112 }
113
FlushOutput_OMX(OMX_U8 * aOutBuffer,OMX_U32 * aOutputLength,OMX_TICKS * aOutTimestamp,OMX_S32 OldWidth,OMX_S32 OldHeight)114 OMX_BOOL AvcDecoder_OMX::FlushOutput_OMX(OMX_U8* aOutBuffer, OMX_U32* aOutputLength, OMX_TICKS* aOutTimestamp, OMX_S32 OldWidth, OMX_S32 OldHeight)
115 {
116 AVCFrameIO Output;
117 AVCDec_Status Status;
118 int32 Index, Release, FrameSize;
119 OMX_S32 OldFrameSize = ((OldWidth + 15) & (~15)) * ((OldHeight + 15) & (~15));
120
121 Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
122 Status = PVAVCDecGetOutput(&(AvcHandle), &Index, &Release, &Output);
123
124 if (Status == AVCDEC_FAIL)
125 {
126 return OMX_FALSE;
127 }
128
129 *aOutTimestamp = DisplayTimestampArray[Index];
130 *aOutputLength = 0; // init to 0
131
132 if (Output.YCbCr[0])
133 {
134 FrameSize = Output.pitch * Output.height;
135 // it should not happen that the frame size is smaller than available buffer size, but check just in case
136 if (FrameSize <= OldFrameSize)
137 {
138 *aOutputLength = (Output.pitch * Output.height * 3) >> 1;
139
140 oscl_memcpy(aOutBuffer, Output.YCbCr[0], FrameSize);
141 oscl_memcpy(aOutBuffer + FrameSize, Output.YCbCr[1], FrameSize >> 2);
142 oscl_memcpy(aOutBuffer + FrameSize + FrameSize / 4, Output.YCbCr[2], FrameSize >> 2);
143 }
144 // else, the frame length is reported as zero, and there is no copying
145 }
146
147
148 return OMX_TRUE;
149 }
150
151
152 /* Initialization routine */
AvcDecInit_OMX()153 OMX_ERRORTYPE AvcDecoder_OMX::AvcDecInit_OMX()
154 {
155 if (OMX_FALSE == InitializeVideoDecode_OMX())
156 {
157 return OMX_ErrorInsufficientResources;
158 }
159
160 //Set up the cleanup object in order to do clean up work automatically
161 pCleanObject = OSCL_NEW(AVCCleanupObject_OMX, (&AvcHandle));
162
163 return OMX_ErrorNone;
164 }
165
166
167 /*Decode routine */
AvcDecodeVideo_OMX(OMX_U8 * aOutBuffer,OMX_U32 * aOutputLength,OMX_U8 ** aInputBuf,OMX_U32 * aInBufSize,OMX_PARAM_PORTDEFINITIONTYPE * aPortParam,OMX_S32 * iFrameCount,OMX_BOOL aMarkerFlag,OMX_TICKS * aOutTimestamp,OMX_BOOL * aResizeFlag)168 OMX_BOOL AvcDecoder_OMX::AvcDecodeVideo_OMX(OMX_U8* aOutBuffer, OMX_U32* aOutputLength,
169 OMX_U8** aInputBuf, OMX_U32* aInBufSize,
170 OMX_PARAM_PORTDEFINITIONTYPE* aPortParam,
171 OMX_S32* iFrameCount, OMX_BOOL aMarkerFlag, OMX_TICKS* aOutTimestamp, OMX_BOOL *aResizeFlag)
172 {
173 AVCDec_Status Status;
174 OMX_S32 Width, Height;
175 OMX_S32 crop_top, crop_bottom, crop_right, crop_left;
176 uint8* pNalBuffer;
177 int32 NalSize, NalType, NalRefId;
178 //int32 PicType;
179 AVCDecObject* pDecVid;
180
181 *aResizeFlag = OMX_FALSE;
182 OMX_U32 OldWidth, OldHeight;
183
184 OldWidth = aPortParam->format.video.nFrameWidth;
185 OldHeight = aPortParam->format.video.nFrameHeight;
186
187
188 if (!aMarkerFlag)
189 {
190 if (AVCDEC_FAIL == GetNextFullNAL_OMX(&pNalBuffer, &NalSize, *aInputBuf, aInBufSize))
191 {
192 Status = (AVCDec_Status) FlushOutput_OMX(aOutBuffer, aOutputLength, aOutTimestamp, OldWidth, OldHeight);
193
194 if (AVCDEC_FAIL != Status)
195 {
196 return OMX_TRUE;
197 }
198 else
199 {
200 return OMX_FALSE;
201 }
202 }
203 }
204 else
205 {
206 pNalBuffer = *aInputBuf;
207 NalSize = *aInBufSize;
208 //Assuming that the buffer with marker bit contains one full NAL
209 *aInBufSize = 0;
210 }
211
212 if (AVCDEC_FAIL == PVAVCDecGetNALType(pNalBuffer, NalSize, &NalType, &NalRefId))
213 {
214 return OMX_FALSE;
215 }
216
217 if (AVC_NALTYPE_SPS == (AVCNalUnitType)NalType)
218 {
219 if (PVAVCDecSeqParamSet(&(AvcHandle), pNalBuffer, NalSize) != AVCDEC_SUCCESS)
220 {
221 return OMX_FALSE;
222 }
223
224 pDecVid = (AVCDecObject*) AvcHandle.AVCObject;
225
226 Width = (pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16;
227 Height = (pDecVid->seqParams[0]->pic_height_in_map_units_minus1 + 1) * 16;
228
229 if (pDecVid->seqParams[0]->frame_cropping_flag)
230 {
231 crop_left = 2 * pDecVid->seqParams[0]->frame_crop_left_offset;
232 crop_right = Width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1);
233
234 if (pDecVid->seqParams[0]->frame_mbs_only_flag)
235 {
236 crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset;
237 crop_bottom = Height - (2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
238 }
239 else
240 {
241 crop_top = 4 * pDecVid->seqParams[0]->frame_crop_top_offset;
242 crop_bottom = Height - (4 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
243 }
244 }
245 else /* no cropping flag, just give the first and last pixel */
246 {
247 crop_bottom = Height - 1;
248 crop_right = Width - 1;
249 crop_top = crop_left = 0;
250 }
251
252 aPortParam->format.video.nFrameWidth = crop_right - crop_left + 1;
253 aPortParam->format.video.nFrameHeight = crop_bottom - crop_top + 1;
254
255 //if( (OldWidth != aPortParam->format.video.nFrameWidth) || (OldHeight != aPortParam->format.video.nFrameHeight))
256 // FORCE RESIZE ALWAYS FOR SPS
257 *aResizeFlag = OMX_TRUE;
258
259 (*iFrameCount)++;
260
261 }
262
263 else if (AVC_NALTYPE_PPS == (AVCNalUnitType) NalType)
264 {
265 if (PVAVCDecPicParamSet(&(AvcHandle), pNalBuffer, NalSize) != AVCDEC_SUCCESS)
266 {
267 return OMX_FALSE;
268 }
269 }
270
271 else if (AVC_NALTYPE_SLICE == (AVCNalUnitType) NalType ||
272 AVC_NALTYPE_IDR == (AVCNalUnitType) NalType)
273 {
274 if ((Status = PVAVCDecodeSlice(&(AvcHandle), pNalBuffer, NalSize)) == AVCDEC_PICTURE_OUTPUT_READY)
275 {
276 FlushOutput_OMX(aOutBuffer, aOutputLength, aOutTimestamp, OldWidth, OldHeight);
277
278 //Input buffer not consumed yet, do not mark it free.
279 if (aMarkerFlag)
280 {
281 *aInBufSize = NalSize;
282 }
283 else
284 {
285 *aInBufSize += InputBytesConsumed;
286 aInputBuf -= InputBytesConsumed;
287 }
288 }
289
290 if (Status == AVCDEC_PICTURE_READY)
291 {
292 (*iFrameCount)++;
293 }
294
295 if ((AVCDEC_NO_DATA == Status) || (AVCDEC_PACKET_LOSS == Status) ||
296 (AVCDEC_NO_BUFFER == Status) || (AVCDEC_MEMORY_FAIL == Status) ||
297 (AVCDEC_FAIL == Status))
298 {
299 return OMX_FALSE;
300 }
301 }
302
303 else if ((AVCNalUnitType)NalType == AVC_NALTYPE_SEI)
304 {
305 if (PVAVCDecSEI(&(AvcHandle), pNalBuffer, NalSize) != AVCDEC_SUCCESS)
306 {
307 return OMX_FALSE;
308 }
309 }
310
311 else if ((AVCNalUnitType)NalType == AVC_NALTYPE_AUD)
312 {
313 //PicType = pNalBuffer[1] >> 5;
314 }
315
316 else if ((AVCNalUnitType)NalType == AVC_NALTYPE_EOSTREAM || // end of stream
317 (AVCNalUnitType)NalType == AVC_NALTYPE_EOSEQ || // end of sequence
318 (AVCNalUnitType)NalType == AVC_NALTYPE_FILL) // filler data
319 {
320 return OMX_TRUE;
321 }
322
323 //else
324 //{
325 //printf("\nNAL_type = %d, unsupported nal type or not sure what to do for this type\n", NalType);
326 // return OMX_FALSE;
327 //}
328 return OMX_TRUE;
329
330 }
331
332
AvcDecDeinit_OMX()333 OMX_ERRORTYPE AvcDecoder_OMX::AvcDecDeinit_OMX()
334 {
335 if (pCleanObject)
336 {
337 OSCL_DELETE(pCleanObject);
338 pCleanObject = NULL;
339 }
340
341 if (pDpbBuffer)
342 {
343 oscl_free(pDpbBuffer);
344 pDpbBuffer = NULL;
345 }
346
347 return OMX_ErrorNone;
348 }
349
350
GetNextFullNAL_OMX(uint8 ** aNalBuffer,int32 * aNalSize,OMX_U8 * aInputBuf,OMX_U32 * aInBufSize)351 AVCDec_Status AvcDecoder_OMX::GetNextFullNAL_OMX(uint8** aNalBuffer, int32* aNalSize, OMX_U8* aInputBuf, OMX_U32* aInBufSize)
352 {
353 uint8* pBuff = aInputBuf;
354 OMX_U32 InputSize;
355
356 *aNalSize = *aInBufSize;
357 InputSize = *aInBufSize;
358
359 AVCDec_Status ret_val = PVAVCAnnexBGetNALUnit(pBuff, aNalBuffer, aNalSize);
360
361 if (ret_val == AVCDEC_FAIL)
362 {
363 return AVCDEC_FAIL;
364 }
365
366 InputBytesConsumed = ((*aNalSize) + (int32)(*aNalBuffer - pBuff));
367 aInputBuf += InputBytesConsumed;
368 *aInBufSize = InputSize - InputBytesConsumed;
369
370 return AVCDEC_SUCCESS;
371 }
372
~AVCCleanupObject_OMX()373 AVCCleanupObject_OMX::~AVCCleanupObject_OMX()
374 {
375 PVAVCCleanUpDecoder(ipavcHandle);
376
377 }
378
ResetDecoder()379 void AvcDecoder_OMX::ResetDecoder()
380 {
381 PVAVCDecReset(&(AvcHandle));
382 }
383
384