• 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     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