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