• 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 #ifndef OSCL_BASE_H_INCLUDED
19 #include "oscl_base.h"
20 #endif
21 
22 #include "mpeg4_dec.h"
23 #include "oscl_mem.h"
24 #include "omx_mpeg4_component.h"
25 
26 
27 #define MAX_LAYERS 1
28 #define PVH263DEFAULTHEIGHT 288
29 #define PVH263DEFAULTWIDTH 352
30 
31 #include <utils/Log.h>
32 #undef LOG_TAG
33 #define LOG_TAG "SW_DEC"
34 // from m4v_config_parser.h
35 OSCL_IMPORT_REF int16 iGetM4VConfigInfo(uint8 *buffer, int32 length, int32 *width, int32 *height, int32 *, int32 *);
36 
Mpeg4Decoder_OMX()37 Mpeg4Decoder_OMX::Mpeg4Decoder_OMX()
38 {
39     pFrame0 = NULL;
40     pFrame1 = NULL;
41 
42     iDisplay_Width = 0;
43     iDisplay_Height = 0;
44 
45     VO_START_CODE1[0] = 0x00;
46     VO_START_CODE1[1] = 0x00;
47     VO_START_CODE1[2] = 0x01;
48     VO_START_CODE1[3] = 0x00;
49 
50     VOSH_START_CODE1[0] = 0x00;
51     VOSH_START_CODE1[1] = 0x00;
52     VOSH_START_CODE1[2] = 0x01;
53     VOSH_START_CODE1[3] = 0xB0;
54 
55     VOP_START_CODE1[0] = 0x00;
56     VOP_START_CODE1[1] = 0x00;
57     VOP_START_CODE1[2] = 0x01;
58     VOP_START_CODE1[3] = 0xB6;
59 
60     H263_START_CODE1[0] = 0x00;
61     H263_START_CODE1[1] = 0x00;
62     H263_START_CODE1[2] = 0x80;
63 
64 }
65 
66 
67 /* Initialization routine */
Mp4DecInit()68 OMX_ERRORTYPE Mpeg4Decoder_OMX::Mp4DecInit()
69 {
70     Mpeg4InitCompleteFlag = OMX_FALSE;
71     return OMX_ErrorNone;
72 }
73 
74 
75 /*Decode routine */
Mp4DecodeVideo(OMX_U8 * aOutBuffer,OMX_U32 * aOutputLength,OMX_U8 ** aInputBuf,OMX_U32 * aInBufSize,OMX_PARAM_PORTDEFINITIONTYPE * aPortParam,OMX_S32 * aFrameCount,OMX_BOOL aMarkerFlag,OMX_BOOL * aResizeFlag)76 OMX_BOOL Mpeg4Decoder_OMX::Mp4DecodeVideo(OMX_U8* aOutBuffer, OMX_U32* aOutputLength,
77         OMX_U8** aInputBuf, OMX_U32* aInBufSize,
78         OMX_PARAM_PORTDEFINITIONTYPE* aPortParam,
79         OMX_S32* aFrameCount, OMX_BOOL aMarkerFlag, OMX_BOOL *aResizeFlag)
80 {
81     OMX_BOOL Status = OMX_TRUE;
82     OMX_S32 OldWidth, OldHeight, OldFrameSize;
83 
84     OldWidth = aPortParam->format.video.nFrameWidth;
85     OldHeight = aPortParam->format.video.nFrameHeight;
86     *aResizeFlag = OMX_FALSE;
87 
88 #ifdef _DEBUG
89     static OMX_U32 FrameCount = 0;
90 #endif
91     uint32 UseExtTimestamp = 0;
92     uint32 TimeStamp;
93     //OMX_S32 MaxSize = BIT_BUFF_SIZE;
94     OMX_S32 FrameSize, InputSize, InitSize;
95     OMX_U8* pTempFrame, *pSrc[3];
96 
97     if (Mpeg4InitCompleteFlag == OMX_FALSE)
98     {
99         if (!aMarkerFlag)
100         {
101             InitSize = GetVideoHeader(0, *aInputBuf, *aInBufSize);
102         }
103         else
104         {
105             InitSize = *aInBufSize;
106         }
107 
108         if (PV_TRUE != InitializeVideoDecode(&iDisplay_Width, &iDisplay_Height,
109                                              aInputBuf, (OMX_S32*)aInBufSize, MPEG4_MODE))
110             return OMX_FALSE;
111 
112         Mpeg4InitCompleteFlag = OMX_TRUE;
113         aPortParam->format.video.nFrameWidth = iDisplay_Width;
114         aPortParam->format.video.nFrameHeight = iDisplay_Height;
115 
116         OMX_U32 min_stride = ((aPortParam->format.video.nFrameWidth + 15) & (~15));
117         OMX_U32 min_sliceheight = ((aPortParam->format.video.nFrameHeight + 15) & (~15));
118 
119 
120         aPortParam->format.video.nStride = min_stride;
121         aPortParam->format.video.nSliceHeight = min_sliceheight;
122 
123 
124         // finally, compute the new minimum buffer size.
125 
126         // Decoder components always output YUV420 format
127         aPortParam->nBufferSize = (aPortParam->format.video.nSliceHeight * aPortParam->format.video.nStride * 3) >> 1;
128 
129 
130         if ((iDisplay_Width != OldWidth) || (iDisplay_Height != OldHeight))
131             *aResizeFlag = OMX_TRUE;
132 
133         *aFrameCount = 1;
134         *aInBufSize -= InitSize;
135         return OMX_TRUE;
136     }
137 
138     //MaxSize = *aInBufSize;
139 
140     if ((*(OMX_S32*)aInBufSize) <= 0)
141     {
142         return OMX_FALSE;
143     }
144 
145     TimeStamp = 0xFFFFFFFF;
146     InputSize = *aInBufSize;
147 
148     // in case of H263, read the 1st frame to find out the sizes (use the m4v_config)
149     if ((0 == *aFrameCount) && (H263_MODE == CodecMode))
150     {
151         int32 aligned_width, aligned_height;
152         int32 display_width, display_height;
153 
154         if (iGetM4VConfigInfo(*aInputBuf, *aInBufSize, &aligned_width, &aligned_height, &display_width, &display_height))
155         {
156             return OMX_FALSE;
157         }
158 
159         iDisplay_Width = display_width;
160         iDisplay_Height = display_height;
161         aPortParam->format.video.nFrameWidth = iDisplay_Width; // use non 16byte aligned values (display_width) for H263
162         aPortParam->format.video.nFrameHeight = iDisplay_Height; // like in the case of M4V (PVGetVideoDimensions also returns display_width/height)
163 
164         OMX_U32 min_stride = ((aPortParam->format.video.nFrameWidth + 15) & (~15));
165         OMX_U32 min_sliceheight = ((aPortParam->format.video.nFrameHeight + 15) & (~15));
166 
167 
168         aPortParam->format.video.nStride = min_stride;
169         aPortParam->format.video.nSliceHeight = min_sliceheight;
170 
171         // finally, compute the new minimum buffer size.
172 
173         // Decoder components always output YUV420 format
174         aPortParam->nBufferSize = (aPortParam->format.video.nSliceHeight * aPortParam->format.video.nStride * 3) >> 1;
175 
176 
177         if ((iDisplay_Width != OldWidth) || (iDisplay_Height != OldHeight))
178             *aResizeFlag = OMX_TRUE;
179 
180         *aFrameCount = 1;
181         return OMX_TRUE;
182     }
183 
184     Status = (OMX_BOOL) PVDecodeVideoFrame(&VideoCtrl, aInputBuf,
185                                            &TimeStamp,
186                                            (int32*)aInBufSize,
187                                            &UseExtTimestamp,
188                                            (OMX_U8*) pFrame0);
189 
190     if (Status == PV_TRUE)
191     {
192 
193 #ifdef _DEBUG
194         //printf("Frame number %d\n", ++FrameCount);
195 #endif
196         // advance input buffer ptr
197         *aInputBuf += (InputSize - *aInBufSize);
198 
199         pTempFrame = (OMX_U8*) pFrame0;
200         pFrame0 = (OMX_U8*) pFrame1;
201         pFrame1 = (OMX_U8*) pTempFrame;
202 
203         int32 display_width, display_height;
204         PVGetVideoDimensions(&VideoCtrl, &display_width, &display_height);
205         iDisplay_Width = display_width;
206         iDisplay_Height = display_height;
207         if ((iDisplay_Width != OldWidth) || (iDisplay_Height != OldHeight))
208         {
209 
210             aPortParam->format.video.nFrameWidth = iDisplay_Width;
211             aPortParam->format.video.nFrameHeight = iDisplay_Height;
212 
213             OMX_U32 min_stride = ((aPortParam->format.video.nFrameWidth + 15) & (~15));
214             OMX_U32 min_sliceheight = ((aPortParam->format.video.nFrameHeight + 15) & (~15));
215 
216 
217             aPortParam->format.video.nStride = min_stride;
218             aPortParam->format.video.nSliceHeight = min_sliceheight;
219 
220             // finally, compute the new minimum buffer size.
221 
222             // Decoder components always output YUV420 format
223             aPortParam->nBufferSize = (aPortParam->format.video.nSliceHeight * aPortParam->format.video.nStride * 3) >> 1;
224 
225             *aResizeFlag = OMX_TRUE;
226         }
227         FrameSize = (((iDisplay_Width + 15) >> 4) << 4) * (((iDisplay_Height + 15) >> 4) << 4);
228         OldFrameSize = (((OldWidth + 15) >> 4) << 4) * (((OldHeight + 15) >> 4) << 4);
229 
230         // THIS SHOULD NEVER HAPPEN, but just in case
231         // check so to not write a larger output into a smaller buffer
232         if (FrameSize <= OldFrameSize)
233         {
234             *aOutputLength = (FrameSize * 3) >> 1;
235 
236             pSrc[0] = VideoCtrl.outputFrame;
237             pSrc[1] = pSrc[0] + FrameSize;
238             pSrc[2] = pSrc[0] + FrameSize + FrameSize / 4;
239 
240             *aOutputLength = (FrameSize * 3) >> 1;
241 
242             oscl_memcpy(aOutBuffer, pSrc[0], FrameSize);
243             oscl_memcpy(aOutBuffer + FrameSize, pSrc[1], FrameSize >> 2);
244             oscl_memcpy(aOutBuffer + FrameSize + FrameSize / 4, pSrc[2], FrameSize >> 2);
245         }
246         else
247         {
248             *aOutputLength = 0;
249         }
250 
251         (*aFrameCount)++;
252     }
253     else
254     {
255         *aInBufSize = InputSize;
256         *aOutputLength = 0;
257     }
258 
259     return Status;
260 }
261 
InitializeVideoDecode(OMX_S32 * aWidth,OMX_S32 * aHeight,OMX_U8 ** aBuffer,OMX_S32 * aSize,OMX_S32 mode)262 OMX_S32 Mpeg4Decoder_OMX::InitializeVideoDecode(
263     OMX_S32* aWidth, OMX_S32* aHeight, OMX_U8** aBuffer, OMX_S32* aSize, OMX_S32 mode)
264 {
265     OMX_U32 VideoDecOutputSize;
266     OMX_S32 OK = PV_TRUE;
267     CodecMode = MPEG4_MODE;
268 
269     if (mode == MODE_H263)
270     {
271         LOGE("PV SW DECODER is used for H.263");
272         CodecMode = H263_MODE;
273     }
274     else
275     {
276         LOGE("PV SW DECODER is used for MPEG4");
277     }
278 
279     OK = PVInitVideoDecoder(&VideoCtrl, aBuffer, (int32*) aSize, 1,
280                             PVH263DEFAULTWIDTH, PVH263DEFAULTHEIGHT, CodecMode);
281 
282     if (OK)
283     {
284         PVGetVideoDimensions(&VideoCtrl, (int32*) aWidth, (int32*) aHeight);
285         CodecMode = PVGetDecBitstreamMode(&VideoCtrl);
286 
287         if (CodecMode == H263_MODE && (*aWidth == 0 || *aHeight == 0))
288         {
289             *aWidth = PVH263DEFAULTWIDTH;
290             *aHeight = PVH263DEFAULTHEIGHT;
291         }
292 
293         PVSetPostProcType(&VideoCtrl, 0);
294         VideoDecOutputSize = (((*aWidth + 15) & - 16) * ((*aHeight + 15) & - 16) * 3) / 2;
295         pFrame0 = (OMX_U8*) oscl_malloc(VideoDecOutputSize);
296         pFrame1 = (OMX_U8*) oscl_malloc(VideoDecOutputSize);
297         PVSetReferenceYUV(&VideoCtrl, pFrame1);
298         return PV_TRUE;
299     }
300     else
301     {
302         return PV_FALSE;
303     }
304 
305 
306 }
307 
Mp4DecDeinit()308 OMX_ERRORTYPE Mpeg4Decoder_OMX::Mp4DecDeinit()
309 {
310     OMX_BOOL Status;
311 
312     if (pFrame0)
313     {
314         oscl_free(pFrame0);
315         pFrame0 = NULL;
316     }
317     if (pFrame1)
318     {
319         oscl_free(pFrame1);
320         pFrame1 = NULL;
321     }
322 
323     Status = (OMX_BOOL) PVCleanUpVideoDecoder(&VideoCtrl);
324     if (Status != OMX_TRUE)
325     {
326         return OMX_ErrorUndefined;
327     }
328     return OMX_ErrorNone;
329 }
330 
GetVideoHeader(int32 aLayer,uint8 * aBuf,int32 aMaxSize)331 OMX_S32 Mpeg4Decoder_OMX::GetVideoHeader(int32 aLayer, uint8* aBuf, int32 aMaxSize)
332 {
333     OSCL_UNUSED_ARG(aLayer);
334 
335     int32 count = 0;
336     char my_sc[4];
337 
338     uint8 *tmp_bs = aBuf;
339 
340     oscl_memcpy(my_sc, tmp_bs, 4);
341     my_sc[3] &= 0xf0;
342 
343     if (aMaxSize >= 4)
344     {
345         if (oscl_memcmp(my_sc, VOSH_START_CODE1, 4) && oscl_memcmp(my_sc, VO_START_CODE1, 4))
346         {
347             count = 0;
348             iShortVideoHeader = OMX_TRUE;
349         }
350         else
351         {
352             count = 0;
353             iShortVideoHeader = FALSE;
354             while (oscl_memcmp(tmp_bs + count, VOP_START_CODE1, 4))
355             {
356                 count++;
357                 if (count > 1000)
358                 {
359                     iShortVideoHeader = OMX_TRUE;
360                     break;
361                 }
362             }
363             if (iShortVideoHeader == OMX_TRUE)
364             {
365                 count = 0;
366                 while (oscl_memcmp(tmp_bs + count, H263_START_CODE1, 3))
367                 {
368                     count++;
369                 }
370             }
371         }
372     }
373     return count;
374 }
375 
376