/* DMW_PsiEngine.c DST TV MW PSI Scan Module PSI Scan Core Engine implementation Copyright 2006~2009 Digital STREAM Technology, Inc. All Rights Reserved */ #include "DMW_Platform.h" // dlib headers #include "DLIB_PSI_Parser.h" #include "DLIB_PSIP_Parser.h" #include "DLIB_PSI_Monitor.h" #include "DLIB_PSIP_Monitor.h" #include "DMW_PsiConfig.h" #include "DMW_PsiEngine.h" #include "DMW_PsiDatabase.h" #include "DMW_PsiUtil.h" DHL_MODULE("psieng", 1); #if COMMENT ____Configs____(){} #endif int gPsiIgnoreEtmLocationInfo = 0; // ETM location Á¤º¸°¡ Á¦´ë·Î µÇ¾î ÀÖ´ÂÁö Å×½ºÆ® Çϱâ À§ÇÏ »ç¿ëÇÏ´Â °ª.. // Àִµ¥ ¾ø´Ù°í ¼ÓÀÌ´Â °Ç ¾Æ´ÑÁö Å×½ºÆ®.. // ÀϹÝÀûÀÎ »óȲ¿¡¼­´Â »ç/¿ë/±Ý/Áö/!!! // // cafrii 060112 // ÀϺΠcustomerÀÇ ¿ä±¸¿¡ ÀÇÇØ ÀÌ ¿É¼ÇÀ» »ç¿ëÇÒ ¼ö ÀÖµµ·Ï ÇÔ. // À̸§¿¡¼­ "Test" »èÁ¦ // // cafrii 060320 add comment // UpdateEtt ÇÔ¼ö ¾È¿¡¼­´Â ÀÌ º¯¼ö¸¦ Âü°íÇÏ¿© ¹«Á¶°Ç ett monitor ½ÃµµÇÏ°Ô µÈ´Ù. // ±×·¯³ª ettÀÇ ¼ö½Å¿©ºÎ¸¦ üũÇÏ´Â ÇÔ¼ö¿¡¼­´Â ÀÌ º¯¼ö¸¦ °í·ÁÇÏÁö ¾ÊÀ¸¹Ç·Î // ¸ø¹Þ¾ÒÀ½¿¡µµ ºÒ±¸Çϰí ett complete·Î °£ÁֵǾî¹ö¸°´Ù. µû¶ó¼­ retry¸¦ ÇÏÁö ¾Ê´Â´Ù. // Áï first try¿¡ download ¼º°øÇÏÁö ¾ÊÀ¸¸é ±× ÈÄ¿¡´Â retryÁ¶Â÷ ¾ÈµÇ°í °è¼Ó ¾È¹ÞÀ½. // epg_print¿¡¼­´Â ±×³É noneÀ¸·Î Ç¥½ÃµÊ. // // ¸¸¾à ett ¼ö½Å¿©ºÎ üũÇÏ´Â ÇÔ¼ö¿¡±îÁö Àû¿ëÇÏ°Ô µÇ¸é, // etm_noneÀÌ Çϳª¶óµµ Á¸ÀçÇÏ´Â ½ºÆ®¸²¿¡¼­´Â ¿µ¿øÀÌ complete°¡ ¾ÈµÉ ¼ö ÀÖÀ¸¹Ç·Î À§Çè. // ±×·¡¼­ ±×³É À§ÀÇ ´ÜÁ¡¿¡µµ ºÒ±¸Çϰí ÀϺθ¸ Àû¿ëÇϵµ·Ï ÇÑ´Ù. #if COMMENT ____Types____(){} #endif #undef IsError #undef ErrorString #define IsError(e) ((e)!=0) #define ErrorString(e) p_dhr2str(e) /* psi engine task¿¡¼­¸¸ »ç¿ëÇÑ´Ù´Â ÀüÁ¦·Î static ¹öÆÛ »ç¿ëÇϵµ·Ï ÇÏÀÚ. */ static const char *p_dhr2str(DHL_RESULT dhr) { static char buf[10]; sprintf(buf, "0x%x", dhr); return buf; } #if COMMENT ____EngineModule____(){} #endif // this is singleton object. should be unique. S_PSIM_CONTEXT *g_psi_engine; #if COMMENT ____DbgPrint____(){} #endif int g_Trace_bPsiEvent = 1; int g_Trace_bPsiSttInfo = 1; #if COMMENT ____Declare____(){} #endif // forward declaration // this is the only psi table event proc. PSI_STATIC void _PsiTableEventProc(tDHL_PSI_Event psiEvent, tDHL_PSI_ControlHandle psiCtl, UINT32 userParam); #if COMMENT ____Private____(){} #endif PSI_STATIC void SendUserCallback(S_PSIM_PORT *tsport, E_PSIM_EVENT event, UINT32 param) { S_PSIM_USER_INPUT *input = (S_PSIM_USER_INPUT *) &tsport->input; if (input->userproc) (*(input->userproc))(tsport->tsd, event, param); } #if 0 PSI_STATIC void SendEventChannelStarted(S_PSIM_PORT *tsport, int id) { S_PSIM_CH_START_CB_PARAM ccb; S_PSIM_CHINFO *chInfo; return; //test.. chInfo = PSIDB_GetPsiChInfo(id); if (1) //if (chInfo->channel_start_notified == 0) { memset(&ccb, 0, sizeof(ccb)); ccb.id = chInfo->id; ccb.tsd = chInfo->tsd; ccb.mgt = chInfo->mgt; ccb.vct = chInfo->vct; ccb.n_subchannel = chInfo->n_subchannel; SendUserCallback(tsport, ePSIM_EVENT_BasePsipReceived, 0); SendUserCallback(tsport, ePSIM_EVENT_ChannelStarted, (UINT32) &ccb); //chInfo->channel_start_notified = 1; } } PSI_STATIC void SendEventSubchannelStarted(S_PSIM_PORT *tsport, int id, int source_id) { S_PSIM_SUBCH_START_CB_PARAM sccb; S_PSIM_SUBCHINFO *subchInfo; subchInfo = PSIDB_GetPsiSubChInfo(id, source_id); if (subchInfo->subchannel_start_notified == 0) { memset(&sccb, 0, sizeof(sccb)); sccb.index = subchInfo->index; sccb.source_id = subchInfo->source_id; sccb.flags = tsport->input.flags; #if 0 // Á¤È®ÇÏ°Ô °°Áö ¾ÊÀº °æ¿ì buffer overflow µîÀÇ ¹®Á¦ ¹ß»ý.. //memcpy(&sccb.vct_info, &subchInfo->vct_info, sizeof(sccb.vct_info)); #else memcpy(sccb.vct_info.short_name, subchInfo->vct_info.short_name, sizeof(sccb.vct_info.short_name)); sccb.vct_info.major_channel_number = subchInfo->vct_info.major_channel_number; sccb.vct_info.minor_channel_number = subchInfo->vct_info.minor_channel_number; sccb.vct_info.program_number = subchInfo->vct_info.program_number; #endif SendUserCallback(tsport, ePSIM_EVENT_SubChannelStarted, (UINT32) &sccb); subchInfo->subchannel_start_notified = 1; } } PSI_STATIC void SendEventEitsCompleted(S_PSIM_PORT *tsport, S_PSIM_SUBCHINFO *subchInfo) { S_PSIM_COMPLETE_CB_PARAM cmcb; if (subchInfo->eit_complete_notified == 0) { cmcb.id = subchInfo->parent->id; cmcb.index = subchInfo->index; cmcb.source_id = subchInfo->source_id; SendUserCallback(tsport, ePSIM_EVENT_EitsCompleted, (UINT32) &cmcb); subchInfo->eit_complete_notified = 1; } } PSI_STATIC void SendEventSubchannelCompleted(S_PSIM_PORT *tsport, S_PSIM_SUBCHINFO *subchInfo) { S_PSIM_COMPLETE_CB_PARAM cmcb; if (subchInfo->subchannel_complete_notified == 0) { cmcb.id = subchInfo->parent->id; cmcb.index = subchInfo->index; cmcb.source_id = subchInfo->source_id; SendUserCallback(tsport, ePSIM_EVENT_SubChannelCompleted, (UINT32) &cmcb); subchInfo->subchannel_complete_notified = 1; } } PSI_STATIC void SendEventChannelCompleted(S_PSIM_PORT *tsport, S_PSIM_CHINFO *chInfo) { S_PSIM_COMPLETE_CB_PARAM cmcb; if (chInfo->channel_complete_notified == 0) { cmcb.id = chInfo->id; cmcb.index = 0; cmcb.source_id = 0; SendUserCallback(tsport, ePSIM_EVENT_ChannelCompleted, (UINT32) &cmcb); chInfo->channel_complete_notified = 1; } } #endif #if COMMENT ____Start_Stop____(){} #endif void StopMonitorPAT(S_PSIM_PORT *tsport) { if (tsport->patPsiCtl) { dprint(3, "cancel prev pat monitor\n"); DHL_PSI_StopMonitor(tsport->patPsiCtl); tsport->patPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } void StopMonitorPMTs(S_PSIM_PORT *tsport) { int i; if (tsport->num_programs) { dprint(3, "cancel all %d pmt ctls..\n", tsport->num_programs); for (i=0; inum_programs; i++) { if (tsport->pmtPsiCtlArray[i]) { DHL_PSI_StopMonitor(tsport->pmtPsiCtlArray[i]); tsport->pmtPsiCtlArray[i] = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } } if (tsport->pmtPsiCtlArray) DHL_OS_Free((void **)&tsport->pmtPsiCtlArray); tsport->num_programs = 0; } void StopMonitorMgt(S_PSIM_PORT *tsport) { if (tsport->mgtPsiCtl) { dprint(3, "cancel prev mgt monitor\n"); DHL_PSI_StopMonitor(tsport->mgtPsiCtl); tsport->mgtPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } void StopMonitorTvct(S_PSIM_PORT *tsport) { if (tsport->tvctPsiCtl) { dprint(3, "cancel prev tvct monitor\n"); DHL_PSI_StopMonitor(tsport->tvctPsiCtl); tsport->tvctPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } void StopMonitorCvct(S_PSIM_PORT *tsport) { if (tsport->cvctPsiCtl) { dprint(3, "cancel prev cvct monitor\n"); DHL_PSI_StopMonitor(tsport->cvctPsiCtl); tsport->cvctPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } void StopMonitorStt(S_PSIM_PORT *tsport) { if (tsport->sttPsiCtl) { dprint(3, "cancel prev stt monitor\n"); DHL_PSI_StopMonitor(tsport->sttPsiCtl); tsport->sttPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } void StopMonitorRrt(S_PSIM_PORT *tsport) { if (tsport->rrtPsiCtl) { dprint(3, "cancel prev rrt monitor\n"); DHL_PSI_StopMonitor(tsport->rrtPsiCtl); tsport->rrtPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } void StopMonitorEit(S_PSIM_PORT *tsport, int iEit) { if (iEit < 0 || iEit >= 128) return; if (tsport->eitPsiCtl[iEit]) { dprint(3, "cancel prev eit[%d] monitor\n", iEit); DHL_PSI_StopMonitor(tsport->eitPsiCtl[iEit]); tsport->eitPsiCtl[iEit] = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } void StopMonitorEtt(S_PSIM_PORT *tsport, int iEit) { if (iEit < 0 || iEit > 128) return; if (iEit == 128) { if (tsport->ettvPsiCtl) { dprint(3, "cancel prev ett-v monitor\n"); DHL_PSI_StopMonitor(tsport->ettvPsiCtl); tsport->ettvPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } else { if (tsport->ettPsiCtl[iEit]) { dprint(3, "cancel prev ett[%d] monitor\n", iEit); DHL_PSI_StopMonitor(tsport->ettPsiCtl[iEit]); tsport->ettPsiCtl[iEit] = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } } void StopMonitorAllEtts(S_PSIM_PORT *tsport) { int iEit; if (tsport->ettvPsiCtl) { dprint(3, "cancel prev ett-v monitor\n"); DHL_PSI_StopMonitor(tsport->ettvPsiCtl); tsport->ettvPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } for (iEit=0; iEit<128; iEit++) { if (tsport->ettPsiCtl[iEit]) { dprint(3, "cancel prev ett[%d] monitor\n", iEit); DHL_PSI_StopMonitor(tsport->ettPsiCtl[iEit]); tsport->ettPsiCtl[iEit] = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } } /* PAT monitor ½ÃÀÛ. */ STATUS StartMonitorPAT(S_PSIM_PORT *tsport) { DHL_RESULT err; STATUS status = statusOK; if (tsport->patPsiCtl) StopMonitorPAT(tsport); dprint(3, "monitor pat..\n"); err = MonitorPAT( tsport->tsd, // tDHL_TSD *tsd, TRUE, // BOOLEAN current_next_indicator, // get current pat only FALSE, // BOOLEAN eager, // get complete table ePSIUPDATE_VERCHANGE, // tDHL_PSI_Update updateMode, _PsiTableEventProc, // tDHL_PSI_EventProc eventProc, (UINT32)tsport, // UINT32 userParam, &tsport->patPsiCtl // tDHL_PSI_ControlHandle *returnPSICtl ); if (err) { dprint(0, "!! monitor pat err %d\n", err); status = statusError; } else { tsport->n_active_monitors++; } return status; } /* PMT ¸ð´ÏÅ͸¦ ½ÃÀÛÇÑ´Ù. pat¸¦ ¹Þ¾Æ¼­ »õ·Î pmt ¸ð´ÏÅÍ ½ÃÀÛÇÏ´Â °æ¿ì: »ç¿ëÀÚ ¸ðµå¿¡ µû¶ó¼­ Àüü, ÀϺΠpmt ½ÃÀÛ. autoscan ¸ðµå: Àüü pmtµéÀ» oneshotÀ¸·Î. ÀÏ¹Ý ¸ðµå: ÁöÁ¤ÇÑ ÇϳªÀÇ pmt¸¸ ¿¬¼ÓÀ¸·Î.. pmt ¸ð´ÏÅ͸¦ resource ºÎÁ·À¸·Î ´Ù ½ÃÀÛÇÏÁö ¸øÇߴµ¥ ´Ù¸¥ tableÀÌ Á¾·áµÈ °æ¿ì ¾ÆÁ÷ ½ÃÀÛÇÏÁö ¾ÊÀº pmt¸¸ ½ÃÀÛ. */ STATUS StartMonitorPMTs(S_PSIM_PORT *tsport, int preferred_program_number) { int i; int pmt_pid, program_number; MPEG_PAT *pat; MPEG_PMT **pmts; DHL_RESULT err; STATUS status = statusOK; tDHL_PSI_Update updateMode; BOOL bScanMode = (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) ? TRUE : FALSE; if (bScanMode) { // for autoscan mode, we need pmts of all program. // but only one copy of pmt is enough. preferred_program_number = -1; updateMode = ePSIUPDATE_ONESHOT; dprint(2, "%s: autoscan mode\n", __FUNCTION__); } else { // for normal mode, only one program pmt needs to be monitored. updateMode = ePSIUPDATE_VERCHANGE; dprint(2, "%s: program_number %d\n", __FUNCTION__, preferred_program_number); } pat = PSIDB_GetPAT(tsport->input.rf); pmts = PSIDB_GetPMTs(tsport->input.rf); if (pat == NULL || pmts == NULL) { dprint(0, "!! %s: pat %x or pmts %x not ready\n", __FUNCTION__, pat, pmts); return statusInvalidState; } // PSI db¿Í ts port Á¤º¸°¡ ¼­·Î ÀÏÄ¡ÇÏÁö ¾ÊÀ» ¼ö ÀÕÀ¸¹Ç·Î üũ. // if (pat->numPrograms != tsport->num_programs) { // pmt monitors Á¤º¸°¡ ºÒÀÏÄ¡. ¸ÕÀú reset.. // ¸Ç óÀ½¿¡ pat°¡ ¼ö½ÅµÇ´Â °æ¿ì¿¡´Â ´ç¿¬È÷ tsport num_programÀº 0ÀÏÅ×´Ï, // ±×·± °æ¿ì´Â µð¹ö±× ¸Þ½ÃÁö Á¦¿Ü.. if (tsport->num_programs) { dprint(0, "!! pat and pmt monitor inconsistent. pat %d, tsport %d, reset pmt monitors first..\n", pat->numPrograms, tsport->num_programs); } // µ¿ÀÛ ÁßÀÎ pmt monitor¸¦ ¸ðµÎ Á¤Áö. StopMonitorPMTs(tsport); tsport->pmtPsiCtlArray = DHL_OS_Malloc(pat->numPrograms * sizeof(tDHL_PSI_ControlHandle)); if (!tsport->pmtPsiCtlArray) { tsport->num_programs = 0; // <- ¹Ýµå½Ã ÇÊ¿ä. status = statusOutOfMemory; goto label_end; } tsport->num_programs = pat->numPrograms; } // PMTÀÇ °æ¿ì´Â Ưº°ÇÏ°Ô monitor ÃÖ´ë °¹¼ö¿¡ ÁÖÀÇÇØ¾ß ÇÔ. if (tsport->n_active_monitors >= tsport->max_monitors) { dprint(1, "!! cur monitor %d exceed limit %d\n", tsport->n_active_monitors, tsport->max_monitors); status = statusOutOfResource; goto label_end; } for (i=0; inumPrograms; i++) { program_number = pat->programs[i].program_number; if (preferred_program_number >= 0) { // ƯÁ¤ program number ¸¸ ¼ö½ÅÇÏ´Â ¸ðµå.. if (program_number != preferred_program_number) continue; } pmt_pid = pat->programs[i].program_map_PID; // normal mode ÀÎ °æ¿ì¶ó¸é ÀÌ¹Ì pmt°¡ ÀÖ´õ¶óµµ monitor °¡µ¿À» ÇØ¾ß ÇÑ´Ù. if (bScanMode && pmts[i]) // this pmt already exist. continue; if (tsport->pmtPsiCtlArray[i]) // this pmt is already started. continue; dprint(3, "new pmt monitor (pid %x, #%d), total monitors %d\n", pmt_pid, program_number, tsport->n_active_monitors); err = MonitorPMT( tsport->tsd, // tDHL_TSD tsd, pmt_pid, program_number, TRUE, // BOOLEAN current_next_indicator, // get current pat only updateMode, // tDHL_PSI_Update updateMode, _PsiTableEventProc, // tDHL_PSI_EventProc eventProc, (UINT32)tsport, // UINT32 userParam, &tsport->pmtPsiCtlArray[i] // tDHL_PSI_ControlHandle *returnPSICtl ); if (err) { dprint(0, "!! %s: monitor pmt err %d\n", __FUNCTION__, err); } else { tsport->n_active_monitors++; } if (preferred_program_number > 0) { // one program monitor.. break; } // PMTÀÇ °æ¿ì´Â Ưº°ÇÏ°Ô monitor ÃÖ´ë °¹¼ö¿¡ ÁÖÀÇÇØ¾ß ÇÔ. if (tsport->n_active_monitors >= tsport->max_monitors) { dprint(1, "!!!! total monitor reached limit %d\n", tsport->n_active_monitors); status = statusOK; goto label_end; } } label_end: return status; } STATUS StartMonitorMgt(S_PSIM_PORT *tsport) { DHL_RESULT err; STATUS status = statusOK; tDHL_PSI_Update updateMode = ePSIUPDATE_VERCHANGE; if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) updateMode = ePSIUPDATE_ONESHOT; // only one instance is enough. if (tsport->mgtPsiCtl) StopMonitorMgt(tsport); dprint(3, "monitor mgt..\n"); err = MonitorMgt( tsport->tsd, // tDHL_TSD *tsd, updateMode, // tDHL_PSI_Update updateMode, _PsiTableEventProc, // tDHL_PSI_EventProc eventProc, (UINT32)tsport, // UINT32 userParam, &tsport->mgtPsiCtl // tDHL_PSI_ControlHandle *returnPSICtl ); if (err) { dprint(0, "!! monitor mgt err %d\n", err); status = statusError; } else { tsport->n_active_monitors++; } return status; } STATUS StartMonitorTvct(S_PSIM_PORT *tsport) { DHL_RESULT err; STATUS status = statusOK; tDHL_PSI_Update updateMode = ePSIUPDATE_VERCHANGE; if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) updateMode = ePSIUPDATE_ONESHOT; // only one instance is enough. if (tsport->tvctPsiCtl) StopMonitorTvct(tsport); dprint(3, "monitor tvct..\n"); err = MonitorTvct( tsport->tsd, // tDHL_TSD *tsd, ePSIMODE_TABLE, // tDHL_PSI_Mode psiMode, updateMode, // tDHL_PSI_Update updateMode, _PsiTableEventProc, // tDHL_PSI_EventProc eventProc, (UINT32)tsport, // UINT32 userParam, &tsport->tvctPsiCtl // tDHL_PSI_ControlHandle *returnPSICtl ); if (err) { dprint(0, "!! monitor tvct err %d\n", err); status = statusError; } else { tsport->n_active_monitors++; } return status; } STATUS StartMonitorCvct(S_PSIM_PORT *tsport) { DHL_RESULT err; STATUS status = statusOK; tDHL_PSI_Update updateMode = ePSIUPDATE_VERCHANGE; if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) updateMode = ePSIUPDATE_ONESHOT; // only one instance is enough. if (tsport->cvctPsiCtl) StopMonitorCvct(tsport); dprint(3, "monitor cvct..\n"); err = MonitorCvct( tsport->tsd, // tDHL_TSD *tsd, ePSIMODE_TABLE, // tDHL_PSI_Mode psiMode, updateMode, // tDHL_PSI_Update updateMode, _PsiTableEventProc, // tDHL_PSI_EventProc eventProc, (UINT32)tsport, // UINT32 userParam, &tsport->cvctPsiCtl // tDHL_PSI_ControlHandle *returnPSICtl ); if (err) { dprint(0, "!! monitor cvct err %d\n", err); status = statusError; } else { tsport->n_active_monitors++; } return status; } STATUS StartMonitorStt(S_PSIM_PORT *tsport) { DHL_RESULT err; STATUS status = statusOK; tDHL_PSI_Update updateMode = ePSIUPDATE_CONTINEOUS; if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) updateMode = ePSIUPDATE_ONESHOT; // only one instance is enough. if (tsport->sttPsiCtl) StopMonitorStt(tsport); dprint(3, "monitor stt..\n"); err = MonitorStt( tsport->tsd, // tDHL_TSD *tsd, updateMode, // tDHL_PSI_Update updateMode, _PsiTableEventProc, // tDHL_PSI_EventProc eventProc, (UINT32)tsport, // UINT32 userParam, &tsport->sttPsiCtl // tDHL_PSI_ControlHandle *returnPSICtl ); if (err) { dprint(0, "!! monitor stt err %d\n", err); status = statusError; } else { tsport->n_active_monitors++; } return status; } STATUS StartMonitorRrt(S_PSIM_PORT *tsport) { DHL_RESULT err; STATUS status = statusOK; tDHL_PSI_Update updateMode = ePSIUPDATE_CONTINEOUS; if (tsport->rrtPsiCtl) StopMonitorRrt(tsport); dprint(3, "monitor rrt..\n"); err = MonitorRrt( tsport->tsd, // tDHL_TSD *tsd, 0, // UINT8 region, // it is not used updateMode, // tDHL_PSI_Update updateMode, _PsiTableEventProc, // tDHL_PSI_EventProc eventProc, (UINT32)tsport, // UINT32 userParam, &tsport->rrtPsiCtl // tDHL_PSI_ControlHandle *returnPSICtl ); if (err) { dprint(0, "!! monitor rrt err %d\n", err); status = statusError; } else { tsport->n_active_monitors++; } return status; } /* eit monitor¸¦ ½ÃÀÛÇÑ´Ù. */ STATUS StartMonitorEits(S_PSIM_PORT *tsport) { int iEit, source_id; DHL_RESULT err; STATUS status = statusOK; tDHL_PSI_Update updateMode; int maxIndex; S_PSIM_SUBCHINFO *subchInfo = NULL; S_PSIM_MGT_DIGEST *smgt; if (tsport->n_active_monitors >= tsport->max_monitors) { dprint(0, "!! cur monitor %d exceed limit %d\n", tsport->n_active_monitors, tsport->max_monitors); return statusOutOfResource; } if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) { subchInfo = NULL; // ƯÁ¤ subch ¿¡ ´ëÇØ µ¿ÀÛÇÏ´Â °ÍÀÌ ¾Æ´Ï´Ù. } else { subchInfo = PSIDB_GetPsiSubChInfo(tsport->input.rf, tsport->source_id); if (!subchInfo) { dprint(0, "!! rf %d, sid %d not ready for eit scan..\n", tsport->input.rf, tsport->source_id); return statusInvalidState; } } smgt = PSIDB_GetMgtDigest(tsport->input.rf); if (!smgt) { dprint(0, "!! rf %d has no smgt\n", tsport->input.rf); return statusInvalidState; } // ¾î¶² subchannel eit¸¦ ½ÃÀÛÇÒ °ÍÀÎÁö, ¾î¶² update mode·Î ÁøÇàÇÒ °ÍÀÎÁö °áÁ¤ÇÑ´Ù. // filter-eit °¡ 1:1 À̶ó¸é oneShotÀÌ Àû´çÇϰí, // ÇϳªÀÇ filter·Î ´Ù¼öÀÇ eit¸¦ ¹ÞÀ»·Á°í ÇÑ´Ù¸é Continueous·Î ÁøÇà. if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) { updateMode = ePSIUPDATE_CONTINEOUS; source_id = 0; // this means that all source_id table should be received.. maxIndex = 0; // eit-0 ¸¸ ¹Þ´Â´Ù. dprint(2, "start eit with autoscan mode..\n"); } else { // todo.. ±âÁ¸ ÄÚµå´Â version change. ¹¹°¡ ³ªÀº°¡?? updateMode = ePSIUPDATE_ONESHOT; //updateMode = ePSIUPDATE_VERCHANGE; source_id = tsport->source_id; maxIndex = min(127, gPsiMaxEitEttIndexToReceive); dprint(2, "start eits, normal mode, sid %d, [0~%d]\n", source_id, maxIndex); } //------------------------------------- // start/restart eit scan for (iEit=0; iEit<=maxIndex; iEit++) { if (tsport->eitPsiCtl[iEit]) continue; // it is already started. // normal mode ¿¡¼­´Â ÀÌ¹Ì ÇØ´ç eit°¡ ¼ö½ÅµÇ¾ú´ÂÁöµµ üũÇÒ ¼ö ÀÖ´Ù. if (subchInfo && subchInfo->eits[iEit]) continue; if (smgt->eit_pids[iEit] == 0) // eit[i] does not exist. continue; dprint(3, "monitor eit[%d] (pid %x, source_id %d), cur monitor %d\n", iEit, smgt->eit_pids[iEit], source_id, tsport->n_active_monitors); err = MonitorEit( tsport->tsd, // tDHL_TSD tsd, smgt->eit_pids[iEit], // UINT16 PID, source_id, // UINT16 source_id, ePSIMODE_TABLE, // tDHL_PSI_Mode psiMode, updateMode, // tDHL_PSI_Update updateMode, _PsiTableEventProc, // tDHL_PSI_EventProc eventProc, (UINT32)tsport, // UINT32 userParam, &tsport->eitPsiCtl[iEit] // tDHL_PSI_ControlHandle *returnPSICtl ); if (err) { dprint(0, "!! monitor eit[%d] err %d\n", iEit, err); status = statusError; goto label_end; } else { tsport->n_active_monitors++; } if (tsport->n_active_monitors >= tsport->max_monitors) { dprint(2, "!!!! total monitor reached limit %d\n", tsport->n_active_monitors); status = statusOK; goto label_end; } } label_end: return status; } /* ett ¸ð´ÏÅ͸¦ ½ÃÀÛÇÑ´Ù. tsport->source_id ¿¡¼­ ÁöÁ¤µÈ ¼­ºêä³ÎÀÇ ett¸¸À» scanÇÑ´Ù. subch ptr, smgt µîÀº ÀÌ¹Ì Áغñ µÇ¾î ÀÖ¾î¾ß ÇÑ´Ù. autoscan ¸ðµåÀÎ °æ¿ì¿¡´Â »ç¿ëµÇÁö ¾Ê´Â´Ù. channel-ett ¸¦ ¸ÕÀú monitor Çϰí, ±× ´ÙÀ½ ÀÏ¹Ý ett monitor ÇÑ´Ù. ÀÌ¹Ì ¹Þ¾ÆÁ® ÀÖ´Â °æ¿ì, ÀÌ¹Ì start µÈ °æ¿ì µîÀº skip ÇϹǷÎ, ett completed ¾Æ´Ñ °æ¿ì¶ó¸é ¾ðÁ¦µçÁö ¿©·¯¹ø È£ÃâÇØµµ »ó°ü ¾ø´Ù. */ STATUS StartMonitorEtts(S_PSIM_PORT *tsport) { int k, t, iEtt, iEvent; // loop variables int n_etm; UINT32 etmid; DHL_RESULT err; STATUS status = statusOK; tDHL_PSI_Update updateMode; int maxIndex; S_PSIM_SUBCHINFO *subchInfo; S_PSIM_MGT_DIGEST *smgt; if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) { dprint(0, "!! ett tried in autoscan mode\n"); return statusOK; } if (tsport->n_active_monitors >= tsport->max_monitors) { dprint(0, "!! cur monitor %d exceed limit %d\n", tsport->n_active_monitors, tsport->max_monitors); return statusOutOfResource; } subchInfo = PSIDB_GetPsiSubChInfo(tsport->input.rf, tsport->source_id); if (!subchInfo) { dprint(0, "!! rf %d, sid %d not ready for ett scan..\n", tsport->input.rf, tsport->source_id); return statusInvalidState; } smgt = PSIDB_GetMgtDigest(tsport->input.rf); if (!smgt) { dprint(0, "!! rf %d has no smgt\n", tsport->input.rf); return statusInvalidState; } // ¾î¶² subchannel eit¸¦ ½ÃÀÛÇÒ °ÍÀÎÁö, ¾î¶² update mode·Î ÁøÇàÇÒ °ÍÀÎÁö °áÁ¤ÇÑ´Ù. updateMode = ePSIUPDATE_CONTINEOUS; maxIndex = min(127, gPsiMaxEitEttIndexToReceive); dprint(2, "start ett monitoring, sid %d, [0~%d]\n", tsport->source_id, maxIndex); //------------------------------------- // start/restart ett scan // ****** channel-ett ********** do { if (tsport->ettvPsiCtl) continue; // already started. if (subchInfo->channel_ett) continue; // already received. if (!PSIDB_IsSubChEttVRequired(tsport->input.rf, tsport->source_id)) continue; // no ettv exist dprint(3, "monitor ett-v (pid %x, source_id %d), cur monitor %d\n", smgt->channel_ett_pid, tsport->source_id, tsport->n_active_monitors); etmid = PSIUTIL_MakeChannelETMID(subchInfo->source_id) | 0xffff; etmid = 0; // we use all pass mode. just ett_pid is the only key. err = MonitorEtt( tsport->tsd, // tDHL_TSD *tsd, smgt->channel_ett_pid, // UINT16 PID, etmid, // UINT32 etm_id, updateMode, // tDHL_PSI_Update updateMode, _PsiTableEventProc, // tDHL_PSI_EventProc eventProc, (UINT32)tsport, // UINT32 userParam, &tsport->ettvPsiCtl // tDHL_PSI_ControlHandle *returnPSICtl ); if (err) { dprint(0, "!! monitor ett-v err %d\n", err); status = statusError; goto label_end; } else { tsport->n_active_monitors++; } if (tsport->n_active_monitors >= tsport->max_monitors) { dprint(2, "!!!! total monitor reached limit %d\n", tsport->n_active_monitors); status = statusOK; goto label_end; } } while (0); // ****** normal etts ********** for (iEtt=0; iEtt<=maxIndex; iEtt++) { if (tsport->ettPsiCtl[iEtt]) continue; // already started. // eit°¡ ¾ø´Ù¸é ett ¼ö½ÅÀº ºÒ°¡´ÉÇÔ.. if (!subchInfo->eits[iEtt] || !subchInfo->eits[iEtt]->event) continue; // eit is not received. ett monitor impossible. if (smgt->ett_pids[iEtt] == 0) // MGT¿¡ ÀÌ ETT-i Á¤º¸°¡ ¾øÀ¸¸é °Ç³Ê¶Ú´Ù. continue; // ------ °ü·ÃµÈ Eit ºÐ¼®.. // ÀÌ EITÀÇ eventµé Áß¿¡¼­ ¸î°³°¡ ETMÀ» °¡Áö°í ÀÖ´ÂÁö ¼ÀÇÑ´Ù. // for (iEvent=0, n_etm=0; iEventeits[iEtt]->numEvents; iEvent++) { if (gPsiIgnoreEtmLocationInfo || // ignore ¿É¼ÇÀÌ¸é ¹«Á¶°Ç ¹Þ´Â´Ù. subchInfo->eits[iEtt]->event[iEvent].ETM_location != ETM_none) n_etm++; // ÀÌ EIT¿¡ °ü·ÃµÈ ETT °¹¼ö.. } if (n_etm == 0) { // ÀÌ EITÀÇ À̺¥Æ®µé¿¡´Â ETT°¡ Çϳªµµ ¾ø´Ù°í ÇÑ´Ù. ´Ù¿î·Îµå ¹ÞÀ» Çʿ䰡 ¾ø´Ù. dprint(3, " no etts of this eit / total %d events\n", subchInfo->eits[iEtt]->numEvents); continue; // go to next EIT.. // ´ÙÀ½ ´Ü°è·Î °¡±â Àü¿¡ ÇöÀç ettµéÀÇ ÀÚ°Ý °Ë»çµµ ÇØ¾ß ÇÏÁö ¾Ê³ª???? } else { dprint(3, " %d etm's are expected in this eit / total %d events\n", n_etm, subchInfo->eits[iEtt]->numEvents); } // ÀÌ EIT¿¡ ÃÑ n_etm(>0)°³ÀÇ ETT°¡ °É·Á ÀÖÀ» °ÍÀ¸·Î ÃßÁ¤µÈ´Ù.. // ------ Ett¿ë ¸Þ¸ð¸® ÇÒ´ç.. // ett¿ë ¸Þ¸ð¸®°¡ ¾øÀ¸¸é »õ·Î ÇÒ´çÇÑ´Ù.. Æ÷ÀÎÅͰ¡ ÀÖ´õ¶óµµ Å©±â°¡ º¯°æµÇ¾ú´ÂÁö üũ. // eit event ³»¿¡ ett¸¦ ÀúÀåÇÏ´Â ¹æ¹ýÀº ¾î¶²°¡?? if (subchInfo->n_ett[iEtt] != subchInfo->eits[iEtt]->numEvents) { // internal error!! dprint(0, "!! eit[%d] num event %d != n_ett %d\n", iEtt, subchInfo->eits[iEtt]->numEvents, subchInfo->n_ett[iEtt]); PSIDB_FreeEtts(subchInfo, iEtt); } if (subchInfo->etts[iEtt] == NULL) { int n_event = subchInfo->eits[iEtt]->numEvents; PSIDB_LockDB(TRUE); //--------------- subchInfo->etts[iEtt] = DHL_OS_Malloc(n_event * sizeof(ettSectionPtr_t)); if (subchInfo->etts[iEtt]) { dprint(3, " ++ alloc etts memory %x (max %d)\n", subchInfo->etts[iEtt], n_event); subchInfo->n_ett[iEtt] = n_event; // ÀÌ Eit¿¡ ¿¬°áµÈ ETT-i ÀÇ °¹¼ö.. } else { dprint(0, "!! out of memory for %d ett ptr\n", n_event); subchInfo->n_ett[iEtt] = 0; } PSIDB_LockDB(FALSE); //---------------- if (!subchInfo->etts[iEtt]) break; // ¸Þ¸ð¸® ºÎÁ·? ´õ ÀÌ»ó ÁøÇàÇÒ Çʿ䰡 ¾ø´Ù. } else dprint(3, " ** reuse etts memory %x (max %d:%d)\n", subchInfo->etts[iEtt], subchInfo->eits[iEtt]->numEvents, subchInfo->n_ett[iEtt]); for (iEvent=0; iEventeits[iEtt]->numEvents; iEvent++) // ÀÌ EIT³»ÀÇ ¸ðµç À̺¥Æ®¿¡ ´ëÇØ¼­ ETT¸¦ ¼ö½ÅÇÑ´Ù.. { BOOL bSkipThisEtt; // MGT¿¡ ETMÀÌ ¾ø´Ù°í µÇ¾î ÀÖÀ¸¸é ¹ÞÀ¸¸é ¾ÈµÈ´Ù. if (gPsiIgnoreEtmLocationInfo == FALSE && subchInfo->eits[iEtt]->event[iEvent].ETM_location == ETM_none) { //dprint(3, " [%d] no ETM\n", iEvent); continue; } etmid = PSIUTIL_MakeEventETMID(subchInfo->source_id, subchInfo->eits[iEtt]->event[iEvent].event_id); // ÀÌ¹Ì ÀÌ event¿¡ ÇØ´çÇÏ´Â ETT¸¦ ¹Þ¾Ò´Ù¸é ¹ÞÀ» Çʿ䰡 ¾ø´Ù.. ETM_id¸¦ ÀÌ¿ëÇÏ¿© ±× ¿©ºÎ¸¦ È®ÀÎÇÑ´Ù. // ±×·±µ¥ event[i] ¿¡ ÇØ´çÇÏ´Â ett°¡ ÀÖ´ÂÁö ¾ø´ÂÁö ã±â°¡ Á» º¹ÀâÇÏ´Ù.. // ²À ÀÌ Eit PID¿¡¸¸ ¾Æ´Ï¶ó ±× ÀÌÀü EitµéÀÇ PID¿¡µµ Á¸ÀçÇÒ °æ¿ì°¡ Àֱ⠶§¹®.. // 3-hour °æ°è¿¡ °ÉÃÄ ÀÖ´Â eventÀÇ °æ¿ì ¾ÕÂÊ eventÀÇ PID¿¡ ett°¡ ÀÖÀ» ¼ö ÀÖ´Ù. // bSkipThisEtt = FALSE; if (subchInfo->etts[iEtt] && subchInfo->n_ett[iEtt] && subchInfo->etts[iEtt][iEvent] && subchInfo->etts[iEtt][iEvent]->ETM_id == etmid) { // ÀÌ Ett°¡ ÀÌ¹Ì ¼ö½ÅµÇ¾î ÀÖ´Ù¸é, ¹ÞÀ» ÇÊ¿ä ¾ø´Ù. dprint(3, " [%d] already exist (etmid 0x%x pid %d)\n", iEvent, etmid, smgt->ett_pids[iEtt]); bSkipThisEtt = TRUE; } for (k=iEtt; !bSkipThisEtt && k>=0; k--) { // ÇöÀç Etts[iEtt]ºÎÅÍ Etts[0] ±îÁö ¾ÕÀ¸·Î µÇµ¹¾Æ°¡¸é¼­, if (subchInfo->etts[k] == NULL) continue; // °¢ Ett sectionÀ» °Ë»çÇØ¼­ ÇöÀç ¹ÞÀ¸·Á°í ÇÏ´Â etmidÀÇ ett°¡ ¹Þ¾ÆÁ® ÀÖ´ÂÁö °Ë»çÇÑ´Ù. for (t=0; tn_ett[k]; t++) { if (subchInfo->etts[k][t] && subchInfo->etts[k][t]->ETM_id == etmid) { // °°Àº etmid¸¦ °¡Áø Ett°¡ ÀÌ¹Ì ¼ö½ÅµÇ¾î ÀÖ´Ù¸é, ¹ÞÀ» ÇÊ¿ä ¾ø´Ù. dprint(2, " [%d] same etmid 0x%x (ett[%d][%d] pid %d) exist\n", iEvent, etmid, k, t, smgt->ett_pids[k]); bSkipThisEtt = TRUE; break; } } if (bSkipThisEtt) break; } if (bSkipThisEtt) continue; dprint(3, " [%d] ett pid 0x%x, etmid 0x%x\n", iEvent, smgt->ett_pids[iEtt], etmid); #if 0 // °³°³ÀÇ ett¸¦ ¼ö½ÅÇÏ´Â ¸ðµå.. // ´Ü ÀÌ·¸°Ô ÇÏ·Á¸é ettPsiCtl ÀúÀå °ø°£µµ ÇÊ¿äÇÑ ¸¸Å­ ÇÒ´ç ¹Þ¾Æ¾ß ÇÑ´Ù. dprint(3, "monitor ett[%d] (pid %x, source_id %d, etmid 0x%x), cur monitor %d\n", iEtt, smgt->ett_pids[iEtt], source_id, etmid, tsport->n_active_monitors); err = MonitorEtt(tsport->tsd, smgt->ett_pids[iEtt], etmid, updateMode, _PsiTableEventProc, // tDHL_PSI_EventProc eventProc, (UINT32)tsport, // UINT32 userParam, &tsport->ettPsiCtl[iEtt][iEvent] // tDHL_PSI_ControlHandle *returnPSICtl ); #endif } dprint(3, "monitor ett[%d] (pid %x, source_id %d), cur monitor %d\n", iEtt, smgt->ett_pids[iEtt], tsport->source_id, tsport->n_active_monitors); etmid = PSIUTIL_MakeChannelETMID(subchInfo->source_id) | 0xffff; etmid = 0; // we use all pass mode. just ett_pid is the only key. err = MonitorEtt( tsport->tsd, // tDHL_TSD *tsd, smgt->ett_pids[iEtt], // UINT16 PID, etmid, // UINT32 etm_id, updateMode, // tDHL_PSI_Update updateMode, _PsiTableEventProc, // tDHL_PSI_EventProc eventProc, (UINT32)tsport, // UINT32 userParam, &tsport->ettPsiCtl[iEtt] // tDHL_PSI_ControlHandle *returnPSICtl ); if (err) { dprint(0, "!! monitor ett[%d] err %d\n", iEtt, err); status = statusError; goto label_end; } else { tsport->n_active_monitors++; } if (tsport->n_active_monitors >= tsport->max_monitors) { dprint(2, "!!!! total monitor reached limit %d\n", tsport->n_active_monitors); status = statusOK; goto label_end; } } label_end: return status; } #if COMMENT ____Subchannel____(){} #endif /* SubChannel scan ½ÃÀÛ. TV ½Ãû ¸ðµå, ·¹ÄÚµù ¸ðµå, Autoscan ¸ðµå ´Ù ÇØ´çµÊ. ¾î¶² subchannelÀ» ½ÃÀÛÇÒ °ÍÀÎÁö´Â µ¿ÀÛ ¸ðµå¿Í @tsport->source_id ¿¡ µû¸¥´Ù. */ STATUS StartSubChannelScan(S_PSIM_PORT *tsport) { STATUS status = statusOK; int i; if (tsport->n_active_monitors >= tsport->max_monitors) { dprint(0, "!! cur monitor %d exceed limit %d\n", tsport->n_active_monitors, tsport->max_monitors); return statusOutOfResource; } if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) { // autoscan Àü¿ë eit complete check ÇÔ¼ö°¡ ¾øÀ¸´Ï, // Á÷Á¢ db search ÇÏ¿© ÆÇ´ÜÇϵµ·Ï ÇÏÀÚ. S_PSIM_CHINFO *chInfo; BOOL bEitsCompleted = TRUE; chInfo = PSIDB_GetPsiChInfo(tsport->input.rf); if (!chInfo) { dprint(0, "!! rf %d not ready for subch scan..\n", tsport->input.rf); goto label_end; } // ¸ðµç eit-0 °¡ ´Ù ¼ö½Å µÈ °ÍÀÎÁö üũ. Çϳª¶óµµ ºüÁ® ÀÖ´Ù¸é restart.. for (i=0; in_subchannel; i++) { if (chInfo->subchannel[i].eits[0] == NULL) { bEitsCompleted = FALSE; break; } } if (!bEitsCompleted) StartMonitorEits(tsport); else dprint(2, "ch %d eits already completed (autoscan mode)\n", tsport->input.rf); } else { // ÀÏ´Ü eit -> ett ¼ø¼­´ë·Î ÁøÇàÇÏÀÚ. if (!PSIDB_IsSubChEitsCompleted(tsport->input.rf, tsport->source_id)) StartMonitorEits(tsport); else if (!PSIDB_IsSubChAllEttsCompleted(tsport->input.rf, tsport->source_id)) StartMonitorEtts(tsport); else dprint(2, "subch (rf %d, sid %d) already completed\n", tsport->input.rf, tsport->source_id); } label_end: return status; } #if COMMENT ____EventMonitor____(){} #endif #define IS_VALID_SOURCE_ID(sid) ((sid)>=0 && (UINT32)(sid)<=0xFFFF) #define EVENT_ID_INIT -2 // last event id °ªÀÇ ÃʱⰪ. #define EVENT_ID_EMPTY -1 // ÇöÀç ½Ã°£¿¡ ÇØ´çÇÏ´Â event °¡ ¾ø´Â °æ¿ìÀÇ id. #define IS_VALID_EVENT_ID(evid) ((evid)>=0) //----------------------------------- // CheckIfProgramEventChanged // // ÇöÀçÀÇ STT¸¦ ÃßÁ¤Çϰí, // // ÀÌ Ã¤³ÎÀÇ ÀúÀåµÇ¾îÁø ¸¶Áö¸· descriptor Á¤º¸·ÎºÎÅÍ // descriptor ³»¿ëÀÌ º¯°æµÈ »çÇ×ÀÌ ÀÖ´ÂÁö °Ë»çÇÑ´Ù. // // PSI_STATIC void CheckIfProgramEventChanged(S_PSIM_PORT *tsport) { int channel_id = tsport->input.rf; int source_id = tsport->input.source_id; S_PSIM_CHINFO *chInfo; S_PSIM_SUBCHINFO *subchInfo; int i; int iEit, iEvent; int stt_offset; UINT32 system_time; eitPtr_t eit; eitEventPtr_t event; if (!PSITASK_IsPsiTask()) { dprint(0, "!! %s: called in wrong task\n", __FUNCTION__); return; } // psi task¿¡¼­ Àб⠿뵵·Î¸¸ »ç¿ëÇÒ °æ¿ì lock Àº ÇÊ¿ä ¾ø´Ù. //Dmc_EpgLockCoreDB(TRUE); chInfo = PSIDB_GetPsiChInfo(channel_id); if (chInfo == NULL) { dprint(0, "!! stt from non-exist channel %d\n", channel_id); goto label_exit; } if (chInfo->stt_valid == 0) { if (g_Trace_bPsiSttInfo) dprint(1, "[STT] stt not available yet\n"); goto label_exit; } // ÇöÀçÀÇ program event¸¦ ã¾Æ³»´Âµ¥ »ç¿ëµÉ ±âÁØ GPS ½Ã°£.. // // STT¸¦ ¼ö½ÅÇÑÁö ¿À·¡ µÈ °æ¿ì¶ó¸é º¸Á¤ °ªÀÌ ÇÊ¿äÇÒ ¼öµµ ÀÖ´Ù. // stt_offset = (DHL_OS_GetMsCount() - chInfo->tick_stt_get) / 1000; system_time = chInfo->flat_stt.system_time + stt_offset; if (g_Trace_bPsiSttInfo) if (stt_offset) dprint(1, "[STT] stt offset %d applied\n", stt_offset); //---------------------- // now, use stt data... search subch info subchInfo = NULL; // cafrii 070801 delete check, source_id °¡ 0ÀÎ ½ºÆ®¸²µéÀÌ ÀÖÀ½. //if (source_id) { if (g_Trace_bPsiSttInfo) dprint(3, "[STT] source id %d, n_subch %d, subch 0x%x\n", source_id, chInfo->n_subchannel, chInfo->subchannel); for (i=0; in_subchannel; i++) { if (chInfo->subchannel[i].source_id == source_id) { subchInfo = &chInfo->subchannel[i]; break; } } } if (!subchInfo) { if (g_Trace_bPsiSttInfo) dprint(3, "[STT] !! subchInfo source_id %d not found..\n", source_id); goto label_exit; } // Spec ´ë·Î¶ó¸é ¹Ýµå½Ã Eit-0 ¿¡ ÀÖ¾î¾ß ÇÒ °ÍÀÌÁö¸¸, Local timeÀ¸·Î 3-hour // boundary¿¡ Á¤È®ÇÏ°Ô Eit change°¡ ¹ß»ýÇÏÁö ¾Ê´Â´Ù¸é ¾à°£ÀÇ ¿ÀÂ÷°¡ ÀÖÀ» ¼öµµ ÀÖ´Ù. // µû¶ó¼­ Eit-0 °ú Eit-1 µÎ°³¸¦ Á¶»çÇÑ´Ù. // for (iEit=0; iEit<=1; iEit++) { eit = subchInfo->eits[iEit]; if (eit == NULL) continue; if (eit->source_id != source_id) { dprint(0, "[STT] !! eit[%d] source id %d mismatch to subch source id %d\n", iEit, eit->source_id, source_id); continue; } if (eit->event == NULL || eit->numEvents <= 0) continue; for (iEvent=0; iEventnumEvents; iEvent++) { // eitEvent_t event = &eit->event[iEvent]; // system_time ÀÌ ÀÌ eventÀÇ ±¸°£ ³»¿¡ µé¾î ÀÖ´ÂÁö È®ÀÎ.. // if (system_time < event->start_time || system_time > event->start_time + event->length_in_seconds-1) continue; // now, this event is current!!! if (g_Trace_bPsiSttInfo) dprint(3, "[STT] event found: evid 0x%x, %d min %d sec long\n", event->event_id, event->length_in_seconds/60, event->length_in_seconds%60); // // °¡Àå ¸¶Áö¸·À¸·Î ±â¾ïÇϰí ÀÖ¾ú´ø event id ¶û ´Þ¶óÁö¸é // program ÀÌ º¯°æµÈ °ÍÀ¸·Î ÆÇ´ÜÇÑ´Ù. // if (event->event_id != tsport->last_event_id) { goto label_notify; } // todo.. // event id °¡ °°´õ¶óµµ ½ÇÁ¦ ³»¿ëÀÌ ¿ÏÀüÈ÷ µ¿ÀÏÇÑÁö Ã¼Å©ÇØº¸ÀÚ. // ±×·²·Á¸é last event »çº»À» Åë°·Î º¸ÀüÇØ¾ß ÇÑ´Ù. // // ÀÏ´Ü Áö±ÝÀº ±âÁ¸ event¿Í µ¿ÀÏÇϹǷΠó¸®ÇÏÁö ¾Ê°í ¹«½ÃÇÑ´Ù. goto label_exit; } // for iEvent } // for iEit // ¾Æ¹« event µµ ¹ß°ßÀÌ ¾ÈµÈ °æ¿ì.. dprint(2, "[STT] no event found. last evid 0x%x\n", tsport->last_event_id); if (tsport->last_event_id != EVENT_ID_EMPTY) { // °¡Àå ¸¶Áö¸· eventÀÇ °æ¿ì valid ÇÑ °ÍÀ̾ú´Âµ¥, // ÀÌÁ¦ valid ÇÑ event°¡ »ç¶óÁ³À¸´Ï ¿ª½Ã notify ÇØ Áà¾ß ÇÑ´Ù. // No Rating Á¤º¸ µîÀ» ó¸®Çϱâ À§ÇØ. event = NULL; goto label_notify; } goto label_exit; label_notify: if (1) { S_PSIM_PROGRAM_CHANGED_CB_PARAM param; int new_event_id = event ? event->event_id : EVENT_ID_EMPTY; dprint(1, "******** program event changed 0x%x -> 0x%x\n", tsport->last_event_id, new_event_id); tsport->last_event_id = new_event_id; // // º¯°æµÈ »õ event Á¤º¸ÀÇ °ÅÀÇ ´ëºÎºÐÀ» callbackÀ¸·Î ¾Ë·ÁÁØ´Ù. // memset(¶m, 0, sizeof(param)); param.channel_id = channel_id; param.source_id = source_id; param.eit_index = event ? iEit : -1; // eit-0 ¿¡¼­ ¿Ô´ÂÁö, eit-1 ¿¡¼­ ¹ß°ßµÇ¾ú´ÂÁö.. param.event_id = new_event_id; param.system_time = system_time; if (event) { param.start_time = event->start_time; param.length_in_seconds = event->length_in_seconds; param.descriptor_length = event->descriptor_length; // ÇÊ¿äÇϸé client°¡ ¾Ë¾Æ¼­ º¹Á¦¸¦ ÇÏ¸é µÈ´Ù. // ±×³É ¿øº» Æ÷ÀÎÅ͸¦ ³Ñ°ÜÁÖÀÚ. param.descriptors = event->descriptors; } //Dmc_EpgSendUserEvent2(epgEventNotifyProgramChange, // (UINT32) new_event_id, (UINT32) ¶m); SendUserCallback(tsport, ePSIM_EVENT_ProgramChanged, (UINT32)¶m); } label_exit: //Dmc_EpgLockCoreDB(FALSE); ; } #if COMMENT ____Private____(){} #endif /* ¼ö½ÅµÈ PAT¸¦ ó¸®ÇÑ´Ù. */ PSI_STATIC STATUS ProcessPAT(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc) { int i; DHL_RESULT err; STATUS status = statusOK; MPEG_PAT *pat, *prev_pat; dprint(4, "%s:\n", __FUNCTION__); err = ParsePAT(desc, &pat); // desc will be freed at caller. if (IsError(err)) { dprint(0, "%s: ParsePAT returned %s\n", __FUNCTION__, ErrorString(err)); return statusInvalidPSI; } // PAT sanity check if (!pat || pat->numPrograms == 0 || !pat->programs) { dprint(0, "!! wrong pat\n"); PSIUTIL_FreeTable(&pat); return statusInvalidPSI; } if (tsport->patPsiCtl != desc->handle) { dprint(0, "!! inconsistent! patPsiCtl %x != desc psictl %x\n", tsport->patPsiCtl, desc->handle); status = statusInvalidState; goto label_end; } //-------------------------------------------------------------------- // now, table becoms vailid. if not updated to DB, free it carefully. if (dprintable(3)) PrintPAT(pat); // ±âÁ¸ pat¿Í ºñ±³ÇÏ¿© º¯°æ »çÇ×ÀÌ ¾øÀ¸¸é skip. --> no!! // // º¯°æ »çÇ×ÀÌ ÀÖ´õ¶óµµ pmt_pid, program_number ¿¡ º¯°æ »çÇ×ÀÌ ¾øÀ¸¸é¼­ pmt°¡ ½ÃÀÛ ÁßÀ̸é // ÇØ´ç pmt monitor´Â ±×´ë·Î À¯Áö. // --> pmt monitor¸¦ restart ÇØµµ º° ¹®Á¦ ¾ÈµÇ¹Ç·Î Ç×»ó restartÇϵµ·Ï ÇÏÀÚ. prev_pat = PSIDB_GetPAT(tsport->input.rf); // something is changed in pat. // reset the pmt monitor that is changed (either pid or program_number) // pmtPsiCtl array Å©±â(numPrograms)°¡ º¯°æ µÇ¾ú´ÂÁö üũ, Àû¿ë. // ÁÖÀÇ: // prev_pat->numPrograms ¿Í ºñ±³ÇÏÁö ¾Ê°í, tsport->num_programs ¿Í ºñ±³ÇÔ. // ¿Ö³Ä¸é ¿¹¿Ü »óȲ µîÀ¸·Î ÀÎÇÏ¿© tsport->num_programs´Â 0 ÀÏ ¼ö ÀÖÀ½. // if (prev_pat == NULL || pat->numPrograms != tsport->num_programs) { if (!prev_pat) { dprint(3, "new pat, %d program\n", pat->numPrograms); } else { dprint(3, "tsport num programs changed, %d -> %d\n", tsport->num_programs, pat->numPrograms); } // ±âÁ¸ µ¿ÀÛ ÁßÀÎ pmt monitor¸¦ ¸ðµÎ Á¤Áö. StopMonitorPMTs(tsport); dprint(3, "alloc %d pmt ctl arrays..\n", pat->numPrograms); tsport->pmtPsiCtlArray = DHL_OS_Malloc(pat->numPrograms * sizeof(tDHL_PSI_ControlHandle)); if (!tsport->pmtPsiCtlArray) { // pat ¿Í pmt monitor °£ÀÇ °ü°è°¡ ¾î±ß³µÀ¸¹Ç·Î ¹®Á¦°¡ ¹ß»ýÇÒ ¼ö ÀÖÀ½!! tsport->num_programs = 0; // <- ¹Ýµå½Ã ÇÊ¿ä. // ÀÌ¿ÕÀ̸é pat ±îÁö ´Ù »èÁ¦Çϸé Àϰü¼ºÀÌ Àִµ¥, DBÀÇ pat¸¸ »èÁ¦ÇÒ ¹æ¹ýÀº ¾øÀ½. status = statusOutOfMemory; goto label_end; } tsport->num_programs = pat->numPrograms; } else // program °¹¼ö º¯°æÀÌ ¾ø´Â °æ¿ì. { // ASSERT (prev_pat->numPrograms == tsport->num_programs); // pmt psictlÀÇ pid, pnÀÌ pat ¿Í ÀÏÄ¡ÇÏ´ÂÁö üũ. // ÀÏÄ¡ÇÏÁö ¾ÊÀº monitor´Â cancel. for (i=0; inumPrograms; i++) { if (tsport->pmtPsiCtlArray[i] == (tDHL_PSI_ControlHandle)0) continue; if (prev_pat->programs[i].program_map_PID != pat->programs[i].program_map_PID || prev_pat->programs[i].program_number != pat->programs[i].program_number) { dprint(3, "pid/pn diff! cancel pmt[%d] monitor..\n", i); DHL_PSI_StopMonitor(tsport->pmtPsiCtlArray[i]); tsport->n_active_monitors--; tsport->pmtPsiCtlArray[i] = (tDHL_PSI_ControlHandle)0; } } } // pat°¡ ±âÁ¸ pat¿Í ´Ù¸¥ °æ¿ì¿¡¸¸ update Çϰí notify ÇÑ´Ù. if (!PSIUTIL_IsEquivalentPat(prev_pat, pat)) { // PAT¸¦ DB¿¡ update ÇÑ´Ù. status = PSIDB_UpdatePAT(tsport->input.rf, pat); if (status) { // ¹«½¼ ÀÌÀ¯¿¡¼­ÀÎÁö pat update ½ÇÆÐ. (´ëºÎºÐ ¸Þ¸ð¸® ¿¡·¯) StopMonitorPMTs(tsport); goto label_end; } SendUserCallback(tsport, ePSIM_EVENT_PatReceived, (UINT32)pat); } // PMT¸¦ monitor ½ÃÀÛÇÑ´Ù. // input flag¿¡ µû¶ó µ¿ÀÛÀÌ ´Þ¶óÁü. if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) { StopMonitorPAT(tsport); if (PSIDB_IsPmtsCompleted(tsport->input.rf)) { SendUserCallback(tsport, ePSIM_EVENT_AllPmtsReceived, 0); // pmt monitor ¸ðµÎ close.. StopMonitorPMTs(tsport); } else { // ´Ù¸¥ monitor ½ÃÀÛ.. StartMonitorPMTs(tsport, -1); // no preference. get all pmts.. } } else { StartMonitorPMTs(tsport, tsport->input.program_number); } pat = NULL; // not to be freed later label_end: if (pat) { dprint(3, " free unused pat %x..\n", pat); PSIUTIL_FreeTable(&pat); } return status; } PSI_STATIC STATUS ProcessPMT(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc) { DHL_RESULT err; STATUS status = statusOK; MPEG_PMT *pmt; MPEG_PAT *pat; int i, index; BOOL bPsiCtlConsistent = FALSE; //BOOL bPmtComplete; err = ParsePMT(desc, &pmt); if (IsError(err)) { dprint(0, "%s: ParsePMT returned %s\n", __FUNCTION__, ErrorString(err)); return statusInvalidPSI; } // PMT sanity check. // todo: pmt of numStreams zero.. // pmt ÀÌÈÄ·ÎÀÇ ¿¬°áµÈ ÀÛ¾÷Àº ¾øÀ¸´Ï, Á» ÀÌ»óÇÑ pmt¶óµµ ÀÏ´Ü ¼ö½ÅÀº ÇØ µÑ±î? // ¾Æ´Ï¸é ÇâÈÄ ÀÛ¾÷µéÀ» ÆíÇÏ°Ô Çϱâ À§Çؼ­ ±×³É ¸ø¹ÞÀº °ÍÀ¸·Î?? // ±×³É ¹ö¸°´Ù¸é.. // pros: ÀÌ»óÇÑ pmt¸¦ ¹Ì¸® filter out ÇØ ¹ö¸®¸é ÇâÈÄ check ÀÛ¾÷ÀÌ ¾ø¾îµµ µÇ´Ï ÆíÇÔ. // cons: pmt ¼ö½Å ¿Ï·á°¡ ¾ÈµÇ´Ï±î autoscan µî¿¡¼­ timeout ¹ß»ý½Ã±îÁö ´À·ÁÁü.. // // --> ¼Óµµº¸´Ù´Â ¾ÈÁ¤¼º.. ±×³É ¹ö¸®ÀÚ. // if (!pmt || pmt->numStreams == 0 || !pmt->streams) { dprint(0, "!! wrong pmt\n"); PSIUTIL_FreeTable(&pmt); return statusInvalidPSI; } for (i=0; tsport->pmtPsiCtlArray && inum_programs; i++) { if (tsport->pmtPsiCtlArray[i] == desc->handle) { bPsiCtlConsistent = TRUE; break; } } if (!bPsiCtlConsistent) { dprint(0, "!! inconsistent! any pmtPsiCtls[] != desc psictl %x\n", desc->handle); status = statusInvalidState; goto label_end; } //-------------------------------------------------------------------- // now, table becoms vailid. if not updated to DB, free it carefully. // determine index using origianl psictl pointer index = -1; for (i=0; inum_programs; i++) { if (tsport->pmtPsiCtlArray[i] == desc->handle) { index = i; break; } } if (index < 0) { dprint(0, "!! cannot find psictl origin\n"); // ¿¹¿Ü ó¸®: ±×³É ÇöÀç pmt ¹«½Ã. Àç½Ãµµ ¾ÈÇÔ. status = statusInvalidPSI; goto label_end; } // pat ³»¿ë°ú ÀÏÄ¡ ¿©ºÎ üũ. (program number ..) pat = PSIDB_GetPAT(tsport->input.rf); if (pat == NULL) { dprint(0, "!! pmt without pat?\n"); // ¿¹¿Ü ó¸®: ±×³É ÇöÀç pmt ¹«½Ã. Àç½Ãµµ ¾ÈÇÔ. status = statusInvalidPSI; goto label_end; } if (pat->numPrograms != tsport->num_programs) { dprint(0, "!! pat not consistent to pmt monitors\n"); PSIUTIL_FreeTable(&pmt); // ¿¹¿Ü ó¸®: pmt monitorµéÀº ¸ðµÎ reset ½ÃÄÑ ³õ´Â´Ù. StopMonitorPMTs(tsport); status = statusInvalidPSI; goto label_end; } if (dprintable(3)) PrintPMT(pmt); // update.. status = PSIDB_UpdatePMT(tsport->input.rf, pmt); // now, don't use pmt any more! if (status) { // ¹«½¼ ÀÌÀ¯¿¡¼­ÀÎÁö pmt update ½ÇÆÐ. (´ëºÎºÐ ¸Þ¸ð¸® ¿¡·¯) goto label_end; } // autoscan ¸ðµå¶ó¸é ÇöÀç ¼ö½ÅÇÑ pmt´Â stop Çϰí Ãß°¡ pmt ¼ö½ÅÀÌ ÇÊ¿äÇϸé Á¶Ä¡ÇÔ. if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) { // ¹æ±Ý ¼ö½ÅÇÑ pmtÀÇ monitor´Â Á¾·á DHL_PSI_StopMonitor(tsport->pmtPsiCtlArray[index]); tsport->pmtPsiCtlArray[index] = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; if (PSIDB_IsPmtsCompleted(tsport->input.rf)) { SendUserCallback(tsport, ePSIM_EVENT_AllPmtsReceived, 0); // ÀÌ¹Ì pat monitor´Â Á¤ÁöµÇ¾î ÀÖÀ» °ÍÀÌÁö¸¸ ´Ù½Ã Çѹø üũ.. StopMonitorPAT(tsport); // pmt monitor ¸ðµÎ close.. StopMonitorPMTs(tsport); } else { // ´Ù¸¥ monitor ½ÃÀÛ.. StartMonitorPMTs(tsport, -1); } } else { #if 1 // pmt pointer ±×´ë·Î access °¡´ÉÇϹǷΠÁ» ´õ °£´ÜÇØÁü. SendUserCallback(tsport, ePSIM_EVENT_PmtReceived, (UINT32)pmt); #else for (i=0; pmtList && inumPrograms; i++) { if (tsport->input.program_number == pmtList[i]->program_number) { SendUserCallback(tsport, ePSIM_EVENT_PmtReceived, (UINT32)pmtList[i]); break; } } #endif } pmt = NULL; // not to be freed later label_end: if (pmt) { dprint(3, " free unused pmt %x..\n", pmt); PSIUTIL_FreeTable(&pmt); } return status; } PSI_STATIC STATUS ProcessMgt(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc) { DHL_RESULT err; STATUS status = statusOK; BOOL bMgtChanged = FALSE; mgtSectionPtr_t mgt, prev_mgt; err = ParseMgtSection(desc->sectPtr[0], &mgt); // desc will be freed at caller. if (IsError(err)) { dprint(0, "%s: ParseMgt returned %s\n", __FUNCTION__, ErrorString(err)); return statusInvalidPSI; } // sanity check if (!mgt || mgt->tables_defined==0 || !mgt->table) { dprint(0, "!! invalid mgt\n"); PSIUTIL_FreeTable(&mgt); return statusInvalidPSI; } if (tsport->mgtPsiCtl != desc->handle) { dprint(0, "!! inconsistent! mgtPsiCtl %x != desc psictl %x\n", tsport->mgtPsiCtl, desc->handle); status = statusInvalidState; goto label_end; } //-------------------------------------------------------------------- // now, table becoms vailid. if not updated to DB, free it carefully. if (dprintable(4)) PrintMgtSection(mgt); //----------------------------------- // ±âÁ¸ table°ú ºñ±³ÇÏ¿© º¯°æ »çÇ×ÀÌ ¿©ºÎ üũ prev_mgt = PSIDB_GetMgt(tsport->input.rf); if (prev_mgt == NULL) { dprint(2, " mgt newly comes.. new mgt ver %d\n", mgt->version_number); bMgtChanged = TRUE; } else if (PSIUTIL_IsEquivalentMgt(prev_mgt, mgt) == FALSE) { dprint(2, " mgt changed.. ver %d --> %d\n", prev_mgt->version_number, mgt->version_number); bMgtChanged = TRUE; } else { dprint(2, " mgt version unchagned %d\n", mgt->version_number); // mgt versionÀÌ º¯°æµÇÁö ¾Ê¾Ò´Ù°í ÇØµµ ¿©·¯°¡Áö ÀÌÀ¯·Î (filter ºÎÁ·) ½ÃÀÛÇÏÁö ¸øÇÑ // sectionµéÀÌ ÀÖÀ» ¼ö ÀÖÀ¸¹Ç·Î ¿©±â¼­ Áß´ÜÇÏÁö ¾Ê°í °è¼Ó ÁøÇàÇÑ´Ù. } //----------------------------------- if (bMgtChanged) { // DB¿¡ update ÇÑ´Ù. À̶§ ³»ºÎ¿¡¼­ ¸¹Àº ºÎ°¡ ÀÛ¾÷ÀÌ °°ÀÌ ÁøÇà µÈ´Ù. // ex: º¯°æ µÇ´Â ¸ðµç Å×À̺í Á¤¸®, mgt digest »ý¼º // status = PSIDB_UpdateMgt(tsport->input.rf, mgt); if (status) { // ¹«½¼ ÀÌÀ¯¿¡¼­ÀÎÁö mgt update ½ÇÆÐ.. goto label_end; } //SendUserCallback(tsport, ePSIM_EVENT_MgtReceived, (UINT32)mgt); } if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) { // autoscan ¸ðµå¿¡¼­´Â ÇϳªÀÇ instance¸¸ ¼ö½ÅÇÏ¸é µÇ¹Ç·Î ¹Ù·Î ÁßÁö. StopMonitorMgt(tsport); } // mgt¿Í vct°¡ ¸ðµÎ ¹Þ¾ÆÁ® ÀÖ´Ù¸é eit/ett ¼ö½ÅÀ» ½ÃÀÛÇÒ ¼ö ÀÖ´Ù. if (!PSIDB_IsSubChScanReadyToStart(tsport->input.rf)) { // not ready. dprint(2, " subch scan not ready.. mgt %x, vct %x\n", PSIDB_GetMgt(tsport->input.rf), PSIDB_GetVct(tsport->input.rf)); } else { //test..SendEventChannelStarted(tsport, tsport->input.rf); StartSubChannelScan(tsport); } mgt = NULL; // not to be freed later label_end: if (mgt) { dprint(3, " free unused mgt %x..\n", mgt); PSIUTIL_FreeTable(&mgt); } return status; } PSI_STATIC STATUS ProcessVct(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc) { DHL_RESULT err; STATUS status = statusOK; xvctPtr_t vct, prev_vct; BOOL bVctChanged = FALSE; dprint(2, "process vct..\n"); err = ParseVct(desc->sectPtr, &vct); // desc will be freed at caller. if (IsError(err)) { dprint(0, "%s: ParseVct returned %s\n", __FUNCTION__, ErrorString(err)); return statusInvalidPSI; } // sanity check if (!vct || vct->numChannels==0 || !vct->channel) { dprint(0, "!! invalid vct\n"); PSIUTIL_FreeTable(&vct); return statusInvalidPSI; } //-------------------------------------------------------------------- // now, table becoms vailid. if not updated to DB, free it carefully. //----------------------------------- // vct °íÀ¯ÀÇ Ã³¸® ·çƾµé.. µÎ°³ÀÇ vct Áß¿¡¼­ ÇϳªÀÇ monitor¸¸ »ì·Á³õ´Â´Ù. if (vct->is_cvct) // cvct { if (tsport->cvctPsiCtl == (tDHL_PSI_ControlHandle)0) { // already cancelled. this is delayed processing. dprint(2, "already cancelled cvct mon\n"); goto label_end; } if (tsport->cvctPsiCtl != desc->handle) { dprint(0, "!! inconsistent! cvctpsictl %x != desc psictl %x\n", tsport->cvctPsiCtl, desc->handle); status = statusInvalidState; goto label_end; } // ´çÀå tvct´Â ÁßÁö½ÃŲ´Ù. ¿ÀÁ÷ ÇϳªÀÇ vct¸¸ °¡´ÉÇϵµ·Ï... StopMonitorTvct(tsport); } else // tvct { if (tsport->tvctPsiCtl == (tDHL_PSI_ControlHandle)0) { // already cancelled. this is delayed processing. dprint(2, "already cancelled tvct mon\n"); goto label_end; } if (tsport->tvctPsiCtl != desc->handle) { dprint(0, "!! inconsistent! tvctpsictl %x != desc psictl %x\n", tsport->tvctPsiCtl, desc->handle); status = statusInvalidState; goto label_end; } // ´çÀå cvct´Â ÁßÁö½ÃŲ´Ù. ¿ÀÁ÷ ÇϳªÀÇ vct¸¸ °¡´ÉÇϵµ·Ï... StopMonitorCvct(tsport); } //----------------------------------- // ±âÁ¸ table°ú ºñ±³ÇÏ¿© º¯°æ »çÇ×ÀÌ ¿©ºÎ üũ prev_vct = PSIDB_GetVct(tsport->input.rf); if (prev_vct == NULL) { dprint(2, " vct newly comes.. new vct ver %d\n", vct->version_number); bVctChanged = TRUE; } else if (PSIUTIL_IsEquivalentVct(prev_vct, vct) == FALSE) { dprint(2, " vct changed.. ver %d --> %d\n", prev_vct->version_number, vct->version_number); bVctChanged = TRUE; } else { dprint(2, " vct version unchagned %d\n", prev_vct->version_number); // vct°¡ º¯°æµÇÁö ¾Ê¾Ò´Ù°í ÇØµµ ¿©·¯°¡Áö ÀÌÀ¯·Î (filter ºÎÁ·) ½ÃÀÛÇÏÁö ¸øÇÑ // sectionµéÀÌ ÀÖÀ» ¼ö ÀÖÀ¸¹Ç·Î ¿©±â¼­ Áß´ÜÇÏÁö ¾Ê°í °è¼Ó ÁøÇàÇÑ´Ù. } //----------------------------------- if (bVctChanged) { // DB¿¡ update ÇÑ´Ù. À̶§ ³»ºÎ¿¡¼­ ¸¹Àº ºÎ°¡ ÀÛ¾÷ÀÌ °°ÀÌ ÁøÇà µÈ´Ù. // ex: subchannel struct re-init.. // status = PSIDB_UpdateVct(tsport->input.rf, vct); if (status) { // something wrong! vct not updated to DB.. goto label_end; } SendUserCallback(tsport, ePSIM_EVENT_VctReceived, (UINT32)vct); } else { // todo // Equivalent ÇÏÁö´Â ¾ÊÁö¸¸, »ç¼ÒÇÑ ¾ÆÁÖ ÀÛÀº Â÷À̵éÀÌ ÀÖÀ» ¼ö ÀÖÁö ¾Ê´Â°¡? // Áï DB¿¡´Â update¸¦ ÇÏ´Â °ÍÀÌ ÁÁÁö ¾Ê³ª? // // --> // Equivalence üũ ·çƾÀÇ Á¤È®µµ¿¡ µû¶ó ¿µÇâÀÌ ´Þ¶óÁü. // ¶Ç ¸¸¾à vct continuous ¸ðµå·Î ¹Þ°í ÀÖ´Ù¸é °è¼Ó DB¾ÈÀÇ vct°¡ replace µÉ ¿°·Á ÀÖÀ½. // µû¶ó¼­ ÀÏ´ÜÀº update ÇÏÁö ¾Êµµ·Ï ÇÏÀÚ. // db update ¿©ºÎ¸¦ ¶°³ª¼­ event callbackÀº ºÒ·¯ÁÖµµ·Ï ÇÏÀÚ. SendUserCallback(tsport, ePSIM_EVENT_VctReceived, (UINT32)vct); } if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) { // ¾î¶² °ÍÀÌ °¡µ¿ÁßÀÎÁö ¾Ë±â ±ÍÂúÀ¸´Ï±î tvct, cvct µÑ ´Ù ÁßÁö. StopMonitorTvct(tsport); StopMonitorCvct(tsport); } // mgt¿Í vct°¡ ¸ðµÎ ¹Þ¾ÆÁ® ÀÖ´Ù¸é eit/ett ¼ö½ÅÀ» ½ÃÀÛÇÒ ¼ö ÀÖ´Ù. if (!PSIDB_IsSubChScanReadyToStart(tsport->input.rf)) { // not ready. dprint(2, " subch scan not ready.. mgt %x, vct %x\n", PSIDB_GetMgt(tsport->input.rf), PSIDB_GetVct(tsport->input.rf)); } else { //test..SendEventChannelStarted(tsport, tsport->input.rf); StartSubChannelScan(tsport); } vct = NULL; // not to be freed later label_end: if (vct) { // DB¿¡ update µÇÁö ¾ÊÀº vct´Â ¾ø¾ÖÁà¾ß ¸Þ¸ð¸® ´©¼ö°¡ ¾øÀ½.. dprint(3, " free unused vct %x..\n", vct); PSIUTIL_FreeTable(&vct); } return status; } // STT°¡ ¼ö½ÅµÉ ¶§¸¶´Ù ÀÌ ÇÔ¼ö°¡ ºÒ¸°´Ù.. // // ÀÌ ÇÔ¼ö¿¡¼­ STT 󸮸¦ Çϰí Program event º¯°æ üũµµ ÇÑ´Ù. // Áï program event º¯°æ üũ´Â STT°¡ ¼ö½Å µÉ °æ¿ì¿¡¸¸ ¼öÇàÇÏ°Ô µÈ´Ù. // // ¸¸¾à STT ÁֱⰡ ±æ°Å³ª, ½ÅÈ£ »óŰ¡ ¾ÊÁÁÀ½ µîÀÇ ÀÌÀ¯·Î STT update°¡ ´Ê¾îÁú °æ¿ì // program event º¯°æ üũµµ ´Ê¾îÁú ¼ö ÀÖ´Ù. // // µû¶ó¼­ User´Â º°µµ·Î ÁÖ±âÀûÀ¸·Î program event º¯°æ üũ¸¦ ºÒ·¯ÁÙ Çʿ䰡 ÀÖ´Ù. // PSI_STATIC STATUS ProcessStt(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc) { DHL_RESULT err; STATUS status = statusOK; UINT32 tick = DHL_OS_GetMsCount(); sttSection_t prev_stt_0; sttSectionPtr_t stt, prev_stt = &prev_stt_0; err = ParseSttSection(desc->sectPtr[0], &stt); // desc will be freed at caller. if (IsError(err)) { dprint(0, "%s: ParseStt returned %s\n", __FUNCTION__, ErrorString(err)); return statusInvalidPSI; } // sanity check if (!stt) { PSIUTIL_FreeTable(&stt); return statusInvalidPSI; } if (tsport->sttPsiCtl != desc->handle) { dprint(0, "!! inconsistent! sttPsiCtl %x != desc psictl %x\n", tsport->sttPsiCtl, desc->handle); status = statusInvalidState; goto label_end; } //-------------------------------------------------------------------- // now, table becoms vailid. if not updated to DB, free it carefully. // Ȥ½Ã ÇöÀçÀÇ SttPsiCtl ÀÌ ÀÌ¹Ì Ãë¼Ò µÇ¾î ÀÖÀ» ¼öµµ Àֱ⠶§¹®¿¡ // ÇöÀç contextÀÇ ³»¿ëÀ» È®ÀÎÇØ º¸´Â °Íµµ ÁÁ´Ù. // if (tsport->sttPsiCtl == (tDHL_PSI_ControlHandle)0) { dprint(0, "!! %s: stt from null psi ctl\n", __FUNCTION__); //return statusInvalidState; return statusOK; } if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) { StopMonitorStt(tsport); //goto label_end; // stt notify ÇØÁÖ±â À§Çؼ­ ±×³É skipÀº ¾ÈÇÔ. // autoscan ¸ðµå¶óµµ stt notify µîÀº ÇÊ¿äÇÒ ¼ö ÀÖÀ¸¹Ç·Î // ¾Æ·¡ ÀÛ¾÷Àº µ¿ÀÏÇÏ°Ô ¼öÇàÇØ ÁÖµµ·Ï ÇÑ´Ù. // ´Ü program change notify´Â ÇÒ ÇÊ¿ä ¾ø´Ù. } // stt ³»¿¡´Â system time »Ó¸¸ ¾Æ´Ï¶ó GPS_UTC offset ¹× daylight saving Á¤º¸µµ ÀÖ´Ù. // ÀÌ ¸ðµç ³»¿ëÀÌ µ¿ÀÏÇÑ °æ¿ì¿¡¸¸ equivalent¶ó°í ÇÒ ¼ö ÀÖÀ½. prev_stt = PSIDB_GetStt(tsport->input.rf); if (PSIUTIL_IsEquivalentStt(prev_stt, stt)) { // µ¿ÀÏÇÑ ½Ã°£À¸·Î stt°¡ ¼ö½ÅµÇ¾úÀ½. ó¸®ÇÒ ÇÊ¿ä ¾ø´Ù. // sarnoff stream: rpbp, fast base pid stream ´ëÀÀ. // stt°¡ ÃÊ´ç 10ȸ¾¿ Àü¼ÛµÊ. } else { // ±âÁ¸ stt¿¡ ºñÇØ ¹º°¡ ´Ù¸¥ stt°¡ ¼ö½ÅµÈ °æ¿ìÀÌ´Ù. // »ç½Ç ´ëºÎºÐÀÇ °æ¿ì ÀÌ ¹üÁÖ¿¡ ¼ÓÇÑ´Ù. if (dprintable(4)) PrintSttSection(stt); // update¸¦ Çϱâ Àü¿¡ backupÀ» ÇØ µÎ¾î¾ß ÇÔ. ±×·¸Áö ¾ÊÀ¸¸é // PSIDB_UpdateStt Çϸ鼭 »õ·Î¿î stt·Î overwrite µÇ¾î ¹ö¸°´Ù. // if (prev_stt) { prev_stt_0 = *prev_stt; prev_stt = &prev_stt_0; } status = PSIDB_UpdateStt(tsport->input.rf, stt, tick); if (status) { goto label_end; } // DBÀÇ stt´Â flat_stt ¶ó°í Á» ´Ù¸¥ ÇüÅÂÀ̹ǷΠ¼ö½Å ¹ÞÀº stt´Â ¹ö¸®°í // DBÀÇ stt Á¤º¸¸¦ Âü°íÇÏÀÚ. PSIUTIL_FreeTable(&stt); stt = PSIDB_GetStt(tsport->input.rf); if (g_Trace_bPsiSttInfo) { char cur_time[100] = {0, }; #if DMW_EPG_TABLE_DUMP_DEBUG Dmc_SetGpsTimeSync(stt); GpsTimeString(stt->system_time, cur_time); #endif dprint(2, "[STT] (rf %d, sid %d) %s gps 0x%x\n", tsport->input.rf, tsport->input.source_id, cur_time, stt->system_time); } // STT Smart Notification // // if 'system time JUMP' is detected, notify to user. // probably stream is changed, tuner setting (rf) is changed, // or signal is re-aquired in weak signal environment. // user had better re-sync system time to this new STT value.. // // »õ stt°¡ ¼ö½ÅµÇ¾ú´Ù°í ÇØ¼­ ¸Å¹ø notify¸¦ ÇÏÁö´Â ¾Ê´Â´Ù. // ´ÙÀ½ µÎ°¡Áö Á¶°Ç¿¡ ÇØ´ç µÉ °æ¿ì¿¡¸¸ notify ÇÑ´Ù. // // 1. ÀÌ RF¿¡¼­ psi scanÀ» ½ÃÀÛ ÇÑ ÈÄ Ã³À½ ¼ö½ÅµÈ stt // 2. stt threshold¸¦ ³Ñ¾î¼± skipÀÌ ¹ß°ßµÈ °æ¿ì.. // if (prev_stt == NULL) { // EpgScanÀÌ ½ÃÀÛµÇ°í ³ª¼­ óÀ½ ¹ÞÀº stt¶ó¸é event¸¦ º¸³»ÁØ´Ù. // dprint(1, "first STT received after psi start..\n"); SendUserCallback(tsport, ePSIM_EVENT_SttReceived, (UINT32)stt); } else if (abs((SINT32)(stt->system_time - prev_stt->system_time)) > STT_JUMP_THRESHOLD) { //int age = (DHL_OS_GetMsCount() - tick_stt_get) / 1000; dprint(1, "STT Jump (%d sec) detected..\n", stt->system_time - prev_stt->system_time); // jump´Â À½ÀÇ °ªÀÌ µÉ ¼öµµ ÀÖ´Ù. stream ÀÌ ¹Ýº¹Çؼ­ Àç»ýµÇ´Â °æ¿ì.. // // age¸¦ °è»êÇØ¼­ ³Ñ°ÜÁÖ´Â ÀÌÀ¯´Â ÀÌ stt ó¸® task°¡ priority°¡ ³·¾Æ¼­ // ½ÇÁ¦·Î stt¸¦ ¹ÞÀº ½Ã°£°ú ÀÌ stt¸¦ ó¸®ÇÏ´Â ½Ã°£¿¡ Â÷À̰¡ ÀÖÀ» ¼ö Àֱ⠶§¹®. // ´ëºÎºÐ ¾ÆÁÖ ÀÛÀº °ªÀ̰ųª 0ÀÇ °ªÀ» °®À» °ÍÀÌ´Ù. SendUserCallback(tsport, ePSIM_EVENT_SttReceived, (UINT32)stt); } // Program Event º¯°æ »çÇ× Ã¼Å©. // autoscan ¸ðµåÀÎ °æ¿ì¿¡´Â ºÒÇÊ¿ä. // if (PSI_FLAGS_MODE(tsport->input.flags) != PSI_FLAGS_AUTOSCAN /* && IS_VALID_SOURCE_ID(tsport->source_id) */) { CheckIfProgramEventChanged(tsport); } } stt = NULL; // not to be freed later label_end: if (stt) { dprint(3, " free unused stt %x..\n", stt); PSIUTIL_FreeTable(&stt); } return status; } PSI_STATIC STATUS ProcessRrt(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc) { STATUS status = statusOK; return status; } /* ¾î¶² eit[k] ÀÎÁö È®ÀÎÇϱâ À§Çؼ­´Â ÀÌ Å×À̺íÀ» ¼ö½ÅÇÑ psiCtlÀ» ¾Ë¾Æ¾ß ÇÑ´Ù. */ PSI_STATIC STATUS ProcessEit(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc) { int index, i; STATUS status = statusOK; DHL_RESULT err; eitPtr_t eit; //BOOL bFilterReleased = FALSE; BOOL bPsiCtlConsistent = FALSE; err = ParseEit(desc->sectPtr, &eit); // desc will be freed at caller. if (IsError(err)) { dprint(0, "%s: ParseEit returned %s\n", __FUNCTION__, ErrorString(err)); return statusInvalidPSI; } // Eit table sanity check if (eit->numEvents && !eit->event) { PSIUTIL_FreeTable(&eit); return statusInvalidPSI; } for (i=0; i<128; i++) { if (tsport->eitPsiCtl[i] == desc->handle) { bPsiCtlConsistent = TRUE; break; } } if (!bPsiCtlConsistent) { dprint(0, "!! inconsistent! any eitPsiCtls[] != desc psictl %x\n", desc->handle); status = statusInvalidState; goto label_end; } //-------------------------------------------------------------------- // now, table becoms vailid. if not updated to DB, free it carefully. // decide which eit it is.. index = -1; for (i=0; i<128; i++) { if (desc->handle == tsport->eitPsiCtl[i]) { index = i; break; } } if (index < 0) { dprint(0, "!! orphan eit?\n"); status = statusInvalidPSI; goto label_end; } dprint(2, "eit[%d] received. sid %d\n", index, eit->source_id); if (dprintable(3)) { //PrintEit(eit); } // Eit¸¦ DB¿¡ update ÇÑ´Ù. PSIDB_UpdateEit(tsport->input.rf, eit, index); #if 0 // this is just for informational declare. if (PSIDB_IsSubChEitsCompleted(tsport->input.rf, eit->source_id)) { dprint(2, "\n#### source_id %d subch eit completed\n", eit->source_id); } #endif // schedule next job.. // Ȥ½Ã filter °¹¼ö Á¦ÇÑ ¶§¹®¿¡ ¹ÞÁö ¸øÇÑ ´Ù¸¥ table µé schedule. // if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) { if (PSIDB_IsAllSubChEitsCompleted(tsport->input.rf, index)) { dprint(2, "all subch's eit[%d] completed. stop monitor..\n", index); StopMonitorEit(tsport, index); //bFilterReleased = TRUE; // monitor remaining pmts.. StartMonitorPMTs(tsport, -1); // no preference. get all pmts.. } } else { // 1:1 À̹ǷÎ, ¼ö½ÅÇÏ¸é ¹Ù·Î ÁßÁöÇÔ. StopMonitorEit(tsport, index); //bFilterReleased = TRUE; // monitor remaining eits.. StartSubChannelScan(tsport); } eit = NULL; // not to be freed later label_end: if (eit) { dprint(3, " free unused eit %x..\n", eit); PSIUTIL_FreeTable(&eit); } return status; } PSI_STATIC STATUS ProcessEtt(S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc) { int index, i; STATUS status = statusOK; DHL_RESULT err; ettSectionPtr_t ett; BOOL bPsiCtlConsistent = FALSE; int ett_source_id, ett_event_id; S_PSIM_SUBCHINFO *subchInfo; err = ParseEttSection(desc->sectPtr[0], &ett); // desc will be freed at caller. if (IsError(err)) { dprint(0, "%s: ParseEtt returned %s\n", __FUNCTION__, ErrorString(err)); return statusInvalidPSI; } // Ett table sanity check if (!ett || ett->ETM_id == 0 || !ett->extended_text_message_length) { dprint(0, "!! invalid ett\n"); PSIUTIL_FreeTable(&ett); return statusInvalidPSI; } for (i=0; i<128; i++) { if (tsport->ettPsiCtl[i] == desc->handle) { bPsiCtlConsistent = TRUE; break; } } if (tsport->ettvPsiCtl == desc->handle) bPsiCtlConsistent = TRUE; if (!bPsiCtlConsistent) { dprint(0, "!! inconsistent! any ettPsiCtls[] != desc psictl %x\n", desc->handle); status = statusInvalidState; goto label_end; } //-------------------------------------------------------------------- // now, table becoms vailid. if not updated to DB, free it carefully. // context consistency.. if (PSI_FLAGS_MODE(tsport->input.flags) == PSI_FLAGS_AUTOSCAN) { dprint(0, "!! ett received in autoscan mode?\n"); PSIUTIL_FreeTable(&ett); return statusInvalidState; } #if 0 // decide which ett it is.. index = -1; if (desc->psiCtl == tsport->ettvPsiCtl) { index = 128; } for (i=0; i<128; i++) { if (desc->psiCtl == tsport->ettPsiCtl[i]) { index = i; break; } } if (index < 0) { dprint(0, "!! orphan ett?\n"); return statusInvalidPSI; } #else // ettÀÇ °æ¿ì ettPsiCtl°úÀÇ ºñ±³·Î iEtt¸¦ ¾Ë¾Æ³»´Â °ÍÀº ¾ÈÀüÇÏÁö ¾Ê´Ù. // Á÷Á¢ ett ³»ÀÇ etmid °ªÀ» ÀÌ¿ëÇÏ¿© eitsÀÇ event_id ¿Í ºñ±³ÇÏ¿© ã¾Æ¾ß ÇÑ´Ù. ett_source_id = PSIUTIL_GetSourceIDFromETMID(ett->ETM_id); ett_event_id = PSIUTIL_GetEventIDFromETMID(ett->ETM_id); if (tsport->source_id != ett_source_id) { dprint(0, "!! ett sid %d not matched to port sid %d\n", ett_source_id, tsport->source_id); PSIUTIL_FreeTable(&ett); return statusInvalidState; } subchInfo = PSIDB_GetPsiSubChInfo(tsport->input.rf, tsport->source_id); if (!subchInfo) { PSIUTIL_FreeTable(&ett); return statusInvalidState; } // ¾î¶² ettÀÎÁö ã´Â´Ù. index = -1; if ((ett->ETM_id & 0xffff) == 0) // channel-ett index = 128; for (i=0; index<0 && i<128; i++) { int k; if (!subchInfo->eits[i]) continue; for (k=0; keits[i]->numEvents; k++) { if (subchInfo->eits[i]->event[k].event_id == ett_event_id) { index = i; break; } } } if (index < 0) { dprint(0, "!! orphan ett? etm 0x%x, no such event_id 0x%x..\n", ett->ETM_id, ett_event_id); PSIUTIL_FreeTable(&ett); return statusInvalidPSI; } #endif // todo // ÀÌ¹Ì ¼ö½ÅÇÑ ett ÀÎÁö °Ë»ç.. dprint(2, "ett[%d] received. etmid 0x%x\n", index, ett->ETM_id); if (dprintable(3)) { //PrintEttSection(ett); } // Eit¸¦ DB¿¡ update ÇÑ´Ù. PSIDB_UpdateEtt(tsport->input.rf, ett, index); // ÇØ´ç pidÀÇ ettµéÀÌ ³¡³µ´Ù¸é ÇØ´ç ett psictlÀ» ÁßÁö. if (PSIDB_IsSubChEttSlotCompleted(tsport->input.rf, tsport->source_id, index)) { dprint(2, " ett[%d] slot all received.\n", index); StopMonitorEtt(tsport, index); } // todo // ÀÌ ¹æ¹ýÀº °áÄÚ È¿À²ÀûÀÌÁö ¸øÇÏ´Ù. ´õ ÁÁÀº ¹æ¹ý Âþ¾Æº¼°Í! if (PSIDB_IsSubChAllEttsCompleted(tsport->input.rf, tsport->source_id)) { dprint(2, " all etts received\n"); StopMonitorAllEtts(tsport); } ett = NULL; // not to be freed later label_end: if (ett) { dprint(3, " free unused ett %x..\n", ett); PSIUTIL_FreeTable(&ett); } return status; } PSI_STATIC void StopAllPsiMonitors(S_PSIM_PORT *tsport) { //int err; int i; dprint(2, "%s:\n", __FUNCTION__); // PAT if (tsport->patPsiCtl) { dprint(3, "\t cancel pat monitor\n"); DHL_PSI_StopMonitor(tsport->patPsiCtl); tsport->n_active_monitors--; tsport->patPsiCtl = (tDHL_PSI_ControlHandle)0; } // PMTs for (i=0; inum_programs; i++) { if (tsport->pmtPsiCtlArray[i]) { dprint(3, "\t cancel pmt[%d] monitor\n", i); DHL_PSI_StopMonitor(tsport->pmtPsiCtlArray[i]); tsport->n_active_monitors--; tsport->pmtPsiCtlArray[i] = (tDHL_PSI_ControlHandle)0; } } tsport->num_programs = 0; DHL_OS_Free((void **)&tsport->pmtPsiCtlArray); // MGT if (tsport->mgtPsiCtl) { dprint(3, "\t cancel mgt monitor\n"); DHL_PSI_StopMonitor(tsport->mgtPsiCtl); tsport->mgtPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } // TVCT if (tsport->tvctPsiCtl) { dprint(3, "\t cancel tvct monitor\n"); DHL_PSI_StopMonitor(tsport->tvctPsiCtl); tsport->tvctPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } // CVCT if (tsport->cvctPsiCtl) { dprint(3, "\t cancel cvct monitor\n"); DHL_PSI_StopMonitor(tsport->cvctPsiCtl); tsport->cvctPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } // STT if (tsport->sttPsiCtl) { dprint(3, "\t cancel stt monitor\n"); DHL_PSI_StopMonitor(tsport->sttPsiCtl); tsport->sttPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } // RRT if (tsport->rrtPsiCtl) { dprint(3, "\t cancel rrt monitor\n"); DHL_PSI_StopMonitor(tsport->rrtPsiCtl); tsport->rrtPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } // EAS if (tsport->easPsiCtl) { dprint(3, "\t cancel eas monitor\n"); DHL_PSI_StopMonitor(tsport->easPsiCtl); tsport->easPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } // EIT for (i=0; i<128; i++) { if (tsport->eitPsiCtl[i]) { dprint(3, "\t cancel eit[%d] monitor\n", i); DHL_PSI_StopMonitor(tsport->eitPsiCtl[i]); tsport->eitPsiCtl[i] = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } // ETT for (i=0; i<128; i++) { if (tsport->ettPsiCtl[i]) { dprint(3, "\t cancel ett[%d] monitor\n", i); DHL_PSI_StopMonitor(tsport->ettPsiCtl[i]); tsport->ettPsiCtl[i] = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } } // Channel-ETT if (tsport->ettvPsiCtl) { dprint(3, "\t cancel ett-v monitor\n", i); DHL_PSI_StopMonitor(tsport->ettvPsiCtl); tsport->ettvPsiCtl = (tDHL_PSI_ControlHandle)0; tsport->n_active_monitors--; } if (tsport->n_active_monitors != 0) { dprint(0, "!! orphan active monitors %d\n", tsport->n_active_monitors); tsport->n_active_monitors = 0; } } /* ¸ðµç tableÀ» ¹Þ´Â event callback ¹«Á¶°Ç parsing ÇÑ ÈÄ¿¡ task·Î Å×ÀÌºí Æ÷ÀÎÅ͸¦ Àü´ÞÇÑ´Ù. */ PSI_STATIC void _PsiTableEventProc(tDHL_PSI_Event psiEvent, tDHL_PSI_ControlHandle psiCtl, UINT32 userParam) { STATUS status; DHL_RESULT err; tDHL_PSI_DataArray *desc; S_PSIM_PORT *tsport = (S_PSIM_PORT *) userParam; if (psiEvent != ePSIEVENT_DATARECEIVED) { if (g_Trace_bPsiEvent) { // ½ÅÈ£°¡ ÁÁÁö ¾ÊÀº °æ¿ì¿¡ lostpacket À̺¥Æ®´Â ¾ÆÁÖ ºó¹øÇÏ°Ô ¹ß»ý °¡´ÉÇϹǷΠÁ¦¿Ü. if (psiEvent != ePSIEVENT_LOSTPACKET) dprint(3, "%s: psiEvent %s\n", __FUNCTION__, DHL_PSIEventString(psiEvent)); } return; } // data recieved event´Â debug printÇÏÁö ¾Ê´Â´Ù. // err = DHL_PSI_ReadPSIData(psiCtl, &desc); if (err) { dprint(0, "%s: ReadPSIData returned %s\n", __FUNCTION__, ErrorString(err)); return; } status = PSITASK_SendCommand(ePSIM_CMD_TableReceived, (UINT32)tsport, (UINT32)desc, FALSE); if (status) { // Q°¡ overflowµÇ¾î µé¾î°¡Áö ¾Ê¾Ò±â ¶§¹®¿¡ // ÇÒ´çÇÑ Å×À̺íÀ» »èÁ¦Çؼ­ ¸Þ¸ð¸® ´©¼ö¸¦ ¸·´Â´Ù //if (g_Trace_bDmcPsiEvent) dprint(0, "!! %s: DmcQ full\n", __FUNCTION__); DHL_PSI_FreePSIData(desc); } } #if COMMENT ____Public____(){} #endif /* ÇØ´ç @tsd Æ÷Æ®¿¡ ´ëÇØ¼­ @input ¼³Á¤À¸·Î psi scanÀ» ½ÃÀÛÇÑ´Ù. */ STATUS PSIE_StartPsiScan(S_PSIM_CONTEXT *pContext, tDHL_TSD tsd, S_PSIM_USER_INPUT *input) { S_PSIM_PORT *tsport; int i; STATUS status = statusOK; // sanity test if (tsd == (tDHL_TSD)0 || input == NULL) return statusInvalidArgument; dprint(2, "%s: input tsd %x, rf %d, #%d, $%d, mode %d, proc %x, param %x\n", __FUNCTION__, tsd, input->rf, input->program_number, input->source_id, input->flags, input->userproc, input->userparam); // ÁöÁ¤µÈ tsd °¡ ÀÌ¹Ì µ¿ÀÛ ÁßÀÎ °ÍÀÎÁö üũ. tsport = NULL; for (i=0; itsport[i].tsd == tsd) { tsport = &pContext->tsport[i]; break; } } if (tsport) { dprint(0, "!! tsd %x already running. stop first!\n", tsd); // ÀÌ¹Ì µ¿ÀÛ ÁßÀ̶ó¸é, ±âÁ¸ µ¿ÀÛ ÁßÁöÇÏ°í »õ·Ó°Ô ½ÃÀÛ. PSIE_StopPsiScan(pContext, tsd); } // ºó tsport entry¸¦ ã´Â´Ù. for (i=0; itsport[i].tsd == NULL) { tsport = &pContext->tsport[i]; break; } } if (tsport == NULL) { dprint(0, "!! no available tsport entry for tsd %x\n", tsd); return statusOutOfResource; } /* ÇÊ¿äÇϸé ÇöÀç task »óŸ¦ ¼³Á¤ÇÑ´Ù. */ #if 0 if (pContext->state != ePSIM_TASK_STATE_Idle) { pContext->state = ePSIM_TASK_STATE_Idle; } #endif /* TransportInput port Á¤º¸¸¦ ÃʱâÈ­ ÇÑ´Ù. TSD, rf, #, sid, mode, */ memset(tsport, 0, sizeof(S_PSIM_PORT)); tsport->tsd = tsd; tsport->input = *input; tsport->max_monitors = MAX_FILTERS_PER_PORT; // use input's source_id as a start point. tsport->source_id = input->source_id; // for program change monitor tsport->last_event_id = EVENT_ID_INIT; // reset last information /* DB¿¡¼­ chinfo ±¸Á¶Ã¼ ÇÒ´ç. */ status = PSIDB_AllocateChInfoNode(tsport->input.rf); if (status) return status; // ½ÃÀÛÇϱâ Àü¿¡ Ç×»ó ¸ÕÀú stt invalidate. // ÀÌÈÄ ÃÖÃÊ ¼ö½ÅµÇ´Â stt´Â ÀÚµ¿ notify µÈ´Ù. // PSIDB_InvalidateStt(tsport->input.rf); /* 1Â÷ Å×ÀÌºí ¼ö½Å ½ÃÀÛ PAT, MGT, VCT, STT, RRT, EAS */ StartMonitorPAT(tsport); // pmt will be started after pat is downloaded. // psiUpdateMode may vary according to psi scan mode. // right now, this should be considered inside each function. StartMonitorStt(tsport); StartMonitorMgt(tsport); StartMonitorTvct(tsport); StartMonitorCvct(tsport); if (PSI_FLAGS_MODE(tsport->input.flags) != PSI_FLAGS_AUTOSCAN) { StartMonitorRrt(tsport); } return status; } /* ÇØ´ç @tsd Æ÷Æ®ÀÇ psi scan ÀÛ¾÷À» ÁßÁöÇÑ´Ù. ÇöÀç±îÁö °Ë»öµÈ °á°ú´Â ±×´ë·Î À¯ÁöµÈ´Ù. */ STATUS PSIE_StopPsiScan(S_PSIM_CONTEXT *pContext, tDHL_TSD tsd) { S_PSIM_PORT *tsport; int i; STATUS status = statusOK; // ÁÖ¾îÁø tsd Á¤º¸·ÎºÎÅÍ port Á¤º¸¸¦ ã´Â´Ù. tsport = NULL; for (i=0; itsport[i].tsd == tsd) { tsport = &pContext->tsport[i]; break; } } if (tsport == NULL) { dprint(0, "!! no such tsd %x\n", tsd); return statusInvalidArgument; } dprint(2, "stop psi scan: rf %d\n", tsport->input.rf); // ¸ÕÀú monitor¸¦ ÁßÁö. StopAllPsiMonitors(tsport); // Àӽà º¯¼ö, Å×ÀÌºí µé ÃʱâÈ­. // user callback // Á¦´ë·Î ±¸ÇöÇÏÀÚ.. todo.. SendUserCallback(tsport, epgEventStopped, 0); memset(tsport, 0, sizeof(*tsport)); return status; } /* ¸ðµç Æ÷Æ®ÀÇ psi scan ÀÛ¾÷À» ÁßÁöÇÑ´Ù. */ STATUS PSIE_StopAllPsiScan(S_PSIM_CONTEXT *pContext) { //S_PSIM_PORT *tsport; int i; STATUS status = statusOK; // ÁÖ¾îÁø tsd Á¤º¸·ÎºÎÅÍ port Á¤º¸¸¦ ã´Â´Ù. //tsport = NULL; for (i=0; itsport[i].tsd == NULL) continue; status = PSIE_StopPsiScan(pContext, pContext->tsport[i].tsd); if (status) dprint(0, "!! stop psi scan err %d\n", status); } return status; } /* ¸Þ¸ð¸®¿¡ °Ë»öµÇ¾î ÀúÀåµÇ¾î ÀÖ´Â psi data Áß¿¡¼­ ÀÎÀÚ @id¿¡ ÇØ´çµÇ´Â °ÍµéÀ» ¸ðµÎ »èÁ¦ÇÑ´Ù. */ STATUS PSIE_DeleteTables(S_PSIM_CONTEXT *pContext, int id) { /* todo : psi scan engineÀÌ µ¿ÀÛÇÏ´Â Áß¿¡ ÀϺΠdata°¡ »èÁ¦°¡ µÈ´Ù¸é ¹®Á¦°¡ »ý±æ °¡´É¼ºÀÌ Àִµ¥, À̸¦ api ³»ºÎ¿¡¼­ ó¸®ÇÏ´Â °ÍÀÌ ¹Ù¶÷Á÷ÇѰ¡? */ PSIE_StopAllPsiScan(pContext); if (id) PSIDB_DeleteTables(id); else PSIDB_DeleteAllTables(); return statusOK; } /* ¼ö½Å µÈ psi data¸¦ ó¸®ÇÑ´Ù. */ STATUS PSIE_ProcessReceivedTable(S_PSIM_CONTEXT *pContext, S_PSIM_PORT *tsport, tDHL_PSI_DataArray *desc) { //int err; UINT8 table_id; STATUS status = statusOK; //dprint(2, "%s: \n", __FUNCTION__); // sanity check if (tsport == NULL || desc == NULL) { return statusInvalidArgument; } #if 0 if (desc->psiCtl != tsport->tsd) { dprint(0, "!! tsd diff: desc %x, port %x\n", desc->psiCtl, tsport->tsd); return statusError; } #endif if (desc->numSections < 1) { dprint(0, "!! invalid numSection %d\n", desc->numSections); return statusError; } table_id = desc->sectPtr[0][0]; dprint(2, "============ pid %x, tid %02x (%s)\n", desc->pid, table_id, PSIUTIL_TidString(table_id)); /* °¢ Å×ÀÌºí º°·Î ³ª´²¼­ ó¸®ÇÑ´Ù. */ switch (table_id) { case PROGRAM_ASSOCIATION_SECTION: status = ProcessPAT(tsport, desc); break; case TS_PROGRAM_MAP_SECTION: status = ProcessPMT(tsport, desc); break; case tid_master_guide_table: status = ProcessMgt(tsport, desc); break; case tid_terr_virtual_chan_table: case tid_cable_virtual_chan_table: status = ProcessVct(tsport, desc); break; case tid_system_time_table: status = ProcessStt(tsport, desc); break; //case tid_rating_region_table: // break; case tid_event_information_table: status = ProcessEit(tsport, desc); break; case tid_extended_text_table: status = ProcessEtt(tsport, desc); break; default: dprint(0, "!! unknown table..\n"); break; }; DHL_PSI_FreePSIData(desc); return status; } E_PSIM_MODULE_STATE PSIE_GetModuleState(S_PSIM_CONTEXT *pContext) { return pContext->state; } void PSIE_ChangeModuleState(S_PSIM_CONTEXT *pContext, E_PSIM_MODULE_STATE newState) { pContext->state = newState; } UINT32 PSIE_GetTimeout(S_PSIM_CONTEXT *pContext) { // module state ¿¡ µû¶ó Àû´çÇÑ timeout À» °áÁ¤Çؼ­ ¸®ÅÏÇÑ´Ù. // periodic processing ÀÌ ÇÊ¿ä ¾ø´Â state¿¡¼­´Â wait_forever ¸¦ ¸®ÅÏ. // return PSIM_WAIT_FOREVER; // wait forever } void PSIE_DoPeridicProcessing(S_PSIM_CONTEXT *pContext) { // this task is stateless and don't have periodic processing. //CheckPmtTimeout(); } /* */ S_PSIM_CONTEXT *PSIE_GetEngine(void) { return g_psi_engine; } #if COMMENT ____Init____(){} #endif void PSIE_DumpTsPort(int index); static DHL_SymbolTable __symbols[] = { //---- func DHL_FNC_SYM_ENTRY2("psi_list", PSIDB_PrintAllTables), DHL_FNC_SYM_ENTRY2("psi_port", PSIE_DumpTsPort), DHL_FNC_SYM_ENTRY2("psi_delete", DMW_PSI_DeleteTables), //---- vars DHL_VAR_SYM_ENTRY(g_Trace_bPsiEvent), DHL_VAR_SYM_ENTRY(g_Trace_bPsiSttInfo), //DHL_VAR_SYM_ENTRY(g_Trace_PsiEngine), }; /* psi scan engineÀ» ÃʱâÈ­ ÇÑ´Ù. */ S_PSIM_CONTEXT *PSIE_InitEngine(void) { S_PSIM_CONTEXT *pContext; S_PSIM_PORT *tsport; int i; dprint(2, "%s:\n", __FUNCTION__); // allow multiple init trying.. // but we don't guarantee race condition. just for testing. if (g_psi_engine && g_psi_engine->magic == PSI_ENGINE_MAGICKEY ) { dprint(0, "already inited\n"); return g_psi_engine; } DHL_DBG_RegisterSymbols(__symbols, DHL_NUMSYMBOLS(__symbols)); pContext = DHL_OS_Malloc(sizeof(S_PSIM_CONTEXT)); if (!pContext) return NULL; pContext->magic = PSI_ENGINE_MAGICKEY; pContext->state = ePSIM_MODULE_STATE_Init; tsport = pContext->tsport; for (i=0; i= MAX_TS_INPUT) { dprint(0, "!! invalid port index %d\n", index); return; } tsport = &pContext->tsport[index]; OS_DbgPrintf("tsport [%d]:\n", index); OS_DbgPrintf(" tsd: 0x%x\n", tsport->tsd); OS_DbgPrintf(" input rf %d, # %d, sid %d, flags 0x%x, proc %x, param %x\n", tsport->input.rf, tsport->input.program_number, tsport->input.source_id, tsport->input.flags, tsport->input.userproc, tsport->input.userparam); OS_DbgPrintf(" # of active monitors %d / max %d\n", tsport->n_active_monitors, tsport->max_monitors); OS_DbgPrintf(" -- psictls --\n"); OS_DbgPrintf(" pat %x, # pgm %d\n", tsport->patPsiCtl, tsport->num_programs); for (i=0; inum_programs; i++) OS_DbgPrintf(" (%d) pmt %x\n", i, tsport->pmtPsiCtlArray[i]); OS_DbgPrintf(" mgt %x, stt %x, tvct %x, cvct %x, rrt %x, eas %x\n", tsport->mgtPsiCtl, tsport->sttPsiCtl, tsport->tvctPsiCtl, tsport->cvctPsiCtl, tsport->rrtPsiCtl, tsport->easPsiCtl); OS_DbgPrintf(" source id %d\n", tsport->source_id); OS_DbgPrintf(" eits %x %x %x %x..\n", tsport->eitPsiCtl[0], tsport->eitPsiCtl[1], tsport->eitPsiCtl[2], tsport->eitPsiCtl[3]); OS_DbgPrintf(" etts %x %x %x %x..\n", tsport->ettPsiCtl[0], tsport->ettPsiCtl[1], tsport->ettPsiCtl[2], tsport->ettPsiCtl[3]); OS_DbgPrintf(" ett-v %x\n", tsport->ettvPsiCtl); } /* End of file */