/* DMW_ChannelAV.c DMW Middleware Channel AV decoding Module Digital STERAM Technology, Inc. */ #include "DMW_Platform.h" #include "DHL_OSAL.h" #include "DHL_Demux.h" #include "DHL_SYS.h" #include "DHL_AVCAP.h" #include "DHL_DBG.h" #define VideoContextIsAnalog(x) FALSE #define DHL_AV_IsDigitalContext(x) TRUE #define SETRECT(rect, xx, yy, ww, hh) { \ (rect)->x = (xx); \ (rect)->y = (yy); \ (rect)->w = (ww); \ (rect)->h = (hh); \ } //#endif #include "DMW_Config.h" #include "DMW_Status.h" #include "DMW_Channel.h" #include "dmw_channel_priv.h" #include "DMW_ChannelDemux.h" #include "DMW_ChannelUtil.h" #include "DMW_ChannelPM.h" // Performance monitor #include "DMW_Timer.h" //#include DHL_MODULE("$dmc", 2); #if COMMENT ____Config____(){} #endif // 1 À̸é video unhide 󸮸¦ seqhdr ¼ö½Å ÀÌÈÄ·Î ¹Ì·ë. // ÇöÀç´Â 1¸¸ Å×½ºÆ® µÇ°í ÀÖÀ½. // #define DMC_DELAYED_VIDEO_SHOW 1 // cafrii 071031 add // // Config Param: TRUE or FALSE // // 1 À̸é ÇÁ·Î±×·¥ÀÌ °©Àڱ⠻ç¶óÁø °æ¿ì // ´Ù¸¥ ÇÁ·Î±×·¥À¸·Î retry ÇÏÁö ¾Ê°í ¿ÏÀüÈ÷ Á¤Áö ½ÃŲ´Ù. // #define DMC_STOP_WHEN_PROGRAM_DISAPPEAR 0 // cafrii 100705 add // »õ·Î¿î DHL API ÀÎÅÍÆäÀ̽º·Î ÀÎÇÑ º¯°æ #define NEW_DHL_API 1 #if 0 // NEW_DHL_API // // // Config Param: TRUE or FALSE // // TRUE À̸é waited audio start ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù. // ½ÇÁ¦·Î pid¸¸ ÀÖ°í audio ES°¡ ¾ø´Â bad streamÀÇ °æ¿ì // audio only check¸¦ ½±°Ô ¼öÇàÇÒ ¼ö ÀÖ´Ù. ±×·¯³ª channel tuning ¼Óµµ´Â ¶³¾îÁø´Ù. // // cafrii 070528 chagne // audio°¡ ¾ø´Â stream üũ¸¦ Çϱâ À§Çؼ­ 1·Î ¼³Á¤. // // cafrii 080910 // audio frame count check api Á¦°ø Àü±îÁö 0À¸·Î.. // cafrii 080923, set to 1 // // cafrii 081222 set to 0. // audio recovery code°¡ º°µµ·Î Á¦°ø ¾ÈµÇ¹Ç·Î 0. // driver ¾ÈÁ¤¼º¿¡ ¹®Á¦°¡ ¾ø´Ù¸é 0À» »ç¿ëÇÏ´Â °ÍÀÌ ´õ ÁÁÀ½. // int dmc_bUseAudioStartWait = 0; #endif // // Config Param: TRUE or FALSE // // Å×½ºÆ® º¯¼ö // // TRUE À̸é PsiMonitor¸¦ »ç¿ëÇÏÁö ¾Ê´Â´Ù. // Psi monitor¸¦ ´Ù¸¥ task¿¡¼­ ´ã´çÇÒ °æ¿ì¿¡ À¯¿ëÇÏ°Ô »ç¿ëÇÒ¼öÀÖÀ½. // int gDmcTestNoPsiMonitor = 0; char *gDmcStringNoPsiMonitor = "******** !!!! DmcTest: PsiMonitor disabled !!!! ************\n"; // // Config Param: 0 / 1 // // ÀÌ flag°¡ 1À̸é Audio¸¦ Àç»ýÇÏÁö ¾Ê´Â´Ù. (Å×½ºÆ® ¿ëµµ) // int dmc_bRunWithoutAudio; // // Config Param: 0 / 1 // // ÀÌ flag°¡ 1À̸é Video¸¦ Àç»ýÇÏÁö ¾Ê´Â´Ù. (Å×½ºÆ® ¿ëµµ) // int dmc_bRunWithoutVideo; // // Config Param: psiVersionChange (2) or psiCRCChange (3) // // PSI Monitor¸¦ ½ÃÀÛÇÒ ¶§ »ç¿ëµÉ update mode // // DMC¿¡¼­´Â Channel tuningÀÌ Á¾·áµÇ¸é Psi monitor¸¦ ½ÃÀÛÇϴµ¥ // À̶§ ÁöÁ¤ÇÏ´Â update modeÀÌ´Ù. ÀϹÝÀûÀ¸·Î version change¸¦ »ç¿ëÇÏÁö¸¸ // CRC change°¡ ´õ ´Ù¾çÇÑ º¯°æ »çÇ×À» ¼ö½ÅÇÒ ¼ö ÀÖ´Ù´Â ÀǰßÀÌ À־ // CRC change¸¦ »ç¿ëÇϰí ÀÖ´Ù. // // cafrii 101208 change // pat´Â crc change¸¦, pmt´Â version change »ç¿ë. // ½ºÆ®¸²ÀÌ º¯°æµÉ ¶§ ¹öÀüÀº µ¿ÀÏÇϸ鼭 ³»¿ëÀÌ ´Ù¸¥ °æ¿ì¿¡ ´ëÀÀÇϱâ À§ÇÔ. // pat°¡ »õ·Î °»½ÅµÇ¸é pmt´Â ´Ù½Ã ½ÃÀÛÇϹǷΠpmt´Â ±×³É ver changeµµ ±¦ÂúÀ» µí.. // tDHL_PSI_Update dmc_PatUpdateMode = ePSIUPDATE_CRCCHANGE; tDHL_PSI_Update dmc_PmtUpdateMode = ePSIUPDATE_VERCHANGE; // // Config Param: TRUE or FALSE // // PSI (Pat/Pmt) Change event ¹ß»ý½Ã "µ¿µî"ÇÑ Psi¸¦ ¹«½ÃÇÒ°ÍÀÎÁö ¿©ºÎ // // TRUEÀ̸é PSI change event°¡ ¹ß»ýÇ߾ equivalent PSI¶ó¸é // Àû¿ëÇÏÁö ¾Ê´Â´Ù. // PMT Equivalence Á¶°Ç: °¢Á¾ Elementary streamµéÀÇ PID°¡ °°Àº °æ¿ì // PAT Equivalence Á¶°Ç: program number, PMT PID°¡ µ¿ÀÏÇÑ °æ¿ì // BOOL dmc_bIgnoreEquivPat = TRUE; BOOL dmc_bIgnoreEquivPmt = TRUE; // // Config Param: TRUE or FALSE // // PSI (Pat/Pmt) Change event ¹ß»ý½Ã "µ¿µî"ÇÑ Psi¸¦ ¹«½ÃÇÒ°ÍÀÎÁö ¿©ºÎ // // TRUEÀ̸é audio¸¦ ½ÃÀÛÇÒ ¶§ Àӽà mute¸¦ °É°í // ³ªÁß¿¡ video°¡ ³ª¿À±â ½ÃÀÛÇÒ ¶§ Àӽà mute¸¦ Ç®¾î¼­ µ¿±âÈ­ ½ÃŲ´Ù. // // ¿©±â¼­ »ç¿ëÇÏ´Â audio mute´Â »ç¿ëÀÚÀÇ audio mute, rating block muteµî°ú // °ãÄ¡Áö ¾Êµµ·Ï µ¶¸³ÀûÀÎ mute API¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù. // // cafrii 080923, // video freeze event not support. so disable this. // for av_sync_start to work correctly, // freeze_end_event and audio_temp_mute should be supported. // // cafrii 100810, add for newby // BOOL dmc_bAudioVideoSyncStart = TRUE; //----------------------------------------------------------- #if COMMENT ____Types____(){} #endif //----------------------------------------------------------- #if COMMENT ____Variables____(){} #endif DMC_FN_USERDATA _Dmc_UserDataProc; // // ÀÌ ÇÔ¼ö Æ÷ÀÎÅͰ¡ À¯È¿Çϸé UserData°¡ ¹ß°ßµÉ ¶§ ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù. // CC moduleÀÌ initializeµÉ ¶§ ÀÌ ÇÔ¼ö Æ÷ÀÎÅ͸¦ ÃʱâÈ­ ÇÏ¸é µÈ´Ù. int dmc_nPmtChangeRetryCount; // PmtChange µµÁß¿¡ ¿¡·¯°¡ ³¯¶§ 1¾¿ Áõ°¡ÇÏ°í ´Ù½Ã Àç ½Ãµµ ÇÑ´Ù. int dmc_LimitPmtChangeRetryCount = 3; // ÀÌ ÀÌ»óÀ¸·Î error°¡ ³ª¸é PmtChange´Â Æ÷±âÇÑ´Ù. //----------------------------------------------------------- // PSI Management // // µðÁöÅРä³ÎÀÇ AV decoding ÀÌ µ¿ÀÛÁßÀÏ ¶§ ÇöÀç ä³ÎÀÇ PAT/PMT´Â Ç×»ó °¨½Ã¸¦ Çϰí // ¸¶Áö¸· Table instance´Â º¸°üÀÌ µÇ¾î ÀÖ´Ù. //MPEG_PAT *av->pat = NULL; //MPEG_PMT *av->pmt = NULL; // Dmc task¿¡¼­´Â PAT¿Í PMT¿¡ ´ëÇØ¼­ MonitoringÀ» ¼öÇàÇÑ´Ù. // µû¶ó¼­ ÀÌ PsiCtlµéÀÌ ÀÛµ¿ÁßÀÏ °æ¿ì¿¡´Â GetPAT³ª GetPMT°¡ µ¿ÀÛÇÏÁö ¾Ê´Â´Ù. // StartDigital() ¿¡¼­ºÎÅÍ StopDigital()ÀÌ ºÒ¸±¶§±îÁö monitor°¡ µ¿ÀÛÇÑ´Ù. // // ÀÌ ±¸°£Áß¿¡ ²À GetPAT/PMT()¸¦ »ç¿ëÇÒ Çʿ䰡 ÀÖÀ»¶§´Â // PausePsiMonitor/ResumePsiMonitor¸¦ »ç¿ëÇϵµ·Ï ÇÏÀÚ. // //PSIControl *av->patPsiCtl = NULL; //PSIControl *av->pmtPsiCtl = NULL; //tDHL_VideoSeqHdr dmc_SeqHdr; // ÇöÀç µðÄÚµù µÇ°í ÀÖ´Â Video streamÀÇ sequence header Á¤º¸ //----------------------------------------------------------- // ¾Æ·¡ º¯¼öµéÀº ¸ðµÎ mutex lock »óÅ¿¡¼­ Á¢±ÙÇØ¾ß ÇÑ´Ù. // static ProgramAVInfo s_programinfo; // // ÇöÀç ½ÃûÁßÀÎ ÇÁ·Î±×·¥¿¡ ´ëÇÑ Á¤º¸ // DHL_OS_SEMA_ID dmc_psiSema4; // // av->pat/pmt, pat/pmt psi control µîÀÇ º¯¼ö¸¦ º¸È£ÇÏ´Â mutex DHL_OS_SEMA_ID dmc_avSema4; // BOOL dmc_bWaitFirstFreezeVideoEndEvent = FALSE; // video¸¦ óÀ½ ½ÃÀÛÇϸé ÀÌ º¯¼ö¸¦ setÇϰí // óÀ½ freeze end°¡ ¿ÔÀ»¶§ callbackÀ» ÇØÁØ´Ù. DMC_FN_NOTIFY _Dmc_Notify; // // applicationÀ¸·Î notify Çϱâ À§ÇÑ callback ÇÔ¼ö. // notify µÇ´Â eventµé.. DMC_FN_NOTIFY _Dmc_DecodeStartCallback; DMC_FN_NOTIFY _Dmc_DecodeStopCallback; // 1394 PTS¸¦ À§ÇÑ callback handler. // // µðÄÚµù óÀ½ ½ÃÀ۽à PMT°¡ »õ·Î ¼ö½ÅµÇ¾úÀ» ¶§, // µðÄÚµùÀÌ ÁøÇà Áß¿¡ PMT°¡ »õ·Î updateµÇ¾úÀ» ¶§¿¡ ºÒ¸°´Ù. // // param1 : ÇöÀç µðÄÚµù ÁßÀÎ ÇÁ·Î±×·¥ÀÇ program number // param2 (bThisPmtIsIgnoredInDmc) : DMC¿¡¼­ ÀÌ PMT°¡ ignoreµÈ °ÍÀ̶ó¸é TRUE // DMC¿¡¼­ ignore°¡ µÇ¾ú´õ¶óµµ callbackÀº ºÒ¸°´Ù. // // DecodeStopCallbackÀº VideoStopÀÌ µÉ ¶§ ºÒ¸®´Â callbackÀ¸·Î PTS ÁßÁö ÀÛ¾÷ µîÀ» À§ÇÔÀÌ´Ù. // ÀÌ callbackÀÇ parameter´Â ¾ÆÁ÷ undefined ÀÌ´Ù. UINT8 dmc_bRequestVideoHide; // ºñµð¿À Hide request°¡ µé¾î¿À¸é ÀÌ flag°¡ TRUEÀÌ´Ù. // // BOOL ¿¡¼­ UINT8 ·Î º¯°æ ÇÏ¿´À¸¸ç, bit flag·Î »ç¿ëÇÑ´Ù. #define TIMER_ID_AUDIO_TEMPMUTE_LIMIT 9191 // ´Ù¸¥ id¿Í °ãÄ¡¸é ¾ÈµÇ´Ï app ¿¡¼­ °ü¸®ÇÏ´Â °ÍÀÌ ÁÁÀºµ¥.. // ÀÏ´Ü À̰÷¿¡¼­ ÀÓÀÇ °ª Á¤Çؼ­ »ç¿ëÇϱâ·Î ÇÔ. int g_AudioTempMuteLimitMs = 3000; // av sync start ±â´É¿¡¼­ Ȥ½Ã video¿¡ ¹®Á¦°¡ À־ audio temp unmute¸¦ ÇÏÁö ¸øÇÏ´Â // ¹®Á¦¿¡ ´ëºñÇϱâ À§Çؼ­ timeoutÀ» °É¾îµÎ´Âµ¥, ±× timeout ½Ã°£. // ´ÜÀ§´Â millisec. // #if COMMENT ________Debug________(){} #endif BOOL g_Trace_bDmcPsiEvent = 0; // PAT/PMT Hanlder¿¡ °ü·ÃµÈ ¸Þ½ÃÁö.. ÀÌ flag´Â TRUE/FALSE ¸¸ ÁöÁ¤ °¡´É. // ÀÌ trace flag´Â g_Trace_DmcMain ¿¡ ÀÇÇØ ´Ù½ÃÇѹø check µÇ±â ¶§¹®¿¡ // true¸¦ ÇÏ´õ¶óµµ g_Trace_DmcMainÀÌ ³·Àº °ªÀ̸é Ãâ·ÂÀÌ µÇÁö ¾ÊÀ» ¼ö ÀÖÀ½. // ÇöÀç video formatÀ» ¾Ë¾Æ³»´Â utility // void Dmc_ShowSeqHeader(int level, tDHL_VideoSeqHdr *seq) { char *chroma[4] = { "Unknown", "4:2:0", "4:2:2", "4:4:4" }; if (seq == NULL) return; dprint(level, "tDHL_VideoSeqHdr %x, %s format\n", seq); dprint(level, "\thorz: %d, vert:%d, framerate %5.2f, aspect_ratio %d (%s)\n", seq->horizontal_size, seq->vertical_size, seq->frame_rate, seq->aspect_ratio_information, DHL_AV_IsWideoFormat(seq) ? "wide" : "narrow"); dprint(level, "\tbitrate %d, vbv buffer %d, constrained param %d, MPEG%d\n", seq->bit_rate, seq->vbv_buffer_size, seq->constrained_parameter_flag, seq->MPEG2 ? 2 : 1); dprint(level, "\tprofile %d, %s, chroma %s, low delay %d\n", seq->profile_and_level_indication, seq->progressive_sequence ? "progressive" : "interlace", chroma[seq->chroma_format & 3], seq->low_delay); } STATUS Dmc_PrintVideoFormat(int level, BOOL bDisplayBrief) { tDHL_VideoSeqHdr seq; BOOL bWide; DHL_RESULT dhlResult = DHL_AV_VideoSeqInfo(0, &seq); if (dhlResult) { dprint(0, "!! Dmc_PrintVideoFormat: no valid seq hdr.\n"); return statusError; } bWide = DHL_AV_IsWideoFormat(&seq); if (bDisplayBrief) { dprint(level, "\tsource: %4dx%4d %c %5.2fHz %s\n", seq.horizontal_size, seq.vertical_size, seq.progressive_sequence ? 'p' : 'i', seq.frame_rate, bWide ? "wide" : "narrow"); } else { Dmc_ShowSeqHeader(level, &seq); } return (STATUS)0; } void Dmc_PrintProgramInfo(int dbglevel) { ProgramAVInfo *av = Dmc_LockAVMutex(); // cafrii 041103 add 'dbglevel' argument if (av->active) { dprint(dbglevel, "\t%s \n", av->analog ? "Analog" : "Digital"); if (av->analog) { if (av->input_video == eDHL_CAP_NTSC0_VIDEO || av->input_video == eDHL_CAP_NTSC1_VIDEO) dprint(dbglevel, "\tNTSC, RF: %d\n", av->rf); else dprint(dbglevel, "\tExt, video %d, audio %d\n", av->input_video, av->input_audio); } else if (av->method == TUNE_METHOD_ByPIDs) dprint(dbglevel, "\tRF %d, Method: by PIDs, #%d, p%d v%d a%d\n", av->rf, av->program_number, av->pcr_pid, av->video_pid, av->audio_pid); else if (av->method == TUNE_METHOD_ByCVCT) dprint(dbglevel, "\tRF %d, Method: by CVCT, %d-%d, #%d, p%d v%d a%d\n", av->rf, av->major, av->minor, av->program_number, av->pcr_pid, av->video_pid, av->audio_pid); else if (av->method == TUNE_METHOD_ByTVCT) dprint(dbglevel, "\tRF %d, Method: by TVCT, %d-%d, #%d, p%d v%d a%d\n", av->rf, av->major, av->minor, av->program_number, av->pcr_pid, av->video_pid, av->audio_pid); else if (av->method == TUNE_METHOD_ByPSI) dprint(dbglevel, "\tRF %d, Method: by PSI, #%d, p%d v%d a%d\n", av->rf, av->program_number, av->pcr_pid, av->video_pid, av->audio_pid); else dprint(dbglevel, "\tUnknown method!\n"); } else dprint(dbglevel, "\tNot tuned!! (inactive)\n"); dprint(dbglevel, "\tfreeze %s, hidden %s\n", av->video_freezed ? "ON" : "Off", av->video_hidden ? "ON" : "Off"); dprint(dbglevel, "\tpat 0x%x, pmt 0x%x\n", av->pat, av->pmt); #if USE_CH_MW_ALL_PMT_DOWNLOAD if (1) { int i; for (i=0; av->pat && av->pmtList && ipat->numPrograms; i++) dprint(dbglevel, "\t pmt[%d] 0x%x\n", i, av->pmtList[i]); } #endif dprint(dbglevel, "\tpatPsiCtl 0x%x, pmtPsiCtl 0x%x\n", av->patPsiCtl, av->pmtPsiCtl); #if USE_CH_MW_ALL_PMT_DOWNLOAD dprint(dbglevel, "\t pmtPsiCtl2 0x%x\n", av->pmtPsiCtl2); #endif dprint(dbglevel, "\tFN_Notify %x\n", _Dmc_Notify); Dmc_UnlockAVMutex(); } #if COMMENT _______Utils________(){} #endif /* DMC tuning taskÀÇ ÇÙ½É Á¤º¸ ±¸Á¶Ã¼ÀÎ ProgramAVInfo Á¤º¸¸¦ ÂüÁ¶ÇÒ ¶§´Â lock/unlockÀ» ÇØ¾ß ÇÑ´Ù. */ ProgramAVInfo *Dmc_LockAVMutex() { DHL_OS_TakeSemaphore(dmc_avSema4, DHL_TIMEOUT_FOREVER); return &s_programinfo; } void Dmc_UnlockAVMutex(void) { DHL_OS_GiveSemaphore(dmc_avSema4); } // Dmc_GetCurrentProgramInfo // DMC ÀÇ Program Á¤º¸¸¦ ³Ñ°ÜÁØ´Ù. // ProgramÀº DMCÀÇ °¢Á¾ »óÅ Á¤º¸°¡ µé¾îÀÖ´Â ¾ÆÁÖ Áß¿äÇÑ Á¤º¸ÀÌ´Ù. // void Dmc_GetCurrentProgramInfo(ProgramAVInfo *av1) { ProgramAVInfo *av2 = Dmc_LockAVMutex(); memcpy(av1, av2, sizeof(ProgramAVInfo)); Dmc_UnlockAVMutex(); } // Dmc_GetCurrentProgramNumber // ÇöÀç µðÄÚµù ÁßÀÎ Program number¸¦ µÇµ¹·ÁÁØ´Ù. // Program Á¤º¸¸¦ ÀÌ¿ëÇØ¼­ ¾Ë ¼öµµ ÀÖ´Ù. // 0À̸é ÇÁ·Î±×·¥ ¹øÈ£¸¦ ¾Ë¼ö ¾ø´Â »óŸ¦ ÀǹÌÇÑ´Ù. // int Dmc_GetCurrentProgramNumber() { int program_number; ProgramAVInfo *av = Dmc_LockAVMutex(); if (av->active) { if (av->analog) program_number = 0; // ¾Æ³¯·Î±× »óÅ¿¡¼­ program number´Â Àǹ̰¡ ¾øÀ½. else program_number = av->program_number; } else program_number = 0; // decoder°¡ Á¤Áö »óÅ¿¡¼­µµ program number´Â Àǹ̰¡ ¾øÀ½. Dmc_UnlockAVMutex(); return program_number; } // Dmc_GetVideoSequenceHeader // Video sequence header Á¤º¸¸¦ ³Ñ°ÜÁØ´Ù. // ¾øÀ¸¸é FALSE¸¦ ¸®ÅÏÇÑ´Ù. // BOOL Dmc_GetVideoSequenceHeader(tDHL_VideoSeqHdr *pSeq) { DHL_RESULT dhlResult; if (pSeq == NULL) return FALSE; dhlResult = DHL_AV_VideoSeqInfo(0, pSeq); return dhlResult ? FALSE : TRUE; } #if COMMENT _______ProgramInfo________(){} #endif void doDmc_ClearProgramInfo() { ProgramAVInfo *av = Dmc_LockAVMutex(); av->active = FALSE; Dmc_UnlockAVMutex(); } // // tuningÀÌ ³¡³­ ÈÄ¿¡ ÇöÀç »óŸ¦ Program ±¸Á¶Ã¼¿¡ ÀúÀåÇÑ´Ù. // void doDmc_UpdateProgramInfoDigital(int rf, ModulationType mod, TUNE_METHOD method, int major, int minor, int program_number, UINT16 vidPid, UINT16 audPid, UINT16 pcrPid, tDHL_VideoCodingType vidType, tDHL_AudioCodingType audType) { ProgramAVInfo *av = Dmc_LockAVMutex(); av->active = TRUE; av->analog = FALSE; // digital av->rf = rf; av->mod = mod; av->method = method; av->major = major; av->minor = minor; av->program_number = program_number; av->video_pid = vidPid; av->audio_pid = audPid; av->pcr_pid = pcrPid; av->video_type = vidType; av->audio_type = audType; av->input_video = eDHL_CAP_DTV_TS0; av->input_audio = eDHL_CAP_DTV_TS0_AUDIO; Dmc_UnlockAVMutex(); } void doDmc_UpdateProgramInfoAnalog(int rf, tDHL_CapVideoInput video, tDHL_CapAudioInput audio) { ProgramAVInfo *av = Dmc_LockAVMutex(); av->active = TRUE; av->analog = TRUE; av->rf = rf; av->mod = Modulation_NTSC; av->input_video = video; av->input_audio = audio; av->method = TUNE_METHOD_NONE; av->major = 0; av->minor = 0; av->program_number = 0; Dmc_UnlockAVMutex(); } // // // »õ·Ó°Ô ¼ö½ÅÇÑ pat/pmt¸¦ AVINFO¿¡ ÀúÀåÇÑ´Ù. // void doDmc_UpdatePsiInfo(MPEG_PAT *pat, MPEG_PMT *pmt) { ProgramAVInfo *av = Dmc_LockAVMutex(); #if DMC_CHECK_HEAP_SIZE UINT32 heap_before; #endif if (pat) { if (av->pat) { #if USE_CH_MW_ALL_PMT_DOWNLOAD // pat°¡ »õ·Ó°Ô °»½ÅÇÏ¸é ¸ðµç pmt µéµµ ´Ù replace µÇµµ·Ï ÇÑ´Ù. int i; for (i=0; ipat->numPrograms; i++) { if (av->pmtList[i]) { //dprint(2, "######## free pmt[%d] %x\n", i, av->pmtList[i]); FreePMT(av->pmtList[i]); } } if (av->pat->numPrograms != pat->numPrograms) { dprint(2, "num programs changed %d -> %d\n", av->pat->numPrograms, pat->numPrograms); DHL_OS_Free((void **)&av->pmtList); } #endif #if DMC_CHECK_HEAP_SIZE heap_before = DHL_GetFreeHeapSize(0); #endif FreePAT(av->pat); // tuning¿¡ ¼º°øÇϸé pat/pmt¿¡ ¹Ù·Î updateÇÑ´Ù. #if DMC_CHECK_HEAP_SIZE dprint(3, "free prev pat %x, heap %u->%u\n", av->pat, heap_before, DHL_GetFreeHeapSize(0)); #else dprint(3, "free prev pat %x\n", av->pat); #endif } av->pat = pat; #if USE_CH_MW_ALL_PMT_DOWNLOAD if (av->pmtList == NULL) av->pmtList = DHL_OS_Malloc(av->pat->numPrograms * sizeof(MPEG_PMT *)); if (av->pmtList == NULL) dprint(0, "!! out of mem for pmtlist\n"); else memset(av->pmtList, 0, av->pat->numPrograms * sizeof(MPEG_PMT *)); #endif } if (pmt) { if (av->pmt) { #if DMC_CHECK_HEAP_SIZE heap_before = DHL_GetFreeHeapSize(0); #endif FreePMT(av->pmt); #if DMC_CHECK_HEAP_SIZE dprint(3, "free prev pmt %x, heap %u->%u\n", av->pmt, heap_before, DHL_GetFreeHeapSize(0)); #else dprint(3, "free prev pmt %x\n", av->pmt); #endif } av->pmt = pmt; } Dmc_UnlockAVMutex(); } #if COMMENT ____EventProc____(){} #endif static void _Dmc_SendDecodeEvent(DmcMsgType msgtype, UINT32 userParam) { STATUS status; status = Dmc_SendCommandEx(msgtype, userParam, NULL, FALSE, // "NO" wait for complete NULL, 0, // user callback¶m FALSE); // do not cancel previous command if (status) dprint(0, "!! send event err %d\n", status); // send message¿¡ ¿¡·¯ ¹ß»ý½Ã Ưº°È÷ ¿¡·¯Ã³¸®¸¦ ÇÒ ÀÏÀº ¾ø´Ù } //----------------------------------------------------------------------------- // ¾Æ·¡ _Dmc_xxx Äݹé ÇÔ¼öµéÀº driver task¿¡¼­ ¹Ù·Î ºÒ¸®±â ¶§¹®¿¡ // high priority À̰í, À̰÷¿¡¼­ ¸¹Àº ÀÏÀ» ÇÏÁö ¾Êµµ·Ï ÇÑ´Ù. // void _Dmc_PatEventProc(tDHL_PSI_Event psiEvent, tDHL_PSI_ControlHandle psiCtl, UINT32 userParam) { STATUS status; DHL_RESULT err; tDHL_PSI_DataArray *desc; MPEG_PAT *pat; DmcMessage msg; #if DMC_CHECK_HEAP_SIZE UINT32 heap_before; #endif // comment: userParamÀº »ç¿ëµÇÁö ¾Ê´Â´Ù. memset(&msg, 0, sizeof(msg)); if (psiEvent == ePSIEVENT_DATARECEIVED) { // data recieved event´Â debug printÇÏÁö ¾Ê´Â´Ù. // err = DHL_PSI_ReadPSIData(psiCtl, &desc); if (err) { dprint(0, "_Dmc_PatEventProc: DHL_PSI_ReadPSIData returned %s\n", ErrorString(err)); return; } #if DMC_CHECK_HEAP_SIZE heap_before = DHL_GetFreeHeapSize(0); #endif err = ParsePAT(desc, &pat); DHL_PSI_FreePSIData(desc); if (IsError(err)) { // cafrii 050315 change dprint(0, "_Dmc_PatEventProc: ParsePAT returned %s\n",ErrorString(err)); return; } #if 0 // cafrii 060303 // ÀÌÁ¦ºÎÅÍ´Â pat/pmt¿¡ Á¢±ÙÇϱâ À§Çؼ­´Â mutex¸¦ lock ÇØ¾ß Çϴµ¥, // ÀÌ task¿¡¼­ lockÀ» ÇÏ´Â °ÍÀº À§ÇèÇÒ ¼ö ÀÖ´Ù. // descriptor ÀÚü¸¦ ÀúÀåÇÏ´Â ´Ù¸¥ ¹æ¹ýÀ» °í·ÁÇØº¸µµ·Ï ÇÏÀÚ. // Note!! // ÀÌ Å½ºÅ©´Â TSDXX ·Î Dmc task°¡ ¾Æ´Ï±â ¶§¹®¿¡ pat/pmt¸¦ ¿©±â¼­ ÂüÁ¶ÇÏ´Â °ÍÀº // ¾ÈÀüÇÏÁö ¸øÇÒ ¼öµµ ÀÖ´Ù.. // if (Dmc_CheckIfSamePat(pat, av->pat)) { // cafrii 040529 add if (av->pmt && av->pmtPsiCtl) { // cafrii 040604 add av->pmtPsiCtl if (g_Trace_bDmcPsiEvent) dprint(2, "_Dmc_PatEventProc: Same PAT\n"); FreePAT(pat); return; } else { //if (g_Trace_bDmcPsiEvent) // dprint(2, "_Dmc_PatEventProc: Same PAT.. notify to DMC\n"); // PMT°¡ ¾ø´Â °æ¿ì¿¡´Â ºñ·Ï °°Àº PAT°¡ ¼ö½ÅµÇ¾ú´Ù ÇÏ´õ¶óµµ Dmc¿¡ ¾Ë·ÁÁà¾ß ÇÑ´Ù. } } #endif if (g_Trace_bDmcPsiEvent) { #if DMC_CHECK_HEAP_SIZE dprint(2, "New PAT: TSID %d, v%d, %d programs, 0x%x, heap: %u->%u\n", pat->transport_stream_id, pat->version_number, pat->numPrograms, pat, heap_before, DHL_GetFreeHeapSize(0)); #else dprint(2, "New PAT: TSID %d, v%d, %d programs\n", pat->transport_stream_id, pat->version_number, pat->numPrograms); #endif } } else { // cafrii 030901, add if (g_Trace_bDmcPsiEvent) { if (psiEvent != ePSIEVENT_LOSTPACKET) dprint(3, "_Dmc_PatEventProc: psiEvent %s\n", DHL_PSIEventString(psiEvent)); } return; } status = Dmc_SendCommandEx(evtPatChange, (UINT32)pat, (DMC_FN_CANCELFREE)FreePAT, FALSE, // "NO" wait for complete NULL, 0, // user callback¶m FALSE); // do not cancel previous command if (status) { // DMC Q°¡ overflowµÇ¾î µé¾î°¡Áö ¾Ê¾Ò±â ¶§¹®¿¡ // ÇÒ´çÇÑ Å×À̺íÀ» »èÁ¦Çؼ­ ¸Þ¸ð¸® ´©¼ö¸¦ ¸·´Â´Ù if (g_Trace_bDmcPsiEvent) dprint(0, "!!_Dmc_PatEventProc: DmcQ full\n"); //neverdai. 081110 À§ ÇÔ¼ö¿¡¼­ ¿¡·¯°¡ »ý±â¸é FreePAT¸¦ È£ÃâÇϱ⠶§¹®¿¡ //µû·Î FreePAT¸¦ È£ÃâÇÏ¸é ¹®Á¦ »ý±æ ¼ö ÀÖÀ½. //FreePAT(pat); } } void _Dmc_PmtEventProc(tDHL_PSI_Event psiEvent, tDHL_PSI_ControlHandle psiCtl, UINT32 userParam) { STATUS status; DHL_RESULT err; tDHL_PSI_DataArray *desc; MPEG_PMT *pmt; DmcMessage msg; #if DMC_CHECK_HEAP_SIZE UINT32 heap_before; #endif // comment: userparamÀº »ç¿ëµÇÁö ¾Ê´Â´Ù. memset(&msg, 0, sizeof(msg)); if (psiEvent == ePSIEVENT_DATARECEIVED) { err = DHL_PSI_ReadPSIData(psiCtl, &desc); if (err) { dprint(0, "_Dmc_PmtEventProc: DHL_PSI_ReadPSIData returned %s\n",ErrorString(err)); return; } #if DMC_CHECK_HEAP_SIZE heap_before = DHL_GetFreeHeapSize(0); #endif err = ParsePMT(desc, &pmt); DHL_PSI_FreePSIData(desc); if (IsError(err)) { // cafrii 050315 change dprint(0, "_Dmc_PmtEventProc: ParsePMT returned %s\n",ErrorString(err)); return; } #if 0 // cafrii 060303 // ÀÌÁ¦ºÎÅÍ´Â pat/pmt¿¡ Á¢±ÙÇϱâ À§Çؼ­´Â mutex¸¦ lock ÇØ¾ß Çϴµ¥, // ÀÌ task¿¡¼­ lockÀ» ÇÏ´Â °ÍÀº À§ÇèÇÒ ¼ö ÀÖ´Ù. // descriptor ÀÚü¸¦ ÀúÀåÇÏ´Â ´Ù¸¥ ¹æ¹ýÀ» °í·ÁÇØº¸µµ·Ï ÇÏÀÚ. // Note!! // ÀÌ Å½ºÅ©´Â TSDXX ·Î Dmc task°¡ ¾Æ´Ï±â ¶§¹®¿¡ av->pat/pmt¸¦ ¿©±â¼­ ÂüÁ¶ÇÏ´Â °ÍÀº // ¾ÈÀüÇÏÁö ¸øÇÒ ¼öµµ ÀÖ´Ù.. // if (Dmc_CheckIfSamePmt(pmt, av->pmt)) { if (g_Trace_bDmcPsiEvent) dprint(2, "_Dmc_PmtEventProc: Same PMT\n"); FreePMT(pmt); return; } #endif if (g_Trace_bDmcPsiEvent) { #if DMC_CHECK_HEAP_SIZE dprint(2, "New PMT: PID %d, #%d, v%d, PCR %d, 0x%x, heap %u->%u\n", pmt->PID, pmt->program_number, pmt->version_number, pmt->PCR_PID, pmt, heap_before, DHL_GetFreeHeapSize(0)); #else dprint(2, "New PMT: PID %d, #%d, v%d, PCR %d\n", pmt->PID, pmt->program_number, pmt->version_number, pmt->PCR_PID); #endif } } else { // cafrii 030918, add if (g_Trace_bDmcPsiEvent) { if (psiEvent != ePSIEVENT_LOSTPACKET) dprint(3, "_Dmc_PmtEventProc: psiEvent %s\n",DHL_PSIEventString(psiEvent)); } return; } status = Dmc_SendCommandEx(evtPmtChange, (UINT32)pmt, (DMC_FN_CANCELFREE)FreePMT, FALSE, // "NO" wait for complete NULL, 0, // user callback¶m FALSE); // do not cancel previous command if (status) { // DMC Q°¡ overflowµÇ¾î µé¾î°¡Áö ¾Ê¾Ò±â ¶§¹®¿¡ // ÇÒ´çÇÑ Å×À̺íÀ» »èÁ¦Çؼ­ ¸Þ¸ð¸® ´©¼ö¸¦ ¸·´Â´Ù if (g_Trace_bDmcPsiEvent) dprint(0, "!!_Dmc_PmtEventProc: DmcQ full\n"); //neverdai. 081110 À§ ÇÔ¼ö¿¡¼­ ¿¡·¯°¡ »ý±â¸é FreePAT¸¦ È£ÃâÇϱ⠶§¹®¿¡ //µû·Î FreePAT¸¦ È£ÃâÇÏ¸é ¹®Á¦ »ý±æ ¼ö ÀÖÀ½. //FreePMT(pmt); } } #if 0 // remove old callback function BOOL _Dmc_UserDataCallback(TLVideoContext *context, UINT32 userParam) { if (_Dmc_UserDataProc) _Dmc_UserDataProc(context); return FALSE; } /* * _Dmc_ImportantVideoChangeEvent is called directly in response to a videoImportantChange event * from the video driver task. We do most of the work by sending * a decode event in a message queue which causes handleImportantVideoChange to be called in the * lower priority video control task. This function needs to return TRUE only in outtput=input * mode when we know that handleImportantVideoChange will change the format anyway. Otherwise * it returns false meaning that the high-level video driver code should handle the format * change for a fixed output format. Performing this check in both tasks avoides changing the * format twice. We should not modify the current TL850VideoDisplay or timing from within the * video driver task. */ BOOL _Dmc_ImportantVideoChangeCallback(TLVideoContext *context, UINT32 userParam) { if (VideoContextIsAnalog(context)) return FALSE; // Don't worry about analog contexts // videoUserProc¿¡¼­ importantChange event°¡ ¼ö½ÅµÈ °æ¿ì ÀÌ ÇÔ¼ö°¡ ºÒ¸°´Ù. // // ¸®ÅϰªÀÇ ÀǹÌ: (bProcessed) // TRUEÀ̸é event 󸮰¡ ³¡³µÀ¸¹Ç·Î driver¿¡¼­ ¾Æ¹« Àϵµ ÇÏÁö ¸»¶ó´Â ÀǹÌ. // application¿¡¼­ ´ëÀÀÀ» Çϰڴ٠// FALSE¸¦ ¸®ÅÏÇϸé driver°¡ ¾Ë¾Æ¼­ ´ëÀÀÇÑ´Ù. // // NaturalMode¸¦ Áö¿øÇÏÁö¸¸ ¿©·¯°¡Áö ¸®¼Ò½º ¹®Á¦ (pixmap planeµî)·Î // ¹Ù·Î ÇØ»óµµ¸¦ º¯°æÇϱ⠾î·Á¿î °æ¿ì°¡ ¸¹´Ù. (¿¹: OSD°¡ ¶°ÀÖ´Â °æ¿ì) // ±×·¡¼­ ÀÏ´Ü driver·Î ÇÏ¿©±Ý ÃÖ¼ÒÇÑÀÇ ´ëÀÀ¸¸À» Çϵµ·Ï ÇÑ´Ù. // ³ªÁß¿¡ ÀûÀýÇÑ »óȲÀÌ µÇ¸é (OSD°¡ exitµÇ´Â µî), application¿¡¼­ õõÈ÷ // Resolution change¸¦ ÇÏ¸é µÈ´Ù. // _Dmc_SendDecodeEvent(evtVideoImportantChange, userParam); // jump to doDmc_HandleImportantVideoChange return FALSE; } BOOL _Dmc_UserVideoChangeCallback(TLVideoContext *context, UINT32 userParam) { // driver¿¡¼­ ¼öÇàÇÏ´Â Äڵ带 Àß º¸°í // ¸¸¾à ±× ¹ÛÀÇ Ãß°¡ ÀÛ¾÷À» ÇÏ°í ½ÍÀ» °æ¿ì ¾Æ·¡¿Í °°ÀÌ low priority task·Î // ÀÛ¾÷À» ¹Ì·ï ¼öÇàÇϵµ·Ï ÇÑ´Ù. // _Dmc_SendDecodeEvent(evtVideoUserChange, userParam); // jump to doDmc_HandleUserChange return FALSE; } BOOL _Dmc_MajorVideoChangeCallback(TLVideoContext *context, UINT32 userParam) { _Dmc_SendDecodeEvent(evtVideoMajorChange, userParam); // jump to doDmc_HandleMajorVideoChange return FALSE; } // cafrii 060721 add BOOL _Dmc_VideoScrambledCallback(TLVideoContext *context, UINT32 userParam) { _Dmc_SendDecodeEvent(evtVideoScrambled, userParam); // jump to doDmc_HandleVideoScrambled return FALSE; } BOOL _Dmc_AudioInfoCallback(void *info, UINT32 userParam) { // note that this event is called directly from driver task. // don't do any heavy job in this callback. doDmc_Notify(DMW_NOTIFY_AudioInfo, 0); return FALSE; } #else // remove old callback function BOOL _Dmc_VideoFreezeEndCallback(TLVideoContext *context, UINT32 userParam) { _Dmc_SendDecodeEvent(evtFreezeVideoEnd, userParam); // jump to doDmc_HandleFreezeVideoEnd return FALSE; } BOOL _Dmc_ImportantVideoChangeCallback(TLVideoContext *context, UINT32 userParam) { if (VideoContextIsAnalog(context)) return FALSE; // Don't worry about analog contexts // videoUserProc¿¡¼­ importantChange event°¡ ¼ö½ÅµÈ °æ¿ì ÀÌ ÇÔ¼ö°¡ ºÒ¸°´Ù. // // ¸®ÅϰªÀÇ ÀǹÌ: (bProcessed) // TRUEÀ̸é event 󸮰¡ ³¡³µÀ¸¹Ç·Î driver¿¡¼­ ¾Æ¹« Àϵµ ÇÏÁö ¸»¶ó´Â ÀǹÌ. // application¿¡¼­ ´ëÀÀÀ» Çϰڴ٠// FALSE¸¦ ¸®ÅÏÇϸé driver°¡ ¾Ë¾Æ¼­ ´ëÀÀÇÑ´Ù. // // NaturalMode¸¦ Áö¿øÇÏÁö¸¸ ¿©·¯°¡Áö ¸®¼Ò½º ¹®Á¦ (pixmap planeµî)·Î // ¹Ù·Î ÇØ»óµµ¸¦ º¯°æÇϱ⠾î·Á¿î °æ¿ì°¡ ¸¹´Ù. (¿¹: OSD°¡ ¶°ÀÖ´Â °æ¿ì) // ±×·¡¼­ ÀÏ´Ü driver·Î ÇÏ¿©±Ý ÃÖ¼ÒÇÑÀÇ ´ëÀÀ¸¸À» Çϵµ·Ï ÇÑ´Ù. // ³ªÁß¿¡ ÀûÀýÇÑ »óȲÀÌ µÇ¸é (OSD°¡ exitµÇ´Â µî), application¿¡¼­ õõÈ÷ // Resolution change¸¦ ÇÏ¸é µÈ´Ù. // _Dmc_SendDecodeEvent(evtVideoImportantChange, userParam); // jump to doDmc_HandleImportantVideoChange return FALSE; } void _Dmc_CommonAVCallback(tDHL_AVCallbackType cb_type, UINT32 param) { if (cb_type == eDHL_CB_VideoSeqHdr) { _Dmc_ImportantVideoChangeCallback((TLVideoContext)0, 0); } else if (cb_type == eDHL_CB_FirstVideoShow) { _Dmc_VideoFreezeEndCallback((TLVideoContext)0, 0); } } #endif #if COMMENT _______________(){} #endif //----------------------------------------------------------------- // doDmc functions. // // These functions can be called only in dmc task. // void doDmc_Notify(UINT32 event, UINT32 param) { const char *name = Dmc_NotifyEventString(event); if (_Dmc_Notify) { dprint(3, "----> %s start.. (%x)\n", name, param); _Dmc_Notify(event, param); } else { dprint(3, " Notify '%s' (%d) not registerred. skip\n", name, event); // cafrii 040521 add event number for easy debugging } } //---------------------------------------------------------------------- // doDmc_StartFinalPsiMonitor // // digital channel tuningÀÌ ¸ðµÎ ³¡³ª°í ³ª¸é PSI ¸ð´ÏÅ͸¦ ½ÃÀÛÇÑ´Ù. // void doDmc_StartFinalPsiMonitor(BOOL bCancelPrevMonitors) { DHL_RESULT err; ProgramAVInfo *av = Dmc_LockAVMutex(); #if USE_EPG_MW_PSI_DOWNLOAD // ±âÁ¸ psi monitor´Â °­Á¦·Î Áß´Ü ÇÑ´Ù. if (av->pmtPsiCtl) DHL_PSI_StopMonitor(av->pmtPsiCtl); av->pmtPsiCtl = NULL; if (av->patPsiCtl) DHL_PSI_StopMonitor(av->patPsiCtl); av->patPsiCtl = NULL; #else // !USE_EPG_MW_PSI_DOWNLOAD //TLASSERT(av->active, "Video should be already started!"); if (bCancelPrevMonitors) { #if USE_CH_MW_ALL_PMT_DOWNLOAD if (av->pmtPsiCtl2) { DHL_PSI_StopMonitor(av->pmtPsiCtl2); av->pmtPsiCtl2 = (tDHL_PSI_ControlHandle)0; } #endif if (av->pmtPsiCtl) { DHL_PSI_StopMonitor(av->pmtPsiCtl); av->pmtPsiCtl = (tDHL_PSI_ControlHandle)0; } if (av->patPsiCtl) { DHL_PSI_StopMonitor(av->patPsiCtl); av->patPsiCtl = (tDHL_PSI_ControlHandle)0; } } if (gDmcTestNoPsiMonitor) { dprint(2, gDmcStringNoPsiMonitor); } else if (av->patPsiCtl) { dprint(2, " Psi monitor already exist\n"); } else { dprint(2, " Start monitor PAT..\n"); err = MonitorPAT(Dmc_GetCurrentTsd(), TRUE, // Ç×»ó current PAT¸¸ ¹Þ´Â´Ù!! FALSE, // not eager dmc_PatUpdateMode, _Dmc_PatEventProc, 0, &av->patPsiCtl); if (err) { dprint(0, "!! MonitorPAT returned %s\n", ErrorString(err)); } } #endif // USE_EPG_MW_PSI_DOWNLOAD Dmc_UnlockAVMutex(); } static void doDmc_CancelMonitors() { int i; ProgramAVInfo *av = Dmc_LockAVMutex(); #if USE_CH_MW_ALL_PMT_DOWNLOAD if(av->pmtPsiCtl2) { DHL_PSI_StopMonitor(av->pmtPsiCtl2); av->pmtPsiCtl2 = (tDHL_PSI_ControlHandle)0; } #endif if(av->pmtPsiCtl) { DHL_PSI_StopMonitor(av->pmtPsiCtl); av->pmtPsiCtl = (tDHL_PSI_ControlHandle)0; } if(av->patPsiCtl) { DHL_PSI_StopMonitor(av->patPsiCtl); av->patPsiCtl = (tDHL_PSI_ControlHandle)0; } if (av->pmt) FreePMT(av->pmt); av->pmt = NULL; #if USE_CH_MW_ALL_PMT_DOWNLOAD for (i=0; av->pat && av->pmtList && ipat->numPrograms; i++) if (av->pmtList[i]) FreePMT(av->pmtList[i]); DHL_OS_Free((void **)&av->pmtList); #endif if (av->pat) FreePAT(av->pat); av->pat = NULL; Dmc_UnlockAVMutex(); } /* app callbackÀ» ÀÌ¿ëÇÏ¿©, app¿¡¼­ ¿øÇÏ´Â audio ½ºÆ®¸²À» ¼±ÅÃÇϵµ·Ï ÇÏ´Â ÇÔ¼ö. ±âº»ÀûÀ¸·Î MW ³»ºÎÀÇ DecidePidInfo ·çƾ¿¡¼­ ÀûÀýÇÑ pid¸¦ ¼±ÅÃÇÑ´Ù. ±×·¯³ª MW ³»ºÎ ·ÎÁ÷Àº language code´Â °í·ÁÇÏÁö ¾ÊÀ¸¹Ç·Î, preferred language ±â´ÉÀÌ ÀÖ´Â Á¦Ç°ÀÇ app À̶ó¸é callbackÀ» ¹Ýµå½Ã ±¸ÇöÇØ¾ß ÇÑ´Ù. */ void doDmc_SelectAudioStream(MPEG_PMT *pmt, xvctChannelPtr_t vctc, UINT32 *pAudioPID, tDHL_AudioCodingType *pAudioType) { // Notification callbackÀ» ÀÌ¿ëÇÏ¿© application¿¡¼­ ¾î¶² audio¸¦ ¿øÇÏ´ÂÁö ¾Ë¾Æ³½´Ù. // AudioPidSelectParam apsp; UINT32 audioPID; tDHL_AudioCodingType audioType; apsp.pmt = pmt; apsp.vctChannel = vctc; // ¾Æ·¡ µÎ °ª¿¡´Â callback ÀÌ ±¸ÇöµÇ¾ú´ÂÁö¸¦ üũÇϱâ À§ÇÑ ÃʱⰪÀ» ³Ö¾îµÐ´Ù. apsp.returnAudioPid = 0; apsp.returnAudioType = eDHL_AUDIO_TYPE_UNKNOWN; doDmc_Notify(DMW_NOTIFY_SelectAudio, (UINT32) &apsp); if (apsp.returnAudioPid || apsp.returnAudioType) { if (apsp.returnAudioPid != 0) audioPID = apsp.returnAudioPid; if (apsp.returnAudioType != eDHL_AUDIO_TYPE_UNKNOWN) audioType = apsp.returnAudioType; dprint(2, "\t user select audio PID %d, type %d\n", audioPID, audioType); if (pAudioPID) *pAudioPID = audioPID; if (pAudioType) *pAudioType = audioType; } else { /* pAudioPID ¿Í pAudioType¿¡´Â ÀÌ¹Ì MW ³»ºÎ¿¡¼­ ¼±ÅÃÇÑ °ªÀÌ µé¾î ÀÖÀ¸¹Ç·Î °ªÀ» º¯°æÇÏ¸é ¾ÈµÈ´Ù. */ } } /* app callbackÀ» ÀÌ¿ëÇÏ¿©, app¿¡¼­ ¿øÇÏ´Â video ½ºÆ®¸²À» ¼±ÅÃÇϵµ·Ï ÇÏ´Â ÇÔ¼ö. ±âº»ÀûÀ¸·Î MW ³»ºÎÀÇ DecidePidInfo ·çƾ¿¡¼­ ÀûÀýÇÑ pid¸¦ ¼±ÅÃÇÑ´Ù. Ưº°ÇÑ ·ÎÁ÷ÀÌ ÇÊ¿äÇÏÁö ¾Ê´Â ÇÑ, callbackÀ» ±¸ÇöÇÒ ÇÊ¿ä ±îÁö´Â ¾ø´Ù. */ void doDmc_SelectVideoStream(MPEG_PMT *pmt, xvctChannelPtr_t vctc, UINT32 *pVideoPID, tDHL_VideoCodingType *pVideoType) { // Notification callbackÀ» ÀÌ¿ëÇÏ¿© application¿¡¼­ ¾î¶² video¸¦ ¿øÇÏ´ÂÁö ¾Ë¾Æ³½´Ù. // VideoPidSelectParam vpsp; UINT32 videoPID; tDHL_VideoCodingType videoType; vpsp.pmt = pmt; vpsp.vctChannel = vctc; // ¾Æ·¡ µÎ °ª¿¡´Â callback ÀÌ ±¸ÇöµÇ¾ú´ÂÁö¸¦ üũÇϱâ À§ÇÑ ÃʱⰪÀ» ³Ö¾îµÐ´Ù. vpsp.returnVideoPid = 0; vpsp.returnVideoType = eDHL_VIDEO_TYPE_UNKNOWN; doDmc_Notify(DMW_NOTIFY_SelectVideo, (UINT32) &vpsp); if (vpsp.returnVideoPid || vpsp.returnVideoType != eDHL_VIDEO_TYPE_UNKNOWN) { if (vpsp.returnVideoPid != 0) videoPID = vpsp.returnVideoPid; if (vpsp.returnVideoType != eDHL_VIDEO_TYPE_UNKNOWN) videoType = vpsp.returnVideoType; dprint(2, "\t user select video PID %d, type %d\n", videoPID, videoType); if (pVideoPID) *pVideoPID = videoPID; if (pVideoType) *pVideoType = videoType; } else if(pmt) { //neverdai 101019 video streamÀÇ °æ¿ì, pid¿Í stream typeÀ» pmt¿¡¼­ ã¾Æ ¼³Á¤ÇØÁÜ. #define StreamTypeToVideoType(t) ( \ (t) == StreamType_MPEG2Video ? eDHL_VIDEO_TYPE_MPEG2 : \ (t) == StreamType_DC2Video ? eDHL_VIDEO_TYPE_MPEG2 : \ (t) == StreamType_MPEG1Video ? eDHL_VIDEO_TYPE_MPEG1 : \ (t) == StreamType_H264 ? eDHL_VIDEO_TYPE_H264 : \ eDHL_VIDEO_TYPE_UNKNOWN ) int i, num_video, video_idx; for(i=0, num_video=0; inumStreams; i++) { if(StreamTypeToVideoType(pmt->streams[i].stream_type)!=eDHL_VIDEO_TYPE_UNKNOWN) { num_video++; videoPID=pmt->streams[i].elementary_PID; videoType=StreamTypeToVideoType(pmt->streams[i].stream_type); } } if(num_video==1) { if (pVideoPID) *pVideoPID = videoPID; if (pVideoType) *pVideoType = videoType; } } else { /* pVideoPID ¿Í pVideoType¿¡´Â ÀÌ¹Ì MW ³»ºÎ¿¡¼­ ¼±ÅÃÇÑ °ªÀÌ µé¾î ÀÖÀ¸¹Ç·Î °ªÀ» º¯°æÇÏ¸é ¾ÈµÈ´Ù. */ } } /* running time Áß¿¡ importantchange (seqhdr ¼ö½Å) ¹ß»ý½Ã È£Ãâ. synchronous start ÀÎ °æ¿ì¿¡´Â video start ½Ã¿¡µµ È£Ãâ. */ BOOL doDmc_CheckIfFormatChanged(void) { DHL_RESULT dhlResult; BOOL bFormatChanged = FALSE; char buf1[80], buf2[80]; tDHL_VideoSeqHdr seqtmp, *seq1, *seq2 = &seqtmp; ProgramAVInfo *av = Dmc_LockAVMutex(); //------- // find new video format. if analog, seq set to NULL. if (!DHL_AV_IsDigitalContext()) seq2 = NULL; else { // ¿©±â¿¡¼­´Â Àý´ë ¿¡·¯°¡ ¹ß»ýÇÏ¸é ¾ÈµÈ´Ù. dhlResult = DHL_AV_VideoSeqInfo(0, seq2); if (dhlResult) { dprint(0, "!! %s: get seqhdr err\n", __func__); seq2 = NULL; } } // previous old video format seq1 = av->seq_hdr_valid ? &av->seq_hdr : NULL; if (seq1 && seq2 && seq1->generationNumber == seq2->generationNumber) { dprint(2, "same seq_hdr number %u\n", seq1->generationNumber); goto label_end; } // make description string. // cafrii 070725 fix, ÀϺΠplatform¿¡¼­ floatÇü print ºÒ°¡´ÉÇÏ¿© // interger type Ãâ·Â¸¸ »ç¿ëÇϵµ·Ï ¼öÁ¤. if (seq1) sprintf(buf1, "(%d: %4dx%4d %c %2d.%02dHz %s)", Dmc_WhichATSCFormat(seq1), seq1->horizontal_size, seq1->vertical_size, seq1->progressive_sequence ? 'p' : 'i', (int)(seq1->frame_rate), (int)(seq1->frame_rate*100) % 100, DHL_AV_IsWideoFormat(seq1) ? "wide" : "narrow"); else strcpy(buf1, "(00: Analog)"); if (seq2) sprintf(buf2, "(%d: %4dx%4d %c %2d.%02dHz %s)", Dmc_WhichATSCFormat(seq2), seq2->horizontal_size, seq2->vertical_size, seq2->progressive_sequence ? 'p' : 'i', (int)(seq2->frame_rate), (int)(seq2->frame_rate*100) % 100, DHL_AV_IsWideoFormat(seq2) ? "wide" : "narrow"); else strcpy(buf2, "(00: Analog)"); dprint(2, "\tsource %s\n\t ---> %s\n", buf1, buf2); if (seq1) { if (seq2) { // digital --> digital bFormatChanged = Dmc_CheckIfFormatChanged(seq2, seq1); // new, old memcpy(&av->seq_hdr, seq2, sizeof(tDHL_VideoSeqHdr)); av->seq_hdr_valid = TRUE; } else { bFormatChanged = TRUE; // digital --> analog av->seq_hdr_valid = FALSE; } } else // seq1 == NULL { if (seq2) { // analog --> digital bFormatChanged = TRUE; memcpy(&av->seq_hdr, seq2, sizeof(tDHL_VideoSeqHdr)); av->seq_hdr_valid = TRUE; } else { bFormatChanged = FALSE; // analog --> analog av->seq_hdr_valid = FALSE; } } label_end: Dmc_UnlockAVMutex(); //------- return bFormatChanged; } // doDmc_ProcessScreenAdjustment // tuning ´Ü°è¿¡¼­, Àû¿ëÇÒ adjustment ¹æ¹ýÀ» callbackÀ¸·Î queryÇØ¼­ Àû¿ëÇÑ´Ù. // // user¿¡°Ô ¾Ë·ÁÁÙ ³»¿ë // input: // ÇöÀç display ratio (wide/narrow) // ÇöÀç source format ratio (wide/narrow) // output: // tDHL_DispARC // force widebar // winRect // void doDmc_ProcessScreenAdjustment(void) { // video start ÇÒ ¶§ display start Çϱâ Àü¿¡ ºÒ¸°´Ù. ScreenAdjustmentParam sap; DHL_RESULT dhr; ProgramAVInfo *av = Dmc_LockAVMutex(); memset(&sap, 0, sizeof(sap)); // input sap.bSourceWide = DHL_AV_IsWideoFormat(&av->seq_hdr) ? TRUE : FALSE; sap.bDisplayWide = TRUE; // ÀÌ display ratio´Â ¿ø·¡ Dmc_ChangeDisplay api ÀÎÀÚ¸¦ ±â¾ïÇØ µÎ¾î¼­ Àü´ÞÇØ ÁÖ´Â °ªÀε¥, // ÇöÀç MW ±¸Á¶¿¡¼­´Â º°µµ·Î ±â¾ïÀ» ¾ÈÇØµÎ°í ÀÖ´Ù. // MW Á¤º¸ º¸´Ù app Á¤º¸°¡ ´õ ½Å·ÚÇÒ ¼ö ÀÖÀ¸¹Ç·Î app ¿¡¼­´Â ÀÌ Á¤º¸¸¦ ¹«½ÃÇϰí, // app º¯¼ö¸¦ Âü°íÇÏ´Â °ÍÀÌ ÁÁ°Ú´Ù. // output // fill with special indicator value. sap.adjustment_hd = eDHL_ARC_UNKNOWN; // this value should not be used. SETRECT(&sap.rect, 0, 0, 0, 0); Dmc_UnlockAVMutex(); doDmc_Notify(DMC_NOTIFY_ScreenAdjustment, (UINT32)&sap); if (sap.bKeepCurrent) { dprint(2, "keep current adj setting\n"); return; } if (sap.adjustment_hd == (tDHL_DispARC)eDHL_ARC_UNKNOWN) { dprint(0, "!! screen adjust noti not impl. use default\n"); sap.adjustment_hd = eDHL_ARC_FULLSCREEN; sap.adjustment_sd = eDHL_ARC_FULLSCREEN; } dhr = DHL_AV_VideoSetARC(sap.adjustment_hd, sap.adjustment_sd); if (dhr) { dprint(0, "!! set arc err 0x%x. retry..\n", dhr); DHL_OS_Delay(100); DHL_AV_VideoSetARC(sap.adjustment_hd, sap.adjustment_sd); } } #if USE_CH_MW_ALL_PMT_DOWNLOAD /* ÇöÀç ½ÃûÁßÀÌ ¾Æ´Ñ ´Ù¸¥ pmtµéµµ ´Ù ´Ù¿î·Îµå ÇÑ´Ù. */ void doDmc_StartAllPmtMonitor(ProgramAVInfo *av) { DHL_RESULT err; int program_index; UINT16 pmt_pid, program_number; int i; if (!av->pat) goto label_exit; if (!av->pmtList) goto label_exit; // ÇϳªÀÇ filter·Î ¿©·¯ pmt¸¦ ÇѲ¨¹ø¿¡ ´Ù ¹Þ´Â °ÍÀÌ ¾Æ´Ï¶ó // pmt¸¦ Çϳª¾¿ ¼øÂ÷ÀûÀ¸·Î ¹Þ´Â ¹æ¹ýÀ» »ç¿ëÇÑ´Ù. // »õ MW¿¡¼­´Â ÀÌ·± ºÎºÐÀº °³¼±ÀÌ °¡´ÉÇÔ.. if (av->pmtPsiCtl2) { dprint(2, " stop allpmt psictl2\n"); DHL_PSI_StopMonitor(av->pmtPsiCtl2); av->pmtPsiCtl2 = (tDHL_PSI_ControlHandle)0; } // ´Ù¸¥ ¼­ºê ä³Î Áß¿¡¼­ ¾ÆÁ÷ ¹Þ¾ÆÁöÁö ¾ÊÀº program ¼±ÅÃ. program_index = -1; for (i=0; av->pmtList && ipat->numPrograms; i++) { if (av->pat->programs[i].program_number == av->program_number) continue; // ÀÌ ÇÁ·Î±×·¥Àº 'ÇöÀç' ÇÁ·Î±×·¥À̹ǷΠskip.. if (av->pmtList[i]) continue; // ÀÌ¹Ì ¹Þ¾ÆÁ® ÀÖ´Ù¸é skip.. program_index = i; pmt_pid = av->pat->programs[i].program_map_PID; program_number = av->pat->programs[i].program_number; break; } if (program_index < 0) { // ÀÌ¹Ì ´Ù ¹Þ¾ÆÁø °æ¿ì¶ó¸é ±×³É Á¾·á. // cafrii 110331 add param AllPsiRxNotifyInfo param; memset(¶m, 0, sizeof(param)); param.av = av; dprint(2, " all other %d pmts are downloaded.\n", av->pat->numPrograms-1); doDmc_Notify(DMC_NOTIFY_AllPsiReceived, (UINT32)¶m); goto label_exit; } // ´Ù¿î·Îµå ½ÃÀÛ.. dprint(2, " monitor other pmt[%d] pid %d, #%d..\n", program_index, pmt_pid, program_number); err = MonitorPMT(Dmc_GetCurrentTsd(), pmt_pid, program_number, TRUE, ePSIUPDATE_ONESHOT, _Dmc_PmtEventProc, 0, &av->pmtPsiCtl2); if (err) { dprint(0, "!! MonitorPMT returned %s\n", ErrorString(err)); } goto label_exit; label_exit: return; } #endif // USE_CH_MW_ALL_PMT_DOWNLOAD void doDmc_AudioTempMute(BOOL bMute) { // ´Ù¸¥ MW µî¿¡¼­ Decoder mute´Â »ç¿ëÇÏÁö ¾Ê°í À־ // À̰ÍÀ» temp mute·Î »ç¿ëÇÔ. DHL_AV_AudioMuteControl(eDHL_AUDIO_MUTE_DECODER, bMute); } void doDmc_AudioTempMuteLimitTimerProc(UINT32 nIDTimer, UINT32 param) { dprint(2, "\t audio temp unmute by timer limit\n"); doDmc_AudioTempMute(FALSE); } #if COMMENT _______EventHandler________(){} #endif // doDmc_HandlePatChange // // PAT monitorÀÇ °á°ú·Î ºÒ¸®´Â event procedure. // PAT Change EventÀÇ DMC level Deferred Procedure // Dmc task ¿¡¼­ È£ÃâµÈ´Ù. // void doDmc_HandlePatChange(DmcMessage *pmsg) { DHL_RESULT err; int i; int program_index = -1; BOOL bIgnoreNewPat = FALSE; UINT16 pmt_pid; UINT16 program_number; MPEG_PAT *pat = (MPEG_PAT *)pmsg->param; ProgramAVInfo *av = Dmc_LockAVMutex(); if (g_Trace_bDmcPsiEvent) dprint(1, "evtPatChange:::: cid %d\n", pmsg->cancelId); #if 1 // PSI_WO_CHVIEW if (av->active == 0) { dprint(2, " psi w/o chview\n"); } #else if (av->active == 0 || av->analog) { dprint(0, "!! pat is received in invalid state\n"); goto label_exit; } #endif if (pat == NULL || pat->numPrograms == 0 || pat->programs == NULL) { dprint(0, "!! invalid new PAT in in HandlePatChange\n"); goto label_exit; } // StopVideo¸¦ ÇÏ´Â ±× ¼ø°£¿¡ MessageQueue¿¡ ÀÖ´Â PAT change event°¡ ³²¾Æ ÀÖ´Ù°¡ // ³ªÁß¿¡ ÀÌ handler¿¡¼­ ´Ù½Ã video°¡ restartµÇ´Â ¹®Á¦°¡ ÀÖÀ» ¼ö ÀÖ´Ù. // ÀÌ ¹®Á¦´Â StopVideo¸¦ Çϸ鼭 Queue¿¡ ÀÖ´Â ¸ðµç event msg¸¦ »èÁ¦ÇÏ´Â °ÍÀ¸·Î ÇØ°áÇÑ´Ù. // // ±×·¡µµ Ȥ½Ã ¿À·¡µÈ event msg°¡ ´Ê°Ô ¿Ã °æ¿ì¸¦ ´ëºñÇØ¼­ psiControlÀÌ ÀÌ¹Ì »èÁ¦µÈ °æ¿ì¶ó¸é // ÀÌ À̺¥Æ®¸¦ ¹«½ÃÇÑ´Ù. // if (av->patPsiCtl == 0) { dprint(0, "!! patPsiCtl is NULL! it is already stopped context\n"); goto label_exit; } // Pat change event°¡ ³Ê¹« ÀÚÁÖ ºÒ¸®´Â °æ¿ì // ±× ó¸® ¼Óµµ°¡ »õ patÀÇ ¼ö½Å ºóµµ¸¦ µû¶ó°¡Áö ¸øÇϸé // Queue¿¡ ½×¿© ÀÖÀ» ¼öµµ ÀÖ´Ù. // Queue¿¡ PAT change event°¡ ÀÌ¹Ì ÀÖÀ¸¸é À̹ø event´Â ¹«½ÃÇØµµ µÈ´Ù. // if (doDmc_CheckMsgExist(evtPatChange)) { dprint(2, "!! Future PAT Change event detected. ignore this..\n"); goto label_exit; } // current program number of decoded program.. program_number = av->program_number; if (g_Trace_bDmcPsiEvent) { dprint(2, "PAT change event! TSID %d, version %d, num_program %d\n", pat->transport_stream_id, pat->version_number, pat->numPrograms); } if (1) { PSIChangeNotifyInfo pcni; // Notify to user first. memset(&pcni, 0, sizeof(pcni)); pcni.pmtchanged = FALSE; // This is PAT. pcni.pat = pat; //pcni.ignore = FALSE; // This is [out] parameter. FALSE by default pcni.program_index = -1; // cafrii 060804 add two more parameters pcni.userParam = av->userParam; pcni.av = av; doDmc_Notify(DMC_NOTIFY_PATChanged, (UINT32)&pcni); program_index = pcni.program_index; } // ¾Æ·¡ Á¶°ÇÀ̸é ÀÌ »õ·Î ¹ÞÀº pat¸¦ ó¸®ÇÏÁö ¾Ê´Â´Ù. // // 1. option¿¡¼­ equiv pat¸¦ ¹«½ÃÇ϶ó°í µÇ¾î ÀÖ°í, // 2. °Ë»ç °á°ú µ¿ÀÏÇÑ pat·Î °á°ú°¡ ³ª¿ÔÀ¸¸ç, // 3. pmt monitor°¡ Á¸ÀçÇϸé (ÀÌ°Ô Á¤¸»·Î µ¿ÀÏÇÑ °ÍÀÎÁö´Â È®ÀÎ ºÒ°¡) // if (dmc_bIgnoreEquivPat && Dmc_CheckIfSamePat(av->pat, pat) && av->pmtPsiCtl) // cafrii 060707 bugfix!! <-- av->pmtPsiCtl == 0 { bIgnoreNewPat = TRUE; } // Note: // PMT Monitor°¡ ¾ÆÁ÷ ±âµ¿µÇÁö ¾Ê¾Ò´Ù¸é ¾î¶°ÇÑ °æ¿ì¶óµµ Ignore¸¦ ÇÏ¸é ¾ÈµÈ´Ù. // ¼³·É NewPat¸¦ ¹«½ÃÇ϶ó´Â °á°ú°¡ ³ª¿Ô´õ¶óµµ // Pmt Monitor°¡ ¾ÆÁ÷ ½ÃÀÛÇÏÁö ¾ÊÀº »óŶó¸é Monitor¸¦ ½ÃÀÛÇØ¾ß ÇÑ´Ù. // // todo.. // is pmtPsiCtl consistent with one of pat's entry? // PSIControl: av->pmtPsiCtl->psiFilter->entries[0..2] ¸¦ Á÷Á¢ Á¶»çÇØ¾ß ÇÔ.. // -> ±×Á¤µµ±îÁö´Â ÇÊ¿ä ¾øÀ» µí.. if (bIgnoreNewPat) { if (g_Trace_bDmcPsiEvent) dprint(2, "!! PAT is ignored. similar PAT is already active..\n"); //FreePAT(pat); // ¾Æ·¡¿¡¼­ °°ÀÌ Ã³¸®ÇÔ. goto label_exit; } doDmc_UpdatePsiInfo(pat, NULL); pat = NULL; //-------------------- // new pat udpated. now processing.. // decide program index.. if (program_index < 0 || program_index >= av->pat->numPrograms) { // »ç¿ëÀÚ°¡ program_index¸¦ ¼³Á¤ÇÏÁö ¾Ê¾Ò°Å³ª // ÁöÁ¤ÇÑ program_index°¡ invalid ÇÑ °æ¿ìÀÌ´Ù. // °¡Àå Àû´çÇÑ program À» ¼±ÅÃÇØ¾ß ÇÑ´Ù. // // search current program in PAT using current program_number. // »õ·Î¿î PAT¿¡¼­ Áö±Ý±îÁö »ç¿ëÇØ¿Ô´ø ÇÁ·Î±×·¥ÀÇ program number¸¦ ã´Â´Ù. // dprint(2, "\tsearch program number %d\n", program_number); for (i=0; ipat->numPrograms; i++) { if (av->pat->programs[i].program_number == program_number) break; } if (i >= av->pat->numPrograms) { dprint(0, "\n!!!! program number %d not found in PAT.\n", program_number); #if !DMC_STOP_WHEN_PROGRAM_DISAPPEAR #if 0 dprint(0, "!!!! re-tune first program..\n"); program_index = 0; // try using first program.. #else //neverdai ÀÓ½Ã..ÃÖ¼Ò program_number¸¦ ¼±ÅÃÇÑ´Ù. { int j,numMin,minIdx; for(j=0, numMin=0xffff,minIdx=0; jpat->numPrograms; j++){ if(numMin>av->pat->programs[j].program_number) { numMin=av->pat->programs[j].program_number; minIdx=j; } } program_index=minIdx; } #endif #else dprint(0, "ignore pat.. do nothing\n"); program_index = -1; // just keep current state. // probably video will be freezed if pid is not matched. // follow your customers optinion.. #endif // DMC_STOP_WHEN_PROGRAM_DISAPPEAR } else { // found matched program. // program_index = i; } } if (program_index < 0 || program_index >= av->pat->numPrograms) { dprint(0, "!! program index %d invalid. should be [%d~%d]\n", program_index, 0, av->pat->numPrograms-1); #if DMC_STOP_WHEN_PROGRAM_DISAPPEAR goto label_fail; #else goto label_exit; #endif } pmt_pid = av->pat->programs[program_index].program_map_PID; program_number = av->pat->programs[program_index].program_number; if (pmt_pid <= 0 || pmt_pid >= 0x1FFF) { dprint(0, "!! PMT pid 0x%x invalid\n", pmt_pid); goto label_exit; } // PMT monitor¸¸ »èÁ¦ÇÑ´Ù. // ±âÁ¸ PMT ¸®¼Ò½º´Â »èÁ¦ÇÏÁö ¾Êµµ·Ï ÇÑ´Ù. // ¹Ø¿¡¼­ PmtMonitor¸¦ ½ÃÀÛÇϹǷΠ¾ó¸¶ ÈÄ¿¡ »õ PMT°¡ ¼ö½ÅµÇ¸é ±×¶§ ±³Ã¼ÇÑ´Ù. // if (av->pmtPsiCtl) DHL_PSI_StopMonitor(av->pmtPsiCtl); av->pmtPsiCtl = (tDHL_PSI_ControlHandle)0; dprint(2, "\tmonitor PMT (pid %d) of program idx %d, prognum %d\n", pmt_pid, program_index, program_number); err = MonitorPMT(Dmc_GetCurrentTsd(), pmt_pid, program_number, TRUE, // current dmc_PmtUpdateMode, _Dmc_PmtEventProc, 0, // userParam &av->pmtPsiCtl); if (err) { dprint(0, "!! MonitorPMT returned %s\n", ErrorString(err)); } // ¸ÕÀú ÇöÀç ½Ãû ÁßÀÎ ÇÁ·Î±×·¥ÀÇ pmt ºÎÅÍ ¹ÞÀº ÈÄ¿¡ ½ÃÀÛÇÏ´Â °ÍÀÌ ÁÁ°ÚÀ½. #if 0 // USE_CH_MW_ALL_PMT_DOWNLOAD //doDmc_StartAllPmtMonitor(av); #endif goto label_exit; #if DMC_STOP_WHEN_PROGRAM_DISAPPEAR label_fail: // ½ÇÇà ÁßÀÎ AV¸¦ ÁßÁö½ÃŲ´Ù. dprint(2, "!! stop current AV..\n"); doDmc_Stop(); // ÇÊ¿äÇϸé application¿¡ ÀÌ »óȲÀ» Åëº¸ÇØ ÁÙ Çʿ䰡 ÀÖ´Ù. doDmc_Notify(DMC_NOTIFY_PATChangeError, 0); #endif label_exit: if (pat) { #if DMC_CHECK_HEAP_SIZE UINT32 heap_before = DHL_GetFreeHeapSize(0); FreePAT(pat); dprint(2, "free pat 0x%x.. heap %u->%u\n", pat, heap_before, DHL_GetFreeHeapSize(0)); #else FreePAT(pat); dprint(2, "free pat 0x%x..\n", pat); #endif } Dmc_UnlockAVMutex(); } // doDmc_HandlePmtChange // // PMT Change EventÀÇ DMC level Deferred Procedure // Dmc task ¿¡¼­ È£ÃâµÈ´Ù. // #if USE_CH_MW_ALL_PMT_DOWNLOAD // ÇöÀç ½Ãû ÁßÀΠä³ÎÀÇ pmt À̵ç, ½ÃûÇÏÁö ¾Ê´Â pmt ÀÌµç °£¿¡ ¸ðµÎ ÀÌ // callback ¿¡¼­ 󸮵ȴÙ. µû¶ó¼­ ÀÌ µÑÀ» Àß ±¸ºÐÇØ¾ß ÇÔ. #endif void doDmc_HandlePmtChange(DmcMessage *pmsg) { UINT32 videoPID = 0, audioPID = 0, pcrPID = 0; tDHL_AudioCodingType audioType = eDHL_AUDIO_TYPE_UNKNOWN; tDHL_VideoCodingType videoType = eDHL_VIDEO_TYPE_UNKNOWN; BOOL bVideoOutputExist; DHL_RESULT err; STATUS status; PidInfo psiPid; MPEG_PMT *pmt = (MPEG_PMT *)pmsg->param; UINT16 pmt_pid, program_number; ProgramAVInfo prev_av, *av = Dmc_LockAVMutex(); if (g_Trace_bDmcPsiEvent) dprint(1, "evtPmtChange:::: cid %d\n", pmsg->cancelId); if (av->pmtPsiCtl == 0) { // VideoStopÀ» ÇÏ°í ³ª¸é doDmc_DeleteAllEventMsg ¸¦ ºÒ·¯¼­ ÀÚµ¿À¸·Î // ¸ðµç PsiCtlÀ» cancel ½Ã۰í Àֱ⠶§¹®¿¡ ³í¸®ÀûÀ¸·Î ÀÌ·±°Ô ¹ß»ýÇÏ¸é ¾ÈµÈ´Ù. // dprint(0, "!! pmtPsiCtl is NULL! it is already stopped context\n"); goto label_exit; } if (doDmc_CheckMsgExist(evtPmtChange)) { dprint(2, "!! Future PMT Change event detected. ignore this..\n"); goto label_exit; } // check integrity // if (av->pat == NULL || av->pat->numPrograms == 0 || av->pat->programs == NULL) goto label_exit; if (pmt == NULL) { dprint(0, "!! Invalid pmt\n"); goto label_exit; } #if 1 // PSI_WO_CHVIEW if (av->active == 0) { dprint(2, " psi w/o chview\n"); } #else if (av->active == 0 || av->analog) { dprint(0, "!! pmt is received in invalid state\n"); goto label_exit; } #endif #if USE_CH_MW_ALL_PMT_DOWNLOAD if (pmt->program_number != av->program_number) { // ÇöÀç ½ÃûÁßÀÌ ¾Æ´Ñ ¼­ºêä³ÎÀÇ pmtÀÎ °æ¿ìÀÌ´Ù. int i; dprint(2, "non-viewing program pmt #%d received\n", pmt->program_number); for (i=0; ipat->numPrograms; i++) { if (av->pat->programs[i].program_number == pmt->program_number) break; } if (i >= av->pat->numPrograms) { dprint(0, "!! pmt #%d received, but not in pat list\n", pmt->program_number); goto label_exit; } if (!av->pmtList) { dprint(0, "!! pmt received without pmtlist\n"); goto label_exit; } if (av->pmtList[i]) { dprint(2, "pmt[%d] already exist. #%d\n", i, av->pmtList[i]->program_number); } else { av->pmtList[i] = pmt; pmt = NULL; } // ÀÌÁ¦ ´Ù¸¥ program pmt°¡ ´õ ÀÖ´ÂÁö ã¾Æº»´Ù. //doDmc_StartAllPmtMonitor(av); goto label_exit; } #endif // USE_CH_MW_ALL_PMT_DOWNLOAD if (g_Trace_bDmcPsiEvent) { dprint(2, "PMT change event! PID %d, program_num %d, version %d\n", pmt->PID, pmt->program_number, pmt->version_number); } // compare // ±âÁ¸ÀÇ PMT¶û ºñ±³¸¦ ÇØº»´Ù. µ¿ÀÏÇÑ PMT·Î ÆÇ¸íµÇ¸é °è¼Ó ÁøÇàÇÒ Çʿ䰡 ¾ø´Ù. // if (dmc_bIgnoreEquivPmt) { int diff; diff = Dmc_CheckPmtDifference(av->pmt, pmt); if (diff == 0) { if (g_Trace_bDmcPsiEvent) dprint(2, "!! Same PMT is already active..\n"); //FreePMT(pmt); // ¾Æ·¡¿¡¼­ µ¿½Ã¿¡ free ÇÔ. goto label_exit; } if (g_Trace_bDmcPsiEvent) dprint(2, "\t new pmt, difference point is %d\n", diff); } // process new PMT.. // pmt_pid = pmt->PID; program_number = pmt->program_number; videoPID = audioPID = pcrPID = 0; // MW µðÆúÆ® ¼±Åà ·ÎÁ÷¿¡ ÀÇÇØ °¢ stream º° pid¸¦ ¼±ÅÃÇÑ´Ù. status = Dmc_DecidePidInfo(pmt, NULL, &psiPid, 0); if (status == statusOK && psiPid.bValid) { videoPID = psiPid.video; audioPID = psiPid.audio; pcrPID = psiPid.pcr; videoType = psiPid.videoType; audioType = psiPid.audioType; } else dprint(2, "!! pid from pmt err %d\n", status); // application callback¿¡ ÀÇÇÑ override¸¦ ó¸®ÇÑ´Ù. // ¸¸¾à callbackÀÌ µî·Ï ¾ÈµÈ °æ¿ì¶ó¸é ¾Õ¿¡¼­ ¼±ÅÃµÈ °ªÀÌ ±×´ë·Î »ç¿ëµÇ¾î¾ß ÇÑ´Ù. doDmc_SelectAudioStream(pmt, NULL, &audioPID, &audioType); doDmc_SelectVideoStream(pmt, NULL, &videoPID, &videoType); if (pcrPID == 0 || (videoPID == 0 && audioPID == 0)) { dprint(0, "!! No valid PIDs in PMT. p%d/v%d/a%d, ignored.\n", pcrPID, videoPID, audioPID); //if (pmt) FreePMT(pmt); // ¾Æ·¡¿¡¼­ µ¿½Ã¿¡ ¼öÇà.. //pmt = NULL; // ´Ù½Ã Çѹø ´õ ÇöÀç PMT ¼ö½ÅÀ» ½ÃµµÇØ º¸´Â°Ô ÁÁ°Ú´Ù. // dmc_nPmtChangeRetryCount++; goto label_retry_pmt_monitor; // cafrii 030916 } if (dmc_bIgnoreEquivPmt) { // ¾Ë¾Æ³½ PID°¡ ÇöÀç PID¿Í µ¿ÀÏÇÏ´Ù¸é Restart¸¦ ÇÒ Çʿ䰡 ¾øÀ» ¼öµµ ÀÖ´Ù. // // NOTE! descriptor°¡ º¯°æµÇ¾úÀ» ¼öµµ ÀÖÀ¸¹Ç·Î app noti´Â »©¸ÔÀ¸¸é ¾ÈµÊ. // todo.. ¾Æ·¡ Äڵ尡 ÇÊ¿äÇÑ ÀÌÀ¯´Â? // cafrii 030916, Only Audio dropÀÇ °æ¿ì¿¡´Â PmtChange¸¦ ¹«½ÃÇϵµ·Ï ÇÏ¿´´Ù. // Audio°¡ ³ª¿À´Ù°¡ ±×³É ¹«À½ »óÅ·θ¸ µÉ °ÍÀÌ´Ù. // // dprint(1,"av->video_type(%d), videoType(%d)\n", av->video_type, videoType); if (av->video_pid == videoPID && av->video_type == videoType && ( (av->audio_pid == audioPID) /* || (prev_av.audio_pid != 0 && audioPID == 0) */ ) && av->pcr_pid == pcrPID) { // PMT°¡ ignore µÈ °æ¿ì¶óµµ ¸î°¡Áö ó¸®ÇØÁÙ ÀÛ¾÷µéÀÌ ÀÖ´Ù. ÀÌ °÷¿¡¼­ ¼öÇà. // if (g_Trace_bDmcPsiEvent) dprint(2, "!! PMT is ignored. similar & active context already running..\n"); av->program_number = pmt->program_number; // PmtChange´Â ¾î·µç ¼º°øÀûÀ¸·Î µÈ °ÍÀ̹ǷΠ0À¸·Î ¸®¼Â. // dmc_nPmtChangeRetryCount = 0; doDmc_UpdatePsiInfo(NULL, pmt); // pmt´Â ÀÌ ³»ºÎ¿¡¼­ º°µµ ÀúÀåÇÑ´Ù. pmt = NULL; goto label_completed; } else dprint(2, "\t pid diff. pva %x %x %x != %x %x %x\n", av->pcr_pid, av->video_pid, av->audio_pid, pcrPID, videoPID, audioPID); } doDmc_UpdatePsiInfo(NULL, pmt); // pmt´Â ÀÌ ³»ºÎ¿¡¼­ º°µµ ÀúÀåÇÑ´Ù. pmt = NULL; // backup av info because other essential parameters are preserved. prev_av = *av; // cafrii 081125 add // ¸¸¾à audio pid¸¸ º¯°æµÈ °æ¿ì¶ó¸é (¶Ç´Â audio°¡ ¾ø´Ù°¡ ½ÃÀÛÇÏ´Â °æ¿ì¶ó¸é) // audio¸¸ restart ÇÏ¸é µÈ´Ù. // // cafrii 090212 bugfix // »õ audio PID°¡ 0ÀÎ °æ¿ì StartDigital¿¡¼­ ¿À·ù ¹ß»ýÇÏ´Â ¹®Á¦ ¹ß°ß. // video°¡ Á¤»óÀûÀÎ °æ¿ì, ±×¸®°í »õ audio PID°¡ Á¤»óÀûÀÎ °æ¿ì¿¡¸¸ // audio restart only ¹æ¹ýÀ» Á¦ÇÑÀûÀ¸·Î Àû¿ëÇÑ´Ù. // »õ audio pid°¡ 0ÀÎ °æ¿ì È­¸éÀÌ 1¹ø ±ôºýÇÏ´Â °æ¿ì ÀÖ´Ù. #if 1 // NEW_DHL_API if (1) { tDHL_VideoStatus video_status; DHL_AV_VideoGetStatus(0, &video_status); bVideoOutputExist = video_status.bOutputExist; } #else bVideoOutputExist = DHL_AV_VideoOutputExist(); #endif if (av->video_pid == videoPID && av->video_type==videoType && bVideoOutputExist && audioPID) { doDmc_StopDigitalAudio(); // video pid¸¦ 0À¸·Î ÁöÁ¤Çϸé audio¸¸ play ÇÑ´Ù. status = doDmc_StartDigital(0, audioPID, pcrPID, (DMC_VIDEO_CACHE)NULL, videoType, audioType); } else { doDmc_StopDigital(FALSE, FALSE); // do not cancel monitors status = doDmc_StartDigital(videoPID, audioPID, pcrPID, (DMC_VIDEO_CACHE)NULL, videoType, audioType); // Note!! // ÀÌ ÇÔ¼ö¸¦ ºÎ¸£´Â ¼ø°£¿¡ video°¡ runningÁßÀ̶ó¸é, // ÀÌ ÇÔ¼ö ¾È¿¡¼­ ±âÁ¸ÀÇ video context¸¦ °­Á¦ stop ½ÃŰ¸é¼­ µ¿½Ã¿¡ MonitorPATµµ ÇØÁ¦µÈ´Ù. // ¹Ýµå½Ã ¹Ì¸®¹Ì¸® light stopÀ» ½ÃÄѳõ¾Æ¼­ ¾È¿¡¼­ ÀÚµ¿ stop µÇ´ÂÀÏÀÌ ¾øµµ·Ï ÇÏÀÚ. // } if (status == statusCancelled) { dprint(1, "\tStartDigital in PMT change cancelled by user\n"); doDmc_ClearProgramInfo(); // cancelÀÌ µÈ °æ¿ì´Â °ð¹Ù·Î ´Ù¸¥ decodingÀ» ½ÃÀÛÇÒ °ÍÀ̱⠶§¹®¿¡ // retryµµ ¾ÈÇϰí callbackµµ ¾ÈÇÑ´Ù. goto label_exit; } else if (status) { // timeout Errorµµ Æ÷ÇÔ.. dprint(0, "!! RestartVideo by NewPMT err %d\n", status); doDmc_ClearProgramInfo(); // ´Ù½Ã Çѹø ´õ PMT ¼ö½Å ½Ãµµ.. ¾Æ¸¶ ¼öÁýµÈ PID°¡ À߸øµÈ °ÍÀÏ ¼ö ÀÖ´Ù. // dmc_nPmtChangeRetryCount++; goto label_retry_pmt_monitor; } doDmc_UpdateProgramInfoDigital(prev_av.rf, prev_av.mod, prev_av.method, prev_av.major, prev_av.minor, av->pmt->program_number, videoPID, audioPID, pcrPID, videoType, audioType); // program number¸¸Àº ±âÁ¸ °Í°ú ´Ù¸¦ ¼öµµ ÀÖ´Ù. ÀÌ Çڵ鷯¿¡¼­ ó¸® Áß¿¡ // »õ PMT¿¡¼­ program_number°¡ ¹Ù²î¾úÀ» ¼öµµ ÀÖÀ¸¹Ç·Î.. dmc_nPmtChangeRetryCount = 0; // ¼º°øÇßÀ¸¹Ç·Î 0À¸·Î ¸®¼ÂÇÑ´Ù. label_completed: if (1) // Notify to user. ApplicationÀ¸·Î PmtChange event¸¦ º¸³½´Ù. { PSIChangeNotifyInfo pcni; memset(&pcni, 0, sizeof(pcni)); pcni.pmtchanged = TRUE; // This is PMT pcni.pmt = av->pmt; // new PMT pcni.pat = av->pat; // new or existing PAT //pcni.ignore = FALSE; // This is [out] parameter. FALSE by default // cafrii 060804 add two more parameters. pcni.userParam = av->userParam; pcni.av = av; doDmc_Notify(DMC_NOTIFY_PMTChanged, (UINT32)&pcni); // arzhna, 100203 // CA PMT¸¦ Àü´ÞÇϱâ À§ÇÑ callback È£Ãâ doDmc_Notify(DMC_NOTIFY_CaPmt, (UINT32)&pcni); } label_exit: #if USE_CH_MW_ALL_PMT_DOWNLOAD doDmc_StartAllPmtMonitor(av); #endif // cafrii 060830 add bugfix!! memory leak for some odd case.. if (pmt) { #if DMC_CHECK_HEAP_SIZE UINT32 heap_before = DHL_GetFreeHeapSize(0); FreePMT(pmt); dprint(2, "free pmt 0x%x.. heap %u->%u\n", pmt, heap_before, DHL_GetFreeHeapSize(0)); #else FreePMT(pmt); dprint(2, "free pmt 0x%x..\n", pmt); #endif } Dmc_UnlockAVMutex(); return; label_retry_pmt_monitor: // cafrii 060830 add bugfix!! memory leak for some odd case.. if (pmt) { dprint(2, "free pmt 0x%x..\n", pmt); FreePMT(pmt); } // 1. ¼ö½ÅµÈ PMTÀÇ ³»¿ë¿¡ ¹®Á¦°¡ ÀÖÀ»¶§ (PID °Ë»ö ºÒ°¡, ¶Ç´Â À߸øµÈ PID) // 2. A/V decoding µµÁß¿¡ ¹®Á¦°¡ »ý°åÀ» ¶§ // dprint(0, "!! PMT change error! retry count %d\n", dmc_nPmtChangeRetryCount); // ApplicationÀ¸·Î callbackÀ» ÇÒ °æ¿ì.. // // doDmc_Notify(DMC_NOTIFY_PMTChangeError, 0); // applicationÀº ÀÌ ·çƾ¿¡¼­ ¸ðÁ¾ÀÇ Á¶Ä¡¸¦ ÃëÇØ¾ß ÇÑ´Ù. // ÇöÀç video´Â ¾È³ª¿À°í ÀÖÀ» ¼öµµ ÀÖ´Ù. if (dmc_nPmtChangeRetryCount > dmc_LimitPmtChangeRetryCount) { dprint(0, "!! PMT change error retry count is over MAX %d, Ignore PmtChange!!\n", dmc_nPmtChangeRetryCount); //return; goto label_retry_exit; } if (pmt_pid <= 0 || pmt_pid >= 0x1FFF) { dprint(0, "!! pmt pid 0x%x invalid\n", pmt_pid); } else { DHL_PSI_StopMonitor(av->pmtPsiCtl); av->pmtPsiCtl = (tDHL_PSI_ControlHandle)0; err = MonitorPMT(Dmc_GetCurrentTsd(), pmt_pid, program_number, TRUE, // current dmc_PmtUpdateMode, _Dmc_PmtEventProc, 0, // userParam &av->pmtPsiCtl); if (err) { dprint(0, "!! MonitorPMT returned %s\n", ErrorString(err)); } } label_retry_exit: #if USE_CH_MW_ALL_PMT_DOWNLOAD doDmc_StartAllPmtMonitor(av); #endif Dmc_UnlockAVMutex(); } /* * handleImportantVideoChange is called from within the video control task * in response to an importantChange event which was in turn sent by the higher priority * video driver task. The change has already occurred and this is an after-the-fact notification. * We use this mostly to handle output=input mode */ void doDmc_HandleImportantVideoChange(DmcMessage *pmsg) { BOOL bFormatChanged = FALSE; DHL_RESULT dhr; dprint(1, "evtVideoImportantChange: cid %d\n", pmsg->cancelId); // todo.. // ÀÌ ½ÃÁ¡¿¡¼­ ÀÌ¹Ì driverÀÇ video context°¡ »õ·Î¿î Á¤º¸·Î °»½ÅµÈ °ÍÀΰ¡? bFormatChanged = doDmc_CheckIfFormatChanged(); if (bFormatChanged == FALSE) { dprint(2, "\t source format not changed. keep current timing..\n"); // important video change ÀÇ °æ¿ì¿¡´Â format ÀÌ unchangeµÈ °æ¿ì¿¡´Â // notifyµîÀÇ ÀÛ¾÷À» ÀüÇô ÇÒ Çʿ䰡 ¾ø´Ù. return; } // todo.. // user¿¡°Ô callbackÀ¸·Î notificationÀ» Çϰí // ÇÊ¿äÇÑ °æ¿ì timing change¸¦ ÇÑ´Ù. // // cafrii 070725 add // runtime ½Ã¿¡ ÇØ»óµµ º¯°æµÇ´Â ½ºÆ®¸² Áö¿ø. doDmc_ProcessScreenAdjustment(); // restore video temp-mute dmc_bRequestVideoHide &= ~DMC_VIDEO_HIDE_VIDEO_START; dprint(2, "check video temp-mute.. 0x%x\n", dmc_bRequestVideoHide); if (dmc_bRequestVideoHide == 0) { dhr = DHL_AV_VideoHide(0, FALSE); if (dhr) dprint(0, "!! video unblank err\n", dhr); } } // doDmc_HandleImportantVideoChange void doDmc_HandleUserChange(DmcMessage *pmsg) { // µðÆúÆ®·Î driver¿¡¼­ ¼öÇàÇÏ´Â ÀÛ¾÷À¸·Î ¸¸Á·ÇÑ´Ù. } void doDmc_HandleMajorVideoChange(DmcMessage *pmsg) { STATUS status; ProgramAVInfo prev_av; MajorChangeEventParam arg; // ¾î¶² °æ¿ì¿¡ ÀÌ major event°¡ ¿À´Â°¡? // --> majorchange video event. // ¹öÆÛ°¡ ºÎÁ·ÇÒ °æ¿ì expand ½Ã۱â À§ÇØ ºÒ¸°´Ù. // Áï ÇöÀç »óÅ ±×´ë·Î¿¡¼­ ´Ù½Ã video context¸¸ ´Ù½Ã ¸¸µé¸é µÉ µí ÇÏ´Ù. // // ÈÄ󸮷ΠPAT monitoringÀ» ´Ù½Ã ÇÏ´Â°Ô Àû´çÇѰ¡? // --> ¿ì¸®´Â ÇöÀç PID Á¤º¸¸¦ ´Ù °¡Áö°í Àֱ⠶§¹®¿¡ À̸¦ Ȱ¿ëÇØ¼­ AV start¸¸ Çϰí, // psiMonitorControlÀº °Çµå¸®Áö ¾Ê´Â´Ù. // ProgramAVInfo *av = Dmc_LockAVMutex(); dprint(1, "evtVideoMajorChange: cid %d\n", pmsg->cancelId); // cafrii 060814 add // US14 streamÀÇ °æ¿ì important change°¡ 1ȸ È£ÃâµÇ°í ³ª¼­ // ±× ÀÌÈÄ major change event°¡ ¿¬´Þ¾Æ¼­ 4ȸ ¹ß»ýÇÑ´Ù. // ¹Ì·¡¿¡ major change°¡ ¹ß°ßµÇ´Â °æ¿ì 󸮸¦ ÇÏÁö ¾Ê°í ¹Ì·çµµ·Ï ÇÏÀÚ. // if (doDmc_CheckMsgExist(evtVideoMajorChange)) { dprint(2, "!! Future Major Change event detected. ignore this..\n"); goto label_exit; } if (!av->active || av->analog) { dprint(0, "!! illegal state (%s, %d)! majorVideoChange ignored.\n", av->active ? "active" : "inactive", av->analog ? "analog" : "digital"); goto label_exit; } if (1) { // application notification memset(&arg, 0, sizeof(arg)); arg.ignore = FALSE; // cafrii 060519, TRUE->FALSE doDmc_Notify(DMW_NOTIFY_MajorChangeEvent, (UINT32)&arg); if (arg.ignore) { dprint(2, "!! User want to ignore this MajorChange event.. skip.\n"); goto label_exit; } } dprint(2, "\tPreviously tuned %s\n", TuneMethodString(av->method)); prev_av = *av; // video context¸¸À» »èÁ¦ÇÑ´Ù. ´Ù¸¥ °ÍµéÀº »èÁ¦ÇÏÁö ¾Ê´Â´Ù. // doDmc_StopDigital(FALSE, FALSE); // do not cancel monitors status = doDmc_StartDigital(prev_av.video_pid, prev_av.audio_pid, prev_av.pcr_pid, (DMC_VIDEO_CACHE)NULL, prev_av.video_type, prev_av.audio_type); if (status == statusCancelled) { dprint(0, "!! StartDigital in MajorChange cancelled by user\n"); doDmc_ClearProgramInfo(); // cancelÀÌ µÈ °æ¿ì´Â °ð¹Ù·Î ´Ù¸¥ decodingÀ» ½ÃÀÛÇÒ °ÍÀ̱⠶§¹®¿¡ // retryµµ ¾ÈÇϰí callbackµµ ¾ÈÇÑ´Ù. } else if (status) { dprint(0, "!! restart video error %d in major change event!\n", status); doDmc_ClearProgramInfo(); // ´Ù½Ã Çѹø ½Ãµµ¸¦ ÇÒ ¹æ¹ýÀÌ Àִ°¡? // } else { // success!! // doDmc_UpdateProgramInfoDigital(prev_av.rf, prev_av.mod, prev_av.method, prev_av.major, prev_av.minor, prev_av.program_number, prev_av.video_pid, prev_av.audio_pid, prev_av.pcr_pid, prev_av.video_type, prev_av.audio_type); } label_exit: Dmc_UnlockAVMutex(); } // doDmc_HandleMajorVideoChange void doDmc_HandleFreezeVideoEnd(DmcMessage *pmsg) { // ´ëºÎºÐÀÇ ÀÛ¾÷Àº video driver¿¡¼­ ó¸®ÇÏ¿´À¸¸ç, // application¿¡ Å뺸ÀÇ ¸ñÀûÀ¸·Î À̺¥Æ®¸¦ ¹Þ´Â´Ù. dprint(1, "eventFreezeVideoEnd: cid %d\n", pmsg->cancelId); if (dmc_bWaitFirstFreezeVideoEndEvent) // ÇöÀç wait ÁßÀ̸é.. { BOOL bProcessed = FALSE; dprint(2, "\tfirst FreezeEndEvent\n"); doDmc_Notify(DMW_NOTIFY_VideoFreezeEndEvent, (UINT32) &bProcessed); // Zoran decoder¿¡¼­´Â ÀϹÝÀûÀ¸·Î óÀ½¿¡ µÎ°³ÀÇ freeze video end // event°¡ ¹ß»ýÇϰí ÀÖ´Ù. óÀ½°Í ¿Ü¿¡´Â Çʿ䰡 ¾ø±â ¶§¹®¿¡ // Ȥ½Ã msgQ ¿¡ Á¸ÀçÇÏ´Â µ¿ÀÏ event´Â »èÁ¦ÇØÁÖ¸é ÁÁ´Ù. // doDmc_DeleteMsg(evtFreezeVideoEnd); if (bProcessed == FALSE) { //dprint(2, "\tAudio TempMute Off in First video frame\n"); // cafrii, 030610, channel change½Ã¿¡ Audio Pop noise¸¦ ¸·±â À§ÇØ, // stop video¿¡¼­ Audio mute, freeze_end½Ã¿¡ mute off¸¦ ÇÑ´Ù. dprint(2, "\t audio temp mute off\n"); doDmc_AudioTempMute(FALSE); // Ç×»ó TempMuteOff¸¦ ÇÒ ÇÊ¿ä´Â ¾ø°í, ¿ø·¡´Â ƯÁ¤ Á¶°ÇÀÌ µÉ¶§¸¸ ÇØ¾ßÇÑ´Ù. // // dmc_bUseAudioTempMuteAtStart == TRUE // dmc_bAudioVideoSyncStart == TRUE // // À§ µÎ Á¶°ÇÀÌ TRUE°¡ ¾Æ´Ï¸é TempMute°¡ ¾ÈµÈ »óÅÂÀÌ´Ù. // ±×·¯³ª TempMuteOff¸¦ ¿©·¯¹ø È£ÃâÇÑ´Ù°í ¹®Á¦°¡ µÇ´Â°ÍÀÌ ¾Æ´Ï¹Ç·Î // ¿©±â¼­´Â ±×³É ¹«Á¶°Ç È£ÃâÇØÁÖµµ·Ï ÇÏÀÚ. } dmc_bWaitFirstFreezeVideoEndEvent = FALSE; } return; } // cafrii 060721 add void doDmc_HandleVideoScrambled(DmcMessage *pmsg) { // cafrii 060831 comment // // °£È¤ driver¿¡¼­ Á¤»óÀûÀÎ ½ºÆ®¸²Àε¥µµ driver¿¡¼­ scrambled event¸¦ º¸³»ÁÙ ¶§°¡ ÀÖ´Ù. // ÀÌ °æ¿ì Çѹø¿¡ scrambleÀ̶ó°í ÆÇ´ÜÇϱ⿡´Â À§ÇèÇÑ ¸éÀÌ ÀÖ´Ù. // // ´ëÃ¥ 1. // scramble check¸¦ ÀÏÁ¤ ½Ã°£ ³»¿¡ ÀÏÁ¤ Ƚ¼ö ÀÌ»ó report µÉ ¶§¿¡¸¸ actionÀ» ÃëÇÑ´Ù. // driver¿¡ °ü·Ã API°¡ Á¦°øµÇ¾î¾ß ÇÔ. // // ´ëÃ¥ 2. // runtime Áß¿¡´Â scramble event¿¡ ´ëÇØ¼­ ´ëÀÀÇÏÁö ¾Ê´Â´Ù. // óÀ½ ½ÃÀÛÇÒ ¶§¿¡ ´ëÀÀ ÇÏ´Â °ÍÀ¸·Î ÃæºÐ. #if 0 // cafrii 060831 delete code, use policy #2. // video ½ÃÀÛÇÒ ¶§ °¡ ¾Æ´Ï¶ó runtime Áß¿¡ scramble·Î º¯°æµÈ °æ¿ì ¹ß»ý. // SigMon µî¿¡¼­ NoProgram / AudioOnly banner¸¦ ¶ç¿ï ¼ö ÀÖµµ·Ï Á¶Ä¡ÇÑ´Ù. // BOOL bAudioExist; // ¸¸¾à audioµµ ¾ø´Â »óŶó¸é ¿ÏÀüÈ÷ ³»·Á¾ß ÇÑ´Ù. // 1ȸ¸¸ Ã¼Å©ÇØµµ ¾ÈÀüÇѰ¡? // { ProgramAVInfo *av = Dmc_LockAVMutex(); dprint(2, "\t \n", av->rf, av->program_number); DHL_AV_SaveVideoToCache(av->rf, av->program_number); Dmc_UnlockAVMutex(); } bAudioExist = DHL_AV_AudioOutputExist(); if (bAudioExist == FALSE) { dprint(2, "video scrambled and no audio detect. stop!\n"); doDmc_StopDigital(TRUE, FALSE); } else { // video context¸¸ ³»¸°´Ù. // dprint(2, "audio detected. stop video only\n"); doDmc_StopDigitalVideo(FALSE); // cache¿¡´Â ÀúÀåÇÏÁö ¸»ÀÚ. scramble µÈ °ÍÀ̶ó¸é Àǹ̰¡ ¾øÀ½. } #endif } #if COMMENT _______AVControl________(){} #endif void doDmc_StopDigitalVideo(BOOL bSaveToCache) { DHL_RESULT dhlResult; dprint(2, " \tstop digital video..\n"); #if 0 // NEW_DHL_API // decoding°ú display±îÁö ¸ðµÎ stopÇÑ´Ù. // DHL_AV_DispStop(); #endif #if SUPPORT_DMW_VIDEO_CACHE if (bSaveToCache) // cafrii 060630 add { ProgramAVInfo *av; av = Dmc_LockAVMutex(); dprint(2, "\tsave video to cache.. rf %d, #%d..\n", av->rf, av->program_number); DHL_AV_SaveVideoToCache(av->rf, av->program_number); Dmc_UnlockAVMutex(); } #endif dhlResult = DHL_AV_VideoStop(0); if (dhlResult) dprint(0, "!! DHL_AV_VideoStop err 0x%x\n", dhlResult); } void doDmc_StopDigitalAudio(void) { AudioDecodeStopParam adsp; DHL_RESULT dhlResult; dprint(2, "\tstop digital audio..\n"); memset(&adsp, 0, sizeof(AudioDecodeStopParam)); //adsp.mode = MOCHA_ATSC_INPUT; adsp.result = statusNotImpl; // my default. doDmc_Notify(DMW_NOTIFY_AudioDecodeStop, (UINT32) &adsp); if (adsp.result == statusNotImpl) { // µðÆúÆ® ±¸Çö: dhlResult = DHL_AV_AudioStop(); if (dhlResult) dprint(0, "!! DHL_AV_AudioStop err 0x%x\n", dhlResult); } else if (adsp.result == statusOK) { // Ưº°È÷ ÇÒÀÏ ¾øÀ½. } } // // tsd stop, routing µîÀº ¼öÇàÇÏÁö ¾Ê°í ¿ÀÁ÷ decoding ¸¸ ÁßÁöÇÑ´Ù. // void doDmc_StopDigital(BOOL bCancelMonitors, BOOL bSaveToCache) { if (!Dmc_IsDmcTask()) { dprint(0, "!! doDmc_StopDigital() should be called only in DmcTask.\n"); return; } dprint(1, "\tStop digital video/audio, cancel monitor %d\n", bCancelMonitors); dmc_bWaitFirstFreezeVideoEndEvent = FALSE; // ´õÀÌ»ó Áö¿øÇÏÁö ¾ÊÀ½. //if (_Dmc_DecodeStopCallback) // _Dmc_DecodeStopCallback(0, 0); // ÇöÀç´Â Ưº°ÇÑ parameter°¡ ¾øÀ½.. doDmc_StopDigitalAudio(); doDmc_StopDigitalVideo(bSaveToCache); if (bCancelMonitors) { doDmc_CancelMonitors(); // StopÀÌ µÇ¸é¼­ Psi Monitor ControlÀÌ »èÁ¦µÇ¾úÀ¸¹Ç·Î // ÀÌ¹Ì DmcQ¿¡ µé¾î¿Í ÀÖ´Â ¸ðµç Psi À̺¥Æ®µéµµ ´Ù ½ÄÁ¦ÇØ¾ß ÇÑ´Ù. // // ´Ü vxWorks message QÀÇ ÇѰè·Î »õ ¹æ½ÄÀÇ UserQue¸¦ »ç¿ëÇÏÁö ¾ÊÀ¸¸é ÀÌ ±â´ÉÀ» ¼öÇàÇÒ ¼ö ¾ø´Ù. dprint(2, "\t Delete all event message..\n"); doDmc_DeleteAllEventMsg(); // ¸ðµç event¸¦ Q¿¡¼­ »èÁ¦.. } doDmc_ClearProgramInfo(); // cafrii 060721 add } void doDmc_StopAnalog() { DHL_RESULT dhlResult; AudioDecodeStopParam adsp; if (!Dmc_IsDmcTask()) { dprint(0, "!! doDmc_StopAnalog() should be called only in DmcTask.\n"); return; } dprint(1, "\tStop analog video/audio\n"); //--------------- Audio Stop -------------- memset(&adsp, 0, sizeof(AudioDecodeStopParam)); adsp.result = statusNotImpl; // my default. //adsp.mode = MOCHA_NTSC_INPUT; doDmc_Notify(DMW_NOTIFY_AudioDecodeStop, (UINT32) &adsp); if (adsp.result == statusNotImpl) { // µðÆúÆ® ±¸Çö: dhlResult = DHL_CAP_AudioStop(); if (dhlResult) dprint(0, "!! DHL_CAP_AudioStop err 0x%x\n", dhlResult); } //--------------- Video Stop -------------- dhlResult = DHL_CAP_VideoStop(0); if (dhlResult) dprint(0, "!! DHL_CAP_VideoStop err 0x%x\n", dhlResult); // Stop context¸¦ ÇÒ ¶§ µðÆúÆ® »óÅ·ΠplaneÀ» º¸ÀÌ°Ô ÇÒ °ÍÀÎÁö ¾Æ´ÑÁö´Â ¾Ë¾Æ¼­ °áÁ¤.. #if 0 DHL_AV_VideoHide(FALSE); av = Dmc_LockAVMutex(); av->video_hidden = FALSE; Dmc_UnlockAVMutex(); #endif // 0 doDmc_ClearProgramInfo(); // cafrii 060721 add } void doDmc_Stop() { ProgramAVInfo *av; if (!Dmc_IsDmcTask()) { dprint(0, "!! doDmc_Stop() should be called only in DmcTask.\n"); return; } av = Dmc_LockAVMutex(); dprint(2, "doDmc_Stop: current activity %d\n", av->active); if (av->active) { if (av->analog) { dprint(2, "Stop Analog TV\n"); doDmc_StopAnalog(); } else { dprint(2, "Stop Digital TV\n"); doDmc_StopDigital(TRUE, TRUE); // cancel all monitors } } else { dprint(2, " video already stopped.\n"); } doDmc_ClearProgramInfo(); // cafrii 060721 add // cafrii 030917 // TunerÀÇ ÀÌ»ó µîÀ¸·Î ÇØ¼­ context°¡ ±âµ¿ÀÌ ¾ÈµÈ °æ¿ì, inactive »óÅÂÀÌÁö¸¸ // application¿¡¼­ PsiMonitor¸¸ º°µµ·Î launchÇßÀ» ¼öµµ ÀÖ´Ù. // µû¶ó¼­ À§¿¡¼­ Á¦´ë·Î stopÀÌ ¾ÈµÇ¾úÀ» ¼öµµ ÀÖÀ¸¹Ç·Î ¿©±â¼­ PsiMonitor´Â // cancelÀ» ÇØÁÖ¾î¾ß ÇÑ´Ù. // doDmc_CancelMonitors(); Dmc_UnlockAVMutex(); } // cafrii 060630, add video cache function // STATUS doDmc_StartDigital(UINT16 uVidPID, UINT16 uAudPID, UINT16 uPcrPID, DMC_VIDEO_CACHE vcache, tDHL_VideoCodingType vtype, tDHL_AudioCodingType atype) { // video pid, pcr pid·Î ºñµð¿À µðÄÚµùÀ», audio pid¸¦ ÀÌ¿ëÇÏ¿© ¿Àµð¿À µðÄÚµùÀ» °³½ÃÇÑ´Ù. // ÀÌ Àü¿¡ ÀÌ¹Ì Demux_tsdStart() µÇ¾î ÀÖ¾î¾ß ÇÑ´Ù. // // context´Â »õ·Î »ý¼ºµÈ´Ù. // ¸¸¾à flatten µÈ Á¤º¸°¡ ÀÖ´Ù¸é ±×°ÍÀ» restore ½ÃÄÑ »ç¿ëÇÑ´Ù. // ¿¡·¯°¡ ³ª¸é ¹Ù·Î ¸®ÅÏÇÑ´Ù. (timeout errorÀÎ °æ¿ì¿¡µµ ¸®ÅÏÇÔ.) // AudioDecodeStartParam adsp; DHL_RESULT dhlResult; BOOL bVideoFormatChanged = FALSE; BOOL bVideoStarted = FALSE; if (!Dmc_IsDmcTask()) { dprint(0, "!! doDmc_StartDigital() should be called only in DmcTask.\n"); return statusInvalidState; } if (uPcrPID == 0 || (uVidPID == 0 && uAudPID == 0)) { dprint(0, "!! doDmc_StartDigital(): PID error. pcr %d, video %d, audio %d\n", uPcrPID, uVidPID, uAudPID); return statusInvalidArgument; } if (dmc_bRunWithoutVideo) { dprint(0, "skip video by flag\n"); goto process_audio; } if (uVidPID == 0) { dprint(2, "\t null video pid. skip..\n"); #if SUPPORT_DMW_VIDEO_CACHE if (vcache) { DHL_AV_DeleteVideoCacheData((tDHL_VideoCacheHandle)vcache); vcache = 0; } #endif goto process_audio; } // ------- video route setting ------------ dhlResult = DHL_CAP_ChangeVideoSource(0, eDHL_CAP_DTV_TS0); if (dhlResult) { dprint(0, "!! DHL_CAP_ChangeVideoSource err\n"); // do nothing.. just go! dhlResult = DHL_OK; } // ------- process video ------------ #if USE_PERF_MON DHL_PerfMonCheck(gDmcPMTune, PM_EV_TUNE_VIDEO_START, 0); #endif // do video temp-mute not to see initial noisy screen dmc_bRequestVideoHide |= DMC_VIDEO_HIDE_VIDEO_START; dprint(2, "apply video temp-mute.. flag 0x%x\n", dmc_bRequestVideoHide); dhlResult = DHL_AV_VideoHide(0, TRUE); if (dhlResult) dprint(0, "!! temp video hide err 0x%x\n", dhlResult); #if SUPPORT_DMW_VIDEO_CACHE if (vcache) // video cache Á¤º¸°¡ ÀÖÀ¸¸é ±×°ÍÀ¸·Î ¸ÕÀú ½Ãµµ.. { dprint(2, "\tvideo start using vcache..\n"); dhlResult = DHL_AV_StartCachedVideo(vcache); if (dhlResult) { dprint(0, "!! video vcache invalid? ignored!\n"); DHL_AV_DeleteVideoCacheData(vcache); vcache = (DMC_VIDEO_CACHE)NULL; } } #endif if (vcache == (DMC_VIDEO_CACHE)NULL) { dprint(2, "\t video normal start, v 0x%x, p 0x%x a 0x%x, vt %d\n", uVidPID, uPcrPID, uAudPID, vtype); dhlResult = DHL_AV_VideoStart(0, uVidPID, uPcrPID, vtype); } #if 1 // for new hal architecture, new approach.. // °ú°Å¿¡´Â DHL_AV_VideoStart() api ¾È¿¡ cancel_check ÇÔ¼ö°¡ °Ç³×Áö°í // Á¦´ë·Î µÈ video decoding ÀÌ È®ÀÎ µÉ ¶§ ±îÁö blocking µÇ´Â ¹æ½ÄÀ̾úÀ½. // neo hal ¿¡¼­ºÎÅÍ api°¡ º¯°æµÇ¾ú´Âµ¥, mw ÂÊ¿¡´Â ¹Ý¿µÀÌ ¾ÈµÇ°í ÀÖÀ½. // arc °ü·Ã ¹®Á¦ ÇØ°áÀ» À§Çؼ­´Â seq hdr Á¤º¸°¡ ÇʼöÀ̹ǷΠ// ¿©±â¼­ waiting À» ÇÒ ¼ö ÀÖÀ½. (doDmc_CheckCancel() polling Çϸ鼭..) // ±×·¯³ª ÀÌ ¹æ¹ýÀº audio start°¡ ´Ê¾îÁø´Ù´Â ´ÜÁ¡ÀÌ ÀÖ´Ù. // // ÀÌ¿¡ ´ëÇÑ ¶Ç ´Ù¸¥ ¹æ¾ÈÀº ¿©±â¼­´Â ±×³É ÁøÇà Çϰí audio start¸¦ Çϸç, // ³ªÁß¿¡ seq hdr change callbackÀÌ ºÒ¸®¸é ±× ¶§ arc Àû¿ëÀ» ÇÏ´Â °ÍÀÌ´Ù. // ±×·¯¸é ¾Æ·¡¿¡ formatchange Á¤º¸´Â ´çºÐ°£Àº ¾ûÅ͸®°¡ µÉ ¼ö ÀÖ´Ù. #endif if (dhlResult) { dprint(0, "!! DHL_AV_VideoStart err 0x%x\n", dhlResult); // cafrii 050723 add // ¸¸¾à video context »ý¼ºÀÌ scrambledError°¡ ¾Æ´Ñ ´Ù¸¥ ¿¡·¯°¡ ¹ß»ýÇß´Ù¸é // video´Â ±×³É µÎ°í audio·Î °è¼Ó ÁøÇàÇÑ´Ù. if (dhlResult == DHL_WARN_SCRAMBLED) { // audio µµ Ʋ¸²¾øÀÌ scramble µÇ¾ú´Ù°í °¡Á¤ÇÏ°í ±×³É Á¾·áÇÑ´Ù. // cafrii 060711 change // video scramble ÀÌ´õ¶óµµ audio ÁøÇàÇϵµ·Ï ÇÑ´Ù. // ¶ÇÇÑ air channelÀÇ °æ¿ì video scrambleÀº À߸øµÈ °ÍÀ̹ǷΠinvalid PES¿Í ´Ù¸¦ ¹Ù ¾ø´Ù. //return statusScrambled; } if (dhlResult == DHL_FAIL_CANCELLED_BY_USER) { return statusCancelled; } if (dhlResult) { //return err; // audio pid°¡ 0ÀÌ¸é ¿¡·¯¸¦ ¸®ÅÏÇØ¾ß ÇÑ´Ù. if (uAudPID == 0) { dprint(0, "!! video only program, but video invalid.\n"); return statusVideoError; } bVideoStarted = FALSE; // uVidPID´Â validÇÏÁö¸¸ ¹®Á¦°¡ À־ video µðÄÚµù ½ÇÆÐ.. goto process_audio; } } bVideoStarted = TRUE; dprint(2, "\tDHL_AV_VideoStart OK\n"); #if DMC_DELAYED_VIDEO_SHOW // ±×³É ¿©±â¼­´Â ±âÁ¸ seq hdr Á¤º¸¸¸ reset À» Çϰí // ³ªÁß¿¡ seq hdr change callback ÀÌ ¿À¸é ±× ¶§ ARC Àû¿ë ¹× temp blank unhide¸¦ ÇÑ´Ù. { ProgramAVInfo *av = Dmc_LockAVMutex(); av->seq_hdr_valid = FALSE; Dmc_UnlockAVMutex(); } #else bVideoFormatChanged = FALSE; // °¡Àå ¸¶Áö¸·¿¡ ÀúÀåµÈ Sequence Header¿Í ÇöÀç seq¿Í ºñ±³Çؼ­ // º¯°æµÈ »çÇ×ÀÌ ÀÖÀ» °æ¿ì¿¡¸¸ Àû¿ëÇÑ´Ù. // bVideoFormatChanged = doDmc_CheckIfFormatChanged(); // Note! // ÃÖÃÊ Tuning½Ã¿¡´Â dmc_SeqHdrÀÇ °ªµéÀÌ ¸ðµÎ 0ÀÏ °ÍÀ̹ǷΠ// óÀ½ 1ȸ format change´Â ²À ºÒ¸®°Ô µÈ´Ù. (¼³·É ÇöÀç timingÀÌ ÀûÀýÇÑ °ÍÀ̶óÇØµµ..) // ÀÌ¹Ì ¼³Á¤ÇØ µÐ timing°ú ºñ±³ÇØ ºÁ¼­ º¯°æÇÒ Çʿ䰡 ¾øÀ» ¼öµµ Àִµ¥, // À̶§´Â application¿¡¼­ Dmc_InitDisplay¿¡¼­ ¼³Á¤ÇÑ °ª°ú ºñ±³Çؼ­ // skip ÇÏ°Ô ÇÒ ¼öµµ ÀÖÀ» °ÍÀÌ´Ù. // MW´Â ¹«Á¶°Ç notify¸¦ ÇØÁØ´Ù. if (bVideoFormatChanged == FALSE) dprint(2, "\t source format not changed\n"); else dprint(2, "\t source format changed\n"); // »ç¿ëÀÚ ¼³Á¤°ªÀÌ ÀÖ´Â °æ¿ì, Adjustment, Sidebar, WinRect µîÀ» ¹Ì¸® ¼³Á¤Çسõ´Â´Ù. // ³ªÁß¿¡ Display startÇÒ ¶§ Àû¿ëµÇµµ·Ï.. // if (bVideoFormatChanged) doDmc_ProcessScreenAdjustment(); #if 0 // NEW_DHL_API dhlResult = DHL_AV_DispStart(NULL); if (dhlResult) dprint(0, "!! DHL_AV_DispStart err 0x%x\n", dhlResult); #endif #if 0 // hide Ǫ´Â ½ÃÁ¡Àº µÚ¿¡.. if (dmc_bRequestVideoHide) { DHL_AV_VideoHide(0, TRUE); } else { // show // ÀÌ ºÎºÐÀÇ Äڵ带 ½ÇÇàÇÏ¸é ºñµð¿À°¡ ±úÁö´Â ¹®Á¦ ¹ß»ý. // todo // video stop½Ã¿¡ hide µÈ °ÍÀ̶ó¸é Ç®¾îÁÖÁö ¾Ê¾Æ¼­ ¹®Á¦°¡ »ý±âÁö ¾Ê´Â°¡? // ±×·² °æ¿ì DHL¿¡¼­ °ü¸®ÇØÁà¾ß ÇÔ. #if 0 DHL_AV_VideoHide(FALSE); #endif } #endif #endif // DMC_DELAYED_VIDEO_SHOW if (1) { ProgramAVInfo *av = Dmc_LockAVMutex(); av->video_hidden = (dmc_bRequestVideoHide & DMC_VIDEO_HIDE_USER) ? TRUE : FALSE; Dmc_UnlockAVMutex(); } #if USE_PERF_MON DHL_PerfMonCheck(gDmcPMTune, PM_EV_TUNE_VIDEO_START, 1); #endif process_audio: if (uAudPID == 0) { dprint(2, "\t null audio pid. skip..\n"); goto label_end; } if (dmc_bRunWithoutAudio) { dprint(0, "skip audio by flag.\n"); goto label_end; } dhlResult = DHL_CAP_ChangeAudioSource(eDHL_CAP_DTV_TS0_AUDIO); if (dhlResult) { dprint(0, "!! DHL_CAP_ChangeAudioSource err\n"); // do nothing.. just go! dhlResult = DHL_OK; } #if USE_PERF_MON DHL_PerfMonCheck(gDmcPMTune, PM_EV_TUNE_AUDIO_START, 0); #endif // ------- audio route setting ------------ dhlResult = DHL_CAP_ChangeAudioSource(eDHL_CAP_DTV_TS0_AUDIO); if (dhlResult) { dprint(0, "!! DHL_CAP_ChangeAudioSource err\n"); // do nothing.. just go! dhlResult = DHL_OK; } // ------- audio processing ------------ dmc_bWaitFirstFreezeVideoEndEvent = TRUE; // 030918 cafrii // audio¸¦ ¼¼ÆÃÇÏ´Â ¼ø°£ pop noise°¡ ¹ß»ýÇÒ ¼ö À־ // º¸Åë Audio ½ÃÀÛ Àü¿¡ mute¸¦ ÇÑ´Ù. // mute¸¦ offÇÏ´Â ½ÃÁ¡Àº video°¡ ³ª¿À±â ½ÃÀÛÇÏ´Â ½ÃÁ¡ÀÌ // Àû´çÇϹǷΠÀÌ ¼ø°£¿¡ freeze video end¸¦ ±â´Ù¸®´Â flag¸¦ Ãß°¡ÇÑ´Ù. // // freeze_end °¡ ³Ê¹« »¡¸® ³ª¿Í¹ö·È´Ù¸é ¾ÕÀ¸·Î ¿µ¿øÈ÷ audio°¡ ³ª¿ÀÁö ¾Ê´Â ¹®Á¦°¡ »ý±æ¼ö°¡ Àִµ¥, // ¾ÆÁ÷ Àû´çÇÑ ÇØ°á ¹æ¹ýÀº ¾ø´Ù. // --> freeze_end °¡ ¾Æ¹«¸® »¡¸® ³ª¿À´õ¶óµµ DMC task¿¡¼­ freeze end¸¦ ó¸®ÇϹǷΠ// ÀÌ ÇÔ¼ö°¡ ³¡³ª±â Àü±îÁö´Â freeze end°¡ 󸮵ÇÁö ¾Ê´Â´Ù. ¹®Á¦ ¾øÀ½. // // ¶ÇÇÑ Audio only channelÀÌ ÀÖÀ»¼ö ÀÖÀ¸¹Ç·Î video°¡ ¾øÀ» °æ¿ì¿¡´Â audio mute¸¦ // ¹Ù·Î ²¨¾ß¸¸ ÇÑ´Ù. memset(&adsp, 0, sizeof(AudioDecodeStartParam)); adsp.result = statusNotImpl; // my default. adsp.audPid = uAudPID; adsp.pcrPid = uPcrPID; adsp.audType = atype; //adsp.mode = MOCHA_ATSC_INPUT; // cafrii 031117 add doDmc_Notify(DMW_NOTIFY_AudioDecodeStart, (UINT32) &adsp); if (adsp.result == statusNotImpl) { tDHL_AudioCodingType dhlAudType; if (dmc_bAudioVideoSyncStart) { dprint(2, "\tAudio muted for sync start\n"); doDmc_AudioTempMute(TRUE); DMW_SYS_SetTimer(TIMER_ID_AUDIO_TEMPMUTE_LIMIT, g_AudioTempMuteLimitMs, doDmc_AudioTempMuteLimitTimerProc, 0, TRUE); } #if 0 // todo // ÇöÀç DD HAL¿¡¼­ Áö¿øÇÏ´Â audio typeÀÌ ¸î°³ ¾ÈµÈ´Ù. // driver¿¡¼­´Â tDHL_AudioCodingType Á¾·ù°¡ »ó´çÈ÷ ¸¹´Ù. (¹°·Ð ¸ðµÎ ´Ù Áö¿øÇϴ°ÍÀº ¾Æ´Ô) // // arzhna, 100315 // audio type°ú stream typeÀ» ±¸ºÐÇØ¾ßÇÔ, // DHL_AV_AudioStart ¿¡¼­ ÇÊ¿äÇÑ ÀÎÀÚ´Â audiotype #define eDHL_AUDIO_TYPE_2_DHLAUDIOTYPE(a) ( \ (a) == eDHL_AUDIO_TYPE_AC3 ? eDHL_AUDIO_TYPE_AC3 : \ (a) == eDHL_AUDIO_TYPE_MPEG_1 ? eDHL_AUDIO_TYPE_MPEG_1 : \ (a) == eDHL_AUDIO_TYPE_MPEG_2 ? eDHL_AUDIO_TYPE_MPEG_2 : \ (a) == eDHL_AUDIO_TYPE_AAC ? eDHL_AUDIO_TYPE_AAC : \ eDHL_AUDIO_TYPE_AC3) // cafrii 070718, use 'atype' argument dhlAudType = eDHL_AUDIO_TYPE_2_DHLAUDIOTYPE(atype); #else dhlAudType = atype; #endif dprint(2, "\t audio start, a 0x%x p 0x%x, at %d\n", uAudPID, uPcrPID, dhlAudType); #if 1 // NEW_DHL_API dhlResult = DHL_AV_AudioStart(uAudPID, uPcrPID, dhlAudType); if (dhlResult) dprint(0, "!! audio start err 0x%x\n", dhlResult); #else // cafrii 060711 add audio start check if (dmc_bUseAudioStartWait == 0) dhlResult = DHL_AV_AudioStart(uAudPID, uPcrPID, dhlAudType); else { dhlResult = DHL_AV_AudioStartWait(uAudPID, uPcrPID, dhlAudType, doDmc_CheckCancel); // cafrii 060808 add, bugfix! if (dhlResult == DHL_FAIL_CANCELLED_BY_USER) { if (bVideoStarted) { #if 0 // NEW_DHL_API DHL_AV_DispStop(); #endif // zooyouny 100629 : tDHL_VDID´Â ÀÏ´Ü 0À¸·Î ó¸®, ¹®Á¦ µÉ ¼ö ÀÖÀ½ DHL_AV_VideoStop(0); } return statusCancelled; } if (dhlResult) { dprint(0, "!! audio start err 0x%x\n", dhlResult); // video ¸¶Àú ¾ø´Ù¸é ÀÌ´Â ¿¡·¯ÀÌ´Ù. if (bVideoStarted == FALSE) return statusError; } } #endif // tDHL_AudioCodingType °ú DHL_AUD_STREAMTYPE ±¸ºÐ.. if (dmc_bAudioVideoSyncStart) { // sync start¸¦ À§Çؼ­´Â ¿©±â¼­ unmute¸¦ ÇÏÁö ¾Ê°í // video first freeze end°¡ ¿ÔÀ»¶§ Ç®¾îÁÖµµ·Ï ÇÑ´Ù. // if (bVideoStarted) { dprint(2, "\tAV SyncStart mode.. AudioTmpMute off deferred later..\n"); } else { dprint(2, "\tAV SyncStart mode, but no video.. Clear AudioTmpMute..\n"); dmc_bWaitFirstFreezeVideoEndEvent = FALSE; // ¿©±â¼­ ¹Ù·Î ó¸®ÇϹǷΠwaitÇÏÁö ¾Ê´Â´Ù. doDmc_AudioTempMute(FALSE); } } } else if (adsp.result == statusOK) { } else { dprint(0, "!! AudioDecodeStart err %d\n", adsp.result); if (bVideoStarted == FALSE) return adsp.result; } #if USE_PERF_MON DHL_PerfMonCheck(gDmcPMTune, PM_EV_TUNE_AUDIO_START, 1); #endif label_end: // ÇöÀç ÀÌ ÇÔ¼ö¿¡¼­´Â program number¸¦ ¾Ë ¼ö ¾ø´Ù. // 1394 Áö¿øÇÏÁö ¾ÊÀ½. //if (_Dmc_DecodeStartCallback) // _Dmc_DecodeStartCallback(dmc_program->program_number, FALSE); return statusOK; } STATUS doDmc_StartAnalog(CaptureParam *pCapParam) { // Analog Video context¸¦ »ý¼ºÇÏ°í °ü·ÃµÈ audio¸¦ ó¸®ÇÑ´Ù. // TS°¡ ¾Æ´Ñ uncompressed video(656 format)Àº ¸ðµÎ analog video context·Î 󸮵ȴÙ. // NTSC, External Video, DV µîÀÌ ¸ðµÎ ÀÌ °æ¿ì¿¡ ÇØ´çÇÑ´Ù. DHL_RESULT dhlResult; AudioDecodeStartParam adsp; ProgramAVInfo *av; STATUS status = statusOK; if (!Dmc_IsDmcTask()) { dprint(0, "!! doDmc_StartAnalog() should be called only in DmcTask.\n"); return statusInvalidState; } av = Dmc_LockAVMutex(); if (av->active) { // ±âº» ¹æÄ§À» StartDigital, StartAnalog Çϱâ Àü¿¡ caller¿¡¼­ // ÀÌÀü video¸¦ stop ½ÃŰ´Â °ÍÀ¸·Î Á¤ÇÔ. // dprint(1, "!! Warning! stop video before tuning new channel!\n"); doDmc_Stop(); // no delete task } // cafrii 070413 add // audio¸¸ capture ½ÃÀÛÇϴ Ư¼ö ¸ðµå Áö¿ø. if (pCapParam->input_video == eDHL_CAP_VIDEO_NONE) { dprint(2, " audio capture only\n"); goto label_audio; } // ------- process video ------------ #if USE_PERF_MON DHL_PerfMonCheck(gDmcPMTune, PM_EV_TUNE_VIDEO_START, 0); #endif dhlResult = DHL_CAP_ChangeVideoSource(0, pCapParam->input_video); if (dhlResult) dprint(0, "!! DHL_CAP_ChangeVideoSource err 0x%x\n", dhlResult); dhlResult = DHL_CAP_VideoStart(0); if (dhlResult) { dprint(0, "!! DHL_CAP_VideoStart err 0x%x\n", dhlResult); status = statusVideoError; goto label_end; // cafrii 060714 bugfix! } // bVideoFormatChanged = doDmc_CheckIfFormatChanged(); // cafrii 060609 add doDmc_ProcessScreenAdjustment(); dhlResult = DHL_CAP_DispStart(); if (dhlResult) { dprint(0, "!! DHL_CAP_DispStart err 0x%x\n", dhlResult); status = statusVideoError; goto label_end; // cafrii 060714 bugfix! } if (dmc_bRequestVideoHide) { DHL_AV_VideoHide(0, TRUE); } else { // show DHL_AV_VideoHide(0, FALSE); } av->video_hidden = dmc_bRequestVideoHide ? TRUE : FALSE; #if USE_PERF_MON DHL_PerfMonCheck(gDmcPMTune, PM_EV_TUNE_VIDEO_START, 1); #endif // ------- process audio ------------ label_audio: #if USE_PERF_MON DHL_PerfMonCheck(gDmcPMTune, PM_EV_TUNE_AUDIO_START, 0); #endif dhlResult = DHL_CAP_ChangeAudioSource(pCapParam->input_audio); if (dhlResult) dprint(0, "!! DHL_CAP_ChangeAudioSource err 0x%x\n", dhlResult); if (dmc_bRunWithoutAudio == 0) { // Âü°í·Î AnalogÀÇ °æ¿ì¿¡´Â AVSyncStart´Â Áö¿øÇÏÁö ¾Ê´Â´Ù. // //dmc_bWaitFirstFreezeVideoEndEvent = FALSE; // do not wait FreezeVideoEnd event. // cafrii 070102, analogµµ freeze end event ÇÊ¿äÇÔ. dmc_bWaitFirstFreezeVideoEndEvent = TRUE; memset(&adsp, 0, sizeof(AudioDecodeStartParam)); adsp.result = statusNotImpl; // my default. //adsp.mode = MOCHA_NTSC_INPUT; doDmc_Notify(DMW_NOTIFY_AudioDecodeStart, (UINT32) &adsp); if (adsp.result == statusNotImpl) { dhlResult = DHL_CAP_AudioStart(); if (dhlResult) dprint(0, "!! DHL_CAP_AudioStart err 0x%x\n", dhlResult); } else if (adsp.result == statusOK) { } else { dprint(0, "!! AudioDecodeStart err %d\n", adsp.result); return adsp.result; // Àüü Æ©´× ¿¡·¯·Î ¸®ÅÏÇÑ´Ù. ÁÖÀÇ!! } } #if USE_PERF_MON DHL_PerfMonCheck(gDmcPMTune, PM_EV_TUNE_AUDIO_START, 1); #endif label_end: Dmc_UnlockAVMutex(); return status; } #if COMMENT _______________(){} #endif #if 0 DMC_VIDEO_CACHE doDmc_LoadVideoCache(int rf, int program_number, int video_pid, int pcr_pid) { DMC_VIDEO_CACHE cache; cache = DHL_AV_LoadVideoFromCache(rf, program_number, video_pid, pcr_pid); return cache; } doDmc_SaveVideoCache() { } #endif #if COMMENT _______________(){} #endif #if !USE_EPG_MW_PSI_DOWNLOAD //----------------------------------------------------------- // PSI Monitor Control °ü¸® // ä³Î Æ©´×ÀÌ ³¡³ª¸é DMC´Â PSI ¸ð´ÏÅ͸¦ °¡µ¿½ÃÄѼ­ PSI Change¿¡ ´ëºñÇϰԲû ÇÑ´Ù. // À̰Ͷ§¹®¿¡ ´Ù¸¥ °÷¿¡¼­ PSI TableÀ» ¹ÞÀ¸·Á°í ÇØµµ timeout ¿¡·¯°¡ ¹ß»ýÇÑ´Ù. // // ÀÌ¿¡ ´ëÇÑ ÇØ°áÃ¥À¸·Î´Â // (1) TableÀ» »õ·Î ¹Þ´Â ´ë½Å DMC°¡ °ü¸®Çϰí ÀÖ´Â PSI tableÀ» lock »óÅ¿¡¼­ ÀÌ¿ëÇϰųª, // (2) Psi monitor¸¦ ÀϽà ÁßÁö½ÃÄѳõ°í ´Ù¿î·Îµå ÇÑ´ÙÀ½ ´Ù½Ã resume½ÃŰ´Â ¹æ¹ýÀ» »ç¿ëÇÑ´Ù. // STATUS Dmc_PausePsiMonitor(UINT32 bPause) { DHL_RESULT err = DHL_OK; ProgramAVInfo *av; if (!Dmc_IsDmcTask()) { dprint(2, "Dmc_PausePsiMonitor(%d)\n", bPause); return Dmc_EnqueueDPC((DMC_FN_DPC)Dmc_PausePsiMonitor, bPause, 0, 0, 0, TRUE); } dprint(1, "cmdPausePsiMonitor(%d):\n", bPause); av = Dmc_LockAVMutex(); if (bPause) // Pause { #if USE_CH_MW_ALL_PMT_DOWNLOAD dprint(2, "\t pause current PsiCtl monitor (pat 0x%08x pmt1 0x%08x pmt2 0x%08x)..\n", av->patPsiCtl, av->pmtPsiCtl, av->pmtPsiCtl2); #else dprint(2, "\tPause current PsiCtl monitor (pat 0x%08x, pmt 0x%08x)..\n", av->patPsiCtl, av->pmtPsiCtl); #endif #if USE_CH_MW_ALL_PMT_DOWNLOAD DHL_PSI_StopMonitor(av->pmtPsiCtl2); av->pmtPsiCtl2 = (tDHL_PSI_ControlHandle)0; #endif DHL_PSI_StopMonitor(av->pmtPsiCtl); av->pmtPsiCtl = (tDHL_PSI_ControlHandle)0; DHL_PSI_StopMonitor(av->patPsiCtl); av->patPsiCtl = (tDHL_PSI_ControlHandle)0; // Queue¿¡ ³²¾ÆÀÖ´Â PAT/PMT Change event´Â ºñ¿ö¾ß Çϴ°¡? // --> ³ªÁß¿¡ pat/pmt handler¿¡¼­ PsiCtlÀÌ NULLÀÎÁö¸¦ üũ¸¦ Çϱ⠶§¹®¿¡ // ±×·² ÇÊ¿ä´Â ¾ø´Ù. } else { // ÇöÀç ¸ð´ÏÅ͸µÀÌ °¡µ¿ÁßÀÌ¸é ¾Æ¹«Àϵµ ÇÏÁö ¾Ê´Â´Ù. if (av->patPsiCtl == 0) { dprint(2, "\tPAT monitor resume..\n"); if (av->pat == NULL || av->pmt == NULL) { dprint(2, " Psi Not prepared (pat %x, pmt %x).. wait first pmt..\n", av->pat, av->pmt); } err = MonitorPAT(Dmc_GetCurrentTsd(), TRUE, // Ç×»ó current PAT¸¸ ¹Þ´Â´Ù!! FALSE, // not eager dmc_PatUpdateMode, _Dmc_PatEventProc, 0, &av->patPsiCtl); if (err) dprint(0, "!! MonitorPAT returned %s\n", ErrorString(err)); } // PMT Monitor´Â PAT°¡ ¼ö½ÅµÈ ÀÌÈÄ¿¡, ±× ½ÃÁ¡¿¡¼­ µ¿ÀÛÁßÀÎ VideoÀÇ program number¸¦ // ÀÌ¿ëÇØ PMT¸¦ ¼±ÅÃÇÑ ´ÙÀ½ ½ÃÀÛÇÑ´Ù. } Dmc_UnlockAVMutex(); return err ? statusError : statusOK; } #endif // !USE_EPG_MW_PSI_DOWNLOAD STATUS Dmc_InitAVResources(void) { dmc_psiSema4 = DHL_OS_CreateMutexSemaphore("DmcPsi"); if (dmc_psiSema4 == 0) { dprint(0, "!! create psi sema4 failed"); return statusOutOfResource; } dmc_avSema4 = DHL_OS_CreateMutexSemaphore("DmcAV"); if (dmc_avSema4 == 0) { dprint(0, "!! create av sema4 failed"); return statusOutOfResource; } DHL_AV_SetCallback(eDHL_CB_VideoSeqHdr, _Dmc_CommonAVCallback); DHL_AV_SetCallback(eDHL_CB_FirstVideoShow, _Dmc_CommonAVCallback); return statusOK; } // Dmc_RegisterDecodeStartCallback // Decode start callback Çڵ鷯¸¦ µî·Ï/ÇØÁ¦ÇÑ´Ù. // µðÄÚµùÀÌ ½ÃÀÛµÉ ¶§ (StartDigital ÀÌÈÄ) ¸¶´Ù ÀÌ Çڵ鷯°¡ È£ÃâµÈ´Ù. // ÁÖ·Î Partial stream Ãâ·ÂÀ» À§Çؼ­ »ç¿ëµÈ´Ù. // ÀÌÀü¿¡ µî·ÏµÇ¾î ÀÖ´Â handler°¡ ¸®ÅϵǹǷΠcallback chainingÀ» ÇÒ¼ö ÀÖ´Ù. // DMC_FN_NOTIFY Dmc_RegisterDecodeStartCallback(DMC_FN_NOTIFY callback) { // return previously registerred callback pointers. // so that notification chaining is possible. DMC_FN_NOTIFY fnPrevCallback; fnPrevCallback = _Dmc_DecodeStartCallback; _Dmc_DecodeStartCallback = callback; if (callback) dprint(1, "DecodeStart callback %x registerred\n", callback); else dprint(1, "DecodeStart callback unregistered\n"); return fnPrevCallback; } // Dmc_RegisterDecodeStopCallback // Decode stop callback Çڵ鷯¸¦ µî·Ï/ÇØÁ¦ÇÑ´Ù. // µðÄÚµùÀÌ ³¡³¯ ¶§ È£ÃâµÈ´Ù. // DMC_FN_NOTIFY Dmc_RegisterDecodeStopCallback(DMC_FN_NOTIFY callback) { // return previously registerred callback pointers. // so that notification chaining is possible. DMC_FN_NOTIFY fnPrevCallback; fnPrevCallback = _Dmc_DecodeStopCallback; _Dmc_DecodeStopCallback = callback; if (callback) dprint(1, "DecodeStop callback %x registerred\n", callback); else dprint(1, "DecodeStop callback unregistered\n"); return fnPrevCallback; } // Dmc_RegisterNotificationCallback // Notification callbackÀ» µî·Ï/ÇØÁ¦ÇÑ´Ù. // DMC¿¡¼­ ÀϾ´Â ¿©·¯°¡Áö À¯¿ëÇÑ Á¤º¸¸¦ Notification À» ÅëÇØ¼­ // ¾Ë·ÁÁֱ⠶§¹®¿¡ °¡´ÉÇϸé ÀÌ ±â´ÉÀ» »ç¿ëÇÏ´Â°Ô ÁÁ´Ù. // DMC_FN_NOTIFY Dmc_RegisterNotificationCallback(DMC_FN_NOTIFY callback) { // return previously registerred callback pointers, // so that notification chaining is possible. DMC_FN_NOTIFY fnPrevCallback; fnPrevCallback = _Dmc_Notify; _Dmc_Notify = callback; if (callback) dprint(1, "Notification callback %x registerred.\n", callback); else dprint(1, "Notification callback unregistered.\n"); return fnPrevCallback; } /* neverdai 101019 add. autoscan ½Ã callbackÀ» ¹Þ¾Æ¼­ ºñµð¿À È­¸é¿¡ º¸ÀÌ´Â ¹®Á¦°¡ ÀÖÀ½ scanÇÒ ¶§´Â callbackÀ» ¹ÞÁö ¾Êµµ·Ï º¯°æÇÏ´Â °ÍÀÌ ÁÁÀ» µíÇÔ. */ void DMC_RegisterVideoCallback(BOOL bset) { if(bset) { DHL_AV_SetCallback(eDHL_CB_VideoSeqHdr, _Dmc_CommonAVCallback); DHL_AV_SetCallback(eDHL_CB_FirstVideoShow, _Dmc_CommonAVCallback); } else { DHL_AV_SetCallback(eDHL_CB_VideoSeqHdr, NULL); DHL_AV_SetCallback(eDHL_CB_FirstVideoShow, NULL); } } // cafrii 060724 add void Dmc_PrintAVInfo(int level) { ProgramAVInfo *av = Dmc_LockAVMutex(); dprint(level, " active %d, analog %d, input video %d/audio %d\n", av->active, av->analog, av->input_video, av->input_audio); dprint(level, " rf %d, mod %d (%s), tune method %d (%s)\n", av->rf, av->mod, ServiceTypeString(av->mod), av->method, TuneMethodString(av->method)); dprint(level, " major %d, minor %d, #%d, pid pva %x/%x/%x\n", av->major, av->minor, av->program_number, av->pcr_pid, av->video_pid, av->audio_pid); dprint(level, " freezed %d, hidden %d\n", av->video_freezed, av->video_hidden); dprint(level, " pat 0x%x, pmt 0x%x, psictl pat %x, pmt %x\n", av->pat, av->pmt, av->patPsiCtl, av->pmtPsiCtl); // pmtlist Á¤º¸¸¦ º¸°í ½Í´Ù¸é Dmc_PrintProgramInfo ¸¦ »ç¿ëÇÒ °Í!! Dmc_UnlockAVMutex(); } #if COMMENT ________(){} #endif #if DMW_REGISTER_DEBUG_SYMBOL static DHL_SymbolTable symbols[] = { //---- functions DHL_FNC_SYM_ENTRY(Dmc_PrintAVInfo), //---- vars DHL_VAR_SYM_ENTRY(dmc_bRunWithoutAudio), DHL_VAR_SYM_ENTRY(dmc_bRunWithoutVideo), DHL_VAR_SYM_ENTRY(dmc_bRequestVideoHide), DHL_VAR_SYM_ENTRY(g_Trace_bDmcPsiEvent), //DHL_VAR_SYM_ENTRY(dmc_bUseAudioStartWait), }; #endif void RegisterChannelAVSymbols(void) { #if DMW_REGISTER_DEBUG_SYMBOL DHL_DBG_RegisterSymbols(symbols, DHL_NUMSYMBOLS(symbols)); #endif }