• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     iAvcActiveFlag = OMX_FALSE;
164 
165     return OMX_ErrorNone;
166 }
167 
168 
169 /*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)170 OMX_BOOL AvcDecoder_OMX::AvcDecodeVideo_OMX(OMX_U8* aOutBuffer, OMX_U32* aOutputLength,
171         OMX_U8** aInputBuf, OMX_U32* aInBufSize,
172         OMX_PARAM_PORTDEFINITIONTYPE* aPortParam,
173         OMX_S32* iFrameCount, OMX_BOOL aMarkerFlag, OMX_TICKS* aOutTimestamp, OMX_BOOL *aResizeFlag)
174 {
175     AVCDec_Status Status;
176     OMX_S32 Width, Height;
177     OMX_S32 crop_top, crop_bottom, crop_right, crop_left;
178     uint8* pNalBuffer;
179     int32 NalSize, NalType, NalRefId;
180     //int32 PicType;
181     AVCDecObject* pDecVid;
182 
183     *aResizeFlag = OMX_FALSE;
184     OMX_U32 OldWidth, OldHeight;
185 
186     OldWidth =  aPortParam->format.video.nFrameWidth;
187     OldHeight = aPortParam->format.video.nFrameHeight;
188 
189 
190     if (!aMarkerFlag)
191     {
192         if (AVCDEC_FAIL == GetNextFullNAL_OMX(&pNalBuffer, &NalSize, *aInputBuf, aInBufSize))
193         {
194             Status = (AVCDec_Status) FlushOutput_OMX(aOutBuffer, aOutputLength, aOutTimestamp, OldWidth, OldHeight);
195 
196             if (AVCDEC_FAIL != Status)
197             {
198                 return OMX_TRUE;
199             }
200             else
201             {
202                 return OMX_FALSE;
203             }
204         }
205     }
206     else
207     {
208         pNalBuffer = *aInputBuf;
209         NalSize = *aInBufSize;
210         //Assuming that the buffer with marker bit contains one full NAL
211         *aInBufSize = 0;
212     }
213 
214     if (AVCDEC_FAIL == PVAVCDecGetNALType(pNalBuffer, NalSize, &NalType, &NalRefId))
215     {
216         return OMX_FALSE;
217     }
218 
219     if (AVC_NALTYPE_SPS == (AVCNalUnitType)NalType)
220     {
221         if (PVAVCDecSeqParamSet(&(AvcHandle), pNalBuffer, NalSize) != AVCDEC_SUCCESS)
222         {
223             return OMX_FALSE;
224         }
225 
226         pDecVid = (AVCDecObject*) AvcHandle.AVCObject;
227 
228         Width = (pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16;
229         Height = (pDecVid->seqParams[0]->pic_height_in_map_units_minus1 + 1) * 16;
230 
231         if (pDecVid->seqParams[0]->frame_cropping_flag)
232         {
233             crop_left = 2 * pDecVid->seqParams[0]->frame_crop_left_offset;
234             crop_right = Width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1);
235 
236             if (pDecVid->seqParams[0]->frame_mbs_only_flag)
237             {
238                 crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset;
239                 crop_bottom = Height - (2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
240             }
241             else
242             {
243                 crop_top = 4 * pDecVid->seqParams[0]->frame_crop_top_offset;
244                 crop_bottom = Height - (4 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
245             }
246         }
247         else  /* no cropping flag, just give the first and last pixel */
248         {
249             crop_bottom = Height - 1;
250             crop_right = Width - 1;
251             crop_top = crop_left = 0;
252         }
253 
254         aPortParam->format.video.nFrameWidth = crop_right - crop_left + 1;
255         aPortParam->format.video.nFrameHeight = crop_bottom - crop_top + 1;
256 
257         OMX_U32 min_stride = ((aPortParam->format.video.nFrameWidth + 15) & (~15));
258         OMX_U32 min_sliceheight = ((aPortParam->format.video.nFrameHeight + 15) & (~15));
259 
260 
261         aPortParam->format.video.nStride = min_stride;
262         aPortParam->format.video.nSliceHeight = min_sliceheight;
263 
264 
265         // finally, compute the new minimum buffer size.
266 
267         // Decoder components always output YUV420 format
268         aPortParam->nBufferSize = (aPortParam->format.video.nSliceHeight * aPortParam->format.video.nStride * 3) >> 1;
269 
270 
271         if ((OldWidth != aPortParam->format.video.nFrameWidth) || (OldHeight !=  aPortParam->format.video.nFrameHeight))
272             *aResizeFlag = OMX_TRUE;
273 
274         (*iFrameCount)++;
275 
276     }
277 
278     else if (AVC_NALTYPE_PPS == (AVCNalUnitType) NalType)
279     {
280         if (PVAVCDecPicParamSet(&(AvcHandle), pNalBuffer, NalSize) != AVCDEC_SUCCESS)
281         {
282             return OMX_FALSE;
283         }
284     }
285 
286     else if (AVC_NALTYPE_SLICE == (AVCNalUnitType) NalType ||
287              AVC_NALTYPE_IDR == (AVCNalUnitType) NalType)
288     {
289 		if (!iAvcActiveFlag)
290 			iAvcActiveFlag = OMX_TRUE;
291 
292         if ((Status = PVAVCDecodeSlice(&(AvcHandle), pNalBuffer, NalSize)) == AVCDEC_PICTURE_OUTPUT_READY)
293         {
294             FlushOutput_OMX(aOutBuffer, aOutputLength, aOutTimestamp, OldWidth, OldHeight);
295 
296             //Input buffer not consumed yet, do not mark it free.
297             if (aMarkerFlag)
298             {
299                 *aInBufSize = NalSize;
300             }
301             else
302             {
303                 *aInBufSize += InputBytesConsumed;
304                 aInputBuf -= InputBytesConsumed;
305             }
306         }
307 
308         if (Status == AVCDEC_PICTURE_READY)
309         {
310             (*iFrameCount)++;
311         }
312 
313         if ((AVCDEC_NO_DATA == Status) || (AVCDEC_PACKET_LOSS == Status) ||
314                 (AVCDEC_NO_BUFFER == Status) || (AVCDEC_MEMORY_FAIL == Status) ||
315                 (AVCDEC_FAIL == Status))
316         {
317             return OMX_FALSE;
318         }
319     }
320 
321     else if ((AVCNalUnitType)NalType == AVC_NALTYPE_SEI)
322     {
323         if (PVAVCDecSEI(&(AvcHandle), pNalBuffer, NalSize) != AVCDEC_SUCCESS)
324         {
325             return OMX_FALSE;
326         }
327     }
328 
329     else if ((AVCNalUnitType)NalType == AVC_NALTYPE_AUD)
330     {
331         //PicType = pNalBuffer[1] >> 5;
332     }
333 
334     else if ((AVCNalUnitType)NalType == AVC_NALTYPE_EOSTREAM || // end of stream
335              (AVCNalUnitType)NalType == AVC_NALTYPE_EOSEQ || // end of sequence
336              (AVCNalUnitType)NalType == AVC_NALTYPE_FILL) // filler data
337     {
338         return OMX_TRUE;
339     }
340 
341     //else
342     //{
343     //printf("\nNAL_type = %d, unsupported nal type or not sure what to do for this type\n", NalType);
344     //  return OMX_FALSE;
345     //}
346     return OMX_TRUE;
347 
348 }
349 
350 
AvcDecDeinit_OMX()351 OMX_ERRORTYPE AvcDecoder_OMX::AvcDecDeinit_OMX()
352 {
353     if (pCleanObject)
354     {
355         OSCL_DELETE(pCleanObject);
356         pCleanObject = NULL;
357     }
358 
359     if (pDpbBuffer)
360     {
361         oscl_free(pDpbBuffer);
362         pDpbBuffer = NULL;
363     }
364 
365     return OMX_ErrorNone;
366 }
367 
368 
GetNextFullNAL_OMX(uint8 ** aNalBuffer,int32 * aNalSize,OMX_U8 * aInputBuf,OMX_U32 * aInBufSize)369 AVCDec_Status AvcDecoder_OMX::GetNextFullNAL_OMX(uint8** aNalBuffer, int32* aNalSize, OMX_U8* aInputBuf, OMX_U32* aInBufSize)
370 {
371     uint8* pBuff = aInputBuf;
372     OMX_U32 InputSize;
373 
374     *aNalSize = *aInBufSize;
375     InputSize = *aInBufSize;
376 
377     AVCDec_Status ret_val = PVAVCAnnexBGetNALUnit(pBuff, aNalBuffer, aNalSize);
378 
379     if (ret_val == AVCDEC_FAIL)
380     {
381         return AVCDEC_FAIL;
382     }
383 
384     InputBytesConsumed = ((*aNalSize) + (int32)(*aNalBuffer - pBuff));
385     aInputBuf += InputBytesConsumed;
386     *aInBufSize = InputSize - InputBytesConsumed;
387 
388     return AVCDEC_SUCCESS;
389 }
390 
~AVCCleanupObject_OMX()391 AVCCleanupObject_OMX::~AVCCleanupObject_OMX()
392 {
393     PVAVCCleanUpDecoder(ipavcHandle);
394 
395 }
396 
ResetDecoder()397 void AvcDecoder_OMX::ResetDecoder()
398 {
399     PVAVCDecReset(&(AvcHandle));
400 }
401 
402