/**************************************************************************** * Copyright (c) 2004 DST Technologies Inc. All Rights Reserved. * * file name: ddPsiSectGather.c * Author: jina * Description: PSI Section Gathering. * * * update info************************************************************** * 2004.08.09. malloc/free debugging À§ÇØ macro·Î ¹Ù·Î »ç¿ë ÇÏ´ø °ÍÀ» * ÇÔ¼ö·Î º¯È¯ ¶Ç´Â º¯¼ö¿¡ ´ëÀÔÇØ¼­ »ç¿ë.*/ /****************************************************************************/ #include "dsthalcommon.h" #include #include #include #ifdef DMALLOC #include #endif #include "dsthalPsiSectGather.h" /****************************************************************************** * Global variable declaration ******************************************************************************/ DS_U32 gdhlPsiDbgLvl = 2; /****************************************************************************** * Imported variable declaration ******************************************************************************/ extern int g_Demux_Debug; /****************************************************************************** * Imported function declaration ******************************************************************************/ /****************************************************************************** * Local definitions ******************************************************************************/ /****************************************************************************** * Local typedefs ******************************************************************************/ /****************************************************************************** * Local variables declaration ******************************************************************************/ /****************************************************************************** * Local function prototypes ******************************************************************************/ extern DHL_RESULT DD_PSI_ResetSectMask ( void *pParent , PSIMask_t *prefList ); #define PSICTX_CNT 12 typedef struct PSICtxManager_t { DS_U32 freeCount; DS_U32 filterManagerLock; PSIContext_t *psiCtxPtrList[PSICTX_CNT]; OS_SEMAPHORE_ID lockSema; } PSICtxManager_t; PSICtxManager_t *gpPsiCtxManager = NULL; #ifndef DMALLOC void * PSI_Malloc( int iSize ) { if( iSize < 0 ) return NULL; if(iSize > 4096*100 ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_Malloc() : warning. it maybe error. iSize = %d. \r\n", iSize ); //return NULL; } return (OS_malloc((size_t)iSize)); } void PSI_Free( void *memBlock ) { if(!memBlock) return; OS_free(memBlock); } #else #define PSI_Free free #define PSI_Malloc malloc #endif void DD_PSI_PrintRegisteredPsiCtx() { #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "\n\n"); #endif if(gpPsiCtxManager && gpPsiCtxManager->lockSema) { int i; // DD_PSI_LockPsiCtxMng(); for( i = 0 ; i < PSICTX_CNT ; i++ ) { if ( gpPsiCtxManager->psiCtxPtrList[i]) { #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "R_PSICtx : index[%d] : pid = %d.\r\n", i , gpPsiCtxManager->psiCtxPtrList[i]->pid ); #endif } } // DD_PSI_UnlockPsiCtxMng(); } else DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_PrintRegisteredPsiCtx : no registered ctx.\r\n"); } void DD_PSI_LockPsiCtxMng() { if(gpPsiCtxManager && gpPsiCtxManager->lockSema) { //AtiCore_SemLock( gpPsiCtxManager->lockSema , OS_WAIT_FOREVER /*infinite*/); OS_TakeSemaphore( gpPsiCtxManager->lockSema ); } else DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_LockPsiCtxMng : lock error.\r\n"); } void DD_PSI_UnlockPsiCtxMng() { if( gpPsiCtxManager && gpPsiCtxManager->lockSema ) { //AtiCore_SemUnlock( gpPsiCtxManager->lockSema ); OS_GiveSemaphore( gpPsiCtxManager->lockSema ); } else DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_UnlockPsiCtxMng : unlock error.\r\n"); } /*PSIContext_t pointer¸¦ °ü¸®ÇÏ´Â global manager¿¡ µî·Ïµµ ÇÑ´Ù.*/ PSIContext_t * DD_PSI_AllocPSIContextWRegister() { int i; PSIContext_t *pRetPsiCtx = NULL; #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the DD_PSI_AllocPSIContextWRegister.\r\n"); #endif if(!gpPsiCtxManager) { gpPsiCtxManager = (PSICtxManager_t *)PSI_Malloc( sizeof(PSICtxManager_t) ); memset( gpPsiCtxManager , 0 , sizeof(PSICtxManager_t)); gpPsiCtxManager->lockSema = OS_CreateCountingSemaphore( "PSICtxSema4", 0/*Option*/,1/*count*/); #ifdef PSI_CTX_MNG_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_AllocPSIContextWRegister : Create PsiCtxManager\r\n"); #endif } if(!gpPsiCtxManager || !(gpPsiCtxManager->lockSema)) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_AllocPSIContextWRegister : alloc psiMng fail.\r\n"); return NULL; } DD_PSI_LockPsiCtxMng(); for( i = 0 ; i < PSICTX_CNT ; i++ ) { /*to find a empty slot.*/ if ( gpPsiCtxManager->psiCtxPtrList[i] == NULL ) { gpPsiCtxManager->psiCtxPtrList[i] = DD_PSI_AllocPSIContext(); if( gpPsiCtxManager->psiCtxPtrList[i] == NULL ) { pRetPsiCtx = NULL; DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_AllocPSIContextWRegister : MEM ERROR\r\n"); } else { pRetPsiCtx = gpPsiCtxManager->psiCtxPtrList[i]; pRetPsiCtx->bRegistered = _TRUE_; pRetPsiCtx->selfIndex = i; } goto GOOUT; } } GOOUT: DD_PSI_UnlockPsiCtxMng(); return pRetPsiCtx; } void DD_PSI_FreePSIContextWUnregister( PSIContext_t *pPsiContext ) { int i; if(!gpPsiCtxManager || !pPsiContext) return; DD_PSI_LockPsiCtxMng(); i = pPsiContext->selfIndex; if( i >= PSICTX_CNT ) return; // for( i = 0 ; i < PSICTX_CNT ; i++ ) { /*to find a same pointer*/ if ( gpPsiCtxManager->psiCtxPtrList[i] == pPsiContext ) { DD_PSI_FreePSIContext(pPsiContext); gpPsiCtxManager->psiCtxPtrList[i] = NULL; // break; }/*if*/ }/*for( i = 0 */ #ifdef PSI_CTX_MNG_DBG DD_PSI_PrintRegisteredPsiCtx(); #endif DD_PSI_UnlockPsiCtxMng(); } PSIContext_t *DD_PSI_AllocPSIContext() { PSIContext_t *pPsiContext = NULL; #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the DD_PSI_AllocPSIContext.\r\n"); #endif pPsiContext = (PSIContext_t *)PSI_Malloc( sizeof(PSIContext_t) ); if(pPsiContext == NULL) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_AllocPSIContext : Error: PSI_Malloc fails\r\n"); } else memset( pPsiContext , 0 , sizeof(PSIContext_t) ); return pPsiContext; } void DD_PSI_FreePSIContext( PSIContext_t *pPsiContext ) { PSIDataArray_t *pDataArrayToDelete = NULL; #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_FreePSIContext : pid = 0x%x \r\n", pPsiContext->pid); #endif if(!pPsiContext) return; if( pPsiContext->psiMask ) PSI_Free( pPsiContext->psiMask ); if( pPsiContext->curDataArray ) pDataArrayToDelete = pPsiContext->curDataArray; else pDataArrayToDelete = pPsiContext->nextDataArray; if(pDataArrayToDelete) { DD_PSI_FreePSIArray(pDataArrayToDelete); DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_FreePSIContext : call PSI_FreeData ; 0x%lx\r\n", (DS_U32)pDataArrayToDelete); } PSI_Free( (void *)pPsiContext ); } /* * PSI_GetEmptyPSIMask is used to allocate and initialize a PSIMask. */ DHL_RESULT DD_PSI_GetEmptyPSIMask( DS_S32 numEntries, PSIMask_t **ppMask ) { int iMaskSize = PSIMaskSize(numEntries); PSIMask_t *ptMask = NULL; *ppMask = NULL; if( numEntries == 0 || ppMask == NULL) return DHL_FAIL_INVALID_PARAM; #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the PSI_GetEmptyMask.\r\n"); #endif ptMask = (PSIMask_t *)PSI_Malloc(iMaskSize); if( ptMask == NULL) return DHL_FAIL_OUT_OF_RESOURCE; memset( ptMask , 0 , iMaskSize ); ptMask->numEntries = numEntries; *ppMask = ptMask; return(DHL_OK); } /* * PSI_GetTIDPSIMask creates a psiMask which accepts anything with a particular Table ID * current_next_indicator should be _TRUE_ to get current data or _FALSE_ for the next * applicable data */ DHL_RESULT DD_PSI_GetTIDPSIMask(PSIMask_t **ppMask, DS_U8 TID, DS_BOOL current_next_indicator) { DHL_RESULT err; PSIMask_t *pMask = NULL; #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the PSI_GetTIDPSIMask.\r\n"); #endif *ppMask = NULL; if( TID == 0xFF ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_GetTIDPSIMask : BAD TID\r\n"); return DHL_FAIL_INVALID_PARAM; } err = DD_PSI_GetEmptyPSIMask(6,&pMask); if( err != DHL_OK ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_GetTIDPSIMask : PSI_GetEmptyPSIMask return error(0x%x)\r\n" , err ); return(err); } pMask->entries[0].value = TID; pMask->entries[0].matchMask = 0xFF; pMask->entries[5].value = current_next_indicator; pMask->entries[5].matchMask = 1; *ppMask = pMask; return(DHL_OK); } /* * PSI_GetTIDPSIMask creates a psiMask which accepts anything with a particular Table ID * current_next_indicator should be _TRUE_ to get current data or _FALSE_ for the next * applicable data */ DHL_RESULT DD_PSI_GetTIDPSISimpleMask(PSIMask_t **ppMask, DS_U8 TID ) { DHL_RESULT err; PSIMask_t *pMask = NULL; #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the DD_PSI_GetTIDPSISimpleMask.\r\n"); #endif *ppMask = NULL; if( TID == 0xFF ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_GetTIDPSISimpleMask : BAD TID\r\n"); return DHL_FAIL_INVALID_PARAM; } err = DD_PSI_GetEmptyPSIMask(1,&pMask); if( err != DHL_OK ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_GetTIDPSISimpleMask : PSI_GetEmptyPSIMask return error(0x%x)\r\n" , err ); return(err); } pMask->entries[0].value = TID; pMask->entries[0].matchMask = 0xFF; *ppMask = pMask; return(DHL_OK); } /* * PSI_GetExTIDPSIMask creates a psiMask which accepts anything with a particular Table ID * as well as a particular table_id_externsion. The table_id_extension is a 16 bit field * at byte offset 3 and 4 from the start of a section header. It is used for a variety of * purposes depending on the type of table. * current_next_indicator should be _TRUE_ to get current data or _FALSE_ for the next * applicable data */ DHL_RESULT DD_PSI_GetExTIDPSIMask( PSIMask_t **ppMask, DS_U8 TID, DS_U16 TIDExtension, DS_BOOL current_next_indicator) { DHL_RESULT err; PSIMask_t *pMask = NULL; #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the PSI_GetExTIDPSIMask.\n"); #endif *ppMask = NULL; if( TID == 0xFF ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_GetExTIDPSIMask : BAD TID\n"); return DHL_FAIL_INVALID_PARAM; } err = DD_PSI_GetEmptyPSIMask(6,&pMask); if( err != DHL_OK ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_GetExTIDPSIMask : PSI_GetEmptyPSIMask return error(0x%x)\n" , err ); return(err); } pMask->numEntries = 6; pMask->entries[0].value = TID; pMask->entries[0].matchMask = 0xFF; if (TIDExtension == 0xFFFF) { pMask->entries[3].value = 0; pMask->entries[3].matchMask = 0; pMask->entries[4].value = 0; pMask->entries[4].matchMask = 0; } else { pMask->entries[3].value = TIDExtension >> 8; pMask->entries[3].matchMask = 0xFF; pMask->entries[4].value = TIDExtension & 0xFF; pMask->entries[4].matchMask = 0xFF; } pMask->entries[5].value = current_next_indicator; pMask->entries[5].matchMask = 1; *ppMask = pMask; return(DHL_OK); } DHL_RESULT DD_PSI_GetDvbEitMask( PSIMask_t **ppMask, DS_U8 TID, DS_U16 TIDExtension, DS_U8 segment_number, DS_BOOL current_next_indicator) { DHL_RESULT err; PSIMask_t *pMask = NULL; #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the PSI_GetExTIDPSIMask.\n"); #endif *ppMask = NULL; if( TID == 0xFF ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_GetExTIDPSIMask : BAD TID\n"); return DHL_FAIL_INVALID_PARAM; } err = DD_PSI_GetEmptyPSIMask(6,&pMask); if( err != DHL_OK ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_GetExTIDPSIMask : PSI_GetEmptyPSIMask return error(0x%x)\n" , err ); return(err); } pMask->numEntries = 7; pMask->entries[0].value = TID; pMask->entries[0].matchMask = 0xFF; pMask->entries[3].value = TIDExtension >> 8; pMask->entries[3].matchMask = 0xFF; pMask->entries[4].value = TIDExtension & 0xFF; pMask->entries[4].matchMask = 0xFF; pMask->entries[5].value = current_next_indicator; pMask->entries[5].matchMask = 1; pMask->entries[6].value = segment_number<<3; pMask->entries[6].matchMask = 0xF8; *ppMask = pMask; return(DHL_OK); } /* * GetExTIDFieldPSIFilter creates a psiFilter which accepts anything with a particular Table ID * as well as a either or both bytes of a particular table_id_externsion. * The table_id_extension is either a 16 bit field at byte offset 3 and 4 (whicField== * BOTH_FIELDS) or an 8 bit field at offet 3 (whicField = TOP_FIELD) or * 4 (whicField == BOTTOM_FIELD) from the start of a section header. * Sepecifying BOTH_FIELDS in whicField is equivalent to calling GetExTIDPSIFilter. * It is used for a variety of purposes depending on the type of table. * current_next_indicator should be _TRUE_ to get current data or _FALSE_ for the next * applicable data */ DHL_RESULT DD_PSI_GetExTIDFieldPSIMask( PSIMask_t **ppMask, DS_U8 TID, DS_U16 TIDExtension, PSIFieldSelect_k whichField, DS_BOOL current_next_indicator) { DHL_RESULT err; PSIMask_t *pMask = NULL; *ppMask = NULL; if(TID == 0xFF) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_GetExTIDFieldPSIMask: Bad TID"); if ((err = DD_PSI_GetEmptyPSIMask(6,&pMask))) { return(err); } pMask->numEntries = 6; pMask->entries[0].value = TID; pMask->entries[0].matchMask = 0xFF; switch(whichField) { case TOP_FIELD: pMask->entries[3].value = TIDExtension & 0xFF; pMask->entries[3].matchMask = 0xFF; break; case BOTTOM_FIELD: pMask->entries[4].value = TIDExtension & 0xFF; pMask->entries[4].matchMask = 0xFF; break; case BOTH_FIELDS: pMask->entries[3].value = TIDExtension >> 8; pMask->entries[3].matchMask = 0xFF; pMask->entries[4].value = TIDExtension & 0xFF; pMask->entries[4].matchMask = 0xFF; break; default: DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_GetExTIDFieldPSIMask: bad field"); } // pMask->entries[5].value = current_next_indicator; // pMask->entries[5].matchMask = 1; *ppMask = pMask; return(DHL_OK); } /*filter °Ë»ö Á¶°Ç : table ID , ƯÁ¤ 4bits°¡ ÁÖ¾îÁø °ª°ú °°ÀºÁö È®ÀÎ ÇÑ´Ù.*/ DHL_RESULT DD_PSI_GetTIDPrivateSubtypePSIMask( PSIMask_t **ppMask, DS_U8 TID, DS_U8 byteToSee, DS_U8 byteValue, PSIFieldSelect_k whichField) { DHL_RESULT err; PSIMask_t *pMask = NULL; int filterSize = 0; *ppMask = NULL; if( TID == 0xFF ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_GetTIDPrivateSubtypeFilter: Bad TID\n"); return DHL_FAIL_INVALID_PARAM; } if( byteToSee < 1 ) filterSize = 1; else filterSize = byteToSee; /*limit the maximum size...*/ if ((err = DD_PSI_GetEmptyPSIMask(filterSize,&pMask))) { return(err); } pMask->numEntries = filterSize; pMask->entries[0].value = TID; pMask->entries[0].matchMask = 0xFF; if( filterSize == 1 ) return(DHL_OK); switch(whichField) { case TOP_FIELD: pMask->entries[filterSize-1].value = (byteValue<<4) & 0xF0; pMask->entries[filterSize-1].matchMask = 0xF0; break; case BOTTOM_FIELD: pMask->entries[filterSize-1].value = byteValue & 0x0F; pMask->entries[filterSize-1].matchMask = 0x0F; break; case BOTH_FIELDS: pMask->entries[filterSize-1].value = byteValue & 0xff; pMask->entries[filterSize-1].matchMask = 0xFF; break; } #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_GetTIDPrivateSubtypePSIMask : pMask->value %d , pMask->matchMask %d \n" , pMask->entries[filterSize-1].value , pMask->entries[filterSize-1].matchMask ); #endif *ppMask = pMask; return DHL_OK; } /* * GetETTPSIFilter creates a psiFilter which is specifically designed to filter * an ATSC PSIP Extended Text Table (ETT) with a specific Extended Text Message ID. * current_next_indicator should be _TRUE_ to get current data or _FALSE_ for the next * applicable data */ DHL_RESULT DD_PSI_GetETTPSIMask( PSIMask_t **ppMask, DS_U8 TID, DS_U32 ETM_id, DS_BOOL current_next_indicator) { DHL_RESULT err; PSIMask_t *pMask = NULL; *ppMask = NULL; if ((err = DD_PSI_GetEmptyPSIMask(13,&pMask))) { return(err); } pMask->numEntries = 13; pMask->entries[0].value = TID; pMask->entries[0].matchMask = 0xFF; pMask->entries[5].value = current_next_indicator; pMask->entries[5].matchMask = 1; pMask->entries[9].value = ETM_id >> 24; pMask->entries[9].matchMask = 0xFF; pMask->entries[10].value = (ETM_id >> 16) & 0xFF; pMask->entries[10].matchMask = 0xFF; pMask->entries[11].value = (ETM_id >> 8) & 0xFF; pMask->entries[11].matchMask = 0xFF; pMask->entries[12].value = ETM_id & 0xFF; pMask->entries[12].matchMask = 0xFF; *ppMask = pMask; return(DHL_OK); } /* * GetETTPSIFilter creates a psiFilter which is specifically designed to filter * an ATSC PSIP Extended Text Table (ETT) with a specific Extended Text Message ID. * current_next_indicator should be _TRUE_ to get current data or _FALSE_ for the next * applicable data */ DHL_RESULT DD_PSI_GetDsmccPSIMask( PSIMask_t **ppMask, DS_U8 TID, DS_U32 DsmccMessageId, DS_BOOL current_next_indicator) { DHL_RESULT err; PSIMask_t *pMask = NULL; *ppMask = NULL; if ((err = DD_PSI_GetEmptyPSIMask(12,&pMask))) { return(err); } pMask->numEntries = 12; pMask->entries[0].value = TID; pMask->entries[0].matchMask = 0xFF; pMask->entries[5].value = current_next_indicator; pMask->entries[5].matchMask = 1; pMask->entries[8].value = DsmccMessageId >> 24; pMask->entries[8].matchMask = 0xFF; pMask->entries[9].value = (DsmccMessageId >> 16) & 0xFF; pMask->entries[9].matchMask = 0xFF; pMask->entries[10].value = (DsmccMessageId >> 8) & 0xFF; pMask->entries[10].matchMask = 0xFF; pMask->entries[11].value = DsmccMessageId & 0xFF; pMask->entries[11].matchMask = 0xFF; *ppMask = pMask; return(DHL_OK); } /* * Call ReadPSIData in response to a PSIDataReceived event. The caller then owns * the data and it is up to the caller to delete the data when it is finished * processing the data. */ DHL_RESULT DD_PSI_ReadPSIArray( PSIContext_t *psi , PSIDataArray_t **returnArray) { int i; DS_BOOL eager = _FALSE_; PSIDataArray_t *desc; if(!psi) return DHL_FAIL_NULL_POINTER; *returnArray = NULL; #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the DD_PSI_ReadPSIArray.\r\n"); #endif eager = (psi->psiMode == eagerTableMode || psi->psiMode == segmentEagerMode);//(((int)master->psiMode) & PSIMODE_EAGER_FLAG)!= 0; // eager = (((int)psi->psiMode) & PSIMODE_EAGER_FLAG)!= 0; if (psi->curDataArray) { *returnArray = desc = psi->curDataArray; if (eager) { /* * If this is an eager client, then there may be some * detached placeholders. Make these NULL to not confuse * the issue. The -1 placeholders are there to make sure * that we don't get the same section twice even after * it has been detached. */ for (i = 0; i < desc->maxSections; ++i) { if (desc->sectPtr[i] == (DS_U8 *)-1) { desc->sectPtr[i] = NULL; } } } psi->curDataArray = NULL; return DHL_OK; } else { *returnArray = NULL; return DHL_FAIL_OUT_OF_RESOURCE; } } /* * FreePSIData deletes a PSIDataArray that was obtained by calling ReadPSIData */ void DD_PSI_FreePSIArray(PSIDataArray_t *psi) { int i; #ifdef PSI_DBG // DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the PSI_FreeArray. psi = 0x%x\n" , psi); #endif if( !psi ) return; if (psi) { for (i = 0; i < psi->maxSections; ++i) { if (psi->sectPtr[i] != NULL && psi->sectPtr[i] != (DS_U8 *)-1) { PSI_Free(psi->sectPtr[i]); } } PSI_Free(psi); } } DHL_RESULT DD_PSI_GetLastReceivedSection( PSIContext_t *psiCtl, DS_BOOL detach, DS_S32 *returnSectionNumber, DS_S32 *returnLastSectionNumber, DS_U8 **returnSectionData) { DS_BOOL eager; if (!psiCtl) return DHL_FAIL_NULL_POINTER; eager = (psiCtl->psiMode == eagerTableMode || psiCtl->psiMode == segmentEagerMode); //(((int)psiCtl->psiMode) & PSIMODE_EAGER_FLAG)!= 0; if (!eager) { printf("|%s| This is not eagerTableMode (%d)\n", __FUNCTION__, psiCtl->psiMode); return DHL_FAIL; } if (psiCtl->curSection < 0 || psiCtl->nextDataArray == NULL || psiCtl->nextDataArray->maxSections <= psiCtl->curSection || psiCtl->nextDataArray->sectPtr[psiCtl->curSection] == NULL || psiCtl->nextDataArray->sectPtr[psiCtl->curSection] == (DS_U8 *)-1) { return(DHL_FAIL_NOT_FOUND); } if (returnSectionNumber) { *returnSectionNumber = psiCtl->curSection; } if (returnLastSectionNumber) { *returnLastSectionNumber = psiCtl->nextDataArray->maxSections-1; } if (returnSectionData) { *returnSectionData = psiCtl->nextDataArray->sectPtr[psiCtl->curSection]; if (detach) { psiCtl->nextDataArray->sectPtr[psiCtl->curSection] = (DS_U8 *)-1; } } return (DHL_OK); } DHL_RESULT DD_PSI_GetLastReceivedSegment( PSIContext_t *psiCtl, DS_BOOL detach, DS_S32 *returnSegmentNumber, DS_S32 *returnSegmentCount, P_DS_U8 returnSectionData[]) { DS_BOOL eager; int segment_count=0; int end_segment=-1; if (!psiCtl) return DHL_FAIL_NULL_POINTER; eager = (psiCtl->psiMode == segmentEagerMode); //(((int)psiCtl->psiMode) & PSIMODE_EAGER_FLAG)!= 0; if (!eager) { printf("|%s| This is not eagerTableMode (%d)\n", __FUNCTION__, psiCtl->psiMode); return DHL_FAIL; } if (psiCtl->curSection < 0 || psiCtl->nextDataArray == NULL || psiCtl->nextDataArray->maxSections <= psiCtl->curSection || psiCtl->nextDataArray->sectPtr[psiCtl->curSection] == NULL || psiCtl->nextDataArray->sectPtr[psiCtl->curSection] == (DS_U8 *)-1) { return(DHL_FAIL_NOT_FOUND); } if (returnSegmentNumber) { *returnSegmentNumber = (psiCtl->curSection>>3); } if (returnSegmentCount) { if (psiCtl->nextDataArray->sectPtr[psiCtl->curSection]) { segment_count = psiCtl->nextDataArray->sectPtr[psiCtl->curSection][SECTION_NUM_LAST]; end_segment = psiCtl->nextDataArray->sectPtr[psiCtl->curSection][SECTION_NUM_LAST+5]; *returnSegmentCount = ((segment_count+8)>>3); } else { printf("|%s| ERROR, sectionPtr is NULL!\n", __FUNCTION__); return DHL_FAIL_NULL_POINTER; } } if (returnSectionData) { int i, j; for (j=0, i=(psiCtl->curSection & (~0x07)); i<=end_segment; i++, j++) { returnSectionData[j] = psiCtl->nextDataArray->sectPtr[i]; if (detach) { psiCtl->nextDataArray->sectPtr[i] = (DS_U8 *)-1; } } } return (DHL_OK); } unsigned long DD_PSI_CalculateCRC( unsigned char *pTargetData , int iByteCount ) { #if 1 unsigned long crc = 0xFFFFFFFF; unsigned char *byte = pTargetData; unsigned short index; int len = 0; while (len++ < iByteCount) { crc ^= *byte++ << 24; for(index = 0; index <= 7; index++) { crc = crc & 0x80000000 ? (crc << 1) ^ 0x04C11DB7 : crc << 1; } } return crc; #else int bit_count = 0; int bit_in_byte = 0; unsigned short int data_bit; unsigned short int shift_reg[32]; int i,nr_bits; unsigned char *data; int crc; unsigned short int g[33] = { 1,1,1,0, 1,1,0,1, 1,0,1,1, 1,0,0,0, 1,0,0,0, 0,0,1,1, 0,0,1,0, 0,0,0,0, 1 }; // Initialize shift register's to '1' for(i=0; i<32; i++) shift_reg[i] = 1; // Calculate nr of data bits if(iByteCount <= 0) return -1; // nr_bits = ((int) (last - first)) * 8; nr_bits = (int)iByteCount*8; data = pTargetData; while (bit_count < nr_bits) { // Fetch bit from bitstream data_bit = (short int) (*data & (0x80 >> bit_in_byte)); data_bit = data_bit >> (7 - bit_in_byte); bit_in_byte++; bit_count++; if (bit_in_byte == 8) { bit_in_byte = 0; data++; } // Perform the shift and modula 2 addition data_bit ^= shift_reg[31]; i = 31; while (i != 0) { if (g[i]) shift_reg[i] = shift_reg[i-1] ^ data_bit; else shift_reg[i] = shift_reg[i-1]; i--; } shift_reg[0] = data_bit; } // make CRC an int crc = 0x00000000; for (i= 0; i<32; i++) crc = (crc << 1) | ((int) shift_reg[31-i]); return crc; #endif //#if 1 } /* * GetDataCRC retrieves the CRC field from the PSI data */ DS_U32 DD_PSI_GetDataCRC(DS_U8 *data, DS_U32 len) { DS_U32 crc; if(len < 4 ) return 0; data += (len - 4); crc = ((*data) << 24) | ((*(data+1)) << 16) | ((*(data+2)) << 8) | *(data+3); return(crc); } void DD_PSI_DataReceived( PSIContext_t *master , DS_U8 *data, int len) { int siLength; PSIDataArray_t *desc; DS_BOOL useCRC; PSIEvent event = psiNoEvent; int maxSections; DS_BOOL eager = _FALSE_; DS_U8 *realData = NULL; DS_U32 crc = 0; DS_U32 givenCRC = 0; int iDescSize = 0; DHL_RESULT err = DHL_OK; DS_U8 sectionNumber = 0; DS_U16 pid = 0; if(!master || !data || len == 0 ) return; pid = master->pid; /* Check to make sure the section is not longer than we asked for. */ siLength = (((data[SECTION_LEN_HI]&0x0F)<<8) | data[SECTION_LEN_LO]) + 3; #ifdef PSI_DBG /*DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the DD_PSI_DataReceived : pisLength = %d \n", siLength );*/ #endif if (siLength > master->maxData) { event = psiSectionTooBig; goto done; } eager = (master->psiMode == eagerTableMode) || (master->psiMode == segmentEagerMode);//(((int)master->psiMode) & PSIMODE_EAGER_FLAG)!= 0; switch(master->psiMode) { case privateMode: case sectionMode: /* * In private mode, we simply pass the data along. We check CRC if * the section_syntax_indicator is set. * Section mode is like private mode except that we assume section * syntax and force a CRC check regardless of the section_syntax_indicator * bit. */ iDescSize = PSIDescriptorSize(1); desc = (PSIDataArray_t *)(PSI_Malloc(iDescSize)); if (!desc) { event = psiMemoryError; goto done; } memset( desc , 0 , iDescSize ); desc->pid = pid; desc->context = master; desc->numSections = 1; desc->maxSections = 1; useCRC =( (master->psiMode == sectionMode) || (data[SECTION_LEN_HI]&0x80 ) ) ; /*crc check.....*/ if( useCRC ) { crc = DD_PSI_CalculateCRC(data , siLength-4); givenCRC = DD_PSI_GetDataCRC(data, siLength); if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_DataReceived : given crc : 0x%x , calculated crc : 0x%x, len = %d\n", (unsigned int)givenCRC , (unsigned int)crc, siLength ); if (crc != givenCRC ) { PSI_Free(desc); event = psiCRCError; goto done; } } if (master->updateMode == psiCRCChange && useCRC) { master->runningCRC = DD_PSI_GetDataCRC(data, siLength); if (master->lastCRCValid && master->runningCRC == master->lastCRC) { master->runningCRC = 0; if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "SIDataReceived-secion mode : no changne in CRC...so, free this table.\n"); PSI_Free(desc); goto done; } }/*to fix.*/ else if( master->updateMode == psiVersionChange ) { int version = data[SECTION_VERSION]&SECTION_VERSION_MASK; if( master->lastVersion == version ) { if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "SIDataReceived-secion mode: no changne in version...so, free this table.\n"); PSI_Free(desc); goto done; } else master->lastVersion = version ; } /*allocate the buffer which will be used by user...*/ realData = (DS_U8 *)PSI_Malloc( siLength ); if( !realData ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto done; } memset( realData , 0 , siLength ); memcpy(realData , data , siLength ); desc->sectPtr[0] = realData; if (master->curDataArray) { DD_PSI_FreePSIArray(master->curDataArray); } master->curDataArray = desc; event = psiDataReceived; if ( g_Demux_Debug >= 2 ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSIDataReceived : master->curDataArray is set with 0x%x\n", (unsigned int)desc); DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "testprint : desc->sectPtr[0][0] = 0x%x\n", (unsigned int)desc->sectPtr[0][0]); } break; case tableMode: case eagerTableMode: case segmentTableMode: case segmentOnlyMode: case segmentEagerMode: desc = master->nextDataArray; if (desc && (master->version != (data[SECTION_VERSION]&SECTION_VERSION_MASK) || (master->psiMode != segmentOnlyMode && desc->maxSections != data[SECTION_NUM_LAST]+1))) { /* * The version number changed or else something weird happened because * last_section_number changed. In any case, throw away what we had */ DD_PSI_FreePSIArray(master->nextDataArray); master->nextDataArray = desc = NULL; master->runningCRC = 0; if (eager) { master->eventProc( psiVersionChanged , master, master->userParam); } } sectionNumber = data[SECTION_NUM]; if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSIDataReceived : sectionNumber = %d\n", sectionNumber); if (desc) { /* * This is a second or subsequent section in the table. Take it if * we haven't seen it yet. Else, discard it. */ if (sectionNumber >= desc->maxSections) { event = psiMaxSectionOverflow; goto done; } else if (desc->sectPtr[sectionNumber] != NULL) { /* * This section is beyond maxSections, but we have already informed * the client that this has happened, or else we have already received * this section, so discard this one quietly. */ if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSIDataReceived : it is already received...so, ignored.\n"); goto done; } } else { /* * We are getting the first section of a new table */ if (data[SECTION_NUM_LAST]+1 > master->maxSections) { event = psiMaxSectionOverflow; maxSections = master->maxSections; } else { maxSections = data[SECTION_NUM_LAST]+1; } //printf("master->segment_number: %d\n", master->segment_number); if ( master->psiMode == segmentOnlyMode ) { if ( (master->segment_number << 3) != (sectionNumber & 0xF8) ) { printf("PSIDataReceived: Invalid segment number in segmentOnlyMode. (%d, %d)\n", master->segment_number, sectionNumber ); goto done; } maxSections = 8; } else { if (sectionNumber >= maxSections) { event = psiLastSectionOverflow; goto done; } } if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the SIDataReceived : decision of maxSections = %d\n", maxSections ); iDescSize = sizeof(PSIDataArray_t);//PSIDescriptorSize(maxSections); desc = (PSIDataArray_t *)(PSI_Malloc(iDescSize)); if (!desc) { event = psiMemoryError; goto done; } memset(desc, 0 , iDescSize ); desc->pid = pid; desc->context = master; desc->numSections = 0; if ( master->psiMode == segmentOnlyMode ) desc->maxSections = 8; else desc->maxSections = maxSections; master->version = data[SECTION_VERSION]&SECTION_VERSION_MASK; master->nextDataArray = desc; } /* * At this point, we have the descriptor and we know that we want the * data */ /*crc check...*/ crc = DD_PSI_CalculateCRC(data , siLength-4); givenCRC = DD_PSI_GetDataCRC(data, siLength); if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in TableMode : given crc : 0x%x , calculated crc : 0x%x, len = %d \n", (unsigned int)givenCRC ,(unsigned int)crc, siLength ); if (crc != givenCRC ) { event = psiCRCError; goto done; } /*allocate the buffer which will be used by user...*/ realData = (DS_U8 *)PSI_Malloc( siLength ); if( !realData ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto done; } memset( realData , 0 , siLength ); memcpy(realData , data , siLength ); desc->sectPtr[sectionNumber] = realData; if (master->updateMode == psiCRCChange) { master->runningCRC ^= DD_PSI_GetDataCRC(data, siLength); } master->curSection = sectionNumber; desc->numSections++; /* * If segmentTableMode, we have to count numSections here. */ if ( master->psiMode == segmentTableMode || master->psiMode == segmentOnlyMode || master->psiMode == segmentEagerMode ) { int subtable_start, subtable_end; int segment_last_section_number; DS_BOOL bSegmentCompleted; int i; segment_last_section_number = data[SECTION_NUM_LAST+5]; subtable_start = sectionNumber & (~0x07); subtable_end = segment_last_section_number; bSegmentCompleted = DS_TRUE; for (i=subtable_start; i<=subtable_end; i++) { if (desc->sectPtr[i] == NULL) { bSegmentCompleted = DS_FALSE; break; } } if ( g_Demux_Debug >= 2 ) printf("We found segment: subtable %d(%d~%d)\n", sectionNumber, subtable_start, subtable_end); if ( bSegmentCompleted == DS_TRUE ) { int increment; if ( (subtable_start+8) > desc->maxSections && (master->psiMode == segmentTableMode || master->psiMode == segmentEagerMode) ) increment = (desc->maxSections-(subtable_end-subtable_start)-subtable_start-1); else increment = 8-(subtable_end-subtable_start)-1; if ( g_Demux_Debug >= 2 ) printf("Increase section counts: %ld -> %ld (max: %ld)\n", desc->numSections, desc->numSections + increment, desc->maxSections); if (eager) { master->eventProc(psiSectionReceived, master, master->userParam); } desc->numSections += increment; } /* * TO DO: Have to check whether segment_last_section_number is changed for same segment. */ for (i=subtable_start; i<=subtable_end; i++) { } } if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the SIDataReceived : numSections = %d.\n" , (int)desc->numSections ); if (eager) { if (master->psiMode != segmentEagerMode) master->eventProc(psiSectionReceived, master, master->userParam); } if (desc->numSections >= desc->maxSections) { /* * We have the whole table, so we can now feed it to the client */ if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the SIDataReceived : we have the whole table...\n"); if (master->updateMode == psiCRCChange) { if (master->lastCRCValid && master->runningCRC == master->lastCRC) { master->runningCRC = 0; master->nextDataArray = NULL; DD_PSI_FreePSIArray(desc); if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the SIDataReceived : no changne in CRC...so, free this table.\n"); if (eager) { master->eventProc(psiCRCUnchanged, master, master->userParam); } goto done; } } #if 1/*to fix.*/ else if( master->updateMode == psiVersionChange ) { int version = data[SECTION_VERSION]&SECTION_VERSION_MASK; if( master->lastVersion == version ) { DD_PSI_FreePSIArray(desc); master->nextDataArray = NULL; if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "SIDataReceived : no changne in version...so, free this table.\n"); goto done; } else master->lastVersion = version ; } #endif /**************/ if (master->curDataArray) { DD_PSI_FreePSIArray(master->curDataArray); } if ( g_Demux_Debug >= 2 ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSIDataReceived : master->curDataArray is set with 0x%x\n",(unsigned int)desc); DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "testprint : desc->sectPtr[0][0] = 0x%x\n", (desc->sectPtr[0] == (DS_U8 *)0 || desc->sectPtr[0] == (DS_U8 *)-1) ? '0' : (unsigned int)desc->sectPtr[0][0]); } master->curDataArray = desc; master->nextDataArray = NULL; event = psiDataReceived; } else { if ( g_Demux_Debug >= 2 ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "Don't inform to upper layer.\n"); } } break; default: break; } /*switch(master->psiMode)*/ if (event == psiDataReceived) { if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "SIDataReceived : we'll send a siDataReceived event to an user.\n"); if (master->updateMode == psiOneShot) { if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "SIDataReceived : psiOneShot\r\n"); if(master->stopProc) { master->stopProc( (DS_U32)(master->pParent) , master->userParamStop); } else { if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the SIDataReceived : no call stopFunction\r\n"); } } else if (master->updateMode == psiVersionChange) { /* * Here, we modify the siFilter to only fire on a version different * from the one we just received. */ #if 0 /*to fix.*/ int version = data[SECTION_VERSION]&SECTION_VERSION_MASK; PSIMask_t *filt = master->psiMask; DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "data[SECTION_VERSION] = 0x%x , version = %d\r\n", data[SECTION_VERSION] , version ); filt->entries[5].matchMask &= ~SECTION_VERSION_MASK; filt->entries[5].noMatchMask |= SECTION_VERSION_MASK; filt->entries[5].value = (filt->entries[5].value & ~SECTION_VERSION_MASK) | version; DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "matchMask = 0x%x , noMatchMask = 0x%x , value = %d \r\n", filt->entries[5].matchMask , filt->entries[5].noMatchMask, filt->entries[5].value ); DD_PSI_ResetSectMask ( master->pParent , filt ); #endif } else if (master->updateMode == psiCRCChange) { if ( g_Demux_Debug >= 2 ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "PSI_DataReceived : currCRC = 0x%x , lastCRC = 0x%x\n" , (unsigned int)master->runningCRC , (unsigned int)master->lastCRC ); master->lastCRC = master->runningCRC; master->lastCRCValid = _TRUE_; master->runningCRC = 0; } } done: /* * Send an event if we have something to tell the client. */ if (event != psiNoEvent && master->eventProc) { master->eventProc(event, master->pParent, master->userParam); } } DHL_RESULT DD_PSI_RegisterPSICtx( void *pParent, DS_U16 pid, PSIMode psiMode, PSIUpdateMode updateMode, PSIMask_t *prefList, DS_U16 maxData, DS_U16 maxSections, PSIEventProc_f eventProc, DS_U32 userParam , PSIRegisterProc_f stopFuncPtr, DS_U32 usrParamStop, DS_BOOL bRegister, void **returnPSIControl ) { PSIContext_t *pPsiContext = NULL; *returnPSIControl = NULL; /* * If we will be monitoring version changes, then we should only look for current, * or next versions. The client can monitor both by calling MonitorPSIPid twice with * two different prefilters. */ #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_RegisterPSICtx : prefList->numEntries = 0x%x\r\n", prefList->numEntries ); #endif if (updateMode == psiVersionChange) { if( !(prefList->numEntries >= 6 && (prefList->entries[5].matchMask&1) != 0 ) ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_RegisterPSICtx : current_next_indicator must be matched for version change. %d.\r\n" , prefList->entries[5].matchMask&1); return DHL_FAIL_INVALID_PARAM; } } if( bRegister == _TRUE_ ) pPsiContext = DD_PSI_AllocPSIContextWRegister(); else pPsiContext = DD_PSI_AllocPSIContext(); if( pPsiContext == NULL ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_RegisterPSICtx : DD_PSI_AllocPSIContext() fail.\r\n"); return DHL_FAIL_OUT_OF_RESOURCE; } pPsiContext->pParent = pParent; /*»ç¿ëÀÚ°¡ ÁöÁ¤ÇÑ parent°¡ ¾ø°í, register°¡ enableµÈ °æ¿ì.*/ if( pParent == NULL && bRegister == _TRUE_ ) pPsiContext->pParent = pPsiContext; // gpPsiCtxManager; pPsiContext->psiMask = prefList; pPsiContext->pid = pid; pPsiContext->psiMode = psiMode; pPsiContext->updateMode = updateMode; pPsiContext->maxData = maxData; pPsiContext->maxSections = maxSections; pPsiContext->curSection = -1; pPsiContext->version = -1; pPsiContext->eventProc = eventProc; pPsiContext->userParam = userParam; pPsiContext->lastCRC = 0; pPsiContext->runningCRC = 0; pPsiContext->lastCRCValid = _FALSE_; pPsiContext->curDataArray = NULL; pPsiContext->nextDataArray = NULL; pPsiContext->lastVersion = 0xff; pPsiContext->stopProc = stopFuncPtr; pPsiContext->userParamStop = usrParamStop; pPsiContext->oneShot = (updateMode == psiOneShot /*|| updateMode == psiVersionChange */ ) && (psiMode != tableMode && psiMode != eagerTableMode && psiMode != segmentTableMode && psiMode != segmentOnlyMode && psiMode != segmentEagerMode ); *returnPSIControl = (void *)pPsiContext; #ifdef PSI_CTX_MNG_DBG DD_PSI_PrintRegisteredPsiCtx(); #endif return DHL_OK; } void DD_PSI_ReleasePSICtx( void * pPSICtx ) { #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "in the DD_PSI_ReleasePSICtx.\r\n"); #endif if(pPSICtx) { if( ((PSIContext_t*) pPSICtx)->bRegistered == _TRUE_ ) DD_PSI_FreePSIContextWUnregister( pPSICtx ); else DD_PSI_FreePSIContext( pPSICtx ); } } DS_BOOL DD_PSI_IsInterestingSection( PSIMask_t *pSectMask , DS_U8 *pData , int iLen ) { DS_BOOL noMatchSucceeded = _FALSE_; DS_BOOL noMatchUsed = _FALSE_; int i; PSIMaskByte_t *entry; int len = 0; if( !pSectMask || !pData || !iLen ) return _FALSE_; len = (iLen < pSectMask->numEntries )?iLen:pSectMask->numEntries; #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "IsInterestingSection : len = %d , filter->entries : \r\n" , len ); for( i = 0 ; i < len ; i++ ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "0x%x ", (pSectMask->entries)[i].value ); } DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "\nIsInterestingSection : len = %d , section : \r\n" , len ); for( i = 0 ; i < len ; i++ ) { DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "0x%x ", pData[i] ); //if( !(i%16) ) DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "\r\n"); } DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "\n"); #endif for (i = 0, entry = pSectMask->entries; i < len; ++i,++pData,++entry) { if ((*pData & entry->matchMask) != (entry->value & entry->matchMask)) { return(_FALSE_); } if (entry->noMatchMask != 0) { noMatchUsed = _TRUE_; if ((*pData & entry->noMatchMask) != (entry->value & entry->noMatchMask)) { noMatchSucceeded = _TRUE_; } } /* if (i == 0) { pData += 2; } */ } #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "noMatchSucceeded = %d : noMatchUsed = %d \r\n" , noMatchSucceeded ,noMatchUsed ); #endif return(noMatchSucceeded || !noMatchUsed); } /*return it's PSIContext if it is the section you want to gather.*/ /*gpPsiCtxManagerÀÇ monitoring list¸¦ checkÇÑ´Ù. table monitoring ½ÃÀÛÇÒ¶§ register°¡ ¾ø¾úÀ¸¸é ÇØ´ç ¾øÀ½.*/ PSIContext_t *DD_PSI_DoSWSectionFiltering( DS_U16 pid , DS_U8 *pData , int iLen ) { int i; PSIContext_t *pRetData = NULL; if( !pData || !iLen ) return NULL; if(!gpPsiCtxManager) return NULL; DD_PSI_LockPsiCtxMng(); DD_PSI_PrintRegisteredPsiCtx(); for( i = 0 ; i < PSICTX_CNT ; i++ ) { /*to find a PsiCtx with same pid & SectinMask.*/ if ( gpPsiCtxManager->psiCtxPtrList[i] && gpPsiCtxManager->psiCtxPtrList[i]->pid == pid && \ DD_PSI_IsInterestingSection( gpPsiCtxManager->psiCtxPtrList[i]->psiMask , pData , iLen ) == _TRUE_ ) { pRetData = gpPsiCtxManager->psiCtxPtrList[i]; #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_DoSWSectionFiltering : find one.\n"); #endif break; } } DD_PSI_UnlockPsiCtxMng(); return pRetData; } void DD_PSI_ResetRegisteredMonitorFiltersExcludingOne( DS_U8 tid , DS_U8 byteIndex , DS_U8 byteMask , DS_U8 byteValue) { int i = 0; PSIContext_t *pPsiCtx = NULL; DD_PSI_LockPsiCtxMng(); for( i = 0 ; i < PSICTX_CNT ; i++ ) { /*to find a empty slot.*/ pPsiCtx = gpPsiCtxManager->psiCtxPtrList[i]; if ( pPsiCtx ) { if( pPsiCtx->psiMask->entries[0].value == tid && ((pPsiCtx->psiMask->entries[byteIndex].value) & byteMask) == byteValue ) { #ifdef PSI_DBG DHL_DbgPrintf( gdhlPsiDbgLvl, DHLDBG_PSI, "DD_PSI_ResetRegisteredMonitorFiltersExcludingDCM : skip DCM section filter resetting.\n"); #endif continue; } pPsiCtx->lastCRC = 0; pPsiCtx->version = 0xff; } } DD_PSI_UnlockPsiCtxMng(); } void DD_PSI_ResetRegisteredMonitorFilters() { int i = 0; PSIContext_t *pPsiCtx = NULL; DD_PSI_LockPsiCtxMng(); for( i = 0 ; i < PSICTX_CNT ; i++ ) { /*to find a empty slot.*/ pPsiCtx = gpPsiCtxManager->psiCtxPtrList[i]; if (pPsiCtx ) { // memset( pPsiCtx , 0 , sizeof(PSIContext_t) ); // pPsiCtx->bRegistered = _TRUE_; // pPsiCtx->selfIndex = i; pPsiCtx->lastCRC = 0; pPsiCtx->version = 0xff; } } DD_PSI_UnlockPsiCtxMng(); } /*2003.12.13. added by jina*/ void DD_PSI_ClearRegisteredMonitorFilters() { int i = 0; PSIContext_t *pPsiCtx = NULL; DD_PSI_LockPsiCtxMng(); for( i = 0 ; i < PSICTX_CNT ; i++ ) { /*to find a empty slot.*/ pPsiCtx = gpPsiCtxManager->psiCtxPtrList[i]; if (pPsiCtx ) { DD_PSI_FreePSIContext(pPsiCtx); gpPsiCtxManager->psiCtxPtrList[i] = NULL; } } DD_PSI_UnlockPsiCtxMng(); } /*when using software section filtering...it is independent from hardware.*/ DHL_RESULT DHL_PSI_ReadPSIDataSw( void *hTblHandle , struct PSIDataArray_t **returnPsi ) { DHL_RESULT dhlResult; if( !hTblHandle || !returnPsi ) return DHL_FAIL_NULL_POINTER; dhlResult = DD_PSI_ReadPSIArray( hTblHandle , returnPsi); return dhlResult; } DHL_RESULT DHL_PSI_MonitorPSIPidSw( DS_U16 pid, PSIMode psiMode, PSIUpdateMode updateMode, PSIMask_t *prefList, DS_U16 maxData, DS_U16 maxSections, PSIEventProc_f eventProc, DS_U32 userParam, void **returnPSIControl ) { DHL_RESULT dhlResult = DHL_OK; /*»õ·Î ¹Þ±â¸¦ ½Ãµµ ÇÑ´Ù.*/ dhlResult = DD_PSI_RegisterPSICtx(NULL, pid, psiMode, updateMode, prefList, maxData, maxSections, eventProc, userParam , NULL, /*no stop function*/ 0, /*no param*/ _TRUE_, /*with register*/ returnPSIControl ); return dhlResult; } DHL_RESULT DHL_PSI_CancelMonitorSw( void * hPsiCtl ) { if(!hPsiCtl) return DHL_FAIL_INVALID_PARAM; DD_PSI_ReleasePSICtx( hPsiCtl ); return DHL_OK; } void DHL_PSI_FreePSIArray( PSIDataArray_t *psi ) { return (DD_PSI_FreePSIArray(psi)); }