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 
82 extern OMX_ERRORTYPE VIDDEC_HandleCommand (OMX_HANDLETYPE pHandle, OMX_U32 nParam1);
83 extern OMX_ERRORTYPE VIDDEC_DisablePort(VIDDEC_COMPONENT_PRIVATE *pComponentPrivate, OMX_U32 nParam1);
84 extern OMX_ERRORTYPE VIDDEC_EnablePort(VIDDEC_COMPONENT_PRIVATE *pComponentPrivate, OMX_U32 nParam1);
85 extern OMX_ERRORTYPE VIDDEC_HandleDataBuf_FromApp( VIDDEC_COMPONENT_PRIVATE *pComponentPrivate);
86 extern OMX_ERRORTYPE VIDDEC_HandleDataBuf_FromDsp( VIDDEC_COMPONENT_PRIVATE *pComponentPrivate );
87 extern OMX_ERRORTYPE VIDDEC_HandleFreeDataBuf( VIDDEC_COMPONENT_PRIVATE *pComponentPrivate );
88 extern OMX_ERRORTYPE VIDDEC_HandleFreeOutputBufferFromApp(VIDDEC_COMPONENT_PRIVATE *pComponentPrivate) ;
89 extern OMX_ERRORTYPE VIDDEC_Start_ComponentThread(OMX_HANDLETYPE pHandle);
90 extern OMX_ERRORTYPE VIDDEC_Stop_ComponentThread(OMX_HANDLETYPE pComponent);
91 extern OMX_ERRORTYPE VIDDEC_HandleCommandMarkBuffer(VIDDEC_COMPONENT_PRIVATE *pComponentPrivate, OMX_U32 nParam1, OMX_PTR pCmdData);
92 extern OMX_ERRORTYPE VIDDEC_HandleCommandFlush(VIDDEC_COMPONENT_PRIVATE *pComponentPrivate, OMX_U32 nParam1, OMX_BOOL bPass);
93 extern 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 
OMX_VidDec_Thread(void * pThreadData)105 void* 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 
OMX_VidDec_Return(void * pThreadData)359 void* 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