1 /*
2 * Copyright (C) 2011 The Android Open Source Project
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 express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "VideoEditorVideoDecoder.h"
17 #include "VideoEditor3gpReader.h"
18
19 #include <utils/Log.h>
20 #include "VideoBrowserInternal.h"
21 #include "LVOSA_FileReader_optim.h"
22
23 //#define M4OSA_TRACE_LEVEL 1
24 #if (M4OSA_TRACE_LEVEL >= 1)
25 #undef M4OSA_TRACE1_0
26 #undef M4OSA_TRACE1_1
27 #undef M4OSA_TRACE1_2
28 #undef M4OSA_TRACE1_3
29
30 #define M4OSA_TRACE1_0(a) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a);
31 #define M4OSA_TRACE1_1(a,b) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b);
32 #define M4OSA_TRACE1_2(a,b,c) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b,c);
33 #define M4OSA_TRACE1_3(a,b,c,d) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b,c,d);
34 #endif
35
36 /******************************************************************************
37 * M4OSA_ERR videoBrowserSetWindow(
38 * M4OSA_Context pContext, M4OSA_UInt32 x,
39 * M4OSA_UInt32 y, M4OSA_UInt32 dx, M4OSA_UInt32 dy);
40 * @brief This function sets the size and the position of the display.
41 * @param pContext (IN) : Video Browser context
42 * @param pPixelArray (IN) : Array to hold the video frame.
43 * @param x (IN) : Horizontal position of the top left
44 * corner
45 * @param y (IN) : Vertical position of the top left corner
46 * @param dx (IN) : Width of the display window
47 * @param dy (IN) : Height of the video window
48 * @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
49 ******************************************************************************/
videoBrowserSetWindow(M4OSA_Context pContext,M4OSA_Int32 * pPixelArray,M4OSA_UInt32 x,M4OSA_UInt32 y,M4OSA_UInt32 dx,M4OSA_UInt32 dy)50 M4OSA_ERR videoBrowserSetWindow(
51 M4OSA_Context pContext,
52 M4OSA_Int32 *pPixelArray,
53 M4OSA_UInt32 x, M4OSA_UInt32 y,
54 M4OSA_UInt32 dx, M4OSA_UInt32 dy)
55 {
56 VideoBrowserContext* pC = (VideoBrowserContext*)pContext;
57 M4OSA_ERR err = M4NO_ERROR;
58
59 M4OSA_TRACE2_5("videoBrowserSetWindow: entering with 0x%x %d %d %d %d ",
60 pContext, x, y, dx, dy);
61
62 /*--- Sanity checks ---*/
63 CHECK_PTR(videoBrowserSetWindow, pContext, err, M4ERR_PARAMETER);
64 CHECK_PTR(videoBrowserSetWindow, pPixelArray, err, M4ERR_PARAMETER);
65 CHECK_STATE(videoBrowserSetWindow, VideoBrowser_kVBOpened, pC);
66
67 pC->m_outputPlane[0].u_topleft = 0;
68
69 pC->m_outputPlane[0].u_height = dy;
70 pC->m_outputPlane[0].u_width = dx;
71 pC->m_x = x;
72 pC->m_y = y;
73
74 if (pC->m_frameColorType == VideoBrowser_kGB565) {
75 pC->m_outputPlane[0].u_stride = pC->m_outputPlane[0].u_width << 1;
76 pC->m_outputPlane[0].pac_data = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
77 pC->m_outputPlane[0].u_stride * pC->m_outputPlane[0].u_height,
78 VIDEOBROWSER, (M4OSA_Char *)"output plane");
79
80 CHECK_PTR(videoBrowserSetWindow,
81 pC->m_outputPlane[0].pac_data, err, M4ERR_ALLOC);
82 }
83 else if (pC->m_frameColorType == VideoBrowser_kYUV420) {
84 pC->m_outputPlane[0].u_stride = pC->m_outputPlane[0].u_width;
85 pC->m_outputPlane[1].u_height = pC->m_outputPlane[0].u_height >> 1;
86 pC->m_outputPlane[1].u_width = pC->m_outputPlane[0].u_width >> 1;
87 pC->m_outputPlane[1].u_topleft = 0;
88 pC->m_outputPlane[1].u_stride = pC->m_outputPlane[1].u_width;
89
90 pC->m_outputPlane[2].u_height = pC->m_outputPlane[0].u_height >> 1;
91 pC->m_outputPlane[2].u_width = pC->m_outputPlane[0].u_width >> 1;
92 pC->m_outputPlane[2].u_topleft = 0;
93 pC->m_outputPlane[2].u_stride = pC->m_outputPlane[2].u_width;
94
95 pC->m_outputPlane[0].pac_data = (M4OSA_UInt8*)pPixelArray;
96
97 CHECK_PTR(videoBrowserSetWindow,
98 pC->m_outputPlane[0].pac_data, err, M4ERR_ALLOC);
99
100 pC->m_outputPlane[1].pac_data =
101 pC->m_outputPlane[0].pac_data +
102 (pC->m_outputPlane[0].u_stride * pC->m_outputPlane[0].u_height);
103
104 pC->m_outputPlane[2].pac_data =
105 pC->m_outputPlane[1].pac_data +
106 (pC->m_outputPlane[1].u_stride * pC->m_outputPlane[1].u_height);
107 }
108
109
110 M4OSA_TRACE2_0("videoBrowserSetWindow returned NO ERROR");
111 return M4NO_ERROR;
112
113 videoBrowserSetWindow_cleanUp:
114
115 M4OSA_TRACE2_1("videoBrowserSetWindow returned 0x%x", err);
116 return err;
117 }
118
119 /******************************************************************************
120 * @brief This function allocates the resources needed for browsing a video file
121 * @param ppContext (OUT): Pointer on a context filled by this function.
122 * @param pURL (IN) : Path of File to browse
123 * @param DrawMode (IN) : Indicate which method is used to draw (Direct draw etc...)
124 * @param pfCallback (IN) : Callback function to be called when a frame must be displayed
125 * @param pCallbackData (IN) : User defined data that will be passed as parameter of the callback
126 * @param clrType (IN) : Required color type.
127 * @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
128 ******************************************************************************/
videoBrowserCreate(M4OSA_Context * ppContext,M4OSA_Char * pURL,M4OSA_UInt32 DrawMode,M4OSA_FileReadPointer * ptrF,videoBrowser_Callback pfCallback,M4OSA_Void * pCallbackData,VideoBrowser_VideoColorType clrType)129 M4OSA_ERR videoBrowserCreate(
130 M4OSA_Context* ppContext,
131 M4OSA_Char* pURL,
132 M4OSA_UInt32 DrawMode,
133 M4OSA_FileReadPointer* ptrF,
134 videoBrowser_Callback pfCallback,
135 M4OSA_Void* pCallbackData,
136 VideoBrowser_VideoColorType clrType)
137 {
138 VideoBrowserContext* pContext = M4OSA_NULL;
139 M4READER_MediaFamily mediaFamily = M4READER_kMediaFamilyUnknown;
140 M4_StreamHandler* pStreamHandler = M4OSA_NULL;
141 M4_VideoStreamHandler* pVideoStreamHandler = M4OSA_NULL;
142 M4DECODER_VideoType decoderType;
143 M4DECODER_OutputFilter FilterOption;
144
145 M4OSA_Bool deb = M4OSA_TRUE;
146 M4OSA_ERR err = M4NO_ERROR;
147
148 M4OSA_TRACE1_2(
149 "videoBrowserCreate: entering with 0x%x 0x%x", ppContext, pURL);
150
151 /*--- Sanity checks ---*/
152 CHECK_PTR(videoBrowserCreate, ppContext, err, M4ERR_PARAMETER);
153 *ppContext = M4OSA_NULL ;
154 CHECK_PTR(videoBrowserCreate, pURL, err, M4ERR_PARAMETER);
155
156 /*--- Create context ---*/
157 pContext = (VideoBrowserContext*)M4OSA_32bitAlignedMalloc(
158 sizeof(VideoBrowserContext),
159 VIDEOBROWSER, (M4OSA_Char*)"Video browser context");
160
161 CHECK_PTR(videoBrowserCreate, pContext,err, M4ERR_ALLOC);
162 memset((void *)pContext, 0,sizeof(VideoBrowserContext));
163
164 /*--- Initialize the context parameters ---*/
165 pContext->m_state = VideoBrowser_kVBCreating ;
166 pContext->m_frameColorType = clrType;
167
168 /*--- Copy the file reader functions ---*/
169 memcpy((void *)&pContext->m_fileReadPtr,
170 (void *)ptrF,
171 sizeof(M4OSA_FileReadPointer)) ;
172
173 /* PR#SP00013 DGR bug 13 : first frame is not visible */
174 pContext->m_drawmode = DrawMode;
175
176
177 /* Retrieve the 3gp reader interface */
178 VideoEditor3gpReader_getInterface(&pContext->m_mediaType,
179 &pContext->m_3gpReader, &pContext->m_3gpData);
180
181 CHECK_PTR(videoBrowserCreate, pContext->m_3gpReader, err, M4ERR_ALLOC);
182 CHECK_PTR(videoBrowserCreate, pContext->m_3gpData, err, M4ERR_ALLOC);
183
184 /*--- Create the file reader ---*/
185 err = pContext->m_3gpReader->m_pFctCreate(&pContext->m_pReaderCtx);
186 CHECK_ERR(videoBrowserCreate, err);
187 CHECK_PTR(videoBrowserCreate, pContext->m_pReaderCtx, err, M4ERR_ALLOC);
188 pContext->m_3gpData->m_readerContext = pContext->m_pReaderCtx;
189
190 /*--- Set the OSAL file reader functions ---*/
191 err = pContext->m_3gpReader->m_pFctSetOption(
192 pContext->m_pReaderCtx,
193 M4READER_kOptionID_SetOsaFileReaderFctsPtr,
194 (M4OSA_DataOption)(&pContext->m_fileReadPtr));
195
196 CHECK_ERR(videoBrowserCreate, err) ;
197
198 /*--- Open the file ---*/
199 err = pContext->m_3gpReader->m_pFctOpen(pContext->m_pReaderCtx, pURL);
200 CHECK_ERR(videoBrowserCreate, err) ;
201
202 /*--- Try to find a video stream ---*/
203 while (err == M4NO_ERROR)
204 {
205 err = pContext->m_3gpReader->m_pFctGetNextStream(
206 pContext->m_pReaderCtx, &mediaFamily, &pStreamHandler);
207
208 /*in case we found a bifs stream or something else...*/
209 if ((err == (M4OSA_UInt32)M4ERR_READER_UNKNOWN_STREAM_TYPE) ||
210 (err == (M4OSA_UInt32)M4WAR_TOO_MUCH_STREAMS))
211 {
212 err = M4NO_ERROR;
213 continue;
214 }
215
216 if (err != M4WAR_NO_MORE_STREAM)
217 {
218 if (M4READER_kMediaFamilyVideo != mediaFamily)
219 {
220 err = M4NO_ERROR;
221 continue;
222 }
223
224 pContext->m_pStreamHandler = pStreamHandler;
225
226 err = pContext->m_3gpReader->m_pFctReset(
227 pContext->m_pReaderCtx, pContext->m_pStreamHandler);
228
229 CHECK_ERR(videoBrowserCreate, err);
230
231 err = pContext->m_3gpReader->m_pFctFillAuStruct(
232 pContext->m_pReaderCtx,
233 pContext->m_pStreamHandler,
234 &pContext->m_accessUnit);
235
236 CHECK_ERR(videoBrowserCreate, err);
237
238 pVideoStreamHandler =
239 (M4_VideoStreamHandler*)pContext->m_pStreamHandler;
240
241 switch (pContext->m_pStreamHandler->m_streamType)
242 {
243 case M4DA_StreamTypeVideoMpeg4:
244 case M4DA_StreamTypeVideoH263:
245 {
246 pContext->m_pCodecLoaderContext = M4OSA_NULL;
247 decoderType = M4DECODER_kVideoTypeMPEG4;
248
249 #ifdef USE_SOFTWARE_DECODER
250 err = VideoEditorVideoDecoder_getSoftwareInterface_MPEG4(
251 &decoderType, &pContext->m_pDecoder);
252 #else
253 err = VideoEditorVideoDecoder_getInterface_MPEG4(
254 &decoderType, (void **)&pContext->m_pDecoder);
255 #endif
256 CHECK_ERR(videoBrowserCreate, err) ;
257
258 err = pContext->m_pDecoder->m_pFctCreate(
259 &pContext->m_pDecoderCtx,
260 pContext->m_pStreamHandler,
261 pContext->m_3gpReader,
262 pContext->m_3gpData,
263 &pContext->m_accessUnit,
264 pContext->m_pCodecLoaderContext) ;
265
266 CHECK_ERR(videoBrowserCreate, err) ;
267 }
268 break;
269
270 case M4DA_StreamTypeVideoMpeg4Avc:
271 {
272 pContext->m_pCodecLoaderContext = M4OSA_NULL;
273
274 decoderType = M4DECODER_kVideoTypeAVC;
275
276 #ifdef USE_SOFTWARE_DECODER
277 err = VideoEditorVideoDecoder_getSoftwareInterface_H264(
278 &decoderType, &pContext->m_pDecoder);
279 #else
280 err = VideoEditorVideoDecoder_getInterface_H264(
281 &decoderType, (void **)&pContext->m_pDecoder);
282 #endif
283 CHECK_ERR(videoBrowserCreate, err) ;
284
285 err = pContext->m_pDecoder->m_pFctCreate(
286 &pContext->m_pDecoderCtx,
287 pContext->m_pStreamHandler,
288 pContext->m_3gpReader,
289 pContext->m_3gpData,
290 &pContext->m_accessUnit,
291 pContext->m_pCodecLoaderContext) ;
292
293 CHECK_ERR(videoBrowserCreate, err) ;
294 }
295 break;
296
297 default:
298 err = M4ERR_VB_MEDIATYPE_NOT_SUPPORTED;
299 goto videoBrowserCreate_cleanUp;
300 }
301 }
302 }
303
304 if (err == M4WAR_NO_MORE_STREAM)
305 {
306 err = M4NO_ERROR ;
307 }
308
309 if (M4OSA_NULL == pContext->m_pStreamHandler)
310 {
311 err = M4ERR_VB_NO_VIDEO ;
312 goto videoBrowserCreate_cleanUp ;
313 }
314
315 err = pContext->m_pDecoder->m_pFctSetOption(
316 pContext->m_pDecoderCtx,
317 M4DECODER_kOptionID_DeblockingFilter,
318 (M4OSA_DataOption)&deb);
319
320 if (err == M4WAR_DEBLOCKING_FILTER_NOT_IMPLEMENTED)
321 {
322 err = M4NO_ERROR;
323 }
324 CHECK_ERR(videoBrowserCreate, err);
325
326 FilterOption.m_pFilterUserData = M4OSA_NULL;
327
328
329 if (pContext->m_frameColorType == VideoBrowser_kGB565) {
330 FilterOption.m_pFilterFunction =
331 (M4OSA_Void*)M4VIFI_ResizeBilinearYUV420toBGR565;
332 }
333 else if (pContext->m_frameColorType == VideoBrowser_kYUV420) {
334 FilterOption.m_pFilterFunction =
335 (M4OSA_Void*)M4VIFI_ResizeBilinearYUV420toYUV420;
336 }
337 else {
338 err = M4ERR_PARAMETER;
339 goto videoBrowserCreate_cleanUp;
340 }
341
342 err = pContext->m_pDecoder->m_pFctSetOption(
343 pContext->m_pDecoderCtx,
344 M4DECODER_kOptionID_OutputFilter,
345 (M4OSA_DataOption)&FilterOption);
346
347 CHECK_ERR(videoBrowserCreate, err);
348
349 /* store the callback details */
350 pContext->m_pfCallback = pfCallback;
351 pContext->m_pCallbackUserData = pCallbackData;
352 /* store the callback details */
353
354 pContext->m_state = VideoBrowser_kVBOpened;
355 *ppContext = pContext;
356
357 M4OSA_TRACE1_0("videoBrowserCreate returned NO ERROR");
358 return M4NO_ERROR;
359
360 videoBrowserCreate_cleanUp:
361
362 if (M4OSA_NULL != pContext)
363 {
364 if (M4OSA_NULL != pContext->m_pDecoderCtx)
365 {
366 pContext->m_pDecoder->m_pFctDestroy(pContext->m_pDecoderCtx);
367 pContext->m_pDecoderCtx = M4OSA_NULL;
368 }
369
370 if (M4OSA_NULL != pContext->m_pReaderCtx)
371 {
372 pContext->m_3gpReader->m_pFctClose(pContext->m_pReaderCtx);
373 pContext->m_3gpReader->m_pFctDestroy(pContext->m_pReaderCtx);
374 pContext->m_pReaderCtx = M4OSA_NULL;
375 }
376 SAFE_FREE(pContext->m_pDecoder);
377 SAFE_FREE(pContext->m_3gpReader);
378 SAFE_FREE(pContext->m_3gpData);
379 SAFE_FREE(pContext);
380 }
381
382 M4OSA_TRACE2_1("videoBrowserCreate returned 0x%x", err);
383 return err;
384 }
385
386 /******************************************************************************
387 * M4OSA_ERR videoBrowserCleanUp(M4OSA_Context pContext);
388 * @brief This function frees the resources needed for browsing a
389 * video file.
390 * @param pContext (IN) : Video browser context
391 * @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE
392 ******************************************************************************/
videoBrowserCleanUp(M4OSA_Context pContext)393 M4OSA_ERR videoBrowserCleanUp(M4OSA_Context pContext)
394 {
395 VideoBrowserContext* pC = (VideoBrowserContext*)pContext;
396 M4OSA_ERR err = M4NO_ERROR;
397
398 M4OSA_TRACE2_1("videoBrowserCleanUp: entering with 0x%x", pContext);
399
400 /*--- Sanity checks ---*/
401 CHECK_PTR(videoBrowserCleanUp, pContext, err, M4ERR_PARAMETER);
402
403 if (M4OSA_NULL != pC->m_pDecoderCtx)
404 {
405 pC->m_pDecoder->m_pFctDestroy(pC->m_pDecoderCtx);
406 pC->m_pDecoderCtx = M4OSA_NULL ;
407 }
408
409 if (M4OSA_NULL != pC->m_pReaderCtx)
410 {
411 pC->m_3gpReader->m_pFctClose(pC->m_pReaderCtx) ;
412 pC->m_3gpReader->m_pFctDestroy(pC->m_pReaderCtx);
413 pC->m_pReaderCtx = M4OSA_NULL;
414 }
415
416 SAFE_FREE(pC->m_pDecoder);
417 SAFE_FREE(pC->m_3gpReader);
418 SAFE_FREE(pC->m_3gpData);
419
420 if (pC->m_frameColorType != VideoBrowser_kYUV420) {
421 SAFE_FREE(pC->m_outputPlane[0].pac_data);
422 }
423 SAFE_FREE(pC);
424
425 M4OSA_TRACE2_0("videoBrowserCleanUp returned NO ERROR");
426 return M4NO_ERROR;
427
428 videoBrowserCleanUp_cleanUp:
429
430 M4OSA_TRACE2_1("videoBrowserCleanUp returned 0x%x", err);
431 return err;
432 }
433 /******************************************************************************
434 * M4OSA_ERR videoBrowserPrepareFrame(
435 * M4OSA_Context pContext, M4OSA_UInt32* pTime);
436 * @brief This function prepares the frame.
437 * @param pContext (IN) : Video browser context
438 * @param pTime (IN/OUT) : Pointer on the time to reach. Updated
439 * by this function with the reached time
440 * @param tolerance (IN) : We may decode an earlier frame within the tolerance.
441 * The time difference is specified in milliseconds.
442 * @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
443 ******************************************************************************/
videoBrowserPrepareFrame(M4OSA_Context pContext,M4OSA_UInt32 * pTime,M4OSA_UInt32 tolerance)444 M4OSA_ERR videoBrowserPrepareFrame(M4OSA_Context pContext, M4OSA_UInt32* pTime,
445 M4OSA_UInt32 tolerance)
446 {
447 VideoBrowserContext* pC = (VideoBrowserContext*)pContext;
448 M4OSA_ERR err = M4NO_ERROR;
449 M4OSA_UInt32 targetTime = 0;
450 M4_MediaTime timeMS = 0;
451 M4OSA_Bool bJumpNeeded = M4OSA_FALSE;
452
453 /*--- Sanity checks ---*/
454 CHECK_PTR(videoBrowserPrepareFrame, pContext, err, M4ERR_PARAMETER);
455 CHECK_PTR(videoBrowserPrepareFrame, pTime, err, M4ERR_PARAMETER);
456
457 targetTime = *pTime ;
458
459 /*--- Check the state, if this is the first call to this function
460 we move to the state "browsing" ---*/
461 if (VideoBrowser_kVBOpened == pC->m_state)
462 {
463 pC->m_state = VideoBrowser_kVBBrowsing;
464 }
465 else if (VideoBrowser_kVBBrowsing != pC->m_state)
466 {
467 err = M4ERR_STATE ;
468 goto videoBrowserPrepareFrame_cleanUp;
469 }
470
471 // If we jump backward or forward to a time greater than current position by
472 // 85ms (~ 2 frames), we want to jump.
473 if (pC->m_currentCTS == 0 ||
474 targetTime < pC->m_currentCTS ||
475 targetTime > (pC->m_currentCTS + 85))
476 {
477 bJumpNeeded = M4OSA_TRUE;
478 }
479
480 timeMS = (M4_MediaTime)targetTime;
481 err = pC->m_pDecoder->m_pFctDecode(
482 pC->m_pDecoderCtx, &timeMS, bJumpNeeded, tolerance);
483
484 if ((err != M4NO_ERROR) && (err != M4WAR_NO_MORE_AU))
485 {
486 return err;
487 }
488
489 err = pC->m_pDecoder->m_pFctRender(
490 pC->m_pDecoderCtx, &timeMS, pC->m_outputPlane, M4OSA_TRUE);
491
492 if (M4WAR_VIDEORENDERER_NO_NEW_FRAME == err)
493 {
494 return err;
495 }
496 CHECK_ERR(videoBrowserPrepareFrame, err) ;
497
498 pC->m_currentCTS = (M4OSA_UInt32)timeMS;
499
500 *pTime = pC->m_currentCTS;
501
502 return M4NO_ERROR;
503
504 videoBrowserPrepareFrame_cleanUp:
505
506 if ((M4WAR_INVALID_TIME == err) || (M4WAR_NO_MORE_AU == err))
507 {
508 err = M4NO_ERROR;
509 }
510 else if (M4OSA_NULL != pC)
511 {
512 pC->m_currentCTS = 0;
513 }
514
515 M4OSA_TRACE2_1("videoBrowserPrepareFrame returned 0x%x", err);
516 return err;
517 }
518
519 /******************************************************************************
520 * M4OSA_ERR videoBrowserDisplayCurrentFrame(M4OSA_Context pContext);
521 * @brief This function displays the current frame.
522 * @param pContext (IN) : Video browser context
523 * @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
524 ******************************************************************************/
videoBrowserDisplayCurrentFrame(M4OSA_Context pContext)525 M4OSA_ERR videoBrowserDisplayCurrentFrame(M4OSA_Context pContext)
526 {
527 VideoBrowserContext* pC = (VideoBrowserContext*)pContext ;
528 M4OSA_ERR err = M4NO_ERROR ;
529
530 /*--- Sanity checks ---*/
531 CHECK_PTR(videoBrowserDisplayCurrentFrame, pContext, err, M4ERR_PARAMETER);
532
533 // Request display of the frame
534 pC->m_pfCallback((M4OSA_Context) pC, // VB context
535 VIDEOBROWSER_DISPLAY_FRAME, // action requested
536 M4NO_ERROR, // error code
537 (M4OSA_Void*) &(pC->m_outputPlane[0]), // image to be displayed
538 (M4OSA_Void*) pC->m_pCallbackUserData); // user-provided data
539
540 #ifdef DUMPTOFILE
541 {
542 M4OSA_Context fileContext;
543 M4OSA_Char* fileName = "/sdcard/textBuffer_RGB565.rgb";
544 M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,
545 M4OSA_kFileWrite | M4OSA_kFileCreate);
546
547 M4OSA_fileWriteData(fileContext,
548 (M4OSA_MemAddr8) pC->m_outputPlane[0].pac_data,
549 pC->m_outputPlane[0].u_height*pC->m_outputPlane[0].u_width*2);
550
551 M4OSA_fileWriteClose(fileContext);
552 }
553 #endif
554
555 M4OSA_TRACE2_0("videoBrowserDisplayCurrentFrame returned NO ERROR") ;
556 return M4NO_ERROR;
557
558 videoBrowserDisplayCurrentFrame_cleanUp:
559
560 M4OSA_TRACE2_1("videoBrowserDisplayCurrentFrame returned 0x%x", err) ;
561 return err;
562 }
563