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