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