1
2/*
3 * Copyright (C) Texas Instruments - http://www.ti.com/
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21/* =============================================================================
22*             Texas Instruments OMAP(TM) Platform Software
23*  (c) Copyright Texas Instruments, Incorporated.  All Rights Reserved.
24*
25*  Use of this software is controlled by the terms and conditions found
26*  in the license agreement under which this software has been supplied.
27* =========================================================================== */
28/**
29* @file OMX_Video_Dec_Thread.c
30*
31* This file implements OMX Component for MPEG-4 decoder that
32* is fully compliant with the Khronos OMX specification 1.0.
33*
34* @path  $(CSLPATH)\src
35*
36* @rev  0.1
37*/
38/* -------------------------------------------------------------------------- */
39/* =============================================================================
40*!
41*! Revision History
42*! =============================================================================
43*!
44*! 02-Feb-2006 mf: Revisions appear in reverse chronological order;
45*! that is, newest first.  The date format is dd-Mon-yyyy.
46* =========================================================================== */
47
48/* ------compilation control switches ----------------------------------------*/
49/*******************************************************************************
50*  INCLUDE FILES
51*******************************************************************************/
52/* ----- system and platform files -------------------------------------------*/
53#ifdef UNDER_CE
54    #include <windows.h>
55    #include <oaf_osal.h>
56    #include <omx_core.h>
57#else
58#define _XOPEN_SOURCE 600
59    #include <wchar.h>
60    #include <sys/select.h>
61    #include <signal.h>
62    #include <unistd.h>
63    #include <sys/time.h>
64    #include <sys/types.h>
65    #include <sys/ioctl.h>
66    #include <fcntl.h>
67    #include <errno.h>
68
69#endif
70
71#include <dbapi.h>
72#include <string.h>
73#include <stdlib.h>
74#include <stdio.h>
75
76#include "OMX_VideoDecoder.h"
77#include "OMX_VideoDec_Utils.h"
78#include "OMX_VideoDec_Thread.h"
79#include "OMX_VideoDec_DSP.h"
80
81
82extern OMX_ERRORTYPE VIDDEC_HandleCommand (OMX_HANDLETYPE pHandle, OMX_U32 nParam1);
83extern OMX_ERRORTYPE VIDDEC_DisablePort(VIDDEC_COMPONENT_PRIVATE *pComponentPrivate, OMX_U32 nParam1);
84extern OMX_ERRORTYPE VIDDEC_EnablePort(VIDDEC_COMPONENT_PRIVATE *pComponentPrivate, OMX_U32 nParam1);
85extern OMX_ERRORTYPE VIDDEC_HandleDataBuf_FromApp( VIDDEC_COMPONENT_PRIVATE *pComponentPrivate);
86extern OMX_ERRORTYPE VIDDEC_HandleDataBuf_FromDsp( VIDDEC_COMPONENT_PRIVATE *pComponentPrivate );
87extern OMX_ERRORTYPE VIDDEC_HandleFreeDataBuf( VIDDEC_COMPONENT_PRIVATE *pComponentPrivate );
88extern OMX_ERRORTYPE VIDDEC_HandleFreeOutputBufferFromApp(VIDDEC_COMPONENT_PRIVATE *pComponentPrivate) ;
89extern OMX_ERRORTYPE VIDDEC_Start_ComponentThread(OMX_HANDLETYPE pHandle);
90extern OMX_ERRORTYPE VIDDEC_Stop_ComponentThread(OMX_HANDLETYPE pComponent);
91extern OMX_ERRORTYPE VIDDEC_HandleCommandMarkBuffer(VIDDEC_COMPONENT_PRIVATE *pComponentPrivate, OMX_U32 nParam1, OMX_PTR pCmdData);
92extern OMX_ERRORTYPE VIDDEC_HandleCommandFlush(VIDDEC_COMPONENT_PRIVATE *pComponentPrivate, OMX_U32 nParam1, OMX_BOOL bPass);
93extern OMX_ERRORTYPE VIDDEC_Handle_InvalidState (VIDDEC_COMPONENT_PRIVATE* pComponentPrivate);
94
95/*----------------------------------------------------------------------------*/
96/**
97  * OMX_VidDec_Thread() is the open max thread. This method is in charge of
98  * listening to the buffers coming from DSP, application or commands through the pipes
99  **/
100/*----------------------------------------------------------------------------*/
101
102/** Default timeout used to come out of blocking calls*/
103#define VIDD_TIMEOUT (1000) /* milliseconds */
104
105void* OMX_VidDec_Thread (void* pThreadData)
106{
107    int status;
108#ifdef UNDER_CE
109    struct timeval tv;
110#else
111    sigset_t set;
112    struct timespec tv;
113#endif
114    int fdmax;
115    fd_set rfds;
116    OMX_ERRORTYPE eError = OMX_ErrorNone;
117    OMX_COMMANDTYPE eCmd;
118    OMX_U32 nParam1;
119    OMX_PTR pCmdData;
120    VIDDEC_COMPONENT_PRIVATE* pComponentPrivate;
121    LCML_DSP_INTERFACE *pLcmlHandle;
122    OMX_U32 aParam[4];
123#ifndef UNDER_CE
124    OMX_BOOL bFlag = OMX_FALSE;
125#endif
126    /*OMX_U32 timeout = 0;*/
127
128    pComponentPrivate = (VIDDEC_COMPONENT_PRIVATE*)pThreadData;
129
130#ifdef __PERF_INSTRUMENTATION__
131    pComponentPrivate->pPERFcomp = PERF_Create(PERF_FOURS("VD T"),
132                                               PERF_ModuleComponent | PERF_ModuleVideoDecode);
133#endif
134
135    pLcmlHandle = (LCML_DSP_INTERFACE *)pComponentPrivate->pLCML;
136
137    /**Looking for highest number of file descriptor for pipes in order to put in select loop */
138    fdmax = pComponentPrivate->cmdPipe[VIDDEC_PIPE_READ];
139
140    if (pComponentPrivate->free_inpBuf_Q[VIDDEC_PIPE_READ] > fdmax) {
141        fdmax = pComponentPrivate->free_inpBuf_Q[VIDDEC_PIPE_READ];
142    }
143
144    if (pComponentPrivate->free_outBuf_Q[VIDDEC_PIPE_READ] > fdmax) {
145        fdmax = pComponentPrivate->free_outBuf_Q[VIDDEC_PIPE_READ];
146    }
147
148    if (pComponentPrivate->filled_inpBuf_Q[VIDDEC_PIPE_READ] > fdmax) {
149        fdmax = pComponentPrivate->filled_inpBuf_Q[VIDDEC_PIPE_READ];
150    }
151
152    if (pComponentPrivate->filled_outBuf_Q[VIDDEC_PIPE_READ] > fdmax) {
153        fdmax = pComponentPrivate->filled_outBuf_Q[VIDDEC_PIPE_READ];
154    }
155
156    while (1) {
157        FD_ZERO (&rfds);
158        FD_SET(pComponentPrivate->cmdPipe[VIDDEC_PIPE_READ], &rfds);
159        FD_SET(pComponentPrivate->filled_outBuf_Q[VIDDEC_PIPE_READ], &rfds);
160        FD_SET(pComponentPrivate->free_inpBuf_Q[VIDDEC_PIPE_READ], &rfds);
161        FD_SET(pComponentPrivate->free_outBuf_Q[VIDDEC_PIPE_READ], &rfds);
162        FD_SET(pComponentPrivate->filled_inpBuf_Q[VIDDEC_PIPE_READ], &rfds);
163
164#ifdef UNDER_CE
165        tv.tv_sec = 0;
166        tv.tv_usec = VIDD_TIMEOUT * 30;
167#else
168        tv.tv_sec = 0;
169        tv.tv_nsec = 30000;
170#endif
171
172
173#ifdef UNDER_CE
174        status = select (fdmax+1, &rfds, NULL, NULL, NULL);
175#else
176        sigemptyset (&set);
177        sigaddset (&set, SIGALRM);
178        status = pselect (fdmax+1, &rfds, NULL, NULL, NULL, &set);
179        sigdelset (&set, SIGALRM);
180#endif
181
182        if (0 == status) {
183            ;
184        }
185        else if (-1 == status) {
186            OMX_TRACE4(pComponentPrivate->dbg, "Error in Select\n");
187            pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
188                                                   pComponentPrivate->pHandle->pApplicationPrivate,
189                                                   OMX_EventError,
190                                                   OMX_ErrorInsufficientResources,
191                                                   OMX_TI_ErrorSevere,
192                                                   "Error from Component Thread in select");
193	     eError = OMX_ErrorInsufficientResources;
194            break;
195        }
196        else {
197            if (FD_ISSET(pComponentPrivate->cmdPipe[VIDDEC_PIPE_READ], &rfds)) {
198#ifndef UNDER_CE
199            if(!bFlag) {
200
201                bFlag = OMX_TRUE;
202#endif
203                read(pComponentPrivate->cmdPipe[VIDDEC_PIPE_READ], &eCmd, sizeof(eCmd));
204                read(pComponentPrivate->cmdDataPipe[VIDDEC_PIPE_READ], &nParam1, sizeof(nParam1));
205
206#ifdef __PERF_INSTRUMENTATION__
207                PERF_ReceivedCommand(pComponentPrivate->pPERFcomp,
208                                     eCmd, nParam1, PERF_ModuleLLMM);
209#endif
210                if (eCmd == OMX_CommandStateSet) {
211                    if ((OMX_S32)nParam1 < -2) {
212                        OMX_ERROR2(pComponentPrivate->dbg, "Incorrect variable value used\n");
213                    }
214                    if ((OMX_S32)nParam1 != -1 && (OMX_S32)nParam1 != -2) {
215                        eError = VIDDEC_HandleCommand(pComponentPrivate, nParam1);
216                        if (eError != OMX_ErrorNone) {
217                            /*pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
218                                                                   pComponentPrivate->pHandle->pApplicationPrivate,
219                                                                   OMX_EventError,
220                                                                   eError,
221                                                                   0,
222                                                                   "Error in HadleCommand function");*/
223                        }
224                    }
225                    else if ((OMX_S32)nParam1 == -1) {
226                        break;
227                    }
228                    else if ((OMX_S32)nParam1 == -2) {
229                        OMX_VidDec_Return(pComponentPrivate);
230                        VIDDEC_Handle_InvalidState( pComponentPrivate);
231                        break;
232                    }
233                }
234                else if (eCmd == OMX_CommandPortDisable) {
235                    eError = VIDDEC_DisablePort(pComponentPrivate, nParam1);
236                    if (eError != OMX_ErrorNone) {
237                        pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
238                                                               pComponentPrivate->pHandle->pApplicationPrivate,
239                                                               OMX_EventError,
240                                                               eError,
241                                                               OMX_TI_ErrorSevere,
242                                                               "Error in DisablePort function");
243                    }
244                }
245                else if (eCmd == OMX_CommandPortEnable) {
246                    eError = VIDDEC_EnablePort(pComponentPrivate, nParam1);
247                    if (eError != OMX_ErrorNone) {
248                        pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
249                                                               pComponentPrivate->pHandle->pApplicationPrivate,
250                                                               OMX_EventError,
251                                                               eError,
252                                                               OMX_TI_ErrorSevere,
253                                                               "Error in EnablePort function");
254                    }
255                } else if (eCmd == OMX_CommandFlush) {
256                    VIDDEC_HandleCommandFlush (pComponentPrivate, nParam1, OMX_TRUE);
257                }
258                else if (eCmd == OMX_CommandMarkBuffer)    {
259                    read(pComponentPrivate->cmdDataPipe[VIDDEC_PIPE_READ], &pCmdData, sizeof(pCmdData));
260                    pComponentPrivate->arrCmdMarkBufIndex[pComponentPrivate->nInCmdMarkBufIndex].hMarkTargetComponent = ((OMX_MARKTYPE*)(pCmdData))->hMarkTargetComponent;
261                    pComponentPrivate->arrCmdMarkBufIndex[pComponentPrivate->nInCmdMarkBufIndex].pMarkData = ((OMX_MARKTYPE*)(pCmdData))->pMarkData;
262                    pComponentPrivate->nInCmdMarkBufIndex++;
263                    pComponentPrivate->nInCmdMarkBufIndex %= VIDDEC_MAX_QUEUE_SIZE;
264
265                }
266#ifndef UNDER_CE
267    bFlag = OMX_FALSE;
268#endif
269
270#ifndef UNDER_CE
271            }
272#endif
273        }
274            if(pComponentPrivate->bPipeCleaned){
275                pComponentPrivate->bPipeCleaned =0;
276            }
277            else{
278                if (FD_ISSET(pComponentPrivate->filled_outBuf_Q[VIDDEC_PIPE_READ], &rfds)) {
279                    if(pComponentPrivate->bDynamicConfigurationInProgress){
280                        VIDDEC_WAIT_CODE();
281                        continue;
282                    }
283                    eError = VIDDEC_HandleDataBuf_FromDsp(pComponentPrivate);
284                    if (eError != OMX_ErrorNone) {
285                        OMX_PRBUFFER4(pComponentPrivate->dbg, "Error while handling filled DSP output buffer\n");
286                        pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
287                                                               pComponentPrivate->pHandle->pApplicationPrivate,
288                                                               OMX_EventError,
289                                                               eError,
290                                                               OMX_TI_ErrorSevere,
291                                                               "Error from Component Thread while processing dsp Responses");
292                    }
293                }
294                if ((FD_ISSET(pComponentPrivate->filled_inpBuf_Q[VIDDEC_PIPE_READ], &rfds))){
295                    OMX_PRSTATE2(pComponentPrivate->dbg, "eExecuteToIdle 0x%x\n",pComponentPrivate->eExecuteToIdle);
296                    /* When doing a reconfiguration, don't send input buffers to SN & wait for SN to be ready*/
297                    if(pComponentPrivate->bDynamicConfigurationInProgress == OMX_TRUE ||
298                            pComponentPrivate->eLCMLState != VidDec_LCML_State_Start){
299                        VIDDEC_WAIT_CODE();
300                         continue;
301                    }
302                    else{
303                   eError = VIDDEC_HandleDataBuf_FromApp (pComponentPrivate);
304                    if (eError != OMX_ErrorNone) {
305                        OMX_PRBUFFER4(pComponentPrivate->dbg, "Error while handling filled input buffer\n");
306                        pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
307                                                               pComponentPrivate->pHandle->pApplicationPrivate,
308                                                               OMX_EventError,
309                                                               eError,
310                                                               OMX_TI_ErrorSevere,
311                                                               "Error from Component Thread while processing input buffer");
312                    }
313                }
314                }
315                if (FD_ISSET(pComponentPrivate->free_inpBuf_Q[VIDDEC_PIPE_READ], &rfds)) {
316                    if(pComponentPrivate->bDynamicConfigurationInProgress){
317                        VIDDEC_WAIT_CODE();
318                        continue;
319                    }
320                    eError = VIDDEC_HandleFreeDataBuf(pComponentPrivate);
321                    if (eError != OMX_ErrorNone) {
322                        OMX_PRBUFFER4(pComponentPrivate->dbg, "Error while processing free input buffers\n");
323                        pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
324                                                               pComponentPrivate->pHandle->pApplicationPrivate,
325                                                               OMX_EventError,
326                                                               eError,
327                                                               OMX_TI_ErrorSevere,
328                                                               "Error from Component Thread while processing free input buffer");
329                    }
330                }
331                if (FD_ISSET(pComponentPrivate->free_outBuf_Q[VIDDEC_PIPE_READ], &rfds)) {
332                     if(pComponentPrivate->bDynamicConfigurationInProgress){
333                        VIDDEC_WAIT_CODE();
334                          continue;
335                     }
336                    OMX_PRSTATE2(pComponentPrivate->dbg, "eExecuteToIdle 0x%x\n",pComponentPrivate->eExecuteToIdle);
337                    eError = VIDDEC_HandleFreeOutputBufferFromApp(pComponentPrivate);
338                    if (eError != OMX_ErrorNone) {
339                        OMX_PRBUFFER4(pComponentPrivate->dbg, "Error while processing free output buffer\n");
340                        pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
341                                                               pComponentPrivate->pHandle->pApplicationPrivate,
342                                                               OMX_EventError,
343                                                               eError,
344                                                               OMX_TI_ErrorSevere,
345                                                               "Error from Component Thread while processing free output buffer");
346                    }
347                }
348            }
349        }
350    }
351
352#ifdef __PERF_INSTRUMENTATION__
353    PERF_Done(pComponentPrivate->pPERFcomp);
354#endif
355
356    return (void *)eError;
357}
358
359void* OMX_VidDec_Return (void* pThreadData)
360{
361    int status = 0;
362    struct timeval tv1;
363#ifdef UNDER_CE
364    struct timeval tv;
365#else
366    sigset_t set;
367    struct timespec tv;
368#endif
369    int fdmax = 0;
370    OMX_U32 iLock = 0;
371    fd_set rfds;
372    OMX_ERRORTYPE eError = OMX_ErrorNone;
373    VIDDEC_COMPONENT_PRIVATE* pComponentPrivate = NULL;
374
375    pComponentPrivate = (VIDDEC_COMPONENT_PRIVATE*)pThreadData;
376    gettimeofday(&tv1, NULL);
377    /**Looking for highest number of file descriptor for pipes in order to put in select loop */
378    fdmax = pComponentPrivate->free_inpBuf_Q[VIDDEC_PIPE_READ];
379
380    if (pComponentPrivate->free_outBuf_Q[VIDDEC_PIPE_READ] > fdmax) {
381        fdmax = pComponentPrivate->free_outBuf_Q[VIDDEC_PIPE_READ];
382    }
383
384    if (pComponentPrivate->filled_inpBuf_Q[VIDDEC_PIPE_READ] > fdmax) {
385        fdmax = pComponentPrivate->filled_inpBuf_Q[VIDDEC_PIPE_READ];
386    }
387
388    if (pComponentPrivate->filled_outBuf_Q[VIDDEC_PIPE_READ] > fdmax) {
389        fdmax = pComponentPrivate->filled_outBuf_Q[VIDDEC_PIPE_READ];
390    }
391    while ((pComponentPrivate->nCountInputBFromApp != 0 &&
392                (pComponentPrivate->eLCMLState == VidDec_LCML_State_Start && pComponentPrivate->bDynamicConfigurationInProgress == OMX_FALSE)) ||
393            pComponentPrivate->nCountOutputBFromApp != 0 ||
394            pComponentPrivate->nCountInputBFromDsp != 0 || pComponentPrivate->nCountOutputBFromDsp != 0) {
395        FD_ZERO (&rfds);
396        FD_SET(pComponentPrivate->filled_outBuf_Q[VIDDEC_PIPE_READ], &rfds);
397        FD_SET(pComponentPrivate->free_inpBuf_Q[VIDDEC_PIPE_READ], &rfds);
398        FD_SET(pComponentPrivate->free_outBuf_Q[VIDDEC_PIPE_READ], &rfds);
399        FD_SET(pComponentPrivate->filled_inpBuf_Q[VIDDEC_PIPE_READ], &rfds);
400
401#ifdef UNDER_CE
402        tv.tv_sec = 0;
403        tv.tv_usec = VIDD_TIMEOUT * 30;
404#else
405    tv.tv_sec = 0;
406    tv.tv_nsec = 10000;
407#endif
408
409
410#ifdef UNDER_CE
411        status = select (fdmax+1, &rfds, NULL, NULL, &tv);
412#else
413        sigemptyset (&set);
414        sigaddset (&set, SIGALRM);
415        status = pselect (fdmax+1, &rfds, NULL, NULL, &tv, &set);
416        sigdelset (&set, SIGALRM);
417#endif
418        if (0 == status) {
419            iLock++;
420            if (iLock > 2){
421                pComponentPrivate->bPipeCleaned = 1;
422                break;
423            }
424        }
425        else if (-1 == status) {
426            OMX_PRINT2(pComponentPrivate->dbg, "Error in Select\n");
427            pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
428                                                   pComponentPrivate->pHandle->pApplicationPrivate,
429                                                   OMX_EventError,
430                                                   OMX_ErrorInsufficientResources,
431                                                   OMX_TI_ErrorSevere,
432                                                   "Error from Component Thread in select");
433	     eError = OMX_ErrorInsufficientResources;
434	     break;
435        }
436        else {
437            if (FD_ISSET(pComponentPrivate->filled_outBuf_Q[VIDDEC_PIPE_READ], &rfds)) {
438                eError = VIDDEC_HandleDataBuf_FromDsp(pComponentPrivate);
439                if (eError != OMX_ErrorNone) {
440                    OMX_PRBUFFER4(pComponentPrivate->dbg, "Error while handling filled DSP output buffer\n");
441                    pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
442                                                           pComponentPrivate->pHandle->pApplicationPrivate,
443                                                           OMX_EventError,
444                                                           eError,
445                                                           OMX_TI_ErrorSevere,
446                                                           "Error from Component Thread while processing dsp Responses");
447                }
448            }
449            if ((FD_ISSET(pComponentPrivate->filled_inpBuf_Q[VIDDEC_PIPE_READ], &rfds))){
450                OMX_PRSTATE2(pComponentPrivate->dbg, "eExecuteToIdle 0x%x\n",pComponentPrivate->eExecuteToIdle);
451                if(!(pComponentPrivate->bDynamicConfigurationInProgress == OMX_TRUE && pComponentPrivate->bInPortSettingsChanged == OMX_FALSE)){
452                eError = VIDDEC_HandleDataBuf_FromApp (pComponentPrivate);
453                if (eError != OMX_ErrorNone) {
454                    OMX_PRBUFFER4(pComponentPrivate->dbg, "Error while handling filled input buffer\n");
455                    pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
456                                                           pComponentPrivate->pHandle->pApplicationPrivate,
457                                                           OMX_EventError,
458                                                           eError,
459                                                           OMX_TI_ErrorSevere,
460                                                           "Error from Component Thread while processing input buffer");
461                }
462                }
463            }
464            if (FD_ISSET(pComponentPrivate->free_inpBuf_Q[VIDDEC_PIPE_READ], &rfds)) {
465                eError = VIDDEC_HandleFreeDataBuf(pComponentPrivate);
466                if (eError != OMX_ErrorNone) {
467                    OMX_PRBUFFER4(pComponentPrivate->dbg, "Error while processing free input buffers\n");
468                    pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
469                                                           pComponentPrivate->pHandle->pApplicationPrivate,
470                                                           OMX_EventError,
471                                                           eError,
472                                                           OMX_TI_ErrorSevere,
473                                                           "Error from Component Thread while processing free input buffer");
474                }
475            }
476            if (FD_ISSET(pComponentPrivate->free_outBuf_Q[VIDDEC_PIPE_READ], &rfds)) {
477                OMX_PRSTATE2(pComponentPrivate->dbg, "eExecuteToIdle 0x%x\n",pComponentPrivate->eExecuteToIdle);
478                eError = VIDDEC_HandleFreeOutputBufferFromApp(pComponentPrivate);
479                if (eError != OMX_ErrorNone) {
480                    OMX_PRBUFFER4(pComponentPrivate->dbg, "Error while processing free output buffer\n");
481                    pComponentPrivate->cbInfo.EventHandler(pComponentPrivate->pHandle,
482                                                           pComponentPrivate->pHandle->pApplicationPrivate,
483                                                           OMX_EventError,
484                                                           eError,
485                                                           OMX_TI_ErrorSevere,
486                                                           "Error from Component Thread while processing free output buffer");
487                }
488            }
489        }
490    }
491
492    pComponentPrivate->bPipeCleaned = OMX_TRUE;
493    return (void *)eError;
494}
495
496