/******************************************************************* * DMW_ChannelScan.c * * Channel Auto Scan Module * * Copyright 2003 Digital STREAM Technology, Inc. * All Rights Reserved * * $Id: DMW_ChannelScan.c,v 1.09 2004/01/14 cafrii Exp $ * ********************************************************************/ #include "DMW_Platform.h" #include "DHL_OSAL.h" #include "DHL_AVCAP.h" #include "DHL_DBG.h" #include "DMW_Config.h" #include "DMW_Status.h" #include "../System/DMW_MsgQue.h" #include "DMW_DebugUtil.h" #include "DMW_Channel.h" // cafrii 031230. for OnePartChannel APIs. #include "DMW_ChannelAPI.h" #include "DMW_ChannelDemux.h" // cafrii 041130 add for Table Download #include "DMW_ChannelUtil.h" #include "dmw_channel_priv.h" #include "dmw_mcm_priv.h" #include "dmw_ucm_priv.h" //#include DHL_MODULE("$scn", 1); #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) //=========================================================================== // // Design Notes // // //=========================================================================== // // Configuration parameters // // °¢Á¾ ¿É¼Ç ±â´ÉÀÇ On/Off ¼³Á¤, ÄÄÆÄÀÏ·¯ ¿É¼Ç ¼³Á¤, // µå¶óÀ̹ö °ü·Ã ȯ°æ ¼³Á¤ µî.. // #define USE_PSI_INDEX_FOR_MINOR 0 // cafrii 060630 add // 1À̸é PSI ä³Î Æ©´×½Ã index¸¦ minor·Î »ç¿ë. // ÀϹÝÀûÀ¸·Î´Â index ´ë½Å program number¸¦ »ç¿ëÇÑ´Ù. #define SUPPORT_CSD_UPDATE 0 // ƯÁ¤ platform ¿¡¼­ CSD ±â´ÉÀÌ ÇÊ¿äÄ¡ ¾Ê´Â °æ¿ì¿¡´Â ÀÌ flag¸¦ 0À¸·Î reset ÇÑ´Ù. // #define USE_DMW_EPGX_LIB 0 // 1 À̸é EPGX LIB ¿¡¼­ »ç¿ëÇÏ´Â MSS °ü·Ã ÇÔ¼öµéÀ» »ç¿ëÇÑ´Ù. #define TEST_AUTOSCAN 1 // Å×½ºÆ® ÄÚµå Æ÷ÇÔ ¿©ºÎ #define USE_PSI_RX_RETRY 0 // cafrii 070117 add // óÀ½¿¡ download_tables¿¡¼­ ÃæºÐÇÑ ½Ã°£µ¿¾È ¸ðµç tableÀ» ¹Þ±â ¶§¹®¿¡ // ³ªÁß¿¡ ´Ù½Ã retry¸¦ ÇÒ ÇÊ¿ä´Â ¾øÀ» µí ÇÏ¿© skipÇϵµ·Ï ÇÑ´Ù. #define USE_RESOLUTION_GATHERING 1 // neverdai add 101018. scan½Ã video ÇØ»óµµ Á¤º¸¸¦ ¾ò¾î³½´Ù. int g_Timeout_PesPidCheck = 100; // // PES packet PID monitor timeout. ´ÜÀ§´Â millisecond // Video/Audio PID¸¦ ¼öÁýÇÑ ´ÙÀ½ TSC bit check¸¦ À§ÇØ ÀÌ ½Ã°£ ¸¸Å­ packet ¼ö½ÅÀ» ±â´Ù¸°´Ù. // BOOL g_TestAutoscanWithoutVct = FALSE; // TRUE À̸é VCT°¡ ¾ø´Â ä³Î°ú °°Àº »óȲÀ» °¡Á¤ÇÏ¿© µ¿ÀÛÇÑ´Ù. // #define CHANNEL_BMP_SIZE 5 // channel bitmap array size (in bytes) #define TEST_LARGE_PROGRAM_NUMBER 0 // cafrii 060728 test #define USE_UNIQUE_PSI_NUMBERING 1 // cafrii 070130 add for APRO-1 // //=========================================================================== // // Constants, Variables, Function declarations // // program number´Â 16 bit·Î Å« ¹üÀ§À̹ǷΠÀû´çÈ÷ assignÀ» ÇÏÀÚ. // ¼­·Î ´Ù¸¥ ÇÁ·Î±×·¥ÀÌ µ¿ÀÏÇÑ minor ¹øÈ£¸¦ °¡Áú ¼öµµ ÀÖÀ½¿¡ À¯ÀÇ. // Minor 0¹øÀº air¿¡¼­ analog programÀ̶ó´Â Àǹ̷Π»ç¿ëµÇ¹Ç·Î 0ÀÇ °ªÀº ÇÇÇÑ´Ù. // #define PROG_NUM_TO_MINOR(pn) \ ((pn <= 999) ? (pn) : ((((pn) - 1000) % 999) + 1)) //((pn <= 1023) ? (pn) : ((((pn) - 1024) % 1023) + 1)) // cafrii 060630, restrict to 3 digits. #if TEST_LARGE_PROGRAM_NUMBER int g_TestLargeProgramNumber = 0; // cafrii 060728 test #endif #define USE_DEFAULT_CB_FN 0 // // »õ·Î¿î mw ±¸Á¶¿¡¼­´Â // scan °úÁ¤ Áß¿¡ tuner ¼³Á¤ ºÎºÐÀº application¿¡¼­ ¼öÇàÇÏ´Â °ÍÀ» ¿øÄ¢À¸·Î Àç¼³°èµÊ. // ±×·±µ¥ ¿©·¯°¡Áö ÀÌÀ¯·Î application¿¡¼­ ÀÌ Äڵ带 ±¸ÇöÇÒ ¼ö ¾ø´Â °æ¿ì // mwÀÇ µðÆúÆ® ±¸ÇöÀ» »ç¿ëÇÒ ¼ö ÀÖÀ½. // ÀÌ µðÆúÆ® Äݹé ÇÔ¼ö´Â ÄÚµå Å©±â°¡ ÀÛÁö ¾Ê±â ¶§¹®¿¡ // ÇÊ¿äÇÑ °æ¿ì¿¡¸¸ compile/link µÉ ¼ö ÀÖµµ·Ï Á¶°ÇºÎ·Î compile µÊ. #if USE_DEFAULT_CB_FN void SCB_ScanStart(ScanStartedCbParam *param); void SCB_ScanEnd(ScanCompleteCbParam *param); void SCB_TunerSet(ScanTunerSetCbParam *param); #endif // USE_DEFAULT_CB_FN void SCB_SkipTunerSet(ScanTunerSetCbParam *param); // ÀÌ ÇÔ¼ö´Â Default CB°¡ ¾Æ´Ï¶ó // Ç×»ó compile µÇ¾î¾ß ÇÑ´Ù. //=========================================================================== // // Debugging Aids // //=========================================================================== // // ä³Î½ºÄµ ÄÁÅØ½ºÆ®.. // ä³Î °Ë»ö ÀÛ¾÷Áß¿¡ ÇÊ¿äÇÑ ¿©·¯°¡Áö Á¤º¸¸¦ ¸ð¾Æ³õÀº ±¸Á¶Ã¼. // ÇöÀç °Ë»öÁßÀΠä³Î ¹øÈ£, ÇöÀç FSMÀÇ »óÅ µîµî.. typedef enum { CTS_IDLE, // ä³Î °Ë»ö ŽºÅ©°¡ ½¬´Â Áß. CTS_RUNNING, // ä³Î °Ë»ö ÀÛ¾÷ÀÌ ÁøÇà Áß. // analog / digital ºÐ¸®Çؼ­ scanÇÏ´Â °æ¿ì¿¡´Â ¾Æ·¡ state¸¦ °¡Áø´Ù. CTS_RUNNING_ANALOG, CTS_RUNNING_DIGITAL, } ChannelScanState; // ä³Î °Ë»ö ŽºÅ©ÀÇ »óÅÂ. typedef struct { //------------------------------ // input variables // tDHL_TSD tsd; // TS source UINT32 original_flag; // StartScan() API¿¡¼­ ³Ñ¾î¿Â Ç÷¡±×. CBTF_XXX »ó¼öµéÀÇ Á¶ÇÕ. UINT32 flag; // °¢ »óȲ¿¡ ¸Â°Ô ½ÇÁ¦ Àû¿ëÇÒ Ç÷¡±×. // cafrii 060628, change to UINT32. bit flag °³¼ö ´Ã¾î³².. int start_channel; // channel RF number to start to scan.. int end_channel; // last channel RF number to scan.. int total_channel; // number of channels to scan.. UINT32 channel_bmp[CHANNEL_BMP_SIZE]; // channel bitmap to scan BOOL quick_scan; // ÇöÀç ÁøÇà ÁßÀÎ scan ÀÛ¾÷ÀÌ normal scan ÀÎÁö quick scan ÀÎÁö. // normal scanÀÇ °æ¿ì scan start, scan end callback ÀÌ È£ÃâµÇÁö¸¸, // quick scanÀÇ °æ¿ì ÀÌ·¯ÇÑ callback ¾øÀÌ È£ÃâµÈ´Ù. ChannelScanCallback fnCallback; // callback function pointer. ChannelScanCancelCheckFn fnCheck; // cancel check function // return TRUE if autoscan cancel is requested. //------------------------------ // state variables int cur_channel; // current channel.. ÇöÀç ä³Î ȤÀº ´ÙÀ½ ´Ü°è¿¡¼­ °Ë»öÇÒ Ã¤³Î. // ÀÌ»ó ¸ðµÎ RF ¹øÈ£ÀÓ. int channel_index; // ¸î¹øÂ° ¼öÇàÇϴ ä³ÎÀÎÁö Ç¥½Ã.. 0 ~ total_channel-1 ÀÇ °ªÀ» °®´Â´Ù. int freq_offset; // ÇöÀç ä³ÎÀÇ frequncy offset (in Hz) int signal_strength; // ÇöÀç ä³ÎÀÇ signal_strength; int tuner_modulation_mode; // ,, mod mode ChannelScanState state; // CTS_IDLE, CTS_RUNNING, ... tDHL_FreqStd cable_system; // ¿ø·¡ÀÇ cable system //-------------------------------- // ÀÛ¾÷ÁßÀÎ PSIP/PSI table pointers // »ç¿ëÀÌ ³¡³ª¸é ¹Ýµå½Ã Free¸¦ ½Ã۰í NULL·Î ¸¸µé¾îÁà¾ß ÇÑ´Ù. // xvctPtr_t xvct; MPEG_PAT *pat; int num_programs; MPEG_PMT **pmtList; } ChannelScanContext; typedef struct { UINT32 flag; ChannelScanCallback pfnCallback; // ÇÑ Ã¤³Î¸¸ scanÇÏ´Â °æ¿ì¿¡´Â rf Çʵ带 ÀÌ¿ëÇϰí, // µÑ ÀÌ»óÀÇ Ã¤³ÎÀ» scanÇÒ ¶§¿¡´Â bitmapÀ» »ç¿ëÇÑ´Ù. int rf; UINT32 bitmap[CHANNEL_BMP_SIZE]; //UINT32 userparam; // userparamÀº one channel scan¿¡¼­ »ç¿ëµÇ°í ÀÖÀ½. // ÀÌ parameter´Â memory pointerÀÌ¸é ¾ÈµÊ. // command°¡ cancel µÉ °æ¿ì¿¡ ´ëÇÑ ´ëÀÀÀÌ ¾øÀ¸¹Ç·Î.. } ChannelScanCmdParam; typedef enum { eScanStop_Completed = 0, // scan ±¸°£À» ¸ðµÎ °Ë»öÇϰí Á¤»ó Á¾·á. eScanStop_StopByUser, // StopScan API°¡ È£ÃâµÇ¾î Á¤»ó Á¾·á. // APIÀÇ ÀÎÀÚ¿¡ µû¶ó¼­ °Ë»öµÈ Á¤º¸°¡ cancel µÉ ¼öµµ ÀÖ´Ù. eScanStop_Abnormal, // StopScan¿¡ ÀÇÇÏÁö ¾Ê°í ºñÁ¤»óÀûÀÎ Á¾·á. ±×·¯³ª DB ±¸¼º±îÁö´Â ¸¶¹«¸®ÇÑ´Ù. } ScanStopMode; #define STATIC #if COMMENT _____A_P_I_________(){} #endif //---------------------------------------------- // M/W APIs STATUS DMW_ASC_StartScan(int flag, ChannelScanCallback fn, int chStart, int chEnd) { ChannelScanSparseMap map; map.num_seg = 1; map.seg[0].ch_start = min(chStart, chEnd); map.seg[0].ch_num = max(chStart, chEnd) - min(chStart, chEnd) + 1; return DMW_ASC_StartSparseScan(flag, fn, &map); } /* scanÇÒ rf ¹øÈ£¸¦ Á÷Á¢ ÀÎÀÚ·Î ³Ñ°Ü¼­ ÇØ´ç rf¸¸ scanÇϵµ·Ï ÇÑ´Ù. ÀÌ ¶§ rfMapÀÇ rf ¹øÈ£´Â ¿À¸§Â÷¼øÀ¸·Î Á¤·ÄÀÌ µÇ¾î ÀÖ¾î¾ß ÇÑ´Ù. */ STATUS DMW_ASC_StartScanEx(int flag, ChannelScanCallback fn, UINT8 *rfMap, int numRf) { ChannelScanSparseMap map; int i, idx; //mode 0 new, 1 normal for(i=0, idx=0; inum_seg = 1; if ((flag & CBTF_ChannelTypeMask) == CBTF_Air) { map->seg[0].ch_start = 2; map->seg[0].ch_num = 68; // 2 ~ 69 } else { map->seg[0].ch_start = 1; map->seg[0].ch_num = 135; // 1 ~ 135 } } param = Dmc_ParamHeapAllocator(sizeof(ChannelScanCmdParam)); if (param == NULL) { return statusOutOfMemory; } param->flag = flag; param->pfnCallback = fn; bmpChannel = ¶m->bitmap[0]; for (i=0; inum_seg; i++) { // ch_start ¿Í ch_num range°¡ 0 ~ 159 »çÀÌ¿¡ µé¾î¿Í¾ß ÇÔ. if (map->seg[i].ch_start < 0 || map->seg[i].ch_start + map->seg[i].ch_num - 1 >= 160) { dprint(0, "!! seg[%d] (%d, %d) invalid range. skip\n", i, map->seg[i].ch_start, map->seg[i].ch_num); continue; } for (k=0; kseg[i].ch_num; k++) { ch = map->seg[i].ch_start + k; if (ch >= 0 && ch < 160) // 5 dword·Î Ç¥½Ã °¡´ÉÇÑ Å©±â´Â 0 ~ 160 bmpChannel[ch/32] |= (0x80000000 >> (ch % 32)); // µ¿ÀÏÇÑ Ã¤³ÎÀÌ ¿©·¯ segment¿¡ Áߺ¹ µÇ¾îµµ »ó°ü ¾ø´Ù } } status = Dmc_SendCommandEx(cmdScanStart, (UINT32)param, Dmc_ParamHeapDeallocator, //DMC_FN_CANCELFREE pfnFree, FALSE, //BOOL bWaitForComplete, NULL, 0, //DMC_FN_COMPLETED fn, UINT32 userparam, FALSE); //BOOL bCancelPrevCommand // jump to SCN_ScanStart if (status) { Dmc_ParamHeapDeallocator((UINT32)param); } return status; } // // ÀÚµ¿ ä³Î °Ë»öÀ» Á¾·áÇÑ´Ù. // STATUS DMW_ASC_StopScan(BOOL bUpdate) { // bUpdate°¡ TRUEÀ̸é Áö±Ý±îÁöÀÇ °á°ú¸¦ updateÇÑ´Ù. STATUS status; dprint(1, "DMW_ASC_StopScan(%s)\n", bUpdate ? "update" : "cancel"); status = Dmc_SendCommandEx(cmdScanStop, (UINT32)bUpdate, NULL, //DMC_FN_CANCELFREE pfnFree, TRUE, //BOOL bWaitForComplete, NULL, 0, //DMC_FN_COMPLETED fn, UINT32 userparam, FALSE); //BOOL bCancelPrevCommand // jump to SCN_ScanStop return status; } //STATUS DMW_ASC_ScanChannel(int rf, int flag, ChannelScanCallback eventcb, UINT32 userparam) STATUS DMW_ASC_ScanChannel(int rf, int flag, BOOL bWaitComplete, ChannelScanCallback eventcb, DMC_FN_COMPLETED pfnComplete, UINT32 userParam, BOOL bCancelPrevCmds) { STATUS status; ChannelScanCmdParam *param; dprint(1, "DMW_ASC_ScanChannel rf %d, flag 0x%x\n", rf, flag); // cafrii 040920 // Air/Cable Ç÷¡±×°¡ ³»ºÎ ÇÔ¼öÀÎ ScanDigitalCableChannel ¾È¿¡¼­ // °Ë»ç ¿ëµµ·Î »ç¿ëµÇ°í ÀÖ´Ù! µû¶ó¼­ ÀûÀýÇÑ ¼³Á¤À» ÇØÁÖÀÚ.. // flag = (flag & ~CBTF_ChannelTypeMask) | // ¸ÕÀú channel_type bitµéÀ» ¾ø¾Ö°í.. (g_CurChannelType == ChannelType_Air ? CBTF_Air : CBTF_Cable); Dmc_StopVideo(); // ¿ø·¡ caller°¡ stopÀ» ÇØ¾ß ÇÏ´Â°Ô ¸ÂÀ½. // caller´Â ¸ðµç background ÀÛ¾÷ (CC, EPG, EA, Rating)À» stopÇÑ ´ÙÀ½¿¡ // ÀÌ ÇÔ¼ö¸¦ È£ÃâÇØ¾ß ÇÑ´Ù. param = Dmc_ParamHeapAllocator(sizeof(ChannelScanCmdParam)); if (param == NULL) { return statusOutOfMemory; } param->flag = flag; param->pfnCallback = eventcb; param->rf = rf; //param->userparam = userParam; status = Dmc_SendCommandEx(cmdScanChannel, (UINT32)param, Dmc_ParamHeapDeallocator, //DMC_FN_CANCELFREE pfnFree, bWaitComplete, pfnComplete, userParam, bCancelPrevCmds); // jump to SCN_ScanOneChannel if (status) { Dmc_ParamHeapDeallocator((UINT32)param); } return status; } /* background·Î ÇöÀç ä³Î °Ë»öÀ» ¼öÇàÇÑ´Ù. ÀÌ ÇÔ¼ö´Â Dmc task¿¡¼­ µ¿ÀÛÇÏ´Â updateÀÌ´Ù. dmc task ³»¿¡¼­ »õ·Ó°Ô vct, psi µîÀ» ¼ö½ÅÇϱ⠶§¹®¿¡ EPG ¹× PsiMonitor°¡ ÁߴܵǾî ÀÖ¾î¾ß ÇÑ´Ù. ¾È±×·¯¸é Çϵå¿þ¾î µ¿ÀÛ¿¡ µû¶ó ¸ðµÎ timeout ¿¡·¯°¡ ¹ß»ýÇÒ ¼ö ÀÖ´Ù. DMW_CDB_UpdateChannel ÇÔ¼ö¿Í´Â »ç¿ë ¸ñÀûÀÌ Á» ´Ù¸£´Ù. */ STATUS DMW_ASC_UpdateChannel(int rf, int flag, BOOL bWaitComplete, DMC_FN_COMPLETED pfnComplete, UINT32 userParam, BOOL bCancelPrevCmds) { STATUS status; ChannelScanCmdParam *param; dprint(1, "DMW_ASC_UpdateChannel rf %d, flag 0x%x\n", rf, flag); // cafrii 040920 // Air/Cable Ç÷¡±×°¡ ³»ºÎ ÇÔ¼öÀÎ ScanDigitalCableChannel ¾È¿¡¼­ // °Ë»ç ¿ëµµ·Î »ç¿ëµÇ°í ÀÖ´Ù! µû¶ó¼­ ÀûÀýÇÑ ¼³Á¤À» ÇØÁÖÀÚ.. // flag = (flag & ~CBTF_ChannelTypeMask) | // ¸ÕÀú channel_type bitµéÀ» ¾ø¾Ö°í.. (g_CurChannelType == ChannelType_Air ? CBTF_Air : CBTF_Cable); flag |= CBTF_SkipTunerSet; //flag &= ~CBTF_CheckScrambleByVideoContext; // ÀÌ flag´Â caller°¡ À¯ÀÇÇØ¼­ ºÒ·¯¾ß ÇÑ´Ù. // update mode¿¡¼­ scramble check´Â ¾ÈÇÏ´Â°Ô ÁÁ´Ù. // ÇöÀç µðÄÚµù µ¿ÀÛ Áß¿¡ ÀÌ·ç¾îÁü¿¡ À¯ÀÇ.. param = Dmc_ParamHeapAllocator(sizeof(ChannelScanCmdParam)); if (param == NULL) { return statusOutOfMemory; } param->flag = flag; param->pfnCallback = NULL; param->rf = rf; //param->userparam = 0; status = Dmc_SendCommandEx(cmdScanChannel, (UINT32)param, Dmc_ParamHeapDeallocator, //DMC_FN_CANCELFREE pfnFree, bWaitComplete, pfnComplete, userParam, bCancelPrevCmds); if (status) { Dmc_ParamHeapDeallocator((UINT32)param); } return status; } // // MW ³»ºÎ¿¡¼­ »ç¿ëµÇ´Â // program_number --> minor º¯È¯ ½ÄÀÌ´Ù. // int DMW_ASC_ProgramNumberToMinor(UINT16 program_number) { return PROG_NUM_TO_MINOR(program_number); } #if COMMENT ___________________(){} #endif ChannelScanContext g_ScanContext; ChannelScanContext *get_scan_context(void) { return &g_ScanContext; } void send_event_message(ChannelScanEventType evt, UINT32 param) { ChannelScanContext *ctx = get_scan_context(); if (ctx->fnCallback) (ctx->fnCallback)(evt, param); } #if 0 // cafrii 100128 comment // DHL_AV_VideoStart ÇÔ¼ö°¡ seqhdr ¼ö½Å üũ±îÁö ´ã´çÇÏÁö ¾Ê°í ±×³É start¸¸ ½ÃŰ´Â °ÍÀ¸·Î º¯°æµÇ¾úÀ¸¹Ç·Î // ÀÌ ÇÔ¼ö´Â Á¦´ë·Î µ¿ÀÛÇÏÁö ¾Ê´Â´Ù. // ÀÌ ³»ºÎ¿¡¼­ DHL_AV_GetSequenceHeader ¸¦ ÀÌ¿ëÇÑ wait code°¡ µé¾î°¡Áö ¾Ê´Â ÇÑ º° ÀÇ¹Ì ¾ø´Â ÇÔ¼öÀÓ. STATUS check_pes_scramble(tDHL_TSD tsd, MPEG_PMT *pmt, int vPid, int pPid) { DHL_RESULT dhlResult = DHL_OK; STATUS status = statusOK; tDHL_VideoCodingType vidType; dprint(0, "\n!! %s not working. check!!\n\n", __func__); vidType=doDmc_SelectVideoStream(pmt, vPid); // zooyouny 100701 : tDHL_VDID¸¦ 0À¸·Î °£ÁÖ, ´Ù¸¦ °æ¿ì ¹®Á¦ µÉ ¼ö ÀÖÀ½ dhlResult = DHL_AV_VideoStart(0, vPid, pPid, (tDHL_VideoCodingType)vidType); if (dhlResult == DHL_OK) status = statusOK; else if (dhlResult == DHL_WARN_SCRAMBLED) status = statusScrambled; else if (dhlResult == DHL_FAIL_CANCELLED_BY_USER) status = statusCancelled; else if (dhlResult == DHL_FAIL_TIMEOUT) status = statusTimeout; else status = statusError; dhlResult = DHL_AV_VideoStop(0); if (dhlResult) dprint(0, "!! Video Stop err %d\n", dhlResult); return status; } #endif #if COMMENT ___________________(){} #endif //======================================================================= // MCM °ü¸® ·çƾ. // // MCM °ü·Ã ÆíÀÇ ÇÔ¼öµé.. // MCMÀÇ ±¸Á¶´Â Çì´õ ÆÄÀÏ¿¡ °ø°³µÇ¾î ÀÖÁö¸¸, MCM DB ÀÚü´Â AutoScan °úÁ¤¿¡¼­¸¸ ÇÊ¿äÇÑ // Àӽà µ¥ÀÌÅÍÀ̱⠶§¹®¿¡ DB ÀÚüÀÇ access´Â application¿¡¼­´Â ±ÝÁöµÈ´Ù. // // °Ë»öµÈ ä³Î Á¤º¸´Â Áß°£Áß°£¿¡ callback ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© applicationÀ¸·Î º¸°íµÈ´Ù. // À̶§ Àü´ÞµÇ´Â µ¥ÀÌÅÍ´Â MCM DB itemÀÇ ¹øÁöÀÌ´Ù. // ±×·¯³ª callback ÇÔ¼ö ¾È¿¡¼­¸¸ »ç¿ëÇØ¾ß ÇÑ´Ù´Â Á¦¾àÁ¶°ÇÀÌ ÀÖÀ¸¹Ç·Î // "Àӽà µ¥ÀÌÅÍ"·Î¼­ÀÇ MCMÀ̶ó´Â ¿ø·¡ Á¤Ã¥À» À§¹ÝÇÏÁö´Â ¾Ê°ÔµÈ´Ù. // // MCMÀÇ ÀÚ·á ±¸Á¶´Â º°µµ ¸ðµâ¿¡¼­ ±¸ÇöÇϰí, ±× ±¸Á¶´Â Â÷ÈÄ º¯°æÀÌ °¡´ÉÇÏ´Ù. // 1Â÷¿ø array ¶Ç´Â linked list µî.. // ÇØ´ç api¸¦ ÅëÇØ¼­ »ç¿ëÇϵµ·Ï ÇÑ´Ù. // MCMÀº Çʿ信 µû¶ó óÀ½ ÇÒ´çµÈ Å©±â ÀÌ»óÀ¸·Î Áõ°¡µÉ ¼ö ÀÖ´Ù. (¸Þ¸ð¸® ÀçÇÒ´ç) // static STATUS update_mcm_analog(int rfchannel, int strength, INT32 freq_offset, MCM_DB_T **ppmcm) { // MCM DB table¿¡ ÇØ´ç ä³Î Á¤º¸¸¦ Ãß°¡ÇÑ´Ù. // ¾Æ³¯·Î±× ä³Î °Ë»ö¿¡¼­ °Ë»öµÈ Á¤º¸ÀÏ °æ¿ì¿¡¸¸ »ç¿ëÇÑ´Ù. // VCT¿¡ Æ÷ÇԵǾî ÀÖ´Â ¾Æ³¯·Î±× ä³Î Á¤º¸´Â ´Ù¸¥ ÇÔ¼ö ÀÌ¿ë. // strength: ½ÅÈ£ ¼¼±â, 0~100 MCM_DB_T *m; if (strength == 0) strength = 1; // 0 °ªÀº Ưº°ÇÑ Àǹ̷Π»ç¿ëµÇ¹Ç·Î ÇÇÇÑ´Ù. m = find_mcm_major_minor_rf_vf(rfchannel, 0, rfchannel, FALSE); // VCT¿¡ µî·ÏµÇ¾î ÀÖ´Â analog ä³Î Á¤º¸´Â update_mcm_xvct() ÇÔ¼ö¿¡¼­ 󸮵ȴÙ. // todo.. // find_mcm_major_minor_rf_vf(rfchannel, 0, rfchannel, TRUE);¸¦ ¸ÕÀú ã¾Æ¾ß ÇÑ´Ù. // ÀÌ°Ô ÀÖÀ¸¸é update¸¦ ÇÏ¸é ¾ÈµÈ´Ù. (¹æÄ§¿¡ µû¶ó) if (m == NULL) { m = new_mcm(); if (m == NULL) return statusOutOfMemory; } m->Major = rfchannel; // RF_channelÀ» major ¹øÈ£·Î µî·ÏÇÔ. m->Minor = 0; m->RF = rfchannel; m->Service_type = Modulation_NTSC; // cafrii 041122 change, from '0' m->signal_strength = strength; m->Skipped = 0; m->SurfIndex = 0; m->VctFlag = FALSE; m->freqOffset = freq_offset; // frequency offset Ãß°¡. m->Uid = get_new_mcm_id(); // cafrii 060726 add if (ppmcm) *ppmcm = m; return statusOK; } static STATUS update_psi_program(ChannelScanContext *ctx, UINT16 tsid, MPEG_PMT *pmt, int programIndex, MCM_DB_T **ppmcm) { // MCM DB table¿¡ ÇØ´ç ä³Î Á¤º¸¸¦ Ãß°¡ÇÑ´Ù. // PSIÁ¤º¸´Â VSB/QAM µîÀÇ modulation ¹æ½Ä°ú´Â ¹«°üÇϹǷΠ// ÇöÀçÀÇ ChannelType¿¡ ¸Â´Â °ªÀ» ServiceTypeÀ¸·Î °£ÁÖÇÑ´Ù. // programIndex´Â minor ¹øÈ£ ºÎ¿©¸¦ ÇÒ ¶§ Ȥ½Ã ÇÊ¿äÇÒ ¼ö ÀÖÀ¸¹Ç·Î °¡Á®¿Â´Ù. // ppmcmÀº »ý¼ºµÈ mcm Æ÷ÀÎÅ͸¦ caller¿¡°Ô ³Ñ°ÜÁÖ±âÀ§ÇÑ place holer int psiRF; int psiFreqOffset; // cafrii 050817 add MCM_DB_T *m, *target, tmp; STATUS status; //DHL_RESULT err; int k, strength; BOOL bScrambled = FALSE; // cafrii 101206, // m ÃʱâÈ­ ÄÚµå À§Ä¡¸¦ ¸Ç óÀ½À¸·Î À̵¿. m = &tmp; // Àӽ÷ΠÇϳª ÁغñÇÑ ´ÙÀ½ ´Ù ÃʱâÈ­¸¦ ÇÏ°í ³ª¼­ MCM¿¡ º¹»çÇÑ´Ù. memset(m, 0, sizeof(MCM_DB_T)); psiRF = ctx->cur_channel; psiFreqOffset = ctx->freq_offset; // cafrii 050817 add strength = ctx->signal_strength; if (strength == 0) strength = 1; // 0 °ªÀº Ưº°ÇÑ Àǹ̷Π»ç¿ëµÇ¹Ç·Î ÇÇÇÑ´Ù. if (pmt == NULL) return statusInvalidArgument; dprint(2, "update_psi_program: pmt [idx %d] #%d, rf %d, tsid %d, str %d\n", programIndex, pmt->program_number, psiRF, tsid, strength); #if 0 // cafrii 041130 add // rf, tsid, program_number µîÀÌ µ¿ÀÏÇϸ鼭 vct flag 1ÀΠä³ÎÀ» ã´Â´Ù. // ÀÌ·± ä³ÎÀÌ ÀÌ¹Ì Á¸ÀçÇÑ´Ù¸é »õ·Î ä³ÎÀ» Ãß°¡ÇÒ Çʿ䰡 ¾ø´Ù. // target = find_mcm_rf_prognum_vf(psiRF, pmt->program_number, 1); if (target) { dprint(2, "\tsame vct mcm already exist. no need to update..\n"); if (ppmcm) *ppmcm = NULL; //return statusOK; return statusChannelDuplicated; // cafrii 060725 bugfix } #else // cafrii 060725 change // fresh field°¡ Ãß°¡µÇ¾úÀ¸¹Ç·Î À̸¦ Ȱ¿ëÇÑ´Ù. // MCM¿¡¼­ ÀÏÄ¡ÇÏ´Â Á¤º¸¸¦ ¹ß°ßÇ߾ ScanÇϱâ Àü ¿¾³¯ µ¥ÀÌÅÍÀ̸é // »õ·Ó°Ô overwriteÇØÁØ´Ù. pid µîÀÇ Á¤º¸µµ Àֱ⠶§¹®. // if (check_mcm_if_rf_prognum_exist(psiRF, pmt->program_number)) { dprint(2, "\tsame vct mcm already exist. no need to update..\n"); if (ppmcm) *ppmcm = NULL; return statusChannelDuplicated; // cafrii 060725 bugfix } #endif //------------- PID Á¤º¸ ÃßÃâ ----------------- // ÀÌÁ¦ pid Á¤º¸ ÃßÃâ ÀÛ¾÷Àº ignore ÇÒ ¼ö ¾ø´Ù. // psipÀÇ °æ¿ì vct recover±â´ÉÀ» À§Çؼ­ Ç×»ó ¼öÇàÇÑ´Ù. #if 0 if (ctx->flag & CBTF_IgnorePidsInfo) // PID Á¤º¸°¡ ÇÊ¿ä ¾ø´Â °æ¿ì. { } else #endif { // cafrii 060728 change PidInfo psiPid; memset(&psiPid, 0, sizeof(psiPid)); // cafrii 041126 add // get pid and stream type, using MW default decision logic. status = Dmc_DecidePidInfo(pmt, NULL, &psiPid, 0); // give application change to override settings. doDmc_SelectAudioStream(pmt, NULL, &psiPid.audio, &psiPid.audioType); doDmc_SelectVideoStream(pmt, NULL, &psiPid.video, &psiPid.videoType); // PCR pid °ªÀº ¹Ýµå½Ã ÀÖ¾î¾ß Çϸç, Video pid ¶Ç´Â Audio pid µÑ Áß Çϳª°¡ ÀÖ¾î¾ß ÇÑ´Ù. // if (status == statusOK && psiPid.bValid && psiPid.pcr && (psiPid.video || psiPid.audio)) { m->Pcr_pid = psiPid.pcr; m->Video_pid = psiPid.video; m->Audio_pid = psiPid.audio; m->Video_type = psiPid.videoType; m->Audio_type = psiPid.audioType; dprint(2, " pid(pva): 0x%x 0x%x 0x%x, pmt0x%x, vt%d at%d\n", m->Pcr_pid, m->Video_pid, m->Audio_pid, pmt->PID, m->Video_type, m->Audio_type); } else { dprint(0, "!! cannot get pids in pmt[%d] #%d, err %s\n", programIndex, pmt->program_number, DMW_CDB_ErrString(status)); // cafrii 070117, too verbose.. remove //if (dprintable(3)) // PrintPMT(pmt); return statusPSIPError; } } // ------------ ¾Ïȣȭ ¿©ºÎ üũ ----------------- if (g_CurChannelType == ChannelType_Cable) { #if 0 // cafrii 050124 fix // // Motorolla HE ¿¡¼­´Â °ÅÀÇ ´ëºÎºÐÀÇ Ã¤³ÎÀÌ CA descriptor°¡ Àֱ⠶§¹®¿¡ // ÀÌ ¹æ¹ýÀ» »ç¿ëÇϱⰡ ¾î·Æ´Ù. // // 1: CA descriptor¸¦ ã¾Æº¸±â if (GetMpegDescriptor(pmt->descriptors,pmt->descriptor_length, CA_tag, 0, NULL) == DHL_OK) { dprint(2, " !! PMT main descriptor has CA descriptor\n"); bScrambled = TRUE; } // 2: TSC bit¸¦ °Ë»çÇϱâ if (m->Video_pid || m->Audio_pid) // PID Á¤º¸°¡ ÀÖ¾î¾ß ÀÌ ¹æ¹ýÀ» »ç¿ëÇÒ ¼ö ÀÖ´Ù. { int pidArray[2] = {0, }; // video and audio.. int tscArray[2] = {0, }; int nPid = 0; if (m->Video_pid) pidArray[nPid++] = m->Video_pid; if (m->Audio_pid && m->Audio_pid != m->Video_pid) pidArray[nPid++] = m->Audio_pid; status = Dmc_GetMultipleTscBits(ctx->tsd, nPid, pidArray, tscArray, g_Timeout_PesPidCheck*1000/1000, ctx->fnCheck); // cafrii 041202, add cancel check function // cafrii 050305, timeout to 100ms // cafrii 050315, change timeout value to variables // statusCancelled, timeoutError, outOfCPUMemoryError, ... if (status == statusCancelled) { return statusCancelled; } else if (status == statusOK) { // cafrii 050228, remove tsc bit 255 case, which is not_found.. if (tscArray[0] == 1 || tscArray[0] == 2 || tscArray[0] == 3 || tscArray[1] == 1 || tscArray[1] == 2 || tscArray[1] == 3 ) { dprint(2, " !! one of stream is scrambled bit checked. 0x%x:%d, 0x%x:%d\n", pidArray[0], tscArray[0], pidArray[1], tscArray[1]); bScrambled = TRUE; } } else dprint(0, "!! scrmabled bit check err %d\n", status); } // 3: Video context¸¦ Á÷Á¢ »ý¼ºÇغ¸±â.. if (1) { // cafrii 031110 add // PSIP/PSI table·ÎºÎÅÍ scramble Á¤º¸¸¦ ¾ò´Â ¹æ¹ýÀÌ ½Å·ÚÇÒ ¼ö ¾ø´Â °æ¿ì¸¦ ´ëºñÇÏ¿© // Á÷Á¢ decodingÀ» ½ÃµµÇØ º¸°í ³ª¼­ scramble ¿©ºÎ¸¦ °áÁ¤ÇÑ´Ù. // if ((ctx->flag & CBTF_CheckScrambleByVideoContext) && m->Video_pid) { // cafrii 040114 bugfix #AudioOnlyChannelMissing // À̶§ AudioOnly ä³ÎÀÇ °æ¿ì VideoDecodingÀÌ Ç×»ó failÀÌ ³ª¼­ Ç×»ó scramble·Î °£ÁֵǴ ¹®Á¦°¡ ÀÖÀ¸¹Ç·Î // Audio only ä³ÎÀÇ °æ¿ì¿¡´Â ±×³É unscramble·Î °£ÁÖÇÑ´Ù. status = check_pes_scramble(ctx->tsd, pmt, m->Video_pid, m->Pcr_pid); if (status == statusScrambled) { if(ctx->flag &CBTF_IgnoreScrambledChannel) { return status; } bScrambled = TRUE; dprint(1, "!! [ClearOnlyMode] PSI: PID v %d/p %d seems scrambled.\n", m->Video_pid, m->Pcr_pid); //return statusPSIPError; // statusOK¸¸ ¾Æ´Ï¸é µÊ. // // cafrii 050614 remove 'return' // scramble ä³Îµµ DB¿¡ ³Ö°í scramble Ç¥½Ã¸¦ ÇØ¾ß ÇÑ´Ù. // µû¶ó¼­ ¿©±â¼­ returnÇÏÁö ¾Ê°í °è¼Ó ÁøÇàÇϵµ·Ï ÇÑ´Ù. } else if (status == statusOK) { // good channel.. } else { dprint(0, "!! video ES seems invalid, status %d\n", status); } } } #endif } m->Major = psiRF; // PMT·ÎºÎÅÍ ¾òÀº ä³Î Á¤º¸¿¡´Â Major/Minor°¡ ¾ø´Ù. // cafrii 050614 change numbering policy // program number¸¦ Minor ¹øÈ£·Î ÇÒ´çÇÑ´Ù. // #if USE_PSI_INDEX_FOR_MINOR m->Minor = programIndex+1; // µû¶ó¼­ RF-index °ªÀ» »ç¿ëÇϵµ·Ï ÇÏÀÚ. index´Â 1,2,3... #else m->Minor = PROG_NUM_TO_MINOR(pmt->program_number); #endif m->Prog_number = pmt->program_number; #if USE_UNIQUE_PSI_NUMBERING // cafrii 070130 add // minor ¹øÈ£°¡ °ãÄ¡Áö ¾Êµµ·Ï Á¶Á¤ÇÑ´Ù. ¾îÂ¥ÇÇ PSI channel¿¡¼­´Â minor´Â º° Àǹ̰¡ ¾ø´Ù. #if 0 // Fake overlapped program number test dprint(0, "\n****** program number overlapping test\n\n"); m->Prog_number = 3 + programIndex*999; m->Minor = PROG_NUM_TO_MINOR(pmt->program_number); #endif // program number°¡ 999 º¸´Ù Å« °æ¿ì´Â ÀÓÀÇ ÇÒ´çÀ» ÇÑ´Ù. if (m->Prog_number > 999) { for (k=0; k<999; k++) // to avoid infinite loop, in case of all 1~999 is full. { if (find_mcm_major_minor(m->Major, m->Minor) == 0) break; // already some channel has same M-m. increase minor number.. if (k == 0) dprint(0, "!! minor ch %d (#%d) overlapped. adjusted\n", m->Minor, m->Prog_number); m->Minor = m->Minor < 998 ? m->Minor+1 : 1; } if (k >= 999) { // all 1~999 minor number is reserved??? dprint(0, "!! full 1~999 minor reserved?\n"); return statusPSIPError; } else if (k != 0) { dprint(0, " minor adjusted to %d --> %d-%d\n", m->Minor, m->Major, m->Minor); } } #endif #if 0 // USE_RESOLUTION_GATHERING //sequence Á¤º¸¸¦ ¾ò¾î¾ß ÇÔ do { #define MAX_SEQ_WAIT 5000 // ÃÖ´ë 5Ãʸ¦ ±â´Ù¸² tDHL_VideoSeqHdr seq; tDHL_DispFormat disp=eDHL_DISP_720x480i; UINT32 ms_start; if(m->Video_pid==0) break; DHL_AV_VideoHide(0, TRUE); DMC_RegisterVideoCallback(FALSE); DHL_AV_VideoStart(0, m->Video_pid, m->Pcr_pid, m->Video_type); for(ms_start=DHL_OS_GetMsCount(); DHL_AV_VideoSeqInfo(0, &seq)!=DHL_OK && DHL_OS_GetMsCount()-ms_start < MAX_SEQ_WAIT; DHL_OS_Delay(100)); if(DHL_OS_GetMsCount()-ms_start >=MAX_SEQ_WAIT) { //timeout ; } else { if(seq.vertical_size>=1080) disp=eDHL_DISP_1920x1080i; else if(seq.vertical_size>=720) disp=eDHL_DISP_1280x720p; else disp=eDHL_DISP_720x480i; } DHL_AV_VideoStop(0); DMC_RegisterVideoCallback(TRUE); m->video_format=disp; } while(0); #endif // cafrii 041122 add more conditions. if (ctx->tuner_modulation_mode == Modulation_8VSB) { m->Service_type = ctx->tuner_modulation_mode; } else if (ctx->tuner_modulation_mode == Modulation_64QAM || ctx->tuner_modulation_mode == Modulation_256QAM) { if (g_CurChannelType == ChannelType_Air) { dprint(0, "!! QAM modulation detected in Air mode scan\n"); m->Service_type = Modulation_8VSB; } else m->Service_type = ctx->tuner_modulation_mode; } else { dprint(0, "!! wrong tuner modulation %d in psi scan\n", ctx->tuner_modulation_mode); m->Service_type = g_CurChannelType == ChannelType_Air ? Modulation_8VSB : Modulation_64QAM; } m->RF = psiRF; m->freqOffset = psiFreqOffset; // cafrii 050817 add m->signal_strength = strength; // pid Á¤º¸ ¹× codec Á¤º¸´Â À§¿¡¼­ ÀÌ¹Ì Á¤¸® ¿Ï·á. m->pmt_pid = pmt->PID; // cafrii 070201 add m->TSID = tsid; // ÇöÀç Æ©´×µÈ ä³Î (ÀÌ DB¸¦ Æ÷ÇÔÇϰí Àִ ä³Î)ÀÇ TSID m->source_id = 0; m->channel_tsid = tsid; // ÀÌ ÇÁ·Î±×·¥ÀÇ TSID m->Skipped = 0; // ÀÌ µÎ°¡Áö´Â ³ªÁß¿¡ ¿©·¯ ä³Î Áß¿¡¼­ ¼±ÅÃÇÏ¿© °áÁ¤ÇÒ ¹®Á¦ÀÌ´Ù. m->SurfIndex = 0; m->hidden = FALSE; // VCTÀÇ hidden Á¤º¸¸¦ º¸°üÇÑ´Ù. ¿©±â¼­´Â ¾Ë¼ö ¾øÀ½. m->VctFlag = 0; // cafrii, add. 030313. m->scrambled = bScrambled; // ÀÌÁ¦ tmp°¡ ´Ù ÁغñµÇ¾ú´Ù. dprint(2, " ====== found psichannel: %d-%d, rf %d, %s, #%d %s\n", m->Major, m->Minor, m->RF, ServiceTypeString(m->Service_type), m->Prog_number, m->scrambled ? "scrambled " : ""); // cafrii 060808, minor Áߺ¹ °¡´É¼º ¶§¹®¿¡ prog numÀ» »ç¿ëÇÏ¿© °Ë»çÇÑ´Ù. // psi ä³Î¿¡¼­ minor´Â Áß¿äÇÑ Á¤º¸°¡ ¾Æ´Ï´Ù. // //target = find_mcm_major_minor_rf_vf(m->Major, m->Minor, m->RF, 0); target = find_mcm_rf_prognum_vf(m->RF, m->Prog_number, 0); if (target) { // cafrii 060808 use 'fresh' field to determin overlapped channel // if (target->fresh == 0) { // ÀÌ targetÀº ¿¹Àü DBÀ̹ǷΠ±×³É overwrit ÇØ¹ö¸®ÀÚ. dprint(2, " same psi mcm found. overwrite to old mcm.\n"); // ±âÁ¸ Á¤º¸°¡ ÀÖÀ¸¸é ±× MCM¿¡´Ù updateÇÑ´Ù. } else { // targetÀº ¹æ±Ý Àü¿¡ Ãß°¡µÈ ½Å±Ô ä³ÎÀ̹ǷΠÀ̹ø Á¤º¸¸¦ ¹ö¸®ÀÚ. dprint(2, " overlapped channel (#d) ignored\n", m->Prog_number); // pat¿¡ ¶È°°Àº program number°¡ µÎ°³ ÀÌ»ó Á¸ÀçÇÏ´Â °æ¿ì // ù¹øÂ° °Í¸¸ ¹Ý¿µµÇ°í ³ª¸ÓÁö´Â ¹ö¸°´Ù. return statusChannelDuplicated; } } else { target = new_mcm(); // ±âÁ¸ MCM Á¤º¸°¡ ¾øÀ¸¸é »õ·Î MCM itemÀ» Çϳª ÇÒ´çÇÏ°í µî·ÏÇÑ´Ù. if (target == NULL) return statusOutOfMemory; } *target = *m; // º¹»ç.. memcpy(target, m, sizeof(MCM_DB_T)); target->Uid = get_new_mcm_id(); // cafrii 060726 add target->fresh = 1; // cafrii 060808 add // À̹ø¿¡ »õ·Ó°Ô updateµÈ DB entryÀÓÀ» ³ªÅ¸³½´Ù. if (ppmcm) *ppmcm = target; return statusOK; } // // update_psi // // VCT°¡ ¼ö½ÅÀÌ ¾ÈµÈ »óÅÂÀ̰ųª, VCT°¡ ÀÖ´õ¶óµµ CBTF_ForcePSI ¿É¼ÇÀÌ »ç¿ëµÈ °æ¿ì, // PsiOnlyMode ÀÎ °æ¿ì¿¡ ÀÌ ÇÔ¼ö°¡ ¼öÇàµÈ´Ù. // // VCT¸¸À¸·Î ä³Î DB ±¸¼º¿¡ ½ÇÆÐÇÑ °æ¿ì¿¡ PSI Á¤º¸·Î ä³Î DB¸¦ ±¸¼ºÇϰųª, // VCTÀÇ Á¤º¸¿¡ PSI Á¤º¸¸¦ Ãß°¡·Î º¸¿ÏÇÏ¿© ä³Î DB¸¦ Ãß°¡ ±¸¼ºÇÑ´Ù. // STATUS update_psi(ChannelScanContext *ctx) { int i, k; STATUS status = statusOK; int _second = 1000; int program_index; // sequencial program index. MPEG_PAT_program *program; // temporary.. MCM_DB_T *pmcm = NULL; BOOL bMinorNumberAutoAdjust = FALSE; // cafrii 060808 add // cafrii 070130 make false. // APRO1¿¡¼­´Â report ÇÒ ½ÃÁ¡ÀÌ ¹ú¼­ adjust°¡ µÇ¾î ÀÖ¾î¾ß ÇϹǷΠ// ÀÌ ¹æ¹ýÀ» »ç¿ëÇÒ ¼ö ¾ø´Ù. // ´ë½Å 2-pass ¹æ¹ýÀ» »ç¿ëÇÑ´Ù. int pass; // cafrii 070130 add ScanNewChannelCbParam cbparam; typedef struct { UINT16 pn; // program number UINT16 id; // mcm id UINT16 minor; } _MinorAdjustParam; _MinorAdjustParam *param2 = NULL; int n_param2 = 0; if (ctx->pat == NULL || ctx->num_programs <= 0) { dprint(0, "!! no psi tables\n"); return statusPSIPError; } // cafrii 070130 add for new callback prototype memset(&cbparam, 0, sizeof(cbparam)); cbparam.fn_lookup_mj_mn = (BOOL (*)(int, int))find_mcm_major_minor; //------ PAT ó¸®. // cafrii 060724 change 1->0 // PMTÀÇ index¶ó´Â Àǹ̷Π0ºÎÅÍ ½ÃÀÛÇÑ °ªÀ» °Ç³×ÁÖÀÚ. // ÇÊ¿äÇÏ¸é ³»ºÎ¿¡¼­ non-zero interger·Î º¯È¯ÇÏ¸é µÈ´Ù. program_index = 0; dprint(2, "total %d programs in PAT\n", ctx->num_programs); // cafrii 070130 add 2-pass scan.. // // for (pass=0; pass<2; pass++) // pass = 0; label_pass_start: if (pass >= 2) goto label_pass_end; for (i=0; inum_programs; i++) { pmcm = NULL; program = &ctx->pat->programs[i]; // cafrii 070130 add // 1st scan, #1~999 processed. 2nd scan, #1000+ processed // if (pass == 0 && program->program_number > 999) continue; if (pass == 1 && program->program_number <= 999) continue; // ¸¸¾à ÀÌ¹Ì VCT¿¡ ÀÇÇØ¼­ Channel DB°¡ updateµÇ¾îÀÖ´Ù¸é ±»ÀÌ ¹ÞÀ» ÇÊ¿ä´Â ¾ø´Âµ¥.... // MCM¿¡ Á¸ÀçÇÏ´Â DB°¡ À̹ø autoscan ¿¡¼­ »õ·Î ¹ÞÀº °ÍÀÎÁö, // ¿¾³¯ °ÍÀÎÁö ±¸ºÐÇÏ´Â flag°¡ ¾ø´Ù... // // if (find_mcm_xx(rf, program->program_number)) // continue;; // // ±×·¯³ª ÇØ´ç program numberÀÇ VCT channelÀÌ Á¸ÀçÇÑ´Ù°í ÇØ¼­ // ±× Á¤º¸°¡ DB¿¡ Ãß°¡µÇ¾ú´Ù°í º¼ ¼ö´Â ¾ø´Ù!! // ¿Ö³ÄÇϸé VCT channelÀÇ Á¤º¸°¡ ¿Ïº®ÇÏÁö ¸øÇؼ­ skipµÇ¾úÀ» ¼öµµ Àֱ⠶§¹®.. // // µû¶ó¼­ vctÀÇ processed flag¸¦ ÂüÁ¶ÇÏ¿© DB¿¡ Àû¿ëµÈ°ÍÀÎÁö ¾Ë¾Æ³½´Ù. // #if 0 // cafrii 060725 delete if (ctx->xvct) { // ¿î³ª»Ú°Ô analog ä³ÎÁ¤º¸¿¡ program number°¡ Àִµ¥ °ªÀÌ ÀÏÄ¡Çϰųª // ¶Ç´Â À߸øµÈ vct channel Á¤º¸°¡ ÀÖ¾ú´Ù¸é ºñ±³°¡ Á¤È®ÇÏÁö ¾Ê°Ô µÈ´Ù. // for (k=0; kxvct->numChannels; k++) { if (ctx->xvct->channel[k].program_number == program->program_number) break; } if (k < ctx->xvct->numChannels && ctx->xvct->channel[k].processed) { dprint(2, "**** same program number channel (#%d) exist. skip updating psi..\n", program->program_number); continue; } } #else // cafrii 060725 change // cafrii 060808 comment: fresh mcm¸¸ °Ë»öÇϵµ·Ï ÇÑ´Ù. // if (check_mcm_if_rf_prognum_exist(ctx->cur_channel, program->program_number)) { dprint(2, "**** same program number channel (#%d) exist. skip updating psi..\n", program->program_number); continue; } #endif if (ctx->fnCheck && ctx->fnCheck()) { status = statusCancelled; goto label_end_scan; } if (ctx->pmtList[i] == NULL) { // ÇöÀç ÀÌ PMT´Â ¾ÆÁ÷ ¼ö½ÅÀÌ ¾ÈµÇ¾úÀ½.. ÀÌÀü ¼ö½ÅÇÒ ¶§ timeout ½ÇÆÐÇßÀ» °¡´É¼ºÀÌ Å©´Ù. #if USE_PSI_RX_RETRY // cafrii 050429 add // ¾Õ¿¡¼­ TVCT/CVCT/PAT/PMT¸¦ ÇѲ¨¹ø¿¡ ¼ö½ÅÇÒ ¶§¿¡ ¾î¶°ÇÑ ÀÌÀ¯·Îµç PMT¸¦ ¸ðµÎ ¼ö½ÅÇÏÁö // ¸øÇßÀ» °æ¿ì°¡ ÀÖÀ» ¼ö ÀÖ´Ù. // ÀÌ °æ¿ì¸¦ º¸¿ÏÇϱâ À§Çؼ­ ¼ö½ÅÇÏÁö ¸øÇÑ PMT´Â ¿©±â¼­ ´Ù½Ã Çѹø Ãß°¡·Î ¼ö½Å½ÃµµÇÑ´Ù. dprint(2, "retry getting pmt[%d], pid 0x%x, #%d\n", i, program->program_map_PID, program->program_number); status = Dmc_GetPMT(ctx->tsd, program->program_map_PID, program->program_number, &ctx->pmtList[i], g_Timeout_PmtLoading*_second/1000, ctx->fnCheck); if (status == statusCancelled) { goto label_end_scan; } if (status) { dprint(0, "!! pmt[%d] pid 0x%x, #%d not loaded\n", i, program->program_map_PID, program->program_number); continue; // ´ÙÀ½ PMT·Î ÁøÇà.. } #else _second = _second; // to avoid warning.. dprint(0, "!! pmt[%d] program number #%d not loaded\n", i, program->program_number); continue; #endif } #if TEST_LARGE_PROGRAM_NUMBER // cafrii 060728 add for test // if (g_TestLargeProgramNumber) { if (i > 0 && ctx->pmtList[i-1] && ctx->pmtList[i]) { ctx->pmtList[i]->program_number = ctx->pmtList[i-1]->program_number+999; dprint(0, "!!!! large PN test: -> #%d\n", ctx->pmtList[i]->program_number); } else dprint(0, "!!!! large PN test: \n"); } #endif status = update_psi_program(ctx, ctx->pat->transport_stream_id, ctx->pmtList[i], program_index++, &pmcm); if (status == statusCancelled) { //return status; goto label_end_scan; } if (pmcm == NULL && status == statusOK) status = statusError; if (status) { // ±×¹ÛÀÇ ´Ù¸¥ ¿¡·¯.. ÀÏ´Ü ¸ØÃßÁö ¸»°í °è¼Ó ÁøÇàÇÏÀÚ. } else // no error and pmcm valid { if (bMinorNumberAutoAdjust) { param2[n_param2].pn = pmcm->Prog_number; param2[n_param2].id = pmcm->Uid; param2[n_param2].minor = pmcm->Minor; n_param2++; } if (bMinorNumberAutoAdjust == FALSE) { if (pmcm) { // »õ·Î ¹ß°ßµÈ ä³ÎÀÌ ¾øÀ» ¼öµµ ÀÖ´Ù. ±×·² °æ¿ì pmcm Àº NULL ÀÌ´Ù. //print_mcm(); cbparam.ucm = pmcm; send_event_message(evtNewChannel, (UINT32) &cbparam); // »õ·Î updateÇÑ mcm item Æ÷ÀÎÅ͸¦ ³Ñ°ÜÁØ´Ù. } } } } if (++pass < 2) goto label_pass_start; label_pass_end: if (bMinorNumberAutoAdjust && n_param2 > 0) { _MinorAdjustParam tmp; int free_minor_number; int nAdjustedChannel = 0; int pn_threshold = 1000; // ÀÌ °ª ÀÌ»óÀÎ pnÀº adjust¸¦ ÇÑ´Ù. // program number·Î sorting.. ¿À¸§ Â÷¼ø.. // for (i=0; i param2[k].pn) { tmp = param2[k]; param2[k] = param2[i]; param2[i] = tmp; } } } // threshold º¸´Ù Å« pnÀº ÀÏ´Ü ¸ðµÎ minor 0À¸·Î Àӽà ÇÒ´ç. for (i=0; i= pn_threshold) ? 0 : param2[i].pn; // minor 0ÀÎ Àӽà ä³ÎÀ» ¼ø¼­´ë·Î Áߺ¹ ¾ÈµÇ°Ô ÇÒ´ç.. free_minor_number = 1; for (i=0; iMinor = param2[i].minor; dprint(2, "\t[%d] %d - %3d, #%d %s\n", i, pmcm->Major, pmcm->Minor, pmcm->Prog_number, pmcm->Minor != pmcm->Prog_number ? "<---" : ""); } } } } if (1) { if (bMinorNumberAutoAdjust) { for (i=0; iMajor, pmcm->Minor, pmcm->Prog_number, pmcm->scrambled); cbparam.ucm = pmcm; send_event_message(evtNewChannel, (UINT32)&cbparam); } } } } label_end_scan: if (param2) DHL_OS_Free((void**)¶m2); return status; } // // // pat°¡ ¼ö½ÅÀÌ ¾ÈµÇ¸é statusNoPSI // STATUS get_pmt_by_program_number(ChannelScanContext *ctx, xvctChannelPtr_t p, int *pIndex) { STATUS status = statusOK; int i; int idx = -1; // matched_pmt_index if (ctx->pat == NULL) { #if USE_PSI_RX_RETRY dprint(2, "\t no pat. get pat again..\n"); status = Dmc_GetPAT(ctx->tsd, &(ctx->pat), g_Timeout_PatLoading*1000/1000, ctx->fnCheck); if (status == statusCancelled) // cafrii 070117 add for bugfix return statusCancelled; if (status || ctx->pat == NULL) { dprint(0, "!! no pat..\n"); return statusNoPSI; } #else if (ctx->pat == NULL) { dprint(0, "!! no pat..\n"); return statusNoPSI; } #endif } // matched pmt index¸¦ ã´Â´Ù. // for (i=0; inum_programs; i++) { if (ctx->pat->programs[i].program_number == p->program_number) { idx = i; break; } } if (idx >= 0) { // ÁÖÀÇ!! pmtList[i] °¡ NULL ÀÏ ¼öµµ ÀÖ´Ù!! // PAT¿¡´Â µî·ÏµÇ¾î ÀÖÀ¸³ª ½ÇÁ¦·Î´Â Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì, // ¶Ç´Â timeoutµÇ¾î¼­ PMT¸¦ ¼ö½ÅÇÏÁö ¸øÇÑ °æ¿ì.. // if (ctx->pmtList[idx] && ctx->pmtList[idx]->program_number != p->program_number) { dprint(0, "!! received pmt[%d]'s pn #%d != vct ch pn#%d\n", idx, ctx->pmtList[idx]->program_number, p->program_number); FreePMT(ctx->pmtList[idx]); ctx->pmtList[idx] = NULL; } if (ctx->pmtList[idx] == NULL) { #if USE_PSI_RX_RETRY dprint(2, "\t no pmt yet. get pmt[%d] again..\n", idx); status = Dmc_GetPmtByProgramNumber(&(ctx->pat), &(ctx->pmtList[idx]), p->program_number, ctx->fnCheck); if (status == statusCancelled) // cafrii 070117 add for bugfix return statusCancelled; if (status) dprint(2, "\t pmt[%d] load failed %d\n", idx, status); #else if (ctx->pmtList[idx] == NULL) dprint(2, "!! no pmt[%d] loaded..\n", idx); #endif } *pIndex = idx; return status; } dprint(0, "!! pn #%d pmt not found. try recover vct..\n", p->program_number); // recover vct!! status = Dmc_RecoverVctProgramNumber(p, ctx->pat, // IN ctx->pmtList, // INOUT &idx, // OUT ctx->fnCheck); if (status == statusCancelled) return status; if (status) dprint(2, "!! recover failed, %d\n", status); else { // recover ¼º°ø.. *pIndex = idx; status = statusOK; } return status; } #if 0 // cafrii 060728 delete. no more used. // »õ·Î¿î pid selection ruleÀ» »ç¿ëÇϱ⠶§¹®. // STATUS find_pids_from_psi(ChannelScanContext *ctx, MPEG_PMT *pmt, UINT16 *pPid, UINT16 *vPid, UINT16 *aPid) { int err = DHL_OK; UINT32 vidPid, audPid, pcrPid; if (pmt == NULL) { return statusNotFound; } //----- PMT ó¸®. err = GetElementaryPIDs(pmt, &vidPid, &audPid, &pcrPid, NULL, NULL, NULL); // °¡´ÉÇÑ ¿¡·¯.. scrambledWarning, or notFoundError.. if (IsError(err)) { // cafrii, 030506 dprint(0, "!! cannot get pids in PMT #%d, err %s\n", pmt->program_number, ErrorString((DHL_RESULT)err)); // cafrii 050707 fix, i -> pmt->program_number if (dprintable(3)) PrintPMT(pmt); return statusPSIPError; } if (pPid) *pPid = (UINT16) pcrPid; if (vPid) *vPid = (UINT16) vidPid; if (aPid) *aPid = (UINT16) audPid; return err; // scrambledWarning °á°ú°¡ ±×´ë·Î Àü´ÞµÉ ¼ö ÀÖµµ·Ï.. } #endif // 0 static STATUS update_vct_subchannel(ChannelScanContext *ctx, UINT16 tsid, xvctChannelPtr_t p, BOOL is_cvct, MCM_DB_T **ppmcm) { // »õ·Î ¹ÞÀº VCT Å×À̺íÀ» ä³Î DB¿¡ Ãß°¡Çϱâ À§Çؼ­ ƯÁ¤ minor ä³ÎÀ» ¼±ÅÃÇÑ ÈÄ (p) // ÀÌ ÇÔ¼ö¸¦ ºÒ·¯ MCM DB¿¡ µî·ÏÇÑ´Ù. // // VCTÀÇ ÇØ´ç minor ä³Î Å×ÀÌºí¿¡¼­ ¹ß°ßµÇ´Â ¸ðµç Á¤º¸¸¦ ±â·ÏÇÑ´Ù. // ±âÁ¸ ä³Î DB¿¡ (Mj/Mn/Rf/VctFlag)°¡ ÀÏÄ¡ÇÏ´Â Ç׸ñÀÌ ÀÖÀ¸¸é updateÇÑ´Ù. // // °¢ ä³Î ŸÀÔ È¯°æ¿¡ ¸ÂÃç update¸¦ ´Ù¸£°Ô ÇÑ´Ù. // // MCM DB¿¡ µî·ÏÇÑ ÈÄ »õ·Î µî·ÏµÈ MCM entryÀÇ pointer´Â ppmcmÀ» ÅëÇØ caller¿¡°Ô ÂüÁ¶¿ëÀ¸·Î ³Ñ°ÜÁø´Ù. // caller´Â ÀÌ Æ÷ÀÎÅ͸¦ ÀÌ¿ëÇÏ¿© ¾î¶² MCMÀÌ µî·ÏµÇ¾ú´ÂÁö ¾Ë ¼ö ÀÖ´Ù. // ´Ü¼øÈ÷ ÂüÁ¶¿ëÀ̸ç, caller´Â ÇÊ¿äÇÑ °æ¿ì MCM Á¤º¸¸¦ º¹»çÇØ¼­ »ç¿ëÇÒ ¼ö ÀÖ´Ù. // // Note: leon 2003.9.2 // ETM_location,access_controlled,hidden,hide_guideµµ °í·ÁÇÒ Çʿ䰡 ÀÖ´Ù. // ¸ÞÀÌÀú ä³Î DB¸¦ »ç¿ëÇÒ °æ¿ì(rfµµ ´Ù¸¦ ¶§ ), // ÀÌÀü¿¡ µî·ÏµÇ¾î ÀÖ´ø ¸ÞÀÌÀú ä³Î(10-1,10-2,10-3,10-4)¿Í »õ·Î Ãß°¡µÈ ä³Î // °°Àº ¸ÞÀÌÀú ¹øÈ£ »ç¿ë(10-1,10-2)ÀÏ °æ¿ì,App°¡ ÀÌ·² °æ¿ì, ¸ÞÀÌÀú ¹øÈ£ 10À» µÎ°³ °¡Áö°Ô ÇØ¾ßµÊ // ´Ù¸¥ ä³ÎÀ̴ϱñ ,,, ´Ù¸¥ ¸ÞÀÌÀú DB¿¡ µî·ÏÇÒ ¼ö ÀÖµµ·Ï ±¸ºÐ ÇÊ¿ä?? ¾î¶»°Ô ±¸ºÐÇÏÁö?? // // int strength; int vctRF; // vctRF´Â vct¸¦ ¼ö½ÅÇÑ Ã¤³Î, channelRF´Â VCT¿¡ ±âÀçµÈ virtual channelÀÇ RF int vctFreqOffset; // cafrii 050603 add MCM_DB_T *m, m_0, *target = NULL; STATUS status; extendedChannelNameDescriptorPtr_t xcnd = NULL; // cafrii 041126 add BOOL is_cable = g_CurChannelType != ChannelType_Cable ? FALSE : TRUE; BOOL bScrambled = FALSE; // TRUE program is scrambled.. UINT32 audioPID32 = 0; // cafrii 060804 add vctRF = ctx->cur_channel; // ÀÌ VCT¸¦ ¼ö½ÅÇß´ø PTCÀÇ RF¹øÈ£ vctFreqOffset = ctx->freq_offset; // ÀÌ VCT¸¦ ¼ö½ÅÇÑ Ã¤³ÎÀÇ FreqOffset // cafrii 050603 add strength = ctx->signal_strength; // ÇöÀç ÀÌ Ã¤³ÎÀÇ ½ÅÈ£ ¼¼±â if (strength == 0) strength = 1; // 0 °ªÀº Ưº°ÇÑ Àǹ̷Π»ç¿ëµÇ¹Ç·Î ÇÇÇÑ´Ù. dprint(2, "update_vct_subchannel: %s, rf %d, tsid %d, str %d\n", is_cvct ? "CVCT" : "TVCT", vctRF, tsid, strength); // A65B specÀÇ ³»¿ëÀ» º¸¸é Air¿¡¼­µµ CVCTÀÇ »ç¿ëÀÌ ±ÝÁöµÈ °ÍÀº ¾Æ´Ñ°Í °°´Ù. // ´Ü, Air¿¡¼­´Â TVCT°¡ CVCT º¸´Ù ¿ì¼±µÇ´Â °Í »ÓÀÌ´Ù. // caller´Â µ¿½Ã¿¡ µÎ°³ÀÇ VCT°¡ ¼ö½ÅµÉ °æ¿ì Àû´çÇÑ VCT¸¦ ¼±ÅÃÇØ¼­ ÀÌ ÇÔ¼ö¸¦ È£ÃâÇØ¾ß ÇÑ´Ù. // // cafrii 041130 add comment // MCM °ü¸® ±ÔÄ¢: // ¸ÕÀú local stack¿¡ Àӽà mcm À» ¸¸µé°í ÃʱâÈ­¸¦ ÇÏ°í ³ª¼­ ½ÇÁ¦ MCM list¿¡ Ãß°¡ÇÏ´Â ¹æ½ÄÀ¸·Î ÇÑ´Ù. m = &m_0; memset(m, 0, sizeof(MCM_DB_T)); m->Major = p->major_channel_number; m->Minor = p->minor_channel_number; m->Prog_number = p->program_number; if (is_cvct && IsOnePartChannelNumber(m->Major)) { if (!is_cable) dprint(0, "!! OnePartChannel number in CVCT/Air.. maybe wrong\n"); m->Major = ConvertToOnePartChannelNumber(m->Major, m->Minor); m->Minor = ONE_PART_CHANNEL_INDICATOR; // ÀÌ Minor °ªÀ¸·ÎºÎÅÍ ¿ì¸®´Â ÀÌ Ã¤³ÎÀÌ OnePartChannelÀ̶ó´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù. dprint(2, "====== %d-%d (%d), #%d, mm 0x%x, st 0x%x, ch_tsid 0x%x\n", p->major_channel_number, p->minor_channel_number, m->Major, // OnePart number m->Prog_number, p->modulation_mode, p->service_type, p->channel_TSID); } else { // cafrii 060630 add // // for air TVCT, // major number range: 1 ~ 99 // minor number range: 0 ~ 999 // for analog service, 0 is used. // for digital or audio only, 1 ~ 99 is used. // for databroadcasting and etc, 1 ~ 999 is used. // we restrict minor number to 3 digits.. // // for cable CVCT, // major number range: 1 ~ 999 // minor number range: 0 ~ 999 // // cable¿¡¼­ 1000 ~ 1007 ±îÁöÀÇ major, // air¿¡¼­ 1000 ÀÌ»óÀÇ major´Â ¾î¶»°Ô ó¸®ÇÒ °ÍÀΰ¡? --> ¿¡·¯ ó¸®. // if (!is_cable && m->Major > 99) { // air À̸é tvctµç cvctµç 99Ãʰú ±ÝÁö. dprint(0, "!! air mode, major %d invalid!\n", m->Major); status = statusPSIPError; goto label_exit; } if (is_cable && m->Major > 999) { // cableÀ̸é tvctµç cvctµç 999 Ãʰú ±ÝÁö. dprint(0, "!! cable mode, major %d invalid!\n", m->Major); status = statusPSIPError; goto label_exit; } // cafrii 060804, major 0 ±ÝÁö // if (m->Minor != ONE_PART_CHANNEL_INDICATOR && m->Major <= 0) { dprint(0, "!! two part channel major 0 invalid\n"); status = statusPSIPError; goto label_exit; } if (m->Minor > 999) { dprint(0, "!! minor %d invalid!\n", m->Minor); status = statusPSIPError; goto label_exit; } dprint(2, "====== %d-%d, #%d, mm %d, st %d, ch_tsid 0x%x\n", m->Major, m->Minor, m->Prog_number, p->modulation_mode, p->service_type, p->channel_TSID); } //-------------------------------------------------------- // service_typeÀ» °áÁ¤. // modulation mode summary: // 00 : reserved // 01 : analog // 02 : SCTE_mode_1, 64QAM // 03 : SCTE_mode_2, 256QAM // 04 : ATSC 8VSB // 05 : ATSC 16VSB // // service type summary: // 00 : reserved // 01 : analog TV // 02 : ATSC digital TV // 03 : ATSC audio // 04 : ATSC data // 05 : ATSC sdds // if (p->modulation_mode == 1) // analog { // // ¾Æ³¯·Î±×ÀÇ °æ¿ì, minor°¡ 0ÀÌ ¾Æ´Ï¸é ¹ö¸°´Ù. // if (p->minor_channel_number != 0) { dprint(0, "!! Err! Analog channel's minor is non-zero? ignore it!\n"); status = statusPSIPError; goto label_exit; } if (p->service_type != 1) { // 1: analog service dprint(0, "!! Err! modulation %d, service %d mismatch! ignore it!\n", p->modulation_mode, p->service_type); status = statusPSIPError; goto label_exit; } m->Service_type = Modulation_NTSC; // NTSC. } else if (p->modulation_mode == 2 || p->modulation_mode == 3 || // 64QAM / 256QAM p->modulation_mode == 4) // 8VSB { // ÁÖÀÇ! TVCT¿¡¼­µµ QAM modulationÀÌ °¡´ÉÇϵµ·Ï ÇØ¾ß ÇÔ.. (CableLab ATP Ç׸ñ) // µû¶ó¼­ TVCT/CVCT ÀÇ ¿©ºÎ°¡ Áß¿äÇÑ°Ô ¾Æ´Ï¶ó Air/Cable ¿©ºÎ°¡ ´õ Áß¿äÇÏ´Ù. // if (!is_cable && // Air ¸ðµå¿¡¼­ (p->modulation_mode == 2 || p->modulation_mode == 3)) { // QAM ÀÎ °æ¿ì.. dprint(0, "!! QAM modulation in Air.. ignore!\n"); status = statusPSIPError; goto label_exit; } // cafrii 060630 change, allow minor 0 for cable cvct.. // we just check cvct or not.. do not check air/cable. // because retransmission of terrestrial (tvct) is actually air case. // if (!is_cable && // Air À̰í, (tvctµç, cvctµç..) m->Minor == 0) { // minor°¡ 0ÀÎ °æ¿ì.. dprint(0, "!! Err! in air, digital minor is zero.. ignore!\n"); status = statusPSIPError; goto label_exit; } if (p->service_type == 1) // Digital Modulation À̸鼭 analog service? dprint(0, "!! Warning! modulation is 8VSB, but analog service? assume Digital!\n"); #if 0 // VCT°ªÀ» »ç¿ëÇÏÁö ¾Ê°í detect µÈ °ªÀ» »ç¿ëÇÏÀÚ. m->Service_type = p->modulation_mode == 2 ? Modulation_64QAM : // 2 ATSC-64QAM p->modulation_mode == 3 ? Modulation_256QAM : // 3 ATSC-256QAM Modulation_8VSB ; // ATSC-VSB #else // cafrii 041122 add more conditions. if (ctx->tuner_modulation_mode == Modulation_8VSB) { m->Service_type = ctx->tuner_modulation_mode; } else if (ctx->tuner_modulation_mode == Modulation_64QAM || ctx->tuner_modulation_mode == Modulation_256QAM) { if (g_CurChannelType == ChannelType_Air) { dprint(0, "!! QAM modulation detected in Air mode scan\n"); m->Service_type = Modulation_8VSB; } else m->Service_type = ctx->tuner_modulation_mode; } else { dprint(0, "!! wrong tuner modulation %d in psi scan\n", ctx->tuner_modulation_mode); m->Service_type = g_CurChannelType == ChannelType_Air ? Modulation_8VSB : Modulation_64QAM; } #endif } else // exceptions.. Áö¿øÇÏÁö ¾Ê´Â modulation mode. ´Ù¸¥ °ªµéÀ» ÀÌ¿ëÇØ¼­ ÃßÁ¤ÇÑ´Ù. { dprint(0, "!! Err! unknown modulation mode %d in vct\n", p->modulation_mode); // invalid VCT Á¤º¸¸¦ ¹ö¸®Áö ¾Ê°í ÃÖ´ëÇÑ »ç¿ëÇÏ·Á°í ½ÃµµÇÔ. // modulation mode °ªÀÌ Á¤È®ÇÏÁö ¾Ê´Ù¸é, service type °ªÀ¸·ÎºÎÅÍ ÃßÁ¤À» ÇÏÀÚ.. // if (p->service_type == 1) { // NTSC.. m->Service_type = Modulation_NTSC; } else { // 2, 3, 4, ... all digital services.. // Table¿¡ Á¦´ë·Î µÈ ModulationMode Á¤º¸°¡ ¾øÀ¸´Ï ¾Æ¹« °ªÀ̳ª »ç¿ëÇÏÀÚ.. // // todo.. // --> cafrii 041122, tunerÀÇ modulation mode¸¦ »ç¿ëÇÏ´Â °ÍÀº ¾î¶²°¡? // self channel ÀÎ °æ¿ì¿¡´Â °¡´ÉÇϰÚÁö¸¸ remote channel ÀÎ °æ¿ì¿¡´Â ¹®Á¦°¡ µÈ´Ù. if (is_cable) { // TVCT°¡ ¿Â °æ¿ì 8VSB·Î ÇÏ´Â°Ô ³ªÀ»±î? m->Service_type = Modulation_64QAM; } else // Air ÀÎ °æ¿ì.. m->Service_type = Modulation_8VSB; } } //-------------------------------------------------------- // °¢ service_type º°·Î ó¸®.. // VCTÀÇ service_type Àº ´ÙÀ½°ú °°´Ù. // 1: analog, 2: ATSC, 3: ATSC audio only, 4: ATSC data // // VCTÀÇ modulation_mode // 1: analog, 2: 64QAM, 3: 256QAM, 4: 8VSB, 5: 16VSB // // MCMÀÇ service typeÀº modulation mode¿¡ ´õ °¡±î¿î °³³äÀÌ´Ù. // // NTSCÀÇ °æ¿ì´Â RF, freqOffset À» °áÁ¤. // DigialÀÇ °æ¿ì´Â Pids, scrambled, RF, freqOffset À» °áÁ¤. // // dprint(2, " service type %d (%s) decided\n", m->Service_type, ServiceTypeString(m->Service_type)); if (m->Service_type == Modulation_NTSC) // NTSC { // cafrii 050902 change. no more support analog channel info in VCT dprint(0, "!! analog channel in VCT not support!\n"); status = statusPSIPError; goto label_exit; } else // digital.. ATSC_XXX. 8VSB/64QAM/256QAM { PidInfo vctPid; // cafrii 041125 add int matched_pmt_index = -1; //dprint(3, " pmtList 0x%x, num program %d\n", ctx->pmtList, ctx->num_programs); //--------------- RF ¹øÈ£ °áÁ¤ ---------------------- // // cafrii 050817 change // tsid Á¤º¸¸¦ ¿ÏÀüÈ÷ ¹«½ÃÇϰí, Ç×»ó ÇöÀç PTC¿¡ Æ÷ÇÔµÈ Ã¤³Î·Î °£ÁÖÇÑ´Ù. // m->RF = vctRF; // ÀÌ VCT¸¦ ¼ö½ÅÇÑ RF ä³Î ¹øÈ£¸¦ »ç¿ëÇÑ´Ù. m->freqOffset = vctFreqOffset; // //------------- PID ¹× CodingType Á¤º¸ ÃßÃâ ----------------- status = get_pmt_by_program_number(ctx, p, &matched_pmt_index); if (status == statusCancelled) // cafrii 070117 add for bugfix goto label_exit; memset(&vctPid, 0, sizeof(vctPid)); // cafrii 041126 add // cafrii 060727 add matched_pmt_index check code if (status == statusOK && matched_pmt_index >= 0) { status = Dmc_DecidePidInfo2(ctx->pmtList[matched_pmt_index], p->descriptors, p->descriptor_length, &vctPid, 0); doDmc_SelectAudioStream(ctx->pmtList[matched_pmt_index], p, &vctPid.audio, &vctPid.audioType); doDmc_SelectVideoStream(ctx->pmtList[matched_pmt_index], p, &vctPid.video, &vctPid.videoType); } else { // pmt¿¡ ¹®Á¦°¡ ÀÖÀ¸¸é vct¸¸À¸·Î ¼öÇà. status = Dmc_DecidePidInfo2(NULL, p->descriptors, p->descriptor_length, &vctPid, 0); doDmc_SelectAudioStream(NULL, p, &vctPid.audio, &vctPid.audioType); doDmc_SelectVideoStream(NULL, p, &vctPid.video, &vctPid.videoType); } // PCR pid °ªÀº ¹Ýµå½Ã ÀÖ¾î¾ß Çϸç, Video pid ¶Ç´Â Audio pid µÑ Áß Çϳª°¡ ÀÖ¾î¾ß ÇÑ´Ù. // if (status == statusOK && vctPid.bValid && vctPid.pcr && (vctPid.video || vctPid.audio)) { // ¼º°øÀûÀ¸·Î PID °ªÀÌ ÃßÃâµÇ¾úÀ½. // m->Pcr_pid = vctPid.pcr; m->Video_pid = vctPid.video; m->Audio_pid = vctPid.audio; m->Video_type = vctPid.videoType; m->Audio_type = vctPid.audioType; //neverdai 081002 && ctx->pmtList[matched_pmt_index] Ãß°¡. //³í¸®ÀûÀ¸·Î ctx->pmtList[matched_pmt_index]´Â NULL °ªÀÌ µÉ ¼ö Àֱ⠶§¹®¿¡ Ã¼Å©ÇØ¾ß ÇÔ. if (matched_pmt_index >= 0 && matched_pmt_index < ctx->num_programs && ctx->pmtList[matched_pmt_index]) m->pmt_pid = ctx->pmtList[matched_pmt_index]->PID; else m->pmt_pid = DMW_PID_NO_INFO; // vct recover ±â´É¿¡ ÀÇÇØ program number°¡ ¹Ù²î¾úÀ» ¼ö ÀÖ´Ù. m->Prog_number = p->program_number; dprint(2, " pid(pva): 0x%x 0x%x 0x%x, pmt 0x%x, vt%d at%d\n", m->Pcr_pid, m->Video_pid, m->Audio_pid, m->pmt_pid, m->Video_type, m->Audio_type); } else { dprint(0, "!! invalid pid info.. skip this subchannel\n"); // cafrii 060728 add // À¯È¿ÇÑ pid°¡ ¾øÀ¸¸é DB¿¡ ³ÖÁö ¾Ê´Â´Ù. status = statusPSIPError; goto label_exit; } // ------------ ä³Î Long Name ----------------- #if USE_DMW_EPGX_LIB status = Dmc_GetInfoFromVctDesc(p->descriptors, p->descriptor_length, NULL, &xcnd); if (xcnd) { dprint(2, " extended channel name: \n"); if (dprintable(2)) { //memdump(xcnd->long_channel_name, xcnd->long_channel_name_length, "LongName"); Dmc_PrintMultipleString(xcnd->long_channel_name, xcnd->long_channel_name_length, 10, 0); // indent 10 } } #endif // ------------ ¾Ïȣȭ ¿©ºÎ üũ ----------------- // if (is_cable) { #if 0 // cafrii 050124 fix // // Motorolla HE ¿¡¼­´Â °ÅÀÇ ´ëºÎºÐÀÇ Ã¤³ÎÀÌ CA descriptor°¡ Àֱ⠶§¹®¿¡ // ÀÌ ¹æ¹ýÀ» »ç¿ëÇϱⰡ ¾î·Æ´Ù. // // 1: CA descriptor¸¦ ã¾Æº¸±â if (matched_pmt_index >= 0) { // by MPEG system spec: // If any elementary stream is scrambled, a CA descriptor shall be // present for the program containing that elementary stream. MPEG_PMT *pmt = ctx->pmtList[matched_pmt_index]; if (GetMpegDescriptor(pmt->descriptors,pmt->descriptor_length, CA_tag, 0, NULL) == DHL_OK) { dprint(2, " !! PMT main descriptor has CA descriptor\n"); bScrambled = TRUE; } } // 2: TSC bit¸¦ °Ë»çÇϱâ if (m->Video_pid || m->Audio_pid) // PID Á¤º¸°¡ ÀÖ¾î¾ß ÀÌ ¹æ¹ýÀ» »ç¿ëÇÒ ¼ö ÀÖ´Ù. { int pidArray[2] = {0, }; // video and audio.. int tscArray[2] = {0, }; int nPid = 0; if (m->Video_pid) pidArray[nPid++] = m->Video_pid; if (m->Audio_pid && m->Audio_pid != m->Video_pid) pidArray[nPid++] = m->Audio_pid; status = Dmc_GetMultipleTscBits(ctx->tsd, nPid, pidArray, tscArray, g_Timeout_PesPidCheck*1000/1000, ctx->fnCheck); // cafrii 041202, add cancel check function // cafrii 050305, timeout to 100ms // cafrii 050315, change timeout value to variables // statusCancelled, timeoutError, outOfCPUMemoryError, ... if (status == statusCancelled) { goto label_exit; } else if (status == statusOK) { //dprint(2, " tsc bit of pid %d, %d : %d, %d\n", // pidArray[0], pidArray[1], tscArray[0], tscArray[1]); // cafrii 050228, remove tsc bit 255 case, which is not_found.. if (tscArray[0] == 1 || tscArray[0] == 2 || tscArray[0] == 3 || tscArray[1] == 1 || tscArray[1] == 2 || tscArray[1] == 3 ) { dprint(2, " !! one of stream is scrambled bit checked. 0x%x:%d, 0x%x:%d\n", pidArray[0], tscArray[0], pidArray[1], tscArray[1]); bScrambled = TRUE; } } else dprint(0, "!! scrmabled bit check err %d\n", status); } // 3: Video context¸¦ Á÷Á¢ »ý¼ºÇغ¸±â.. if (1) { if ((ctx->flag & CBTF_CheckScrambleByVideoContext) && m->Video_pid) { // cafrii 040114 bugfix #AudioOnlyChannelMissing // À̶§ AudioOnly ä³ÎÀÇ °æ¿ì VideoDecodingÀÌ Ç×»ó failÀÌ ³ª¼­ Ç×»ó scramble·Î °£ÁֵǴ ¹®Á¦°¡ ÀÖÀ¸¹Ç·Î // Audio only ä³ÎÀÇ °æ¿ì¿¡´Â ±×³É unscramble·Î °£ÁÖÇÑ´Ù. if (matched_pmt_index >= 0) { // by MPEG system spec: // If any elementary stream is scrambled, a CA descriptor shall be // present for the program containing that elementary stream. status = check_pes_scramble(ctx->tsd, ctx->pmtList[matched_pmt_index], m->Video_pid, m->Pcr_pid); } else status = check_pes_scramble(ctx->tsd, NULL, m->Video_pid, m->Pcr_pid); if (status == statusScrambled) { if(ctx->flag &CBTF_IgnoreScrambledChannel) { return status; } bScrambled = TRUE; dprint(1, " !! video context (pid v %d/p %d) creation err. scrambled\n", m->Video_pid, m->Pcr_pid); } else if (status == statusOK) { // good channel.. } else { dprint(0, "!! video ES seems invalid.. status %d\n", status); } } } #endif } } // end if Service_type #if 0 // USE_RESOLUTION_GATHERING //sequence Á¤º¸¸¦ ¾ò¾î¾ß ÇÔ do { #define MAX_SEQ_WAIT 5000 // ÃÖ´ë 5Ãʸ¦ ±â´Ù¸² tDHL_VideoSeqHdr seq; tDHL_DispFormat disp=eDHL_DISP_720x480i; UINT32 ms_start; if(m->Video_pid==0) break; //video pid°¡ Á¸ÀçÇØ¾ß ¾Æ·¡ Äڵ带 ½ÇÇàÇÔ. DHL_AV_VideoHide(0, TRUE); DMC_RegisterVideoCallback(FALSE); DHL_AV_VideoStart(0, m->Video_pid, m->Pcr_pid, m->Video_type); for(ms_start=DHL_OS_GetMsCount(); DHL_AV_VideoSeqInfo(0, &seq)!=DHL_OK && DHL_OS_GetMsCount()-ms_start < MAX_SEQ_WAIT; DHL_OS_Delay(100)); if(DHL_OS_GetMsCount()-ms_start >=MAX_SEQ_WAIT) { //timeout ; } else { if(seq.vertical_size>=1080) disp=eDHL_DISP_1920x1080i; else if(seq.vertical_size>=720) disp=eDHL_DISP_1280x720p; else disp=eDHL_DISP_720x480i; } DHL_AV_VideoStop(0); DMC_RegisterVideoCallback(TRUE); m->video_format=disp; } while(0); #endif m->signal_strength = m->RF == vctRF ? strength : 0; // ÇöÀç TSÀÇ Ã¤³Î Á¤º¸ÀÏ °æ¿ì¿¡¸¸ ½ÅÈ£ ¼¼±â ±â¾ï. // 0 : ÃøÁ¤ ¾ÈµÈ µ¥ÀÌÅÍ. // analogÀÇ °æ¿ìµµ 0. m->TSID = tsid; // ÇöÀç Æ©´×µÈ ä³Î (ÀÌ VCT¸¦ Æ÷ÇÔÇϰí Àִ ä³Î)ÀÇ TSID m->source_id = p->source_id; m->channel_tsid = p->channel_TSID; // ÀÌ ÇÁ·Î±×·¥ÀÇ TSID m->Skipped = 0; // ÀÌ µÎ°¡Áö´Â ³ªÁß¿¡ ¿©·¯ ä³Î Áß¿¡¼­ ¼±ÅÃÇÏ¿© °áÁ¤ÇÒ ¹®Á¦ÀÌ´Ù. m->SurfIndex = 0; m->hidden = p->hidden; // VCTÀÇ hidden Á¤º¸¸¦ º¸°üÇÑ´Ù. m->VctFlag = 1; // analog, digital °øÈ÷ VctFlag 1. m->scrambled = bScrambled; memcpy(m->ShortName, p->short_name, 14); dprint(2, " found subchannel: %d-%d, rf %d, %s(%d), $%d, #%d %s%s\n", m->Major, m->Minor, m->RF, ServiceTypeString(m->Service_type), m->Service_type, m->source_id, m->Prog_number, m->hidden ? "hidden " : "", m->scrambled ? "scrambled " : ""); // cafrii 060724 delete // µÚ¿¡¼­ ¿ÏÀüÈ÷ DB¿¡ updateÇÏ°í ³ª¼­ flag ¼³Á¤ÇÑ´Ù. //p->processed = TRUE; // ÀÌ vct channel Á¤º¸´Â Á¦´ë·Î DB¿¡ ¹Ý¿µ µÇ¾úÀ½À» Ç¥½Ã.. //------------------------------------------------------------------ // ÀÌÁ¦ local stackÀÇ Àӽà MCMÀÌ ¸ðµÎ ÁغñµÇ¾ú´Ù. // update Á¤Ã¥¿¡ µû¶ó updateÇÑ´Ù. Áߺ¹µÇ´Â Á¤º¸°¡ ÀÖÀ» °æ¿ì ¾Æ·¡ Á¶°ÇÀ» Àû¿ëÇÑ´Ù. // // 1. Analog ä³Î Á¤º¸ÀÇ °æ¿ì´Â VCT flag¸¦ ¿ì¼±ÇÑ´Ù. Á÷Á¢ °Ë»öÇÑ Ã¤³Î Á¤º¸º¸´Ù Á¤º¸°¡ ¸¹±â ¶§¹®. // RF != majorÀÎ VctFlag=1ÀÇ Ã¤³Îµµ Çã¿ëÇÑ´Ù. // 2. µðÁöÅÐÀÇ °æ¿ì: [030317 cafrii, »èÁ¦..] // // ASSERT (m->Service_type != Modulation_NTSC) // NTSC target = find_mcm_major_minor_rf_vf(m->Major, m->Minor, m->RF, 1); if (target == NULL) { target = new_mcm(); // ±âÁ¸ MCM Á¤º¸°¡ ¾øÀ¸¸é »õ·Î MCM itemÀ» Çϳª ÇÒ´çÇÏ°í µî·ÏÇÑ´Ù. if (target == NULL) { status = statusOutOfMemory; goto label_exit; } *target = *m; target->Uid = get_new_mcm_id(); // cafrii 060726 add } else { // cafrii 060724 comment // »ç½Ç M,m,R,V °¡ ¸ðµÎ µ¿ÀÏÇϸ鼭 program number°¡ ´Ù¸¥ °æ¿ì´Â ¼­·Î ±¸ºÐÀÌ ¾ÈµÇ¹Ç·Î // ±¸ºÐ Æ©´×ÀÌ ºÒ°¡´ÉÇϰí, DB¿¡ Ãß°¡ÇÏ´Â °ÍÀÌ Àǹ̰¡ ¾ø°Ô µÈ´Ù. // // À̹ø¿¡ Ãß°¡µÈ ä³ÎÀÎÁö, ÀÌÀü¿¡ Ãß°¡µÇ¾ú´ø ä³ÎÀÎÁö ±¸ºÐÇÒ ¼ö ÀÖÀ¸¸é ÁÁÀ½. // fresh field¸¦ Ȱ¿ëÇÑ´Ù. if (target->Prog_number == m->Prog_number) { dprint(2, " previous ch found. overwrite to old one.\n"); } else { if (target->fresh == 0) { // ÀÌ targetÀº ¿¹Àü DBÀ̹ǷΠ±×³É overwrit ÇØ¹ö¸®ÀÚ. dprint(2, " pn# mismatch, %d!=%d, but overwrite with new info\n", target->Prog_number, m->Prog_number); } else { // targetÀº ¹æ±Ý Àü¿¡ Ãß°¡µÈ ½Å±Ô ä³ÎÀ̹ǷΠÀ̹ø Á¤º¸¸¦ ¹ö¸®ÀÚ. dprint(2, " pn# mismatch. %d != %d, ignore this subchannel\n", target->Prog_number, m->Prog_number); status = statusChannelDuplicated; goto label_exit; } } m->csd = target->csd; m->num_csd = target->num_csd; m->max_csd = target->max_csd; *target = *m; target->Uid = get_new_mcm_id(); // cafrii 060726 add } #if SUPPORT_CSD_UPDATE if (xcnd) // cafrii 041126 add { dprint(2, " update_csd_entry: size %d\n", xcnd->long_channel_name_length); status = DMW_CDB_UpdateCsdEntry(&target->csd, &target->num_csd, &target->max_csd, CSD_TAG_EXTENDED_NAME, xcnd->long_channel_name_length, xcnd->long_channel_name); if (status) { if (status != statusNotChanged) dprint(0, "!! update_vct_subchannel: long name tag update err %d\n", status); } } #endif // SUPPORT_CSD_UPDATE target->fresh = 1; // cafrii 060724 add // À̹ø¿¡ »õ·Ó°Ô updateµÈ DB entryÀÓÀ» ³ªÅ¸³½´Ù. p->processed = TRUE; // cafrii 060724 move position here if (ppmcm) *ppmcm = target; status = statusOK; label_exit: if (xcnd) FreeMpegDescriptor(xcnd); return status; } //------------------------------------------------------ STATUS update_vct(ChannelScanContext *ctx) { STATUS status = statusOK; int i = 0; MCM_DB_T *pmcm; xvctPtr_t vct = ctx->xvct; int pass; ScanNewChannelCbParam cbparam; // cafrii 070130 add for new callback prototype memset(&cbparam, 0, sizeof(cbparam)); cbparam.fn_lookup_mj_mn = (BOOL (*)(int, int))find_mcm_major_minor; if (vct == NULL) return statusPSIPError; if (vct->numChannels <= 0) { dprint(0, "!! VCT has 0 channel!\n"); return statusPSIPError; } if (vct->channel == NULL) { dprint(0, "!! [%d] NULL channel in VCT!\n", i); return statusPSIPError; } dprint(2, "update VCT. total %d channel. signal %d\n", vct->numChannels, ctx->signal_strength); if (ctx->pat && ctx->pat->transport_stream_id != vct->transport_stream_id) { dprint(0, "!! pat tsid 0x%x != vct tsid 0x%x\n", ctx->pat->transport_stream_id, vct->transport_stream_id); } // cafrii 050802 add for (i=0; inumChannels; i++) vct->channel[i].processed = FALSE; // °¢ subchannel º°·Î process ¿©ºÎ¸¦ ±â¾ïÇÏ´Â flag. // óÀ½¿¡´Â default·Î FALSEÀ̰í, 󸮵Ǹé TRUE·Î ¼³Á¤µÈ´Ù. // ---------- first pass -------------- // VCTÀÇ ¸ðµç ä³ÎÀ» MCM¿¡ ¸ðµÎ updateÇÑ´Ù. // // cafrii 070130 add, use 2-pass mode // for (pass=0; pass<2; pass++) { for (i=0; inumChannels; i++) { pmcm = 0; // user¿¡°Ô event callbackÀ» Çϱâ À§ÇØ, ÇöÀç ¼öÁýµÈ mcm Á¤º¸°¡ ÇÊ¿äÇÏ´Ù. if (ctx->fnCheck && ctx->fnCheck()) { //dprint(2, "\t channel scan cancelled!!\n"); status = statusCancelled; goto label_end_scan; // cafrii 060617 fix memory leak } // cafrii 070130 add // 1st scan, #1~999 processed. 2nd scan, #1000+ processed // if (pass == 0 && vct->channel[i].program_number > 999) continue; if (pass == 1 && vct->channel[i].program_number <= 999) continue; if ((ctx->flag & CBTF_IgnoreNtscInVct) && vct->channel[i].modulation_mode == 1) { // 1:Analog if (!pass) dprint(1, " [%d] analog channel! ignored by user\n", i); continue; // If this channel is analog, skip it. } status = update_vct_subchannel(ctx, vct->transport_stream_id, &(vct->channel[i]), vct->is_cvct, &pmcm); if (status == statusCancelled) // cafrii 081006 add goto label_end_scan; if (1) { if (status == statusOK) { //print_mcm(); cbparam.ucm = pmcm; send_event_message(evtNewChannel, (UINT32)&cbparam); // »õ·Î updateÇÑ mcm item Æ÷ÀÎÅ͸¦ ³Ñ°ÜÁØ´Ù. } else { // ¼³·É ÇÑ Ã¤³ÎÀÌ À߸øµÇ¾ú´Ù°í ÇÏ´õ¶óµµ // ´ÙÀ½ ä³ÎÀº ±¦ÂúÀ» ¼ö ÀÖÀ¸¹Ç·Î °è¼Ó ÁøÇàÇØ¾ß ÇÑ´Ù. } } } // for } label_end_scan: return status; } #if COMMENT ___________________(){} #endif // // ChannelScanContext ³»ÀÇ °¢Á¾ Å×À̺íµéÀ» ¸ðµÎ free½ÃŲ´Ù. // // static void free_tables_in_context(ChannelScanContext *ctx) { int i; Dmc_FreeAtscTable(&ctx->xvct); Dmc_FreeAtscTable(&ctx->pat); if (ctx->pmtList) { for (i=0; inum_programs; i++) { Dmc_FreeAtscTable(&ctx->pmtList[i]); } DHL_OS_Free((void**)&ctx->pmtList); ctx->num_programs = 0; } } static STATUS download_tables(ChannelScanContext *ctx) { DmcMainTables tbls; xvctPtr_t vct = NULL; STATUS status; int _second = 1000; memset(&tbls, 0, sizeof(tbls)); // todo.. // CBTF_PsiOnlyMode ¿¡¼­´Â VCT¸¦ ÀüÇô »ç¿ëÇÏÁö ¾ÊÀ» °ÍÀ̱⠶§¹®¿¡ // ´Ù¿î·Îµå ½Ãµµ¸¦ ÇÒ ÇÊ¿äÁ¶Â÷µµ ¾ø´Ù. // ±×·¯³ª ÇöÀç PAT/PMT¸¸ ´Ù¿î·Îµå ¹Þ´Â ÇÔ¼ö°¡ ¾øÀ½.. // status = Dmc_GetMainChannelTables(ctx->tsd, &tbls, g_Timeout_VctLoading*_second/1000, ctx->fnCheck); if (status == statusCancelled) { // µµÁß¿¡ Ãë¼Ò°¡ µÈ °æ¿ì¶ó ÇÏ´õ¶óµµ // ÀϺΠ¼ö½ÅµÈ tableÀÌ ÀÖÀ» ¼ö ÀÖÀ½. ÇØÁ¦½ÃÄÑ¾ß ÇÑ´Ù. Dmc_FreeMainChannelTables(&tbls); return statusCancelled; } if (g_TestAutoscanWithoutVct) { dprint(0, "**** test mode: NO VCT case, only psi available ****\n"); Dmc_FreeAtscTable(&tbls.tvct); Dmc_FreeAtscTable(&tbls.cvct); } // Antenna ¸ðµå¿¡¼­´Â CVCT°¡ ¼ö½ÅÀÌ µÇ¾ú¾îµµ À̰ÍÀ» »ç¿ëÇÏÁö ¾Êµµ·Ï ÇÑ´Ù. if (tbls.cvct && g_CurChannelType == ChannelType_Cable) { status = Dmc_TranslateCvct(tbls.cvct, &vct); dprint(2, "\tCVCT found. total %d channels\n", vct->numChannels); } else if (tbls.tvct) { status = Dmc_TranslateTvct(tbls.tvct, &vct); dprint(2, "\tTVCT found. total %d channels\n", vct->numChannels); } if (tbls.tvct) FreeAtscTable(tbls.tvct); if (tbls.cvct) FreeAtscTable(tbls.cvct); // context¿¡ ÇÊ¿äÇÑ table ¸ðµÎ À̵¿.. ctx->xvct = vct; ctx->pat = tbls.pat; ctx->num_programs = tbls.num_programs; ctx->pmtList = tbls.pmtList; if (dprintable(2)) // cafrii 070117 add { char buf[100]; int i, n_pmt = 0, n; n = ctx->num_programs; for (i=0; ipmtList[i]) n_pmt++; dprint(2, "\t pat %d, pmt %d/%d\n", ctx->pat ? 1 : 0, n_pmt, ctx->num_programs); buf[0] = 0; n = min(80, ctx->num_programs); // print max 80 pmts.. for (i=0; ipmtList[i] ? '1' : '.'); // print each pmt's existance.. dprint(2, "\t rx map: %s\n", buf); } return statusOK; } //----------------------------------------------------- // ScanCableChannel // // ÄÉÀÌºí ¸ðµå¿¡¼­ ÇÑ Ã¤³ÎÀ» °Ë»öÇÑ´Ù. // // bSetTuner °¡ FALSEÀ̸é Tuner setÀ» ÇÏÁö ¾Ê´Â´Ù. // caller Ãø¿¡¼­ ÀÌ¹Ì Æ©´×À» ÇÑ °æ¿ì¿¡ »ç¿ëµÈ´Ù. // static STATUS scan_one_channel(ChannelScanContext *ctx) { // TableÀÇ ¿ì¼±¼øÀ§´Â CVCT -> TVCT -> PSI ÀÌ´Ù. // // ¿É¼Ç¿¡ µû¶ó¼­ Cable ȯ°æ¿¡¼­´Â TVCT¸¦ ¹«½ÃÇÒ ¼öµµ ÀÖ´Ù. // Antenna ¸ðµå¿¡¼­´Â CVCT´Â ¹«½ÃµÈ´Ù. // STATUS status = statusOK; ScanTunerSetCbParam param; BOOL bCable; ScanNewChannelCbParam cbparam; memset(&cbparam, 0, sizeof(cbparam)); bCable = (ctx->flag & CBTF_ChannelTypeMask) == CBTF_Cable ? TRUE : FALSE; dprint(1, "scan_one_channel (%s %d)\n", bCable ? "cable" : "air", ctx->cur_channel); //------------------------------------------- // user¿¡°Ô callbackÀ» º¸³»¼­ Æ©³Ê/Demod ¼³Á¤À» Çϵµ·Ï ÇÑ´Ù. // flag¿¡ µû¶ó skipÇÒ ¼öµµ ÀÖÀ½. // memset(¶m, 0, sizeof(param)); if ((ctx->flag & CBTF_SkipTunerSet) == 0) { // skip optionÀÌ ¾Æ´Ñ °æ¿ì, callbackÀ» ºÒ·¯¼­ tuner ¼³Á¤À» ¼öÇàÇÑ´Ù. param.channel = ctx->cur_channel; // cafrii 061219 add // analog separate scan Áö¿ø.. // if (ctx->state == CTS_RUNNING_ANALOG) // analog only scan stage param.flag = (ctx->flag & ~(CBTF_8VSB | CBTF_QAM)); // remove digital flag else if (ctx->state == CTS_RUNNING_DIGITAL) // digital only scan stage param.flag = (ctx->flag & ~CBTF_NTSC); // remove analog flag else param.flag = ctx->flag; // pass all flag untouched param.one_channel_scan = ctx->quick_scan; // app ¿¡¼­ ÀûÀýÇÑ ´ëÀÀÀ» ÇÒ ¼ö ÀÖµµ·Ï quick scan ÀÓÀ» ¾Ë·ÁÁÜ. param.chkfn = ctx->fnCheck; param.return_value = statusNotImpl; send_event_message(evtScanTunerSet, (UINT32)¶m); // execute tuner set if (param.return_value == statusCancelled) goto label_cancelled; if (param.return_value == statusNotImpl) { dprint(0, " !! scan tune callback not implemented\n"); #if USE_DEFAULT_CB_FN SCB_TunerSet(¶m); if (param.return_value == statusCancelled) goto label_cancelled; #else status = statusNotImpl; goto label_end_scan; #endif } } else { SCB_SkipTunerSet(¶m); } if (param.return_value == statusCancelled) goto label_cancelled; if (! param.locked) { dprint(3, " !! rf signal unlocked..\n"); goto label_end_scan; } // cafrii 060814 add // analog¸¦ ÁöÁ¤ÇÏÁö ¾Ê¾Ò´Âµ¥ analog¶ó¸é unlock°ú °°À½. if ((ctx->flag & CBTF_NTSC) == 0 && param.mode == Modulation_NTSC) { dprint(3, " !! ntsc detected..\n"); goto label_end_scan; } // ¾Æ³¯·Î±× ä³ÎÀÎÁö ¸ÕÀú üũ // if (param.mode == Modulation_NTSC) { MCM_DB_T *pmcm = NULL; dprint(2, " Analog signal locked. offset %d, strength %d\n", param.freq_offset, param.strength); status = update_mcm_analog(ctx->cur_channel, param.strength, param.freq_offset, &pmcm); // possible err: statusOutOfMemory if (status == statusOK) { //print_mcm(); cbparam.ucm = pmcm; send_event_message(evtNewChannel, (UINT32)&cbparam); } goto label_end_scan; } // ÀÌÇÏ µðÁöÅРä³ÎÀÓ. ctx->freq_offset = param.freq_offset; ctx->tuner_modulation_mode = param.mode; ctx->signal_strength = param.strength; dprint(2, " digital signal locked! offset %d, mode %d, strength %d\n", param.freq_offset, param.mode, param.strength); if (ctx->fnCheck && ctx->fnCheck()) goto label_cancelled; //------------------------------------------- dprint(2, " Start loading VCT, PSI..\n"); status = download_tables(ctx); if (status == statusCancelled) goto label_cancelled; if (ctx->flag & CBTF_PsiOnlyMode) goto label_psi_scan; status = update_vct(ctx); if (status == statusCancelled) goto label_cancelled; // cafrii 060808, vct¿¡¼­ failÀ̸é flag¿¡ »ó°ü ¾øÀÌ psi scanÀ» ¼öÇà. if (status) goto label_psi_scan; if (ctx->flag & CBTF_ForcePSI) // CVCT¸¦ ¼º°øÀûÀ¸·Î ¼ö½ÅÇß´õ¶óµµ flag¿¡ µû¶ó PSI¸¦ Ãß°¡Çϱ⵵ ÇÑ´Ù. goto label_psi_scan; else goto label_end_scan; label_psi_scan: if (ctx->fnCheck && ctx->fnCheck()) goto label_cancelled; status = update_psi(ctx); goto label_end_scan; label_cancelled: dprint(2, "\tchannel scan cancelled!!\n"); status = statusCancelled; label_end_scan: free_tables_in_context(ctx); return status; } static STATUS process_mcm(BOOL bSelectMaxChannel) { // MCM Á¤º¸¸¦ ÀÌ¿ëÇÏ¿© UCMÀ» ¸¸µç´Ù. // ÀÌ ÇÔ¼ö´Â Ç×»ó ChannelScan ŽºÅ©¿¡¼­¸¸ ºÒ¸®µµ·Ï µÇ¾î ÀÖÀ¸¸ç, staticÀÌ´Ù. // ÀÌ ÇÔ¼ö¿Í ºñ½ÁÇÑ ¿ªÇÒÀ» ÇÏ´Â ÇÔ¼ö·Î update_current_scan() ÇÔ¼ö°¡ ÀÖ´Ù. // À̰ÍÀº ÇöÀç ä³Î¿¡ ´ëÇØ¼­ background¿¡¼­ ä³Î ½ºÄµÀ» ÇÏ¿© update¸¦ ÇÏ´Â ÇÔ¼öÀÌ´Ù. // // Áߺ¹µÇ´Â ä³ÎÀº signal strength °ªÀ» ºñ±³ÇÏ¿© Çϳª¸¸ ¼±ÅÃÇÑ´Ù. "´ëǥä³Î¼±ÅÃ" // // // ÁÖÀÇ! UCM¿¡µµ ¸ðµç ä³Î Á¤º¸°¡ µé¾î°¡¾ß ÇÑ´Ù. // UCMÀº Major/Minor¸¦ ±âÁØÀ¸·Î ¿À¸§Â÷¼øÀ¸·Î Á¤·ÄµÇ¾î¾ß ÇÑ´Ù. print_mcm(); // 1. MCMÀ» Á¤·ÄÇÑ´Ù. updateÇϸ鼭 Á¤·ÄÀÌ µÇ¾î ÀÖ´Â »óŶó¸é ¿©±â¼­ ÇÒ ÇÊ¿ä´Â ¾ø´Ù. dprint(2, "*** Sort MCM..\n"); sort_mcm(); print_mcm(); // cafrii 050721 add condition if (bSelectMaxChannel) { // 2. µ¿ÀÏÇÑ Mj/Mn/Vf Á¶ÇÕÀÌ ÀÖÀ¸¸é ½ÅÈ£ ¼¼±â°¡ °¡Àå Å« °ÍÀ» ¼±ÅÃÇϰí, // ³ª¸ÓÁö´Â skip flag¸¦ ¼¼ÆÃÇÑ´Ù. dprint(2, "*** Select favorite channels.\n"); select_max_mcms(); print_mcm(); } // 3. UCMÀ¸·Î º¹»çÇÑ´Ù. (skip flag ¼¼ÆÃµÈ °Í Æ÷ÇÔ) dprint(2, "*** Generate UCM.\n"); copy_to_ucm(); // 4. mcm Á¦°Å. free_all_mcm(); return statusOK; } void post_process_ucm(int flag) { int i; DMW_MSC_LockUcm(); for (i=0; i