/* DMW_PsiDatabase.c DST TV MW PSI Scan Module PSI Database management implementation Copyright 2006~2009 Digital STREAM Technology, Inc. All Rights Reserved */ #include "DMW_Platform.h" #include "DMW_PsiUtil.h" #include "DMW_PsiDatabase.h" #include "DMW_PsiEngine.h" #include "DMW_PsiLinkedList.h" #include "DMW_PsiAPI.h" // additional headers #include "DMW_Mutex.h" #include "DMW_CodeConv.h" #if COMMENT ____DbgPrint____(){} #endif DHL_MODULE("psidb", 1); #if COMMENT ____Config____(){} #endif int gPsiDontDownloadChannelEtt = 0; // ½ÇÁ¦ Çʵ忡¼­ Channel ETT°°Àº °æ¿ì´Â Mgt¿¡ µî·ÏÀº µÇ¾î ÀÖÀ¸¸é¼­ ½ÇÁ¦·Î´Â ¾ø´Â °æ¿ì°¡ ÀÖ´Ù. // ±×·¡¼­ Å×/½º/Æ®/·Î À̸¦ ¸·¾Æ¹ö¸®´Â ¿É¼ÇÀ» µÎ¾úÀ½. // ±×·¯³ª ÀÌ ¿É¼ÇÀ» ½ÇÁ¦ ¾ç»ê ÇÁ·Î±×·¥¿¡ Àû¿ëÇϱâ´Â ¾î·Æ´Ù.. int gPsiReloadAllTableAtMgtChange = 0; // Mgt check·çƾÀÌ ¹®Á¦°¡ ÀÖÀ» °æ¿ì À̰ÍÀ» 1·Î ÇØ¼­ ¹«Á¶°Ç ´Ù½Ã ¹Þµµ·Ï ÇÏ´Â ¿É¼Ç.. // ÀÌ ¿É¼ÇÀ» ¾²¸é À߸øµÈ PSIP¿¡ ´ëÇØ Á» ´õ ¾ÈÀüÇÏ°Ô ´ëÀÀÀÌ °¡´ÉÇϱâ´Â ÇÏ´Ù.. // ´ë½Å ´Ù½Ã ¸ðµç tableÀ» ¹Þ¾Æ¾ß ÇϹǷΠ½Ã°£Àº ´õ °É¸±°ÍÀÓ.. // Á¦´ë·Î ÇÏ·Á¸é FALSE À̾î¾ß ÇÔ. // Å×½ºÆ® °á°ú ÀÌ ¿É¼ÇÀÌ ¾øÀ̵µ ´ëü·Î Àß µ¿ÀÛÇÏ´Â °Í °°¾Æ¼­ ¸·¾ÆµÒ.. int gPsiFakeMgtVersionChange = 0; // mgt°¡ ¹öÀüÀÌ ¹Ù²ï°Íó·³ Èä³»³»´Â Å×½ºÆ® Ç÷¡±×.. // TRUEÀÌ¸é ¸Å¹ø mgt ÀÌÇÏ ¸ðµç Å×À̺íÀ» ´Ù½Ã ¹ÞÀ¸¹Ç·Î »ç¿ë ÁÖÀÇ!!! int gPsiInterTableCompareInMgtChange = 1; // ÀÌ °ªÀÌ TRUE À̸é Mgt version change ½Ã¿¡ ¼­·Î ´Ù¸¥ index °£ÀÇ Eit/Ett tableµéÀ» // ºñ±³Çغ¸¾Æ¼­ ÃÖ´ëÇÑ Àç»ç¿ëÀ» ÇÑ´Ù. // ¿¹¸¦ µé¾î ÀÌÀü mgtÀÇ Eit-3 °ú »õ mgtÀÇ Eit-2 °¡ ¹öÀü°ú table Å©±â°¡ °°À¸¸é À̸¦ // Àç»ç¿ëÀ» ÇÑ´Ù. // ±×·±µ¥ Spec¿¡ ÀÇÇϸé ÀÌ °ªÀº 0ÀÌ µÇ¾î¾ß ÇÑ´Ù. (A/65) // ¾îµð±îÁö³ª À̰ÍÀº ¹æ¼Û»ç PSIP generation programÀÇ µ¿ÀÛ¿¡ µû¶ó À¯¿ëÇÒ¼öµµ, ¾øÀ» ¼öµµ ÀÖ´Ù. // ±×·¯³ª 1À̶ó¸é Sarnoff ¿¹Á¦¿Í °°ÀÌ Eit shiftÇÏ´Â °æ¿ì ÁÁÀº ¼º´ÉÀ» º¸ÀÏ ¼ö ÀÖ´Ù. // ´ëü·Î ¿ÏÀüÈ÷ ¼­·Î ´Ù¸¥ Å×À̺íÀÌ ¹öÀüµµ °°°í, table sizeµµ °°À» °æ¿ì°¡ ÈçÇÏÁö ¾ÊÀ¸¹Ç·Î // ÀÏ´Ü TRUE·Î ÇØ¼­ Å×½ºÆ®¸¦ Çϰí ÀÖÀ½.. // ¹®Á¦°¡ µÇ¸é 0À¸·Î ¼³Á¤Çϱ⠹ٶ÷. int gPsiDeleteEttsWhenEitChange = 1; // Eit°¡ ¹Ù²ð°æ¿ì ±×¿¡ ÇØ´çÇÏ´Â Ett¸¦ ¹«Á¶°Ç Áö¿ì´Â Ç÷¡±× // º¸ÅëÀº Ettµµ ¹öÀü üũ¸¦ ÇØ¼­ º¯°æµÇ¾ú´Ù°í ÆÇ´ÜµÇ´Â °æ¿ì¿¡¸¸ Áö¿ì´Â°Ô ÁÁ°Ú´Ù. // PSIP Ç¥ÁØ¿¡ ÀÇÇÏ¸é ³»¿ëÀÌ ¹Ù²î¸é ¹Ýµå½Ã ¹öÀüµµ ¹Ù²ð °ÍÀ̹ǷΠ// ¹«Á¶°Ç Áö¿ìÁö ¾Ê¾Æµµ ¹öÀü üũ ·çƾ¿¡¼­ ÆÇ´ÜÇÏ¿© ÇÊ¿äÇÏ¸é ´Ù½Ã ¹ÞÀ» °ÍÀÌ´Ù. int gPsiMaxEitEttIndexToReceive = 127; // // Eit/Ett¸¦ ¸ðµÎ ´Ù ¹ÞÀ» Çʿ䰡 ¾ø´Â ½Ã½ºÅÛÀÌ Àִµ¥, // ±×·± °æ¿ì ÃÖ´ë Index¸¦ ÁöÁ¤ÇØ ³õÀ¸¸é ÇÊ¿äÇÑ ¸¸Å­¸¸ ¹Þ°Ô µÈ´Ù. // 127 ÀÌ¸é ¸ðµÎ ´Ù ¹Þ´Â °ÍÀ̰í, // -1·Î ÁöÁ¤Çϸé Eit/Ett´Â Çϳªµµ ¹ÞÁö ¾Ê´Â´Ù.. // // 0 ºÎÅÍ 127 ±îÁö ÀÓÀÇÀÇ ¼ö¸¦ ÁöÁ¤ ÇÒ ¼ö ÀÖ´Ù. ´Ü Runtime Áß¿¡´Â º¯°æµÇÁö ¾Êµµ·Ï ÇÏÀÚ. int gPsiSkipCheckVersionMatchMgtAndEit = 0; int gPsiSkipCheckVersionMatchMgtAndEtt = 0; // // mgt¿¡¼­ ±â¼úÇϰí ÀÖ´Â EitÀÇ version ¹øÈ£¿Í ½ÇÁ¦ EitÀÇ version ¹øÈ£°¡ // ÀÏÄ¡ÇÏ´ÂÁö üũÇÏ´Â Äڵ带 skip. // ºÎÀÛ¿ëÀÌ ÀÖÀ» ¼ö ÀÖÀ½. // mgt versionÀÌ º¯°æµÇ¸é¼­ ½ÇÁ¦·Î eit versionÀº º¯°æµÇÁö ¾Ê¾Ò´õ¶óµµ // eit¸¦ ´Ù½Ã ´Ù¿î·Îµå ¹Þ°Ô µÊ. // ORIONÀÇ ¿©·¯ ½ºÆ®¸²µéÀ» Å×½ºÆ® ÇÏ·Á¸é ÀÌ flag ÇÊ¿ä. #if COMMENT ____DB____(){} #endif #if DMW_EPG_SUPPORT_RRT extern rrtSectionPtr_t g_EpgRrt; // ¼ö½ÅÇÑ rrt extern UINT32 g_EpgRrtUpdateCount; // rrt°¡ update µÉ ¶§ ¸¶´Ù Áõ°¡ÇÏ´Â counter extern int g_EpgRrtForceUpdateMode; // force update mode: // ÀÌ¹Ì ¼ö½ÅµÇ¾î ÀÖ´Â rrt version¿¡ °ü°è¾øÀÌ ¹«Á¶°Ç rrt¸¦ ´Ù½Ã ¹Þ´Â ¸ðµå. // ³»ºÎ state variable À̸ç, // menu¿¡¼­ »ç¿ëÀÚ°¡ "rrt update" ±â´ÉÀ» ¼±ÅÃÇϸé ÀÌ flag°¡ setµÇ°í // rrt¸¦ 1ȸ updateÇϸé ÀÚµ¿À¸·Î reset µÈ´Ù. #endif #if COMMENT ____Mutex____(){} #endif //=========================================================================== // // Mutex Service // // Mutex = { SemID, Owner, lockCnt, FailCnt, UseOsMutex, Name, flag, traceLvl } // DMW_MUTEX g_MutexPsiDB = { 0, 0, 0, 0, TRUE, "PSI", OS_SEM_PRIO, FALSE, }; // cafrii 050701 change UseOsMutex param to TRUE // ThreadX¿¡¼­´Â OS mutex°¡ ¾ÈÀüÇϱ⠶§¹®¿¡ µð¹ö±ë ÆíÀÇ»ó OS Mutex¸¦ »ç¿ëÇÑ´Ù. // g_EpgDB --> ChannelInfo, SubChannelInfo µ¥ÀÌÅ͸¦ º¸È£Çϴµ¥ »ç¿ëµÇ´Â mutex semaphore // // Rule 1: // EPG Scan Task ¿¡¼­´Â EpgDB´Â ¾Æ¹«¶§³ª ¸¶À½µ¥·Î ÀÐÀ» ¼ö ÀÖ´Ù. // EPG Scan Task ¿¡¼­ EpgDB¸¦ ¼öÁ¤ (write) ÇÒ °æ¿ì¿¡´Â Mutex LockÀ» ÇØ¾ß ÇÑ´Ù. // // Rule 2: // ÀÓÀÇÀÇ Task ¿¡¼­´Â EpgDB¸¦ Àý´ë ¼öÁ¤ ÇÒ ¼ö ¾ø´Ù. // ÀÓÀÇÀÇ Task ¿¡¼­ EpgDB¸¦ ÀÐÀ¸·Á¸é Mutex Lock »óÅ¿¡¼­ Àоî¾ß ÇÑ´Ù. // PSI_STATIC void LockPsiDB(BOOL bLock) { if (bLock) DMW_LockMutex(&g_MutexPsiDB); else DMW_UnlockMutex(&g_MutexPsiDB); } #if 0 void DeletePsiDBMutex(void) { DMW_DeleteMutex(&g_MutexPsiDB); } #endif #if COMMENT ____Get_API____(){} #endif PSI_STATIC S_PSIM_SUBCHINFO *GetSubChInfo(int id, int source_id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); int i; if (!chInfo) return NULL; if (chInfo->n_subchannel == 0 || chInfo->subchannel == NULL) return NULL; for (i=0; in_subchannel; i++) { if (chInfo->subchannel[i].source_id == source_id) return &chInfo->subchannel[i]; } return NULL; } /* database lockÀº ÇÏÁö ¾ÊÀ¸¹Ç·Î, caller°¡ ÁÖÀÇÇØ¼­ »ç¿ëÇÒ °Í. */ MPEG_PAT *PSIDB_GetPAT(int id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); return chInfo ? chInfo->pat : NULL; } MPEG_PMT **PSIDB_GetPMTs(int id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); return chInfo ? chInfo->pmts : NULL; } mgtSectionPtr_t PSIDB_GetMgt(int id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); return chInfo ? chInfo->mgt : NULL; } xvctPtr_t PSIDB_GetVct(int id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); return chInfo ? chInfo->vct : NULL; } sttSectionPtr_t PSIDB_GetStt(int id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); return (chInfo && chInfo->stt_valid) ? &chInfo->flat_stt : NULL; } eitPtr_t *PSIDB_GetEits(int id, int source_id) { S_PSIM_SUBCHINFO *subchInfo = GetSubChInfo(id, source_id); return subchInfo ? subchInfo->eits : NULL; } eitPtr_t PSIDB_GetEit(int id, int source_id, int iEit) { eitPtr_t *eits; if (iEit<0 || iEit>=128) return NULL; eits = PSIDB_GetEits(id, source_id); return eits ? eits[iEit] : NULL; } S_PSIM_MGT_DIGEST *PSIDB_GetMgtDigest(int id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); return chInfo ? &chInfo->smgt : NULL; } #if COMMENT ____Check____(){} #endif /* check that all pmts (and pat) are received. */ BOOL PSIDB_IsPmtsCompleted(int id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); int i; BOOL bPmtComplete = TRUE; if (!chInfo) return FALSE; if (!chInfo->pat || !chInfo->pmts) return FALSE; for (i=0; ipat->numPrograms; i++) { if (chInfo->pmts[i] == NULL) { bPmtComplete = FALSE; break; } } return bPmtComplete; } /* check that subchannel scan is ready to start. both mgt and vct is required. */ BOOL PSIDB_IsSubChScanReadyToStart(int id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); if (!chInfo) return FALSE; return (chInfo->mgt && chInfo->vct) ? TRUE : FALSE; } /* ÇØ´ç subchannel (@id, @source_id)ÀÇ ¸ðµç EIT°¡ ¼ö½ÅµÇ¾ú´ÂÁö °Ë»ç. complete µÇ¾ú´Ù¸é TRUE ¸®ÅÏ. return true if all eits in the specified subchannel (with @source_id) are received. */ BOOL PSIDB_IsSubChEitsCompleted(int id, int source_id) { int i, maxEitIndex; BOOL bEitsCompleted = FALSE; S_PSIM_SUBCHINFO *subchInfo; S_PSIM_CHINFO *chInfo; S_PSIM_MGT_DIGEST *smgt; subchInfo = PSIDB_GetPsiSubChInfo(id, source_id); if (!subchInfo) goto label_end; chInfo = subchInfo->parent; if (!chInfo) goto label_end; smgt = &chInfo->smgt; maxEitIndex = min(127, gPsiMaxEitEttIndexToReceive); for (i=0; i<=maxEitIndex; i++) { if (smgt->eit_pids[i] == 0) continue; // no such eit[i]. if (subchInfo->eits[i] == NULL) { dprint(2, " eit-%d not received..\n", i); goto label_end; } if (smgt->eit_ver[i] != subchInfo->eits[i]->version_number) { if (gPsiSkipCheckVersionMatchMgtAndEit) dprint(1, "!! eit-%d (ver %d) version mismatch (mgt's %d), but continue\n", i, subchInfo->eits[i]->version_number, smgt->eit_ver[i]); else { dprint(0, "!! eit-%d (ver %d) version mismatch (mgt's %d)\n", i, subchInfo->eits[i]->version_number, smgt->eit_ver[i]); goto label_end; // need to receive again.. } } } bEitsCompleted = TRUE; label_end: return bEitsCompleted; } /* check eit[@iEit] of all subch received or not. if all received, return true. if it returns true, caller will close eit psi filter. it is used for autoscan mode. if status is not correct, return false. */ BOOL PSIDB_IsAllSubChEitsCompleted(int id, int iEit) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); int i; if (iEit < 0 || iEit >= 128) return FALSE; if (!chInfo) return FALSE; if (chInfo->n_subchannel == 0 || chInfo->subchannel == NULL) return FALSE; for (i=0; in_subchannel; i++) { if (chInfo->subchannel[i].eits[iEit] == NULL) return FALSE; } return TRUE; } /* PSIDB_IsSubChEttVRequired ƯÁ¤ subchannel (@id, @source_id)ÀÇ channel_ett°¡ ¼ö½ÅµÇ¾î¾ß ÇÏ´ÂÁö¸¦ °Ë»ç. ¼ö½ÅµÇ¾î¾ß ÇÑ´Ù¸é true ¸®ÅÏ. ÁÖÀÇ! channel_ett°¡ ¹Þ¾ÆÁ³´ÂÁö¸¦ üũÇÏ´Â °ÍÀÌ ¾Æ´Ï¶ó ¹Þ¾Æ¾ß ÇÏ´ÂÁö¸¦ üũ. */ BOOL PSIDB_IsSubChEttVRequired(int id, int source_id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); BOOL bEttvRequired = FALSE; int i; int ettv_etm_loc = -1; if (chInfo->vct && chInfo->vct->channel) { for (i=0; ivct->numChannels; i++) { if (chInfo->vct->channel[i].source_id == source_id) { ettv_etm_loc = chInfo->vct->channel[i].ETM_location; break; } } } if (ettv_etm_loc == -1) { dprint(0, "!! vct invalid! cannot find source_id %d\n", source_id); } else if (chInfo->smgt.channel_ett_pid && // MGT¿¡ channel ETT°¡ µî·ÏÀÌ µÇ¾î ÀÖ°í, gPsiDontDownloadChannelEtt == FALSE && // Å×½ºÆ® Á¶°ÇÀÌ ¾Æ´Ï¸é¼­, (ettv_etm_loc == ETM_in_this_PTC || ettv_etm_loc == ETM_in_channel_TSID_PTC)) // ETT°¡ ÀÖ´Ù°í µî·ÏµÇ¾î ÀÖÀ¸¸é, { bEttvRequired = TRUE; } #if 0 // IgnoreEtmLocationInfo optionÀº psi engine module ¿¡¼­¸¸ »ç¿ëÇϵµ·Ï ÇÏÀÚ. else if (chInfo->smgt.channel_ett_pid && gPsiDontDownloadChannelEtt == FALSE && gPsiIgnoreEtmLocationInfo) // ettv_etm_locÀÇ °ª¿¡ °ü°è¾øÀÌ (ETM_none Æ÷ÇÔ) ¹«Á¶°Ç ¹Þ´Â ¿É¼Ç { bEttvRequired = TRUE; } #endif return bEttvRequired; } /* PSIDB_IsSubChEttSlotCompleted ÁöÁ¤ÇÑ subchannelÀÇ Æ¯Á¤ time slot (iEit)ÀÇ ¸ðµç Eit/Ett °¡ ¼ö½Å ¿Ï·á µÇ¾ú´ÂÁö¸¦ üũÇÑ´Ù. return true if all etts in the specified subchannel (with @source_id) are received. */ BOOL PSIDB_IsSubChEttSlotCompleted(int id, int source_id, int iEit) { // ÀÌ ÇÔ¼ö´Â Eit °¡ ¸ðµÎ ¿Ï·áµÈ »óÅ¿¡¼­¸¸ ±× Àǹ̰¡ ÀÖ´Ù. // Eit°¡ ¾øÀÌ Ett¸¦ ¼ö½ÅÇÒ ¼ö´Â ¾ø±â ¶§¹®... // Eit°¡ ¾øÀ¸¸é FALSE ¸®ÅÏ.. Ett°¡ ¾ø¾îµµ FALSE ¸®ÅÏ.. Eit/Ett ¸ðµÎ ÀÖÀ¸¸é TRUE ¸®ÅÏ.. // int k; //, maxEttIndex; int n_etm; // number of etm in one eit instance. BOOL bEttsCompleted = FALSE; S_PSIM_SUBCHINFO *subchInfo; S_PSIM_CHINFO *chInfo; S_PSIM_MGT_DIGEST *smgt; subchInfo = PSIDB_GetPsiSubChInfo(id, source_id); if (!subchInfo) goto label_end; chInfo = subchInfo->parent; if (!chInfo) goto label_end; // get mgt digest info smgt = &chInfo->smgt; if (iEit == 128) { if (!PSIDB_IsSubChEttVRequired(id, source_id) || subchInfo->channel_ett) bEttsCompleted = TRUE; goto label_end; } if (iEit < 0 || iEit >= 128) { // invalid index.. goto label_end; } do { //---------- ¸ÕÀú eit À¯È¿¼º ºÎÅÍ Ã¼Å© ----------- if (smgt->eit_pids[iEit] == 0) continue; // Á¸ÀçÇÏÁö ¾Ê´Â EIT if (subchInfo->eits[iEit] == NULL) { dprint(2, " Eit-%d not received..\n", iEit); goto label_end; } if (smgt->eit_ver[iEit] != subchInfo->eits[iEit]->version_number) { if (gPsiSkipCheckVersionMatchMgtAndEit) dprint(1, "!! eit-%d (ver %d) version mismatch (mgt's %d) but continue\n", iEit, subchInfo->eits[iEit]->version_number, smgt->eit_ver[iEit]); else { dprint(0, "!! eit-%d (ver %d) version mismatch (mgt's %d)\n", iEit, subchInfo->eits[iEit]->version_number, smgt->eit_ver[iEit]); goto label_end; // need to receive again.. } } if (subchInfo->eits[iEit]->event == NULL) continue; // ºñ¾ú´Â eitÀ̸é? ETT°¡ ÀÖÀ» ¼ö°¡ ¾øÀ» °ÍÀÌ´Ù.. ´ÙÀ½ eit üũ.. //---------- ett À¯È¿¼º üũ ----------- if (smgt->ett_pids[iEit] == 0) continue; // ETT°¡ ¾ø´Ù¸é ´ÙÀ½.. for (k=0, n_etm=0; keits[iEit]->numEvents; k++) { if (subchInfo->eits[iEit]->event[k].ETM_location != ETM_none) n_etm++; // ÀÌ EIT¿¡ °ü·ÃµÈ ETT °¹¼ö.. } if (n_etm <= 0) continue; // ¿ø·¡ ETT ¾øÀ½.. if (subchInfo->etts[iEit] == NULL || subchInfo->n_ett[iEit] == 0) { dprint(2, " eit[%d] exist, but etts array NULL or n_ett 0 %d\n", iEit, subchInfo->n_ett[iEit]); goto label_end; } if (subchInfo->eits[iEit]->numEvents != subchInfo->n_ett[iEit]) { dprint(2, " num event %d != n_ett %d\n", subchInfo->eits[iEit]->numEvents, subchInfo->n_ett[iEit]); goto label_end; } //---------- ett °¢ event º° üũ ----------- for (k=0; kn_ett[iEit]; k++) { BOOL bSkipThisEtt = FALSE; UINT32 etmid = PSIUTIL_MakeEventETMID(subchInfo->source_id, subchInfo->eits[iEit]->event[k].event_id); int ii, kk; if (subchInfo->etts[iEit][k] && subchInfo->etts[iEit][k]->ETM_id == etmid) continue; // ¼ö½ÅµÇ¾úÀ½.. ´ÙÀ½.. // ²À ÀÌ Eit PID¿¡¸¸ ¾Æ´Ï¶ó ±× ÀÌÀü EitµéÀÇ PID¿¡µµ Á¸ÀçÇÒ °æ¿ì°¡ ÀÖ´Ù.. // 3-hour °æ°è¿¡ °ÉÃÄ ÀÖ´Â eventÀÇ °æ¿ì ¾ÕÂÊ eventÀÇ PID¿¡ ett°¡ ÀÖÀ» ¼ö ÀÖ´Ù. // ±×·¯¹Ç·Î ÇöÀç Ett table pointer°¡ NULL À̶ó°í ÇØ¼­ ¹Ù·Î FALSE ó¸®ÇÏ¸é ¾ÈµÈ´Ù. // ¾ÕÀÇ ¸ðµç tableµéÀ» ã¾ÆºÁ¾ß ÇÑ´Ù. // for (ii=iEit; ii>=0; ii--) { // ÇöÀç Etts[iEit]ºÎÅÍ Etts[0] ±îÁö ¾ÕÀ¸·Î µÇµ¹¾Æ°¡¸é¼­, if (subchInfo->etts[ii] == NULL) continue; // °¢ Ett sectionÀ» °Ë»çÇØ¼­ ÇöÀç ¹ÞÀ¸·Á°í ÇÏ´Â etm_idÀÇ ett°¡ ¹Þ¾ÆÁ® ÀÖ´ÂÁö °Ë»çÇÑ´Ù. for (kk=0; kkn_ett[ii]; kk++) { if (subchInfo->etts[ii][kk] && subchInfo->etts[ii][kk]->ETM_id == etmid) { // °°Àº etm_id¸¦ °¡Áø Ett°¡ ÀÌ¹Ì ¼ö½ÅµÇ¾î ÀÖ´Ù¸é, ¹ÞÀ» ÇÊ¿ä ¾ø´Ù. dprint(3, " Ett-%d[ev %d]: same etmid 0x%x (ett-%d ev%d pid %d) exist. \n", iEit, k, etmid, ii, kk, smgt->ett_pids[ii]); bSkipThisEtt = TRUE; break; } } if (bSkipThisEtt) break; } if (bSkipThisEtt) continue; if (subchInfo->eits[iEit]->event[k].ETM_location != ETM_none && subchInfo->etts[iEit][k] == NULL) { dprint(2, " ett-%d[ev %d] etm_loc %d, but ett NULL\n", iEit, k, subchInfo->eits[iEit]->event[k].ETM_location); goto label_end; } } } while (0); bEttsCompleted = TRUE; // OK.. All eits are completed. label_end: return bEttsCompleted; } /* PSIDB_IsSubChAllEttsCompleted ÁöÁ¤ÇÑ subchannelÀÇ ¸ðµç Eit/Ett °¡ ¼ö½Å ¿Ï·á µÇ¾ú´ÂÁö¸¦ üũÇÑ´Ù. ÀÌ ÇÔ¼ö´Â channel ett ÀÇ ¼ö½Å ¿©ºÎ¸¦ üũÇÒ ¶§ ¹Ì¸® °è»êµÈ boolean flag¸¦ »ç¿ëÇϱ⠶§¹®¿¡ ÇØ´ç subchannel¿¡ ´ëÇØ¼­ update etts ÇÔ¼ö°¡ ¸ÕÀú ºÒ¸° ´ÙÀ½¿¡¸¸ »ç¿ëµÇ¾î¾ß ÇÑ´Ù. Áï »ç¿ë ½ÃÁ¡¿¡ ÁÖÀǸ¦ ¿äÇÑ´Ù. return true if all etts in the specified subchannel (with @source_id) are received. */ BOOL PSIDB_IsSubChAllEttsCompleted(int id, int source_id) { // ÀÌ ÇÔ¼ö´Â Eit °¡ ¸ðµÎ ¿Ï·áµÈ »óÅ¿¡¼­¸¸ ±× Àǹ̰¡ ÀÖ´Ù. // Eit°¡ ¾øÀÌ Ett¸¦ ¼ö½ÅÇÒ ¼ö´Â ¾ø±â ¶§¹®... // Eit°¡ ¾øÀ¸¸é FALSE ¸®ÅÏ.. Ett°¡ ¾ø¾îµµ FALSE ¸®ÅÏ.. Eit/Ett ¸ðµÎ ÀÖÀ¸¸é TRUE ¸®ÅÏ.. // int i, k, maxEttIndex; int n_etm; // number of etm in one eit instance. BOOL bEttsCompleted = FALSE; S_PSIM_SUBCHINFO *subchInfo; S_PSIM_CHINFO *chInfo; S_PSIM_MGT_DIGEST *smgt; // ÀÓÀÇ task¿¡¼­µµ »ç¿ëÇÒ ¼ö ÀÖ´Â ¿ëµµ¸¦ °í·ÁÇÒ ÇÊ¿ä´Â ¾øÀ» µí ÇÔ. //if (PSITASK_IsPsiTask()) // PSIDB_LockDB(TRUE); //------------------------- subchInfo = PSIDB_GetPsiSubChInfo(id, source_id); if (!subchInfo) goto label_end; chInfo = subchInfo->parent; if (!chInfo) goto label_end; // get mgt digest info smgt = &chInfo->smgt; if (PSIDB_IsSubChEttVRequired(id, source_id) && subchInfo->channel_ett == NULL) goto label_end; // ett-v °¡ ¼ö½ÅµÇ¾î¾ß Çϴµ¥ ¾ÆÁ÷ ¼ö½ÅÀÌ ¾ÈµÇ¾úÀ¸¹Ç·Î FALSE.. maxEttIndex = min(127, gPsiMaxEitEttIndexToReceive); // cafrii 041202 add for (i=0; i<=maxEttIndex; i++) { if (smgt->eit_pids[i] == 0) continue; // Á¸ÀçÇÏÁö ¾Ê´Â EIT if (subchInfo->eits[i] == NULL) { dprint(2, " Eit-%d not received..\n", i); goto label_end; } if (smgt->eit_ver[i] != subchInfo->eits[i]->version_number) { if (gPsiSkipCheckVersionMatchMgtAndEit) dprint(1, "!! eit-%d (ver %d) version mismatch (mgt's %d) but continue\n", i, subchInfo->eits[i]->version_number, smgt->eit_ver[i]); else { dprint(0, "!! eit-%d (ver %d) version mismatch (mgt's %d)\n", i, subchInfo->eits[i]->version_number, smgt->eit_ver[i]); goto label_end; // need to receive again.. } } if (subchInfo->eits[i]->event == NULL) continue; // ºñ¾ú´Â eitÀ̸é? ETT°¡ ÀÖÀ» ¼ö°¡ ¾øÀ» °ÍÀÌ´Ù.. ´ÙÀ½ eit üũ.. if (smgt->ett_pids[i] == 0) continue; // ETT°¡ ¾ø´Ù¸é ´ÙÀ½.. for (k=0, n_etm=0; keits[i]->numEvents; k++) { if (subchInfo->eits[i]->event[k].ETM_location != ETM_none) n_etm++; // ÀÌ EIT¿¡ °ü·ÃµÈ ETT °¹¼ö.. } if (n_etm <= 0) continue; // ¿ø·¡ ETT ¾øÀ½.. if (subchInfo->etts[i] == NULL || subchInfo->n_ett[i] == 0) { dprint(2, " eit[%d] exist, but etts array NULL or n_ett 0 %d\n", i, subchInfo->n_ett[i]); goto label_end; } if (subchInfo->eits[i]->numEvents != subchInfo->n_ett[i]) { dprint(2, " num event %d != n_ett %d\n", subchInfo->eits[i]->numEvents, subchInfo->n_ett[i]); goto label_end; } for (k=0; kn_ett[i]; k++) { BOOL bSkipThisEtt = FALSE; UINT32 etmid = PSIUTIL_MakeEventETMID(subchInfo->source_id, subchInfo->eits[i]->event[k].event_id); int ii, kk; if (subchInfo->etts[i][k] && subchInfo->etts[i][k]->ETM_id == etmid) continue; // ¼ö½ÅµÇ¾úÀ½.. ´ÙÀ½.. // ²À ÀÌ Eit PID¿¡¸¸ ¾Æ´Ï¶ó ±× ÀÌÀü EitµéÀÇ PID¿¡µµ Á¸ÀçÇÒ °æ¿ì°¡ ÀÖ´Ù.. // 3-hour °æ°è¿¡ °ÉÃÄ ÀÖ´Â eventÀÇ °æ¿ì ¾ÕÂÊ eventÀÇ PID¿¡ ett°¡ ÀÖÀ» ¼ö ÀÖ´Ù. // ±×·¯¹Ç·Î ÇöÀç Ett table pointer°¡ NULL À̶ó°í ÇØ¼­ ¹Ù·Î FALSE ó¸®ÇÏ¸é ¾ÈµÈ´Ù. // ¾ÕÀÇ ¸ðµç tableµéÀ» ã¾ÆºÁ¾ß ÇÑ´Ù. // for (ii=i; ii>=0; ii--) { // ÇöÀç Etts[i]ºÎÅÍ Etts[0] ±îÁö ¾ÕÀ¸·Î µÇµ¹¾Æ°¡¸é¼­, if (subchInfo->etts[ii] == NULL) continue; // °¢ Ett sectionÀ» °Ë»çÇØ¼­ ÇöÀç ¹ÞÀ¸·Á°í ÇÏ´Â etm_idÀÇ ett°¡ ¹Þ¾ÆÁ® ÀÖ´ÂÁö °Ë»çÇÑ´Ù. for (kk=0; kkn_ett[ii]; kk++) { if (subchInfo->etts[ii][kk] && subchInfo->etts[ii][kk]->ETM_id == etmid) { // °°Àº etm_id¸¦ °¡Áø Ett°¡ ÀÌ¹Ì ¼ö½ÅµÇ¾î ÀÖ´Ù¸é, ¹ÞÀ» ÇÊ¿ä ¾ø´Ù. dprint(3, " Ett-%d[ev %d]: same etmid 0x%x (ett-%d ev%d pid %d) exist. \n", i, k, etmid, ii, kk, smgt->ett_pids[ii]); bSkipThisEtt = TRUE; break; } } if (bSkipThisEtt) break; } if (bSkipThisEtt) continue; if (subchInfo->eits[i]->event[k].ETM_location != ETM_none && subchInfo->etts[i][k] == NULL) { dprint(2, " ett-%d[ev %d] etm_loc %d, but ett NULL\n", i, k, subchInfo->eits[i]->event[k].ETM_location); goto label_end; } } } bEttsCompleted = TRUE; // OK.. All eits are completed. label_end: //if (PSITASK_IsPsiTask()) // PSIDB_LockDB(FALSE); //------------------------- return bEttsCompleted; } #if COMMENT ____Free____(){} #endif // // note!! below PSIDB_FreeXXX don't care mutex lock. caller should lock. // /* eit[iEit]¿Í ¿¬°üµÈ ¸ðµç ettµé, ±×¸®°í ±×°Íµé°ú °ü·Ã data structure¸¦ Á¦°ÅÇÑ´Ù. ÃÖ´ë eit[iEit]->numEvents ¸¸Å­ÀÇ ettµé, ±×¸®°í ÀÌ ettµéÀ» ´ã°í ÀÖ´Â ett array¸¦ freeÇÔ. channel ett´Â ÇØ´ç »çÇ× ¾øÀ½. ÀÏ¹Ý event ett¸¸ »èÁ¦ÇÑ´Ù. */ void PSIDB_FreeEtts(S_PSIM_SUBCHINFO *subchInfo, int iEit) { // subchInfo´Â Non-NULL, i´Â 0 ~ 128-1 »çÀÌÀÇ °ªÀ̾î¾ß ÇÑ´Ù. int k; if (subchInfo == 0 || iEit < 0 || iEit >= 128) return; if (subchInfo->etts[iEit] == NULL) { // it is already freed. subchInfo->n_ett[iEit] = 0; return; } // ett ¸ðµÎ »èÁ¦ for (k=0; kn_ett[iEit]; k++) PSIUTIL_FreeTable(&subchInfo->etts[iEit][k]); // ett container »èÁ¦ DHL_OS_Free((void **)&subchInfo->etts[iEit]); subchInfo->n_ett[iEit] = 0; } /* eit[iEit]¸¦ Æ÷ÇÔÇÏ¿© °ü·ÃµÈ ¸ðµç ettµé°ú data structure¸¦ Á¦°ÅÇÑ´Ù. */ void PSIDB_FreeEitAndRelatedEtts(S_PSIM_SUBCHINFO *subchInfo, int iEit) { // subchInfo´Â Non-NULL, i´Â 0 ~ 128-1 »çÀÌÀÇ °ªÀ̾î¾ß ÇÑ´Ù. int k; if (subchInfo == NULL || iEit < 0 || iEit >= 128) return; // invalid argument error if (subchInfo->etts[iEit] == NULL) { subchInfo->n_ett[iEit] = 0; } else { // ett ¸ðµÎ »èÁ¦ for (k=0; kn_ett[iEit]; k++) PSIUTIL_FreeTable(&subchInfo->etts[iEit][k]); // ett container »èÁ¦ DHL_OS_Free((void **)&subchInfo->etts[iEit]); subchInfo->n_ett[iEit] = 0; } // eit »èÁ¦ PSIUTIL_FreeTable(&subchInfo->eits[iEit]); } /* subchannel³»ÀÇ ¸ðµç Á¤º¸¸¦ freeÇÑ´Ù. subchInfo ±¸Á¶Ã¼ ÀÚü´Â free ÇÏÁö ¾ÊÀ½. */ void PSIDB_FreeSubChInfo(S_PSIM_SUBCHINFO *subchInfo) { // subchannel info ¸ðµç Á¤º¸¸¦ »èÁ¦ÇÑ´Ù. int j, k; if (subchInfo == NULL) return; // todo.. inactive subchÀÇ °æ¿ì ÀÌ ÇÔ¼ö°¡ ºÒ¸®´Â°¡? if (subchInfo->active == 0) return; if (subchInfo->channel_ett) { dprint(2, " delete ett-v.. \n"); PSIUTIL_FreeTable(&subchInfo->channel_ett); } #if 0 for (k=0; k<128; k++) PSIDB_FreeEitAndRelatedEtts(subchInfo, k); #else // ¾î¶² tableµéÀÌ Áö¿öÁö´ÂÁö debug print¸¦ À§ÇØ Àç ÀÛ¼º.. // free etts for (k=0; k<128; k++) { if (subchInfo->etts[k] == NULL) continue; // No ETTs here.. for (j=0; jn_ett[k]; j++) { if (subchInfo->etts[k][j]) { dprint(3, " ett[%d][%d]: %x\n", k, j, subchInfo->etts[k][j]); PSIUTIL_FreeTable(&subchInfo->etts[k][j]); } } DHL_OS_Free((void **)&subchInfo->etts[k]); // ett container »èÁ¦ subchInfo->n_ett[k] = 0; } // free eits for (k=0; k<128; k++) { if (subchInfo->eits[k] == NULL) continue; dprint(3, " eit[%d]: %x\n", k, subchInfo->eits[k]); PSIUTIL_FreeTable(&subchInfo->eits[k]); } #endif //DHL_OS_Free((void **)&(subchInfo->eits)); // À̰ÍÀº µ¿ÀûÇÒ´çµÈ °ÍÀÌ ¾Æ´Ô!! subchInfo->active = FALSE; } void PSIDB_FreeChInfo(S_PSIM_CHINFO *chInfo) { int i; if (chInfo == NULL) return; if (chInfo->subchannel) { //dprint(2, " total %d subchannels..\n", chInfo->n_subchannel); for (i=0; in_subchannel; i++) { //dprint(2, " delete subchannel[%d] data..\n", i); PSIDB_FreeSubChInfo(&chInfo->subchannel[i]); } } //dprint(2, " delete subchannel info itself..\n"); DHL_OS_Free((void **)&(chInfo->subchannel)); //dprint(2, " delete tables in channel..\n"); //PSIUTIL_FreeTable(&chInfo->tvct); //PSIUTIL_FreeTable(&chInfo->cvct); PSIUTIL_FreeTable(&chInfo->vct); #if 0 PSIUTIL_FreeTable(&chInfo->stt); // cafrii 050330, stt changed to flat_stt #endif PSIUTIL_FreeTable(&chInfo->mgt); PSIUTIL_FreeTable(&chInfo->mgt_old); for (i=0; chInfo->pat && chInfo->pmts && ipat->numPrograms; i++) { //dprint(2, " delete pmt[%d]..\n", i); PSIUTIL_FreeTable(&chInfo->pmts[i]); } //dprint(2, " delete pat..\n"); PSIUTIL_FreeTable(&chInfo->pat); // do not reset contents!! // we need prev/next link to remove from linked list. //---memset(chInfo, 0, sizeof(S_PSIM_CHINFO)); } #if COMMENT ____Alloc_Remove____(){} #endif STATUS PSIDB_AllocateChInfoNode(int id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); if (chInfo) return statusOK; chInfo = PSI_NewChInfo(id); if (chInfo == NULL) return statusOutOfMemory; LockPsiDB(TRUE); PSI_InsertChInfo(chInfo); LockPsiDB(FALSE); return statusOK; } STATUS PSIDB_RemoveChInfoNode(int id) { S_PSIM_CHINFO *chInfo = PSI_GetChInfo(id); if (!chInfo) return statusOK; // not exist. LockPsiDB(TRUE); PSI_RemoveChInfo(chInfo); LockPsiDB(FALSE); return statusOK; } #if COMMENT ____Private____(){} #endif /* »õ·Î ¼ö½ÅµÈ MGT¸¦ º¸°í, ±âÁ¸ EpgDBÀÇ TableµéÀ» Á¤¸®ÇÑ´Ù. »õ·Î ¹Þ¾Æ¾ß ÇÏ´Â tableµéÀ̶ó¸é »èÁ¦, Àç»ç¿ëÀÌ °¡´ÉÇÏ¸é ±×´ë·Î µÐ´Ù. ÇöÀç @chInfo ³»¿¡ ÀúÀåµÇ¾î ÀÖ´Â mgt´Â old_mgt À̰í, ÀÎÀÚ·Î Àü´ÞµÈ @mgt´Â »õ mgtÀÌ´Ù. */ PSI_STATIC STATUS CheckAndProcessMgtVersionChange(S_PSIM_CHINFO *chInfo, mgtSectionPtr_t mgt) { // mgt version change ºÐ¼®.. // ÁÖÀÇ: // ÀÌ ÇÔ¼ö°¡ ºÒ¸®´Â ½ÃÁ¡Àº update ¶Ç´Â ÃÖÃÊ downloadÀÎ °æ¿ìÀε¥, // ÃÖÃÊ·Î ºÒ¸®´Â °æ¿ì¶ó¸é subchannel Á¤º¸°¡ ¾øÀ» ¼öµµ ÀÖÀ¸¹Ç·Î À¯ÀÇÇÑ´Ù. // int i, j, k; int offset; // EIT, ETTµéÀÇ shiftµÈ Â÷ÀÌ.. UINT8 candidate[128]; // Eit/EttÀÇ time-shift¿¡ ÀÇÇÑ mgt version changeÀÇ °æ¿ì ÇöÀç tableÀÇ Èĺ¸ °ªÀÌ´Ù. // ¿¹¸¦ µé¾î EitÀÇ °æ¿ì candidate[3] == 4 ÀÎ °æ¿ì, // ÇöÀç Eit-3 ÀÇ È帴 ¿¹Àü Eit-4 ÀÌ´Ù. // Áï, ÇöÀç mgtÀÇ Eit-3°ú ¿¹Àü mgtÀÇ Eit-4ÀÇ version°ú byte size°¡ µ¿ÀÏÇÏ´Ù´Â ÀǹÌÀÌ´Ù. // candidateÀÇ µðÆúÆ® °ªÀº 0xff ·Î¼­ ÀÌ´Â È帰¡ ¾øÀ½À» ÀǹÌÇÑ´Ù. S_PSIM_SUBCHINFO *subchInfo; mgtTablePtr_t tbl1, tbl2; dprint(1, "%s:\n", __FUNCTION__); if (chInfo == NULL) return statusInvalidArgument; if (chInfo->mgt == NULL) { dprint(2, "No Previous mgt..\n"); return statusOK; } if (chInfo->mgt->version_number == mgt->version_number && !gPsiFakeMgtVersionChange) { dprint(2, "MGT version (%d) same.. \n", mgt->version_number); // cafrii 050331 // ¹öÀü ºñ±³ ¸¸À¸·Î´Â ¾ÈÀüÇÏÁö ¸øÇÒ ¼ö ÀÖ´Ù. // version bit°¡ Àû±â ¶§¹®¿¡ ¼­·Î ´Ù¸¥ MgtÀÓ¿¡µµ ºÒ±¸ÇÏ°í ¹öÀüÀº °°À» ¼ö Àֱ⠶§¹®. // if (PSIUTIL_IsEquivalentMgt(chInfo->mgt, mgt)) { // equivalent¶õ Àǹ̴ mgtÀÇ versionÀº ½Å°æ¾²Áö ¾Ê°í // mgt ¾ÈÀÇ tableµéÀ» Çϳª¾¿ ºñ±³ÇØ ºÁ¼­ ³»¿ëÀÌ °°Àº ³»¿ëÀ̶ó´Â ¶æ. //dprint(2, "MGTs are equivalent..\n"); return statusOK; } else dprint(2, "!! MGTs are different while versions are same\n"); } // Basic Rule: // 1. ±âÁ¸ Å×À̺í Á¤º¸°¡ ¾ø¾úÀ¸¸é ´ç¿¬È÷ ¹«Á¶°Ç ¹Þ¾Æ¾ß ÇÑ´Ù. // (Ȥ½Ã Á¤º¸µµ ¾øÀÌ tableÀº ÀÖÀ» ¼öµµ ÀÖÀ¸¹Ç·Î ÀÌ °æ¿ì ±âÁ¸ Å×À̺íÀº »èÁ¦Çعö¸®ÀÚ) // // 2. ±âÁ¸ Å×ÀÌºí ¹öÀü°ú »õ Å×ÀÌºí ¹öÀüÀÌ ´Ù¸£¸é, ±âÁ¸ Å×À̺íÀÌ ÀÌ¹Ì ¼ö½ÅµÇ¾î ÀÖ´Â »óȲÀÌ¶óµµ // ±âÁ¸ Å×À̺íÀ» »èÁ¦ÇÏ°í ´Ù½Ã ¹Þ´Â´Ù. (¹°·Ð ±âÁ¸ Å×À̺íÀº ½Ã°£Á¦ÇÑÀ¸·Î ¸ø ¹Þ¾Æ¼­ ¾øÀ» ¼öµµ ÀÖ´Ù) // // 3. ±âÁ¸ Å×ÀÌºí ¹öÀü°ú »õ Å×ÀÌºí ¹öÀüÀÌ °°À¸¸é ±âÁ¸ Å×À̺íÀÌ ¾ø´Â °æ¿ì¿¡¸¸ Ãß°¡ÇÏ¿© ¹Þ´Â´Ù. // dprint(2, "MGT version changed %d -> %d.. analyzing..\n", chInfo->mgt->version_number, mgt->version_number); dprint(2, " old mgt : 0x%x, new mgt : 0x%x\n", chInfo->mgt, mgt); PSIUTIL_ComparePrintTwoMgts(chInfo->mgt, mgt, 3); // ÀÌ ½ÃÁ¡ºÎÅÍ ÀÌ ÇÔ¼ö ³¡³¯¶§±îÁö ¸ðµÎ DB LockÀ» ÇÑ´Ù. LockPsiDB(TRUE); // ¸ðµç subchannel¿¡ ÀÖ´Â eit/ett complete flag¸¦ reset ÇÑ´Ù.. for (i=0; in_subchannel; i++) { chInfo->subchannel[i].eit_complete = FALSE; chInfo->subchannel[i].ett_complete = FALSE; } if (gPsiReloadAllTableAtMgtChange) // mgt ¹öÀüÀÌ ¹Ù²î¸é Ç×»ó ¸ðµç Å×À̺íÀ» ´Ù½Ã ¹Þ´Â ¾ÈÀüÇÑ ¸ðµå.. { dprint(2, "## Policy1: Reload all tables at mgt version change\n"); if (chInfo->subchannel) // subchannel Á¤º¸°¡ ¾øÀ» ¼öµµ ÀÖÀ¸¹Ç·Î Ç×»ó üũÇÑ´Ù. { dprint(2, " total %d subchannels..\n", chInfo->n_subchannel); for (i=0; in_subchannel; i++) { PSIDB_FreeSubChInfo(&chInfo->subchannel[i]); } dprint(2, " delete subchannel info..\n"); // subchannel info ±× ÀÚü±îÁö ´Ù Áö¿ï Çʿ䰡 ÀÖ³ª? DHL_OS_Free((void **)&(chInfo->subchannel)); } dprint(2, " delete vct tables in channel..\n"); PSIUTIL_FreeTable(&chInfo->vct); } if (chInfo->vct && !chInfo->vct->is_cvct) { // ---------- TVCT check tbl1 = PSIUTIL_FindTableInMgt(chInfo->mgt, tt_terrestrial_VCT_cni_1); // ±âÁ¸ MGT¿¡¼­ ã°í, tbl2 = PSIUTIL_FindTableInMgt(mgt, tt_terrestrial_VCT_cni_1); // »õ MGT¿¡¼­ ã´Â´Ù. if (tbl2 == NULL || tbl1 == NULL) //PSIUTIL_FreeTable(&chInfo->tvct); PSIUTIL_FreeTable(&chInfo->vct); else { if (tbl1->table_type_version_number != tbl2->table_type_version_number) { dprint(2, "TVCT version changed %d->%d\n", tbl1->table_type_version_number, tbl2->table_type_version_number); //PSIUTIL_FreeTable(&chInfo->tvct); PSIUTIL_FreeTable(&chInfo->vct); // todo.. // À̶§ subchannel infoÀÇ ³»¿ëÀ» ´Ù Áö¿ö¾ß Çϴ°¡? source_idÀÇ ³»¿ëÀÌ º¯°æµÇ¾ú´ÂÁö üũ´Â? // n_subchannelÀÇ °¹¼ö°¡ º¯°æµÇ¾ú´ÂÁöÀÇ ¿©ºÎ?? } } } else if (chInfo->vct && chInfo->vct->is_cvct) { // ----------- CVCT check tbl1 = PSIUTIL_FindTableInMgt(chInfo->mgt, tt_cable_VCT_cni_1); tbl2 = PSIUTIL_FindTableInMgt(mgt, tt_cable_VCT_cni_1); if (tbl2 == NULL || tbl1 == NULL) //PSIUTIL_FreeTable(&chInfo->cvct); PSIUTIL_FreeTable(&chInfo->vct); else { if (tbl1->table_type_version_number != tbl2->table_type_version_number) { dprint(2, "CVCT version changed %d->%d\n", tbl1->table_type_version_number, tbl2->table_type_version_number); //PSIUTIL_FreeTable(&chInfo->cvct); PSIUTIL_FreeTable(&chInfo->vct); // todo.. // À̶§ subchannel infoÀÇ ³»¿ëÀ» ´Ù Áö¿ö¾ß Çϴ°¡? source_idÀÇ ³»¿ëÀÌ º¯°æµÇ¾ú´ÂÁö üũ´Â? // n_subchannelÀÇ °¹¼ö°¡ º¯°æµÇ¾ú´ÂÁöÀÇ ¿©ºÎ?? } } } if (gPsiFakeMgtVersionChange) { dprint(2, "******** simulation of mgt version change\n"); // ¸¶Ä¡ mgt version change°¡ ÀϾ°Í°ú °°Àº Èä³»¸¦ ³½´Ù. candidate´Â Çϳªµµ ¾ø´Â »óÅ·Π°¡Á¤.. // for (i=0; i<128; i++) candidate[i] = 0xff; // ¸ðµÎ ÀûÀýÇÑ candidate°¡ ¾ø´Â »óÅÂ.. offset = 0; goto label_move_new_eits; } // ----------- All EIT check dprint(2, " check eit version..\n"); for (i=0; i<128; i++) { // EITÀÇ °æ¿ì´Â 3-hour time shiftÀÇ °æ¿ì¸¦ °í·ÁÇÏ¿©, PID, version, byte size°¡ °°À¸¸é ´Ù¸¥ EIT¶ó ÇÏ¿©µµ // °°Àº ³»¿ëÀÏ ¼ö°¡ ÀÖ´Ù. // int search_end; candidate[i] = 0xff; // no candidate yet.. tbl2 = PSIUTIL_FindTableInMgt(mgt, tt_EIT_min+i); // »õ MGT¿¡¼­ EIT-i Á¤º¸¸¦ ã´Â´Ù. if (tbl2 == NULL) { //dprint(3, " new EIT-%d not exist..\n", i); continue; } if (gPsiInterTableCompareInMgtChange) search_end = min(i+3, 127); // Eit-i ºÎÅÍ Eit-(i+3)±îÁö ºñ±³.. else search_end = i; // µ¿ÀÏÇÑ Eit-i¸¸ ºñ±³.. // ±âÁ¸ MGT¿¡¼­ »õ EIT-iÀÇ Á¤º¸ (PID, version, bytesize)¿Í °°Àº EIT¸¦ ã´Â´Ù.. // for (k=i; k<=search_end; k++) { tbl1 = PSIUTIL_FindTableInMgt(chInfo->mgt, tt_EIT_min+k); // ¿¾³¯ MGT¿¡¼­ EIT-k Á¤º¸¸¦ ã´Â´Ù. if (tbl1 == NULL) continue; if (tbl1->table_type_PID == tbl2->table_type_PID && tbl1->table_type_version_number == tbl2->table_type_version_number && tbl1->number_bytes == tbl2->number_bytes) { // ÀÏ´Ü ¸ðµç Á¤º¸°¡ °°À¸¹Ç·Î ÀÌ tblÀ» »ç¿ëÇÒ ¼ö ÀÖÀ»°Í °°´Ù.. candidate[i] = k; dprint(3, " new Eit-%d same as Eit-%d (PID %x, v%d, %d)\n", i, k, tbl1->table_type_PID, tbl1->table_type_version_number, tbl1->number_bytes); break; } } if (candidate[i] == 0xff) dprint(3, " new Eit-%d should be downloaded..\n", i); } // ÀÌÁ¦ candidate[i]´Â // »õ EIT-i°¡ ¾ø´Ù¸é 0xff // »õ EIT-i°¡ Á¸ÀçÇϴµ¥ µ¿ÀÏÇÑ ¿¹Àü EIT°¡ ¾ø´Ù¸é 0xff // »õ EIT-i°¡ Á¸ÀçÇÏ°í µ¿ÀÏÇÑ ¿¹Àü EIT-k°¡ Á¸ÀçÇÑ´Ù¸é k¸¦ °¡Áø´Ù. // (±×·¯³ª EIT-k°¡ Áö±Ý ÇöÀç ¼ö½ÅµÇ¾î ÀÖ´Â »óŶó´Â°ÍÀ» ÀǹÌÇÏÁö´Â ¾Ê´Â´Ù. ´Ü¼øÈ÷ MGT Á¤º¸¿¡ ÀÇÇÑ °ªÀÌ´Ù.) // case 1: 3-hour boundary shiftÀÎ °æ¿ì // case 2: ÀϺΠEITÀÇ ³»¿ë¸¸ º¯°æµÈ °æ¿ì // µÎ °æ¿ì ¸ðµÎ µ¿ÀÏÇÑ ·ÎÁ÷À¸·Î ó¸® °¡´ÉÇÏ´Ù.. // // ¸ðµç offsetµéÀÌ µ¿ÀÏÇÑÁö üũÇÑ´Ù. Çϳª¶óµµ Ʋ¸®¸é ¸ðµÎ ¹«È¿È­ ½ÃŰÀÚ!! offset = -1; // offset default value.. for (i=0; i<128; i++) { if (candidate[i] == 0xff) continue; if (offset < 0) offset = candidate[i] - i; // candidate[i]´Â ¹Ýµå½Ã iº¸´Ù Å©°Å³ª °°Àº °ªÀÌ´Ù. else if (offset != (candidate[i] - i)) { dprint(2, " !! candidate[%d]=%d mismatch with offset %d\n", i, candidate[i], offset); dprint(2, " ignore all candidate offset value..\n"); for (k=0; k<128; k++) candidate[k] = 0xff; // ¸ðµÎ ¹«È¿È­... break; } } if (offset >= 0) dprint(2, " Eit match offset value is %d\n", offset); else { dprint(2, " No available old tables. offset is set to default 0\n"); offset = 0; // ÀÏÄ¡ÇÏ´Â °ÍÀÌ Çϳªµµ ¾ø´Ù¸é.. } label_move_new_eits: // ÀÌÁ¦ candidate°¡ ¾Æ´Ñ EIT´Â »èÁ¦Çϰí À̵¿ÇÑ´Ù.. for (k=0; chInfo->subchannel && kn_subchannel; k++) { if (chInfo->subchannel[k].active == 0) continue; subchInfo = &chInfo->subchannel[k]; dprint(2, " move eits for subchannel[%d]..\n", k); for (i=0; i<128; i++) { if (candidate[i] == i) { // same dprint(3, " reuse old Eit-%d\n", i); } else if (candidate[i] == 0xff) { // no match if (subchInfo->eits[i]) dprint(3, " delete old Eit-%d\n", i); // Ett±îÁö ´Ù °°ÀÌ Áö¿ï±î?? if (gPsiDeleteEttsWhenEitChange) PSIDB_FreeEitAndRelatedEtts(subchInfo, i); else PSIUTIL_FreeTable(&subchInfo->eits[i]); } else { // match with other eit if (subchInfo->eits[i]) { dprint(3, " overwrite old EIT-%d --> EIT-%d\n", candidate[i], i); if (gPsiDeleteEttsWhenEitChange) //dprint(3, " delete old Eit-%d and Ett-%d\n", i, i); PSIDB_FreeEitAndRelatedEtts(subchInfo, i); else { //dprint(3, " delete old Eit-%d\n", i); PSIUTIL_FreeTable(&subchInfo->eits[i]); } subchInfo->eits[i] = subchInfo->eits[candidate[i]]; subchInfo->eits[candidate[i]] = NULL; // cafrii add 040713 } else { dprint(3, " move old Eit-%d --> Eit-%d\n", candidate[i], i); subchInfo->eits[i] = subchInfo->eits[candidate[i]]; subchInfo->eits[candidate[i]] = NULL; // cafrii add 040713 } } } } // ----------- ETT check // ETTÀÇ °æ¿ì´Â EIT¿¡¼­ Á¤ÇØÁø offset value¸¦ ±×´ë·Î »ç¿ëÇϵµ·Ï ÇÑ´Ù. ¸ÂÁö ¾Ê´Â °æ¿ì ¸ðµÎ reloadÇÏÀÚ. if (gPsiInterTableCompareInMgtChange == 0) offset = 0; // inter table compare ¸ðµå°¡ ¾Æ´Ñ °æ¿ì¿¡´Â Ç×»ó °°Àº ¹øÈ£ÀÇ Ett-j : Ett-k¸¸À» ºñ±³ÇØ¾ß ÇÑ´Ù. dprint(2, " check ett version..\n"); for (i=0; i<128; i++) { candidate[i] = 0xff; // no candidate yet.. tbl2 = PSIUTIL_FindTableInMgt(mgt, tt_event_ETT_min+i); // »õ MGT¿¡¼­ EIT-i Á¤º¸¸¦ ã´Â´Ù. if (tbl2 == NULL) { //dprint(3, " new ETT-%d not exist..\n", i); continue; } tbl1 = PSIUTIL_FindTableInMgt(chInfo->mgt, tt_event_ETT_min+i+offset); // ¿¾³¯ MGT¿¡¼­ ETT-(i+offset) Á¤º¸¸¦ ã´Â´Ù. if (tbl1 == NULL) continue; if (tbl1->table_type_PID == tbl2->table_type_PID && tbl1->table_type_version_number == tbl2->table_type_version_number && tbl1->number_bytes == tbl2->number_bytes) { // ÀÏ´Ü ¸ðµç Á¤º¸°¡ °°À¸¹Ç·Î ÀÌ tblÀ» »ç¿ëÇÒ ¼ö ÀÖÀ»°Í °°´Ù.. candidate[i] = i + offset; dprint(3, " new Ett-%d same as Ett-%d (PID %x, v%d, %d)\n", i, i+offset, tbl1->table_type_PID, tbl1->table_type_version_number, tbl1->number_bytes); } else { dprint(3, " new Ett-%d should be downloaded..\n", i); } } // ÀÌÁ¦ candidate°¡ ¾Æ´Ñ ETT´Â »èÁ¦Çϰí À̵¿ÇÑ´Ù.. for (k=0; chInfo->subchannel && kn_subchannel; k++) { if (chInfo->subchannel[k].active == 0) continue; subchInfo = &chInfo->subchannel[k]; dprint(2, " move Etts for subchannel[%d]..\n", k); for (i=0; i<128; i++) { if (candidate[i] == i) { // same dprint(3, " reuse old Ett-%d (%d events)\n", i, subchInfo->n_ett[i]); } else if (candidate[i] == 0xff) { // no match if (subchInfo->etts[i]) dprint(3, " delete old Ett-%d (%d events)\n", i, subchInfo->n_ett[i]); PSIDB_FreeEtts(subchInfo, i); } else { // match with other ett if (subchInfo->eits[i]) { dprint(3, " overwrite old %d Ett-%d --> Ett-%d\n", subchInfo->n_ett[candidate[i]], candidate[i], i); PSIDB_FreeEtts(subchInfo, i); subchInfo->etts[i] = subchInfo->etts[candidate[i]]; subchInfo->n_ett[i] = subchInfo->n_ett[candidate[i]]; subchInfo->etts[candidate[i]] = NULL; // cafrii 040713 add subchInfo->n_ett[candidate[i]] = 0; } else { dprint(3, " move old %d Ett-%d --> Ett-%d\n", subchInfo->n_ett[candidate[i]], candidate[i], i); subchInfo->etts[i] = subchInfo->etts[candidate[i]]; subchInfo->n_ett[i] = subchInfo->n_ett[candidate[i]]; subchInfo->etts[candidate[i]] = NULL; // cafrii 040713 add subchInfo->n_ett[candidate[i]] = 0; } } } } // ----------- channel ETT check tbl1 = PSIUTIL_FindTableInMgt(chInfo->mgt, tt_channel_ETT); tbl2 = PSIUTIL_FindTableInMgt(mgt, tt_channel_ETT); if (tbl2 == NULL || tbl1 == NULL) { dprint(2, " Delete all channel ETT\n"); for (k=0; chInfo->subchannel && kn_subchannel; k++) { if (chInfo->subchannel[k].active == 0) continue; PSIUTIL_FreeTable(&chInfo->subchannel[k].channel_ett); } } else { if (tbl1->table_type_version_number != tbl2->table_type_version_number) { dprint(2, " ETT-v version changed %d->%d\n", tbl1->table_type_version_number, tbl2->table_type_version_number); for (k=0; chInfo->subchannel && kn_subchannel; k++) { if (chInfo->subchannel[k].active == 0) continue; PSIUTIL_FreeTable(&chInfo->subchannel[k].channel_ett); } } } // ¸ðµç tableµéÀ» Ãâ·ÂÇØº¸ÀÚ.. dprint(2, "------- Eit/Ett tables after version check ---------\n"); for (k=0; chInfo->subchannel && kn_subchannel; k++) { subchInfo = &chInfo->subchannel[k]; if (subchInfo->active == 0) continue; for (i=0; i<128; i++) { if (subchInfo->eits[i]) dprint(2, " Eit-%d: 0x%x ver %d\n", i, subchInfo->eits[i], subchInfo->eits[i] ? subchInfo->eits[i]->version_number : 0); for (j=0; jn_ett[i]; j++) dprint(2, " Ett-%d [%d]: 0x%x ver %d\n", i, j, subchInfo->etts[i][j], subchInfo->etts[i][j] ? subchInfo->etts[i][j]->version_number : 0); } } dprint(2, "\n"); LockPsiDB(FALSE); return statusOK; } //----------------------------------- // PSIDB_MakeMgtSummary // // mgt¿¡¼­ ¾î¶² VCT°¡ »ç¿ë °¡´ÉÇÑÁö ¾Ë¾Æ³½´Ù. // ¶Ç, ´Ù¿î·Îµå ¹ÞÀ» ¼ö ÀÖ´Â ¸ðµç EIT°¡ ¸î°³³ª µÇ´ÂÁö, PID°¡ ¾î¶²Áö ã´Â´Ù. // PSI_STATIC void MakeMgtDigest(S_PSIM_MGT_DIGEST *smgt, mgtSectionPtr_t mgt) { int i; dprint(1, "%s:\n", __FUNCTION__); if (!smgt || !mgt) return; // ÀÌ ½ÃÁ¡ºÎÅÍ ÀÌ ÇÔ¼ö ³¡±îÁö ¸ðµÎ LockÀ» ÇÑ´Ù. LockPsiDB(TRUE); smgt->tvct_exist_in_mgt = smgt->cvct_exist_in_mgt = FALSE; smgt->tvct_ver = smgt->cvct_ver = 0xFF; smgt->channel_ett_pid = 0; smgt->channel_ett_ver = 0xff; for (i=0; i<128; i++) { smgt->eit_pids[i] = 0; smgt->eit_ver[i] = 0xff; smgt->ett_pids[i] = 0; smgt->ett_ver[i] = 0xff; } for (i=0; itables_defined; i++) // search all tables.. { int index; if (mgt->table[i].table_type == tt_terrestrial_VCT_cni_1) { // TVCT smgt->tvct_exist_in_mgt = TRUE; smgt->tvct_ver = mgt->table[i].table_type_version_number; } else if (mgt->table[i].table_type == tt_cable_VCT_cni_1) { // CVCT smgt->cvct_exist_in_mgt = TRUE; smgt->cvct_ver = mgt->table[i].table_type_version_number; } else if (mgt->table[i].table_type >= tt_EIT_min && // EIT mgt->table[i].table_type <= tt_EIT_max) { index = (mgt->table[i].table_type - tt_EIT_min); if (smgt->eit_pids[index] == 0) { // cafrii 070712 add check for bugfix if (mgt->table[i].table_type_PID == 0 || mgt->table[i].table_type_PID >= 0x1FFF) { dprint(0, "!! MGT table[%d] EIT-%d pid 0x%x invalid. ignored!\n", i, index, mgt->table[i].table_type_PID); } else { smgt->eit_pids[index] = mgt->table[i].table_type_PID; smgt->eit_ver[index] = mgt->table[i].table_type_version_number; } } else { if (mgt->table[i].table_type_PID != smgt->eit_pids[index]) dprint(0, "!! MGT table[%d] pid 0x%x != prev EIT-%d pid 0x%x! ignored!\n", i, mgt->table[i].table_type_PID, index, smgt->eit_pids[index]); else dprint(0, "!! MGT table[%d] is EIT-%d but redundant! ignored!\n", i, index); } } else if (mgt->table[i].table_type == tt_channel_ETT) { // channel ETT if (smgt->channel_ett_pid == 0) { // cafrii 070712 add check for bugfix if (mgt->table[i].table_type_PID == 0 || mgt->table[i].table_type_PID >= 0x1FFF) { dprint(0, "!! MGT table[%d] ETT-v pid 0x%x invalid. ignored!\n", i, smgt->channel_ett_pid); } else { smgt->channel_ett_pid = mgt->table[i].table_type_PID; smgt->channel_ett_ver = mgt->table[i].table_type_version_number; } } else { if (mgt->table[i].table_type_PID != smgt->channel_ett_pid) dprint(0, "!! MGT table[%d] pid 0x%x != prev ETT-v pid 0x%x! ignored!\n", i, mgt->table[i].table_type_PID, smgt->channel_ett_pid); else dprint(0, "!! MGT table[%d] is ETT-v but redundant! ignored!\n", i); } } else if (mgt->table[i].table_type >= tt_event_ETT_min && // ETT mgt->table[i].table_type <= tt_event_ETT_max) { index = (mgt->table[i].table_type - tt_event_ETT_min); if (smgt->ett_pids[index] == 0) { // cafrii 070712 add check for bugfix if (mgt->table[i].table_type_PID == 0 || mgt->table[i].table_type_PID >= 0x1FFF) { dprint(0, "!! MGT table[%d] ETT-%d pid 0x%x invalid. ignored!\n", i, index, mgt->table[i].table_type_PID); } else { smgt->ett_pids[index] = mgt->table[i].table_type_PID; smgt->ett_ver[index] = mgt->table[i].table_type_version_number; } } else { if (mgt->table[i].table_type_PID != smgt->ett_pids[index]) dprint(0, "!! MGT table[%d] pid 0x%x != prev ETT-%d pid 0x%x! ignored!\n", i, mgt->table[i].table_type_PID, index, smgt->ett_pids[index]); else dprint(0, "!! MGT table[%d] is ETT-%d but redundant! ignored!\n", i, index); } } else if (mgt->table[i].table_type >= tt_RRT_region_1 && // RRT mgt->table[i].table_type <= tt_RRT_region_255) { //dprint(2, "RRT not supported yet..\n"); } else { dprint(0, "!! unknown table type %d\n", mgt->table[i].table_type); } } LockPsiDB(FALSE); if (smgt->tvct_exist_in_mgt == FALSE && smgt->cvct_exist_in_mgt == FALSE) { #if 0 sprintf(context->event_string_buf, "Neither of VCT exist in mgt"); Dmc_EpgSendUserEvent(context, epgEventError, (UINT32)statusPSIPError, (UINT32) context->event_string_buf); dprint(0, "!! %s\n", context->event_string_buf); return statusPSIPError; // ÀÌ·± ¿¡·¯ÀÇ °æ¿ì¿¡´Â ´Ù½Ã retry¸¦ ÇÒ Çʿ䵵 ¾ø´Ù. ¾ÆÁÖ À߸øµÈ °ÍÀ̱⠶§¹®.. #else // mgt¿¡´Â ¾øÁö¸¸ ½ÇÁ¦·Î Á¸ÀçÇÒ ¼öµµ ÀÖÀ¸¹Ç·Î °è¼Ó ÁøÇà. dprint(0, "!! neither of vct exist in mgt\n"); #endif } } /* vctÀÇ subch °¹¼ö¸¦ ¾Ë¾Æ³»°í, ÇÊ¿äÇÑ °æ¿ì ±âÁ¸ subch Á¤º¸¸¦ ÃʱâÈ­ ÇÑ´Ù. subch Á¤º¸ ¾ÈÀÇ vct backup ºÎºÐµµ ÃʱâÈ­ ÇÑ´Ù. ó¸®ÇÒ vct´Â ÀÌ¹Ì @chInfo ¾È¿¡ ÀúÀåµÇ¾î ÀÖ¾î¾ß ÇÑ´Ù. */ PSI_STATIC STATUS PrepareSubchStructUsingVct(S_PSIM_CHINFO *chInfo) { STATUS status = statusOK; int i; int n_subchannel; BOOL bSubchResetRequired; if (!chInfo->vct) return statusInvalidArgument; // ÀÌÁ¦ ¿©±â¼­ºÎÅÍ´Â tvct³ª cvct µÑ Áß Çϳª´Â ¹Ýµå½Ã Á¸ÀçÇÑ´Ù°í °¡Á¤Çϰí ÁøÇàÇÑ´Ù. // »ç½Ç ÅëÇÕ xvct Çϳª¸¸ Á¸ÀçÇÔ. dprint(2, "prepare_subch:\n"); #if 0 //------------------------------------------------------ // VCT integrity check.. // MGT¿¡¼­ ÁöÁ¤Çϰí ÀÖ´Â ¹öÀü°ú µ¿ÀÏÇÑ °ÍÀÎÁö üũÇÑ´Ù. ¹Ýµå½Ã ±×·² ÇÊ¿ä´Â ¾øÁö¸¸ ÇÏ´Â°Ô ÁÁ°Ú´Ù.. // if (chInfo->tvct_ver != chInfo->tvct->version_number) { dprint(0, "!! Warning! TVCT version in MGT %d mismatch with real TVCT version %d\n", chInfo->tvct_ver, chInfo->tvct->version_number); // todo.. // ¹öÀüÀÌ ´Þ¶óÁø ÀÌ·± °æ¿ì ¾î¶»°Ô ÇÒ °ÍÀΰ¡? ÀÏ´Ü ±×´ë·Î ÁøÇàÇÏÀÚ. } #endif //------------------------------------------------------ // »õ vct Á¤º¸·ÎºÎÅÍ ¸¸µé¾î¾ß ÇÒ subch °¹¼ö ¾Ë¾Æ³¿. // if (chInfo->vct->channel == NULL) { // ParseTvct ¿¡¼­ numChannels °¡ 0À̸é ÀÌ·² ¼öµµ ÀÖÁö ¾Ê´Â°¡? --> No.. // NULL channel ÀÎ °æ¿ì numChannels 0 À¸·Î °£ÁÖÇØ¼­ µ¿ÀÛ½ÃŰ¸é ¾ÈµÇ³ª? --> OK.. // dprint(0, "!! vct channel info NULL\n"); n_subchannel = 0; } else n_subchannel = chInfo->vct->numChannels; // ÁÖÀÇ! vct syntax »ó n_subchannel ÀÌ 0ÀÏ ¼öµµ ÀÖÀ½. //------------------------------------------------------ // subchannel Á¤º¸ ÃʱâÈ­ ÇÊ¿äÇÑ °æ¿ì.. // case 1. óÀ½ vct¸¦ ¹Þ´Â °æ¿ì (±âÁ¸ subchannel Á¤º¸°¡ ¾ø´Â °æ¿ì) -> »õ·Ó°Ô malloc // case 2. subchannel °¹¼ö°¡ ´Þ¶óÁø °æ¿ì.. -> buffer re-alloc // case 3. source_id Á¤º¸°¡ Çϳª¶óµµ ¹Ù²î¾î ¹ö¸° °æ¿ì -> ³»¿ë reset // bSubchResetRequired = FALSE; // case 1, 2. if (chInfo->subchannel == NULL || chInfo->n_subchannel != n_subchannel) { if (chInfo->subchannel) dprint(1, "!! subchannel number different!! old %d, new %d\n", chInfo->n_subchannel, n_subchannel); bSubchResetRequired = TRUE; } else { // case 3. for (i=0; isubchannel[i].source_id != chInfo->vct->channel[i].source_id) { dprint(1, "!! subchannel[%d] sid changed!! %d->%d\n", i, chInfo->subchannel[i].source_id, chInfo->vct->channel[i].source_id); bSubchResetRequired = TRUE; break; } } } if (bSubchResetRequired) { dprint(2, " subch reset required.. prev n_subch = %d\n", chInfo->n_subchannel); LockPsiDB(TRUE); //------------- // num channelÀÌ ´Þ¶ó¼­ reallocationÇÏ´Â °æ¿ì, ³»ºÎ ³»¿ëÀ» ´Ù free½ÃÄÑ¾ß ÇÑ´Ù.. for (i=0; chInfo->subchannel && in_subchannel; i++) { //dprint(2, " deleting subchannel info [%d] \n", i); PSIDB_FreeSubChInfo(&chInfo->subchannel[i]); } DHL_OS_Free((void **)&chInfo->subchannel); chInfo->n_subchannel = 0; // ÀÌ¹Ì ¾ð±ÞÇßµíÀÌ n_subchannelÀº 0ÀÏ °¡´É¼ºÀÌ ÀÖ´Ù. if (n_subchannel > 0) { dprint(2, " make new subchannel info.. n_subch %d\n", n_subchannel); // subchannel Á¤º¸ ±¸Á¶Ã¼ ÃʱâÈ­.. // chInfo->subchannel = DHL_OS_Malloc(n_subchannel * sizeof(S_PSIM_SUBCHINFO)); if (!chInfo->subchannel) { dprint(0, "!! out of memory for %d subch..\n", n_subchannel); chInfo->n_subchannel = 0; status = statusOutOfMemory; } else { chInfo->n_subchannel = n_subchannel; } for (i=0; in_subchannel; i++) { chInfo->subchannel[i].parent = chInfo; // make back pointer chInfo->subchannel[i].index = i; chInfo->subchannel[i].source_id = chInfo->vct->channel[i].source_id; chInfo->subchannel[i].active = TRUE; #if DMW_PSI_SUPPORT_ELAPSED_TIMER DMW_ResetCounter(&chInfo->subchannel[i].counter); DMW_HoldCounter(&chInfo->subchannel[i].counter); #endif } } LockPsiDB(FALSE); //------------- } else { dprint(2, " prev n_subch %d not changed\n", chInfo->n_subchannel); } //------------------------------------------------------ // vctÀÇ ÀϺΠÁ¤º¸¸¦ °¢ subchannel ·Î ¹é¾÷ÇØµÐ´Ù. // for (i=0; in_subchannel; i++) { memcpy(chInfo->subchannel[i].vct_info.short_name, chInfo->vct->channel[i].short_name, sizeof(UINT16)*7); if (chInfo->vct->is_cvct) { chInfo->subchannel[i].vct_info.major_channel_number = EpgMajorNumberInCVCT(&chInfo->vct->channel[i]); chInfo->subchannel[i].vct_info.minor_channel_number = EpgMinorNumberInCVCT(&chInfo->vct->channel[i]); } else { chInfo->subchannel[i].vct_info.major_channel_number = chInfo->vct->channel[i].major_channel_number; chInfo->subchannel[i].vct_info.minor_channel_number = chInfo->vct->channel[i].minor_channel_number; } chInfo->subchannel[i].vct_info.program_number = chInfo->vct->channel[i].program_number; chInfo->subchannel[i].vct_info.analog = (chInfo->vct->channel[i].modulation_mode == mm_analog || chInfo->vct->channel[i].service_type == st_analog_television) ? 1 : 0; chInfo->subchannel[i].vct_info.etm_location = chInfo->vct->channel[i].ETM_location; } return status; } #if COMMENT ____Update____(){} #endif /* °¢Á¾ TableÀ» PSI DB¿¡ update ÇÔ. °øÅë Rule: statusOK¸¦ ¸®ÅÏÇϸé, Á¦´ë·Î DB¿¡ ¹Ý¿µµÇ¾ú´Ù´Â ÀǹÌÀÓ. µû¶ó¼­ caller´Â ÀÎÀÚ·Î ÁöÁ¤ÇÑ table pointer¸¦ Àбâ Àü¿ëÀ¸·Î »ç¿ë °¡´É. statusOK°¡ ¾Æ´Ñ ¿¡·¯¸¦ ¸®ÅÏÇÑ´Ù¸é DB¿¡ ¹Ý¿µµÇÁö ¾Ê¾Ò´Ù´Â ÀǹÌÀ̹ǷΠcaller´Â »ç¿ëµÇÁö ¾ÊÀº table pointer¸¦ free ½ÃŰ´Â µîÀÇ Á¶Ä¡¸¦ ÇØ¾ß ÇÑ´Ù. ±âÁ¸ table °úÀÇ Àϰü¼º ¹®Á¦: »õ table ó¸® µµÁß¿¡ ¿¡·¯°¡ ¹ß»ýÇÒ °æ¿ì Àϰü¼º Â÷¿ø¿¡¼­ ÇÊ¿äÇÏ´Ù¸é ±âÁ¸ Å×À̺í (µ¥ÀÌÅ͵é) µµ »èÁ¦ÇØ¾ß ÇÑ´Ù. */ /* PAT¸¦ update ÇÑ´Ù. ÇÊ¿äÇϸé pmts array¸¦ resizeµµ ÇÑ´Ù. ÀÌ¹Ì pmt°¡ Á¸ÀçÇÏ´Â °æ¿ì »õ·Î¿î pat¿Í ºñ±³Çؼ­ ¹®Á¦°¡ ÀÖ´Ù¸é pmtµéÀ» freeÇÑ´Ù. ¾î´À ¼ø°£¿¡µç Ç×»ó pat->numPrograms ¿Í pmts array Å©±â´Â ÀÏÄ¡½Ã۵µ·Ï ÇÑ´Ù. ÀÌ Á¶°ÇÀÌ À¯ÁöµÇÁö ¾ÊÀ¸¸é update ºÒ°¡!! */ STATUS PSIDB_UpdatePAT(int id, MPEG_PAT *pat) { S_PSIM_CHINFO *chInfo; int i; STATUS status = statusOK; LockPsiDB(TRUE); // >>>>>>>>>>>> chInfo = PSI_GetChInfo(id); if (!chInfo || !pat) { status = statusInvalidArgument; goto label_end; } if (chInfo->pat) // ±âÁ¸ pat °¡ Á¸ÀçÇÏ´Â °æ¿ì.. { dprint(2, "pat update, ver %d -> %d, #pgm %d -> %d\n", chInfo->pat->version_number, pat->version_number, chInfo->pat->numPrograms, pat->numPrograms); // resize pmts array if (chInfo->pat->numPrograms != pat->numPrograms) { // ASSERT (chInfo->pmts != NULL) <- true because chInfo->pat exists. // delete all pmts for (i=0; ipat->numPrograms; i++) { PSIUTIL_FreeTable(&chInfo->pmts[i]); } DHL_OS_Free((void **)&chInfo->pmts); // »õ·Î¿î pat¿¡ ¸ÂÃç¼­ pmt list ¹öÆÛ ´Ù½Ã ÇÒ´ç.. chInfo->pmts = DHL_OS_Malloc(pat->numPrograms * sizeof(MPEG_PMT *)); if (!chInfo->pmts) { // critical!! // our assumption is that (pat->numPrograms == size of pmts array). // so, easy way to keep this assumption is delete whole pat! dprint(0, "!! re-alloc pmts err. free pat!\n"); PSIUTIL_FreeTable(&chInfo->pat); // free previous pat also!! status = statusOutOfMemory; goto label_end; } } else { // free only inconsistent pmts.. for (i=0; ipat->numPrograms; i++) { if (chInfo->pat->programs[i].program_map_PID != chInfo->pmts[i]->PID || chInfo->pat->programs[i].program_number != chInfo->pmts[i]->program_number) { dprint(2, " pmt[%d] (pid %x, #%d) unmatched to pat info (pid %x, #%d). free it..\n", i, chInfo->pmts[i]->PID, chInfo->pmts[i]->program_number, chInfo->pat->programs[i].program_map_PID, chInfo->pat->programs[i].program_number); PSIUTIL_FreeTable(&chInfo->pmts[i]); // keep pmt whose pid & program number is unchanged. } } } // now, replace old pat.. PSIUTIL_FreeTable(&chInfo->pat); chInfo->pat = pat; } else // ±âÁ¸ pat°¡ ¾ø´Â °æ¿ì. óÀ½ ¹Þ´Â pat.. { dprint(2, "new pat, ver %d, %d programs\n", pat->version_number, pat->numPrograms); chInfo->pmts = DHL_OS_Malloc(pat->numPrograms * sizeof(MPEG_PMT *)); if (!chInfo->pmts) { // critical!! dprint(0, "!! alloc pmts err. free pat!\n"); PSIUTIL_FreeTable(&chInfo->pat); status = statusOutOfMemory; goto label_end; } chInfo->pat = pat; pat = NULL; } label_end: LockPsiDB(FALSE); // <<<<<<<<<<<< // caller¿¡¼­ °ü¸®ÇÔ.. »èÁ¦.. // now, un-registered table pointer should be freed. //if (pat) // PSIUTIL_FreeTable(&pat); return status; } /* */ STATUS PSIDB_UpdatePMT(int id, MPEG_PMT *pmt) { S_PSIM_CHINFO *chInfo; int i, index; STATUS status = statusOK; LockPsiDB(TRUE); // >>>>>>>>>>>> chInfo = PSI_GetChInfo(id); if (!chInfo || !pmt) { status = statusInvalidArgument; goto label_end; } // pmts list ¾È¿¡¼­ÀÇ ¼ø¼­´Â pat ³»ÀÇ ¼ø¼­´ë·Î ÇÑ´Ù. index = -1; for (i=0; ipat->numPrograms; i++) { if (chInfo->pat->programs[i].program_number == pmt->program_number) { index = i; break; } } if (index < 0) { // warning! this pmt is not related to pat!! dprint(0, "!! cannot find pmt (#%d) info in pat\n", pmt->program_number); status = statusInvalidPSI; goto label_end; } if (chInfo->pmts[index]) { // previous pmt already exist. dprint(2, "pmt[%d] update, #%d, ver %d -> %d\n", index, pmt->program_number, chInfo->pmts[index]->version_number, pmt->version_number); PSIUTIL_FreeTable(&chInfo->pmts[index]); } else { dprint(2, "new pmt[%d], #%d, ver %d\n", index, pmt->program_number, pmt->version_number); } chInfo->pmts[index] = pmt; //pmt = NULL; label_end: LockPsiDB(FALSE); // <<<<<<<<<<<< // caller¿¡¼­ °ü¸®ÇÔ.. »èÁ¦.. // now, un-registered table pointer should be freed. //if (pmt) // PSIUTIL_FreeTable(&pmt); return status; } /* »õ @mgt¸¦ DB¿¡ update ÇÑ´Ù. ¹Ù·Î update Çϱâ Àü¿¡ º¯°æ µÇ´Â »çÇ׵鿡 ´ëÇÑ impact¿¡ ´ëÇÑ Ã³¸®¸¦ ¼öÇàÇÑ´Ù. ±×¸®°í mgt summary Á¤º¸ µîµµ »ý¼ºÇÑ´Ù. */ STATUS PSIDB_UpdateMgt(int id, mgtSectionPtr_t mgt) { S_PSIM_CHINFO *chInfo; STATUS status = statusOK; dprint(3, "update_mgt: id %d, %x\n", id, mgt); LockPsiDB(TRUE); // >>>>>>>>>>>> chInfo = PSI_GetChInfo(id); if (!chInfo || !mgt) { status = statusInvalidArgument; goto label_end; } //------------------------------------------------------------------------ // MGT ¹öÀü º¯°æ ó¸®.. // // ÀÌ ÇÔ¼ö´Â chInfo ¿¡ ÀÖ´Â mgt¿Í, mgt¸¦ ºñ±³Çϱ⠶§¹®¿¡ ÀÌ ½ÃÁ¡±îÁö´Â chInfo¿¡ // mgt¸¦ ÀúÀåÇÏ¸é ¾ÈµÈ´Ù. // CheckAndProcessMgtVersionChange(chInfo, mgt); //------------------------------------------------------------------------ // MGT ºÐ¼® // chInfo ¿¡ ÀúÀåµÈ mgt°¡ ¾Æ´Ï¶ó ÁöÁ¤ÇÑ mgt·Î üũ¸¦ ÇÑ´Ù.. // MakeMgtDigest(&chInfo->smgt, mgt); PSIUTIL_FreeTable(&chInfo->mgt_old); chInfo->mgt_old = chInfo->mgt; // ÀÌÀü MGT´Â º¸°üÇØµÐ´Ù. chInfo->mgt = mgt; //mgt = NULL; label_end: LockPsiDB(FALSE); // <<<<<<<<<<<< // caller¿¡¼­ °ü¸®ÇÔ.. »èÁ¦.. // now, un-registered table pointer should be freed. //if (mgt) // PSIUTIL_FreeTable(&mgt); return status; } /* DB¿¡ »õ @vct¸¦ update ÇÑ´Ù. */ STATUS PSIDB_UpdateVct(int id, xvctPtr_t vct) { S_PSIM_CHINFO *chInfo; STATUS status = statusOK; dprint(2, "update_vct: id %d, vct 0x%x\n", id, vct); DHL_ASSERT(vct!=0, "null vct"); LockPsiDB(TRUE); // >>>>>>>>>>>> chInfo = PSI_GetChInfo(id); if (!chInfo || !vct) { dprint(0, "!! chInfo of id %d is %x, vct %x\n", id, chInfo, vct); status = statusInvalidArgument; goto label_end; } PSIUTIL_FreeTable(&chInfo->vct); // ±âÁ¸ vct¸¦ Á¦°Å.. chInfo->vct = vct; //--------------------------- // »õ vct Á¤º¸¿¡ µû¶ó subch struct ³»¿ëÀ» ÀÏÄ¡½ÃŲ´Ù. // status = PrepareSubchStructUsingVct(chInfo); if (status) { // ¹«½¼ ÀÌÀ¯¿¡¼­ÀÎÁö subch ±¸¼ºÀÌ ½ÇÆÐÇÏ¿´À½. // vct¸¦ ±×´ë·Î µÑ °ÍÀΰ¡? ¾Æ´Ï¸é Àϰü¼ºÀ» À§ÇØ »èÁ¦ÇÒ °ÍÀΰ¡? // --> ¾ÈÁ¤¼º À§ÁÖ·Î µ¿ÀÛ. // status ¸¦ ¿¡·¯·Î ¸®ÅÏÇϸé caller¿¡¼­ table °ü¸®¸¦ ´ã´çÇϹǷΠ// ±×³É NULL setting ¸¸ ÇÏ¸é µÈ´Ù. chInfo->vct = NULL; } label_end: LockPsiDB(FALSE); // <<<<<<<<<<<< // caller¿¡¼­ °ü¸®ÇÔ.. »èÁ¦.. //if (vct) // PSIUTIL_FreeTable(&vct); return status; } STATUS PSIDB_UpdateStt(int id, sttSectionPtr_t stt, UINT32 tick_stt_get) { S_PSIM_CHINFO *chInfo; STATUS status = statusOK; LockPsiDB(TRUE); // >>>>>>>>>>>> chInfo = PSI_GetChInfo(id); if (!chInfo || !stt) { status = statusInvalidArgument; goto label_end; } dprint(2, "stt updated, gps %x\n", stt->system_time); // copy whole stt contents. chInfo->flat_stt = *stt; // reset descriptor info.. chInfo->flat_stt.descriptors = NULL; chInfo->flat_stt.descriptor_length = 0; chInfo->tick_stt_get = tick_stt_get; // stt Ãëµæ ½ÃÁ¡ÀÇ tick chInfo->stt_valid = TRUE; label_end: LockPsiDB(FALSE); // <<<<<<<<<<<< // caller¿¡¼­ °ü¸®ÇÔ.. »èÁ¦.. // now, un-registered table pointer should be freed. //if (stt) // PSIUTIL_FreeTable(&stt); return status; } STATUS PSIDB_InvalidateStt(int id) { S_PSIM_CHINFO *chInfo; STATUS status = statusOK; LockPsiDB(TRUE); // >>>>>>>>>>>> chInfo = PSI_GetChInfo(id); if (!chInfo) { status = statusInvalidArgument; goto label_end; } chInfo->stt_valid = FALSE; label_end: LockPsiDB(FALSE); // <<<<<<<<<<<< return status; } STATUS PSIDB_UpdateRrt(int id, rrtSectionPtr_t rrt) { STATUS status = statusOK; return status; } /* eit¸¦ DB¿¡ update ÇÑ´Ù. °ü·Ã ett Á¤º¸ data structureµµ ÃʱâÈ­ÇÑ´Ù. */ STATUS PSIDB_UpdateEit(int id, eitPtr_t eit, int iEit) { S_PSIM_CHINFO *chInfo; S_PSIM_SUBCHINFO *subchInfo; int source_id; int i; STATUS status = statusOK; dprint(2, "update_eit: (rf %d, idx %d)\n", id, iEit); // 1. sanity check // valid iEit range is 0 ~ 127. if (!eit || iEit < 0 || iEit >= 128) return statusInvalidArgument; if (eit->numEvents && !eit->event) // invalid table! return statusInvalidArgument; source_id = eit->source_id; LockPsiDB(TRUE); // >>>>>>>>>>>> chInfo = PSI_GetChInfo(id); if (!chInfo) { status = statusInvalidArgument; goto label_end; } // find subchannel index and get 'subchInfo' pointer. subchInfo = NULL; for (i=0; in_subchannel; i++) { if (chInfo->subchannel[i].source_id == source_id) { subchInfo = &chInfo->subchannel[i]; break; } } if (!subchInfo) { // ¼ö½ÅÇÑ eit¿¡ ÇØ´çµÇ´Â subch°¡ ¾ø´Ù? // burst eit °¡ queue¿¡ ½×¿©¼­ ´Ê°Ô ó¸®µÉ ¶§ ÀÌ·² ¼ö ÀÖÀ½. dprint(0, "!! no subchannel of source_id %d\n", source_id); status = statusInvalidState; goto label_end; } // ok.. eit index found. check if any changes of events and ett arrays. if (subchInfo->eits[iEit]) { if (subchInfo->eits[iEit]->version_number != eit->version_number) dprint(2, " eit[%d] update, ver %d -> %d\n", iEit, subchInfo->eits[iEit]->version_number, eit->version_number); else dprint(2, " same eit[%d] ver %d exist\n", eit->version_number); // check ett arrays are consistent. #if 0 // 1. n_ett vs. etts if (subchInfo->etts[iEit] == NULL && subchInfo->n_ett[iEit]) { dprint(0, "!!!! etts[%d] null but n_ett[%d]=%d\n", iEit, iEit, subchInfo->n_ett[iEit]); subchInfo->n_ett[iEit] = 0; } else if (subchInfo->etts[iEit] && subchInfo->n_ett[iEit] == 0) { dprint(0, "!!!! n_ett[%d]=0, but etts[%d]=%x\n", iEit, iEit, subchInfo->etts[iEit]); DHL_OS_Free((void **)&subchInfo->etts[iEit]); // ÀÌ °æ¿ì´Â ºñÁ¤»óÀû »óȲÀÓ.. } #endif // 2. number of events and n_ett if (subchInfo->n_ett[iEit] > 0 && eit->numEvents != subchInfo->n_ett[iEit]) { dprint(2, "!! n_event changed, %d -> %d. clear etts[%d] array\n", subchInfo->n_ett, eit->numEvents, iEit); PSIDB_FreeEtts(subchInfo, iEit); } // 3. event_id match if (subchInfo->n_ett[iEit] && subchInfo->etts[iEit]) { // ¸¸¾à ±âÁ¸ Ett°¡ ÀÏºÎ¶óµµ Á¸ÀçÇÑ´Ù¸é, À̰͵éÀÌ ¸ðµÎ EitÀÇ event ³»¿ë°ú ÀÏÄ¡ÇØ¾ß¸¸ Àç»ç¿ëÀÌ °¡´ÉÇÏ´Ù. // Çϳª¶óµµ ¹º°¡ ¾È¸Â´Â°Ô ÀÖÀ¸¸é À̰ÍÀº Àç»ç¿ëÇÒ ¼ö ¾ø´Ù. // // --> ¸Â´Â°ÍÀº Àç »ç¿ëÇϴ°ÍÀº ¾î¶³±î?? // BOOL bReuseEtt = TRUE; UINT16 eit_event_id; UINT32 etm_id; // n_ett[k] == eits[k]->numEvents ÀÌ´Ù. for (i=0; in_ett[iEit]; i++) { if (subchInfo->etts[iEit][i] == NULL) continue; // ¾ø´Â ETT´Â ±»ÀÌ Ã¼Å©ÇÒ ÇÊ¿ä ¾ø´Ù. eit_event_id = eit->event[i].event_id; etm_id = subchInfo->etts[iEit][i]->ETM_id; if (eit_event_id != PSIUTIL_GetEventIDFromETMID(etm_id)) { dprint(0, " !! Ett[%d][%d] event id mismatch! eit(%x) != etm(%x)\n", iEit, i, eit_event_id, PSIUTIL_GetEventIDFromETMID(etm_id)); bReuseEtt = FALSE; break; } } if (bReuseEtt == FALSE) { // Àç»ç¿ë ºÒ°¡Çϸé, ¸ðµÎ Áö¿î´Ù. dprint(1, " !! cannot reuse old Etts[%d].. delete!\n", iEit); PSIDB_FreeEtts(subchInfo, iEit); } } PSIUTIL_FreeTable(&subchInfo->eits[iEit]); subchInfo->eits[iEit] = eit; //eit = NULL; } else { dprint(2, " new eit[%d], ver %d\n", iEit, eit->version_number); subchInfo->eits[iEit] = eit; //eit = NULL; // clear any related etts. actually they should not exist at all! if (subchInfo->n_ett[iEit] || subchInfo->etts[iEit]) { dprint(0, "!! etts should not exist! clear etts[%d]..\n", iEit); PSIDB_FreeEtts(subchInfo, iEit); } } label_end: LockPsiDB(FALSE); // <<<<<<<<<<<< // caller¿¡¼­ °ü¸®ÇÔ.. »èÁ¦.. // now, un-registered table pointer should be freed. //if (eit) // PSIUTIL_FreeTable(&eit); return status; } #if 0 void PSIDB_PrepareEttDownload(int id, int iEit) { // eitÀÇ event °¹¼ö¿Í etts array °¹¼ö ÀÏÄ¡ üũ. int n_etm; // ÀÌ EITÀÇ eventµé Áß¿¡¼­ ¸î°³°¡ ETMÀ» °¡Áö°í ÀÖ´ÂÁö ¼ÀÇÑ´Ù. // for (i=0, n_etm=0; ieits[iEit]->numEvents; i++) { if (gPsiIgnoreEtmLocationInfo || // ignore ¿É¼ÇÀÌ¸é ¹«Á¶°Ç ¹Þ´Â´Ù. subchInfo->eits[iEit]->event[i].ETM_location != ETM_none) n_etm++; // ÀÌ EIT¿¡ °ü·ÃµÈ ETT °¹¼ö.. } if (n_etm == 0) { // ÀÌ EITÀÇ À̺¥Æ®µé¿¡´Â ETT°¡ Çϳªµµ ¾ø´Ù°í ÇÑ´Ù. ´Ù¿î·Îµå ¹ÞÀ» Çʿ䰡 ¾ø´Ù. dprint(3, " no ETTs of this eit[%d]..\n", iEit); // ´ÙÀ½ ´Ü°è·Î °¡±â Àü¿¡ ÇöÀç ettµéÀÇ ÀÚ°Ý °Ë»çµµ ÇØ¾ß ÇÏÁö ¾Ê³ª???? } else { dprint(3, " %d ETM's are expected in this EIT..\n", n_etm); } // ------ Ett¿ë ¸Þ¸ð¸® ÇÒ´ç.. // ett¿ë ¸Þ¸ð¸®°¡ ¾øÀ¸¸é »õ·Î ÇÒ´çÇÑ´Ù.. ¸¸¾à etts°¡ ÀÖ´Ù¸é n_ett´Â numEvents¿Í °°À» °ÍÀÌ´Ù. (ÀÌ¹Ì Ã¼Å©¿Ï·á) if (subchInfo->etts[iEit] == NULL) { int n_event = subchInfo->eits[iEit]->numEvents; subchInfo->etts[iEit] = DHL_OS_Malloc(n_event * sizeof(ettSectionPtr_t)); if (subchInfo->etts[iEit] == NULL) { dprint(0, "!! out of memory for %d ETT ptr\n", n_event); subchInfo->n_ett[iEit] = 0; break; // ¸Þ¸ð¸® ºÎÁ·? ´õ ÀÌ»ó ÁøÇàÇÒ Çʿ䰡 ¾ø´Ù. // ·çÇÁ ¹Ù±ùÀ¸·Î ³ª°¡¸é Áö±Ý±îÁö requestµÈ °Í¸¸ÀÌ¶óµµ download¸¦ ½Ãµµ ÇÒ ¼ö´Â ÀÖ´Ù... } dprint(3, " ++ alloc etts memory %x (max %d)\n", subchInfo->etts[iEit], subchInfo->eits[iEit]->numEvents); subchInfo->n_ett[iEit] = subchInfo->eits[iEit]->numEvents; // ÀÌ Eit¿¡ ¿¬°áµÈ ETT-i ÀÇ °¹¼ö.. } else dprint(3, " ** reuse etts memory %x (max %d:%d)\n", subchInfo->etts[iEit], subchInfo->eits[iEit]->numEvents, subchInfo->n_ett[iEit]); } #endif /* channel-ett index is passed as 128. */ STATUS PSIDB_UpdateEtt(int id, ettSectionPtr_t ett, int iEit) { S_PSIM_CHINFO *chInfo; S_PSIM_SUBCHINFO *subchInfo; int source_id, event_id; UINT32 etm_id; int i, iEvent; STATUS status = statusOK; eitPtr_t eit; ettSectionPtr_t *p_ett = NULL; // pointer of ett to be updated dprint(2, "update_ett: (rf %d, idx %d)\n", id, iEit); // sanity check // note that iEit 128 is considered as channel-ett. // if (!ett || iEit < 0 || iEit > 128) return statusInvalidArgument; etm_id = ett->ETM_id; source_id = PSIUTIL_GetSourceIDFromETMID(etm_id); event_id = PSIUTIL_GetEventIDFromETMID(etm_id); LockPsiDB(TRUE); // >>>>>>>>>>>> chInfo = PSI_GetChInfo(id); if (!chInfo) { status = statusInvalidArgument; goto label_end; } // find subchannel index and 'subchInfo' ptr subchInfo = NULL; for (i=0; in_subchannel; i++) { if (chInfo->subchannel[i].source_id == source_id) { subchInfo = &chInfo->subchannel[i]; break; } } if (!subchInfo) { dprint(0, "!! no subchannel of source_id %d\n", source_id); status = statusInvalidState; goto label_end; } // first, consider channel-ett.. if (iEit == 128) { iEvent = 0; // meaningless for channel-ett.. p_ett = &subchInfo->channel_ett; goto label_update; } // now, consider normal event ett.. // check consistency.. eit = subchInfo->eits[iEit]; if (!eit) { dprint(0, "!! ett[%d] received without eit[%d]?\n", iEit); status = statusInvalidState; goto label_end; } if (eit->numEvents != subchInfo->n_ett[iEit]) { dprint(0, "!! eit[%d] num event %d != n_ett %d\n", eit->numEvents, subchInfo->n_ett[iEit]); status = statusInvalidState; goto label_end; } // find related eit using event_id iEvent = -1; for (i=0; inumEvents; i++) { if (eit->event[i].event_id == event_id) { iEvent = i; break; } } if (iEvent < 0) { dprint(0, "ett[%d] event_id 0x%x not matched to eit\n", iEit, event_id); status = statusInvalidState; goto label_end; } // check etts array exist and its length is consistent to eit events.. if (eit->numEvents != subchInfo->n_ett[iEit]) { dprint(0, "!! eit events %d != n_ett[%d] %d !!\n", eit->numEvents, iEit, subchInfo->n_ett[iEit]); PSIUTIL_FreeTable(&ett); status = statusInvalidState; goto label_end; } p_ett = &subchInfo->etts[iEit][iEvent]; label_update: if (*p_ett == NULL) { dprint(2, " new ett[%d][%d], ver %d, etm %x\n", iEit, iEvent, ett->version_number, ett->ETM_id); (*p_ett) = ett; } else if ((*p_ett)->version_number != ett->version_number) { dprint(2, " ett[%d][%d] update, ver %d->%d, etm %x\n", iEit, iEvent, (*p_ett)->version_number, ett->version_number, ett->ETM_id); PSIUTIL_FreeTable(p_ett); (*p_ett) = ett; } else { // same version number dprint(2, " same ett[%d][%d] ver %d exist, etm %x\n", iEit, iEvent, ett->version_number, ett->ETM_id); PSIUTIL_FreeTable(&ett); // »õ·Î ¹ÞÀº ett¸¦ »èÁ¦ÇÑ´Ù. } //ett = NULL; // not to be freed later.. label_end: LockPsiDB(FALSE); // <<<<<<<<<<<< // caller¿¡¼­ °ü¸®ÇÔ.. »èÁ¦.. // now, un-registered table pointer should be freed. //if (ett) // PSIUTIL_FreeTable(&ett); return status; } #if COMMENT ____Modify____(){} #endif void PSIDB_DeleteTables(int id) { S_PSIM_CHINFO *chInfo; if (!PSITASK_IsPsiTask()) { dprint(0, "!! changing psi db in other task is illegal!\n"); return; } LockPsiDB(TRUE); chInfo = PSI_GetChInfo(id); if (chInfo){ dprint(2, "delete chinfo rf %d\n", id); PSIDB_FreeChInfo(chInfo); PSIDB_RemoveChInfoNode(id); } LockPsiDB(FALSE); } void PSIDB_DeleteAllTables(void) { S_PSIM_CHINFO *chInfo; int id; if (!PSITASK_IsPsiTask()) { dprint(0, "!! changing psi db in other task is illegal!\n"); return; } dprint(2, "delete all chinfo..\n"); LockPsiDB(TRUE); while (1) { chInfo = PSI_FirstChInfo(); if (!chInfo) break; id = chInfo->id; dprint(2, " delete chinfo rf %d\n", chInfo->id); PSIDB_FreeChInfo(chInfo); PSIDB_RemoveChInfoNode(id); } LockPsiDB(FALSE); } #if COMMENT ____Public_API____(){} #endif /* ´Ù¸¥ task¿¡¼­ DB¿¡ Á¢±ÙÇϱâ À§Çؼ­´Â ¹Ýµå½Ã lock ÇÊ¿ä. ´Ù¸¥ task¿¡¼­´Â Àб⸸ °¡´ÉÇϸç, ¾²±â´Â ±ÝÁö. */ void PSIDB_LockDB(BOOL bLock) { LockPsiDB(bLock); } // below two function should be called with lock in arbitrary task. // if not found, returns NULL. // S_PSIM_CHINFO *PSIDB_GetPsiChInfo(int id) { return PSI_GetChInfo(id); } S_PSIM_SUBCHINFO *PSIDB_GetPsiSubChInfo(int id, int source_id) { return GetSubChInfo(id, source_id); } #if COMMENT ____Test____(){} #endif void PSIDB_PrintAllTables(int id, int source_id, BOOL bDetail) { // id : channelInfo id // index : subchannel index 0 ~ n_subchannel-1 int i, k; int index=0; BOOL bSimple = bDetail ? 0 : 1; // cafrii 061106, 'simple' is default now. int program_number = -1; S_PSIM_CHINFO *chInfo; S_PSIM_SUBCHINFO *subchInfo; //int org_flag; //org_flag = OS_UsePrintfSemaphore(0); // do not use printf task.. #undef OS_DbgPrintf #define OS_DbgPrintf DMW_DBG_SimplePrint OS_DbgPrintf("%s: (id %d, source_id %d)\n", __FUNCTION__, id, source_id); LockPsiDB(TRUE); //------------------ chInfo = PSI_GetChInfo(id); if (chInfo == NULL) { int cnt=0; OS_DbgPrintf(" !! EpgDB of id %d not found!!\n", id); // // ÇöÀç ¸ðµç channel Á¤º¸¸¦ Ç¥½ÃÇØÁÖÀÚ.. OS_DbgPrintf("==== Summary List of all EPG ====\n"); chInfo = PSI_FirstChInfo(); while (chInfo) { OS_DbgPrintf(" (%d) id %d, num subch %d, %d sec%s\n", cnt++, chInfo->id, chInfo->n_subchannel, #if DMW_PSI_SUPPORT_ELAPSED_TIMER DMW_GetTickCount(&chInfo->counter)/OS_GetTicksPerSecond(), DMW_GetCounterHoldState(&chInfo->counter) ? "" : ".." #else 0, "" #endif ); for (i=0; in_subchannel; i++) OS_DbgPrintf(" [%d] source id %d, %s [%s], #%d, %s %sactive, %d sec%s, %s\n", i, chInfo->subchannel[i].source_id, PSIUTIL_ChannelNumberString(chInfo->subchannel[i].vct_info.major_channel_number, chInfo->subchannel[i].vct_info.minor_channel_number, 0), DMW_Unicode2Ks(chInfo->subchannel[i].vct_info.short_name, 7, 0), chInfo->subchannel[i].vct_info.program_number, // cafrii 060320 add chInfo->subchannel[i].vct_info.analog ? "analog," : "", chInfo->subchannel[i].active ? "" : "NOT ", #if DMW_PSI_SUPPORT_ELAPSED_TIMER DMW_GetTickCount(&chInfo->subchannel[i].counter)/OS_GetTicksPerSecond(), DMW_GetCounterHoldState(&chInfo->subchannel[i].counter) ? "" : "..", #else 0, "", #endif chInfo->subchannel[i].eit_complete == 0 ? "Incomplete!!" : chInfo->subchannel[i].ett_complete == 0 ? "Eit Completed" : "Completed"); chInfo = PSI_NextChInfo(chInfo); } OS_DbgPrintf("\n"); goto label_exit; } #if DMW_EPG_TABLE_DUMP_DEBUG //DMW_InitCodeConvLib(); // cafrii 041102 delete. ÀÌ°Ô ¾øÀ̵µ Á¦´ë·Î Ãâ·Â µÇ´Â °Í °°´Ù. // Unicode --> Ks º¯È¯ table ¹× °ü·Ã ÇÔ¼ö¸¦ ÃʱâÈ­ ÇÑ´Ù. #endif OS_DbgPrintf("\nPrint EPG Tables of Ch %d, Subch %d..\n\n", id, index); // ÇöÀç´Â subchannel Çϳª¸¸ Å×½ºÆ® Çϰí ÀÖÀ¸´Ï±î, 1°³¸¸ Ãâ·ÂÇÑ´Ù. // index = -1; #if 0 // ÀϺη¯ Ʋ¸° sid¸¦ ÁöÁ¤ÇÏ¿© Àüü °³¿äº¸±â¸¦ ÇÒ ¼öµµ ÀÖÀ½. // cafrii 041030 add, subchannel ÀÌ ÇѰ³ÀÌ¸é ±×³É ±×°Í Ãâ·ÂÇϵµ·Ï ÇÔ.. if (chInfo->n_subchannel == 1) source_id = chInfo->subchannel[0].source_id; #endif // ÁöÁ¤ÇÑ source_id °¡ ÀÖ´ÂÁö È®ÀÎ.. for (i=0; in_subchannel; i++) { if (chInfo->subchannel[i].source_id == source_id) { index = i; break; } } //-------------------------------------------------------------------- // ÁöÁ¤ÇÑ source_id ¼­ºê ä³ÎÀÌ ¾ø´Â °æ¿ì.. if (index < 0) { OS_DbgPrintf(" !! source id %d not found\n", source_id); // // subchannel Á¤º¸¸¸ °£´ÜÇÏ°Ô º¸¿©ÁØ´Ù.. OS_DbgPrintf("**** ChannelInfo of id %d: total %d subchannel\n", chInfo->id, chInfo->n_subchannel); //---- PSI info if (chInfo->pat) { OS_DbgPrintf(" PAT : 0x%x, ver %d, %d programs\n", chInfo->pat, chInfo->pat->version_number, chInfo->pat->numPrograms); for (i=0; chInfo->pmts && ipat->numPrograms; i++) { OS_DbgPrintf(" (%d) PMT: 0x%x, pid %04x, #%d, %d streams\n", i, chInfo->pmts[i], chInfo->pmts[i]->PID, chInfo->pmts[i]->program_number, chInfo->pmts[i]->numStreams); } } //---- PSIP info summary OS_DbgPrintf(" MGT: 0x%x, VCT: 0x%x\n", chInfo->mgt, chInfo->vct); for (i=0; in_subchannel; i++) { OS_DbgPrintf(" [%d] source id %d, %s [%s], #%d, %sactive, %d sec%s, %s\n", i, chInfo->subchannel[i].source_id, PSIUTIL_ChannelNumberString(chInfo->subchannel[i].vct_info.major_channel_number, chInfo->subchannel[i].vct_info.minor_channel_number, 0), DMW_Unicode2Ks(chInfo->subchannel[i].vct_info.short_name, 7, 0), chInfo->subchannel[i].vct_info.program_number, chInfo->subchannel[i].active ? "" : "NOT ", #if DMW_PSI_SUPPORT_ELAPSED_TIMER DMW_GetTickCount(&chInfo->subchannel[i].counter)/OS_GetTicksPerSecond(), DMW_GetCounterHoldState(&chInfo->subchannel[i].counter) ? "" : "..", #else 0, "", #endif chInfo->subchannel[i].eit_complete == 0 ? "Incomplete!!" : chInfo->subchannel[i].ett_complete == 0 ? "Eit Completed" : "Completed"); } OS_DbgPrintf("\n"); goto label_exit; } if (chInfo->subchannel[index].active == 0) { OS_DbgPrintf("!! subchannel %d is inactive now..\n", index); goto label_exit; } //-------------------------------------------------------------------- // ÁöÁ¤ÇÑ source_id ¼­ºê ä³ÎÀÌ ÀÖ´Â °æ¿ì.. subchInfo = &chInfo->subchannel[index]; OS_DbgPrintf(" [%d] source id %d, %s [%s], #%d, %sactive, %d sec%s, %s\n", index, subchInfo->source_id, PSIUTIL_ChannelNumberString(subchInfo->vct_info.major_channel_number, subchInfo->vct_info.minor_channel_number, 0), DMW_Unicode2Ks(subchInfo->vct_info.short_name, 7, 0), subchInfo->vct_info.program_number, subchInfo->active ? "" : "NOT ", #if DMW_PSI_SUPPORT_ELAPSED_TIMER DMW_GetTickCount(&subchInfo->counter)/OS_GetTicksPerSecond(), DMW_GetCounterHoldState(&subchInfo->counter) ? "" : "..", #else 0, "", #endif subchInfo->eit_complete == 0 ? "Incomplete!!" : subchInfo->ett_complete == 0 ? "Eit Completed" : "Completed"); program_number = subchInfo->vct_info.program_number; if (chInfo->pat) OS_DbgPrintf(" PAT : 0x%x, ver %d, %d programs\n", chInfo->pat, chInfo->pat->version_number, chInfo->pat->numPrograms); if (chInfo->pat && chInfo->pmts) { for (i=0; ipat->numPrograms; i++) { if (chInfo->pmts[i]->program_number == program_number) OS_DbgPrintf(" PMT[%d] : 0x%x, ver %d, %d streams\n", i, chInfo->pmts[i], chInfo->pmts[i]->version_number, chInfo->pmts[i]->numStreams); } } if (chInfo->mgt) OS_DbgPrintf(" MGT : 0x%x, ver %d\n", chInfo->mgt, chInfo->mgt->version_number); if (chInfo->mgt_old) OS_DbgPrintf(" preMGT : 0x%x, ver %d\n", chInfo->mgt_old, chInfo->mgt_old->version_number); //if (chInfo->tvct) OS_DbgPrintf(" TVCT : 0x%x, ver %d\n", chInfo->tvct, chInfo->tvct->version_number); //if (chInfo->cvct) OS_DbgPrintf(" CVCT : 0x%x, ver %d\n", chInfo->cvct, chInfo->cvct->version_number); if (chInfo->vct) OS_DbgPrintf(" VCT : 0x%x, ver %d %s, %d subchannels\n", chInfo->vct, chInfo->vct->version_number, chInfo->vct->is_cvct ? "(cvct)" : "(tvct)", chInfo->vct->numChannels); #if 0 // cafrii 050330 stt »èÁ¦ if (chInfo->stt) OS_DbgPrintf(" STT : 0x%x\n", chInfo->stt); #else // cafrii 060724, show stt time // cafrii 061106, show local time and timezone also OS_DbgPrintf(" STT time: 0x%x, (%s)\n", chInfo->flat_stt.system_time, PSIUTIL_GpsTimeString2(chInfo->flat_stt.system_time, NULL, 4)); #endif #if DMW_EPG_SUPPORT_RRT if (g_EpgRrt) { OS_DbgPrintf(" RRT : 0x%x (region %d)\n", g_EpgRrt, (int)g_EpgRrt->rating_region); PSIUTIL_PrintRrt(g_EpgRrt, 4, 0); } #endif OS_DbgPrintf(" EIT-array : 0x%x\n", subchInfo->eits); OS_DbgPrintf("\n"); //if (subchInfo->channel_ett_exist) if (PSIDB_IsSubChEttVRequired(id, source_id)) { if (subchInfo->channel_ett) { OS_DbgPrintf("...ETT-v : 0x%x\n", subchInfo->channel_ett); #if DMW_EPG_TABLE_DUMP_DEBUG Dmc_PrintEtt(subchInfo->channel_ett, 6); OS_DbgPrintf("\n"); #endif } else OS_DbgPrintf("...ETT-v : **** Not loaded yet ****\n"); // cafrii 041123 add } for (k=0; k<128; k++) { if (k == gPsiMaxEitEttIndexToReceive+1) { // cafrii 050412 change to variables OS_DbgPrintf("-------- MAX EIT/ETT index %d --------\n", gPsiMaxEitEttIndexToReceive); if (bSimple) break; // simple mode¿¡¼­´Â ´õ ÀÌ»ó Ãâ·ÂÇÏÁö ¸»ÀÚ. } if (chInfo->smgt.eit_pids[k] == 0) continue; // mgt¿¡ ¾Æ¿¹ µî·ÏÀÌ ¾ÈµÈ eit´Â Ç¥½Ãµµ ÇÏÁö ¾Ê´Â´Ù. if (subchInfo->eits[k] == NULL) { OS_DbgPrintf("...EIT-%d : **** Not loaded yet ****\n", k); continue; } //OS_DbgPrintf("...EIT-%d : 0x%x, ETT-array: 0x%x\n", k, subchInfo->eits[k], subchInfo->etts[k]); OS_DbgPrintf("...EIT-%d : 0x%x (pid 0x%x) ETT-array: 0x%x\n", k, subchInfo->eits[k], chInfo->smgt.eit_pids[k], subchInfo->etts[k]); // cafrii 050413, Eit PID Ç¥½Ã Ãß°¡ PSIUTIL_PrintEit(subchInfo->eits[k], 6, bSimple ? subchInfo->etts[k] : 0); OS_DbgPrintf("\n"); if (bSimple) // °£´ÜÇÏ°Ô Ç¥½ÃÇÏ´Â ¸ðµå¶ó¸é PrintEit ¿¡¼­ Ettµµ °°ÀÌ Ãâ·ÂµÇ¾úÀ» °ÍÀÌ´Ù. ¿©±â¼­ Á¾·á.. continue; //if (chInfo->ett_pids[k] == 0) continue; // pid Á¤º¸ °°Àº °ÍµéÀº ÃÖÁ¾ °á°ú¹°Àº ¾Æ´Ï´Ù. ÂüÁ¶ÇÏÁö ¸»ÀÚ. if (subchInfo->etts[k] == NULL) continue; for (i=0; in_ett[k]; i++) { //if (subchInfo->eits[k]->event[i].ETM_location == ETM_none) continue; if (subchInfo->etts[k][i] == NULL) { if (subchInfo->eits[k]->event[i].ETM_location == ETM_none) OS_DbgPrintf("........ETT-%d [%d] : None\n", k, i); else { UINT32 etmid = PSIUTIL_MakeEventETMID(subchInfo->source_id, subchInfo->eits[k]->event[i].event_id); // cafrii 041028, MakeETMID -> MakeEventETMID // ¾ÆÁ÷ ¼ö½ÅÀÌ ¾ÈµÈ °ÍÀÎÁö, ¾Æ´Ï¸é °ãÄ¡´Â°Ô ÀÖ´Â °ÍÀÎÁö Á¶»ç.. BOOL bMatchExist = FALSE; int t1, t2; for (t1=k; t1>=0; t1--) { // Çϳª¾¿ °Å²Ù·Î µÇµ¹¾Æ°¡¸é¼­.. if (subchInfo->etts[t1] == NULL) continue; for (t2=0; t2n_ett[t1]; t2++) { if (subchInfo->etts[t1][t2] && subchInfo->etts[t1][t2]->ETM_id == etmid) { bMatchExist = TRUE; break; } } if (bMatchExist) break; } if (bMatchExist) OS_DbgPrintf("........ETT-%d [%d] : same etm (0x%x) exist\n", k, i, etmid); else OS_DbgPrintf("........ETT-%d [%d] : **** Not loaded yet, etmid 0x%x, pid 0x%x ****\n", k, i, etmid, chInfo->smgt.ett_pids[k]); } continue; } OS_DbgPrintf("........ETT-%d [%d] : 0x%x (pid 0x%x)\n", k, i, subchInfo->etts[k][i], chInfo->smgt.ett_pids[k]); // ¿¡·¯°¡ ¹ß»ýÇß´Ù¸é 0x0 À¸·Î Ç¥½ÃµÈ´Ù. // cafrii 050413 ett pid Ç¥½Ã Ãß°¡. PSIUTIL_PrintEtt(subchInfo->etts[k][i], 8); OS_DbgPrintf("\n"); } } label_exit: LockPsiDB(FALSE); //------------------ //OS_UsePrintfSemaphore(org_flag); #undef OS_DbgPrintf }