/* DMW_ChannelUtil.c */ #include "DMW_Platform.h" #include "DHL_SYS.h" #include "DHL_AVCAP.h" #include "DHL_DBG.h" #include "DMW_Config.h" #include "DMW_Channel.h" #include "dmw_channel_priv.h" #include "DMW_ChannelUtil.h" #include "DMW_Status.h" #include "DMW_DebugUtil.h" //#include //#include DHL_MODULE("$dmc", 1); #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) // cafrii 100705 // »õ·Î¿î DHL API ÀÎÅÍÆäÀ̽º¿¡ µû¸¥ º¯°æ // #define NEW_DHL_API 1 #if COMMENT ______UserMsgQueue______(){} #endif #include "../System/DMW_MsgQue.h" DMW_MSGQUE g_DmcMsgQue = { NULL, // msg pool buffer. should be NULL. 0, //sizeof(DmcMessage), // sizeof each message 0, //MAX_DECODE_MESSAGES, // que size 0, // current number of messages 0, // mutex 0, // semaphore NULL, // pfn name }; char *dmc_cmd_name(DmcMessage *pmsg) { return Dmc_MsgString(pmsg->type); } STATUS doDmc_InitUserMsgQue(int nSizeOfMsg, int nMaxNumMsgInQue) { if (nSizeOfMsg == 0 || nMaxNumMsgInQue == 0) { return statusInvalidArgument; } return DMW_SYS_InitMsgQue(&g_DmcMsgQue, nSizeOfMsg, nMaxNumMsgInQue, (DMW_FN_MSG_NAME) dmc_cmd_name); } void doDmc_DeleteUserMsgQue(void) { // todo.. // ¸®¼Ò½º¸¦ »èÁ¦ÇÒ ¼ö ÀÖ´Â API? } STATUS doDmc_AddUserMsg(DmcMessage *pmsg) { return DMW_SYS_AddUserMsg(&g_DmcMsgQue, pmsg); } STATUS doDmc_GetUserMsg(DmcMessage *pmsg, UINT32 timeout) { return DMW_SYS_GetUserMsg(&g_DmcMsgQue, pmsg, timeout); } BOOL doDmc_UserMsgExist() { return DMW_SYS_UserMsgExist(&g_DmcMsgQue); } BOOL dmc_cmd_is_event(DmcMessage *pmsg, UINT32 param) { if (pmsg && !Dmc_IsCommand(pmsg->type)) return TRUE; // this is event.. return FALSE; } // cafrii 060831 add void dmc_cmd_delete_event(DmcMessage *pmsg) { // ¾îÂ¥ÇÇ event¶ó¸é status report¸¦ ÇÏÁö ¾ÊÀ» °ÍÀ̹ǷΠ¾î¶² °ªÀ» ÁöÁ¤Çصµ ¹«°ü. // Dmc_DeleteDmcMessage(pmsg, statusCancelled); } void doDmc_DeleteAllEventMsg() { DMW_SYS_DeleteMsgConditionally(&g_DmcMsgQue, (DMW_FN_MSG_CHECK) dmc_cmd_is_event, 0, (DMW_FN_MSG_DELETE) dmc_cmd_delete_event); } BOOL dmc_cmd_is_matched(DmcMessage *pmsg, UINT32 param) { if (pmsg && pmsg->type == (DmcMsgType) param) return TRUE; return FALSE; } void doDmc_DeleteMsg(DmcMsgType msgtype) { DMW_SYS_DeleteMsgConditionally(&g_DmcMsgQue, (DMW_FN_MSG_CHECK) dmc_cmd_is_matched, msgtype, (DMW_FN_MSG_DELETE) dmc_cmd_delete_event); } BOOL doDmc_CheckMsgExist(DmcMsgType msgtype) { return DMW_SYS_CheckSpecificMsgExist(&g_DmcMsgQue, (DMW_FN_MSG_CHECK) dmc_cmd_is_matched, msgtype); } char *dmc_cmd_cid_name(DmcMessage *pmsg) { static char buf[10]; sprintf(buf, "%d", pmsg->cancelId); return buf; } void doDmc_PrintUserMsgs() { DMW_SYS_PrintUserMsgs(&g_DmcMsgQue, (DMW_FN_MSG_NAME) dmc_cmd_cid_name); } #if COMMENT _____CancelQue______(){} #endif //--------------------------------------------------------------- // Command cancel °ü·Ã.. // #define NUM_CANCEL_ID 10000000 // cancel ID ¹øÈ£ ¸Å±èÀ» ÇÒ¶§ »ç¿ëµÇ´Â ¹üÀ§. 0 ~ NUM_CANCEL_ID-1 // cafrii 030701 // I increase this value upto 1000 times larger. // There was bugs about event cancel. this number is not the reason of error, // but this fix will minimize occurence of overwrap. // If events occurs at every seconds, this number correspond to 115 days. int dmc_lastCancelId = -1; int dmc_currentCancelId = -1; // -1 means not-initialized. // normal range is 0 ~ MAX_CANCEL_ID-1 #define NEXT_CANCEL_ID(c, step) (((c) + (step)) % NUM_CANCEL_ID) // // »ç¿ë °¡´ÉÇÑ cancel ID range ³»¿¡¼­ step °¹¼ö¸¸Å­À» skipÇÑ ÈÄÀÇ ´ÙÀ½ cancel ID¸¦ // °è»êÇÏ´Â ¸ÅÅ©·Î. DHL_OS_MSGQ_ID dmc_cancelQ; int doDmc_GetLastCancelId() { return dmc_lastCancelId; } void doDmc_SetLastCancelId(int id) { dmc_lastCancelId = id; } int doDmc_GetNextCancelId(int c, int step) { return NEXT_CANCEL_ID(c, step); } int doDmc_GetNewCancelId() { // Cancel ID¸¦ Çϳª »õ·Ó°Ô ºÎ¿©ÇÏ´Â ÇÔ¼ö. // // Dmc Task·Î message¸¦ º¸³¾¶§¿¡´Â Ç×»ó cancel ID¸¦ Çϳª ºÎ¿© ¹Þ¾Æ °°ÀÌ ÇÔ²² º¸³½´Ù. // Dmc Task¿¡¼­´Â ÀÌ cancel ID¸¦ ÀÌ¿ëÇÏ¿© ¼ö½ÅµÈ message°¡ ÀÌ¹Ì cancel µÈ °ÍÀÎÁö ¾Ë¼ö ÀÖ´Ù. // // ÀÌ ÇÔ¼ö´Â DMC task¿¡¼­ callµÉ¼öµµ ÀÖ°í ÀÓÀÇÀÇ Å½ºÅ©¿¡¼­ call µÉ¼öµµ ÀÖ´Ù. int cancelId; if (1) { UINT32 mask = DHL_OS_DisableInterrupts(); dmc_currentCancelId = NEXT_CANCEL_ID (dmc_currentCancelId, 1); cancelId = dmc_currentCancelId; DHL_OS_RestoreInterrupts(mask); } return cancelId; } int doDmc_GetNewMultipleCancelIds(UINT32 count) { // Cancel ID¸¦ 'count' °¹¼ö¸¸Å­ ºÎ¿©ÇÏ´Â ÇÔ¼ö. // ÁغñÇÑ cancel ID´Â ÀϷùøÈ£À̸ç, ¸Ç óÀ½ cancel ID°ªÀ» ¸®ÅÏÇÑ´Ù. // caller´Â ¸®ÅϵǴ cancel IDÀÇ ½ÃÀÛºÎÅÍ ÃÑ 'count' °¹¼ö¸¸Å­ÀÇ ID¸¦ »ç¿ëÇÒ ¼ö ÀÖ´Ù. // // caller´Â DMC¿¡ º¸³¾ message¿¡ ±â·ÏÇÏ´Â cancel ID¿Í, cancel command¿¡ º¸³»´Â cancel ID¸¦ // ¿¬¼ÓµÈ °ªÀ¸·Î ¾ò±â¸¦ ¿øÇÑ´Ù. À̶§ ÀÌ ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù. // // ÀÌ ÇÔ¼ö´Â DMC task¿¡¼­ callµÉ¼öµµ ÀÖ°í ÀÓÀÇÀÇ Å½ºÅ©¿¡¼­ call µÉ¼öµµ ÀÖ´Ù. // count 0 is ignored. (set to 1 forcefully) // int cancelIdStart; if (count <= 1) return doDmc_GetNewCancelId(); if (1) { UINT32 mask = DHL_OS_DisableInterrupts(); cancelIdStart = NEXT_CANCEL_ID (dmc_currentCancelId, 1); dmc_currentCancelId = NEXT_CANCEL_ID (cancelIdStart, count-1); DHL_OS_RestoreInterrupts(mask); } return cancelIdStart; // cancelIdStart ºÎÅÍ ½ÃÀÛÇØ¼­ count °¹¼ö¸¸Å­ »ç¿ëÀÌ °¡´ÉÇÏ´Ù. } BOOL doDmc_IsCancelledMsg(int msgId) { int lastCancelId = dmc_lastCancelId; // µÎ ID°ªÀ» ºñ±³ÇÑ´Ù. // // lastCancelId: °¡Àå ¸¶Áö¸·À¸·Î ÀÔ·ÂµÈ cancel ID. // // msgId: ÇöÀç ¼ö½ÅµÈ ¸Þ½ÃÁöÀÇ ID if (abs(msgId - lastCancelId) > NUM_CANCEL_ID/2) { // ! it is wrapped state. // Á¤´çÇÑ ºñ±³¸¦ À§Çؼ­ ÀÛÀº °ª¿¡ NUM_CANCEL_ID¸¦ ´õÇÑ´Ù. // if (msgId < lastCancelId) msgId += NUM_CANCEL_ID; else lastCancelId += NUM_CANCEL_ID; } if (msgId <= lastCancelId) return TRUE; // cancelled!! else return FALSE; } /* return true if new cancel id is updated. */ BOOL doDmc_RefreshCancelQue() { // clear cancel queue. // °¡Àå ¸¶Áö¸· cancel_number¸¦ ¸®ÅÏÇÑ´Ù. // ¸¸¾à cancel queue°¡ ºñ¾îÀÖÀ¸¸é cancel_numÀº ¼Õ´ëÁö ¾Ê´Â´Ù. int rc; int msg, msgLen; BOOL bNewCancelRefreshed = FALSE; rc = DHL_OS_ReceiveMessage(dmc_cancelQ, (char *)&msg, 0); while (rc == DHL_OK) { doDmc_SetLastCancelId(msg); bNewCancelRefreshed = TRUE; //OS_Delay(1); rc = DHL_OS_ReceiveMessage(dmc_cancelQ, (char *)&msg, 0); } return bNewCancelRefreshed; } BOOL doDmc_CheckCancel() { int rc; int msg, msgLen; // 030613 // // cancel Q¿¡ ¸Þ½ÃÁö°¡ ÀÖ´Ù°í ÇØ¼­ ÇöÀç ¸Þ½ÃÁö°¡ cancelµÇ¾ú´Ù°í º¼¼ö´Â ¾ø´Ù. // ÀÌ cancel msgÀÇ cid°¡ ÇöÀç ¸Þ½ÃÁöÀÇ cidº¸´Ù ³ªÁßÀÇ °ªÀÎÁö ºñ±³ÇØ ºÁ¾ß ÇÏÁö ¾ÊÀ»±î? // // --> message¸¦ ¹ÞÀº Á÷ÈÄ¿¡ cancel üũ¸¦ Çѹø ÇÏ°Ô µÇ¾î Àִµ¥, // À̶§ OK¶ó¸é ±× ÀÌÈÄ¿¡´Â cancel QÀÇ emptyness ¸¸ üũÇÏ´Â °ÍÀ¸·Îµµ ÃæºÐÇÏ´Ù. // // ±×¸®°í cancel Q¸¦ ¿©±â¼­ empty·Î ¸¸µé ÇÊ¿ä´Â ¾ø´Ù. // ´ÙÀ½ message¸¦ ¹Þ±â Àü¿¡ ClearCancelQ¸¦ ºÒ·¯ û¼Ò¸¦ Çϱ⠶§¹®. // // Áï, ¾Æ·¡ ÄÚµå´Â ÀüÇô ¹®Á¦ ¾ø´Â ÄÚµåÀÓ. // // cafrii 041110 add comment // ´Ü¼øÈ÷ message queue¿¡¼­ msg°¡ ÀÖ´ÂÁöÀÇ ¿©ºÎ¸¸À¸·Î cancel üũ¸¦ ¼öÇàÇϱ⠶§¹®¿¡ // ÀÏ´Ü cancel msg¸¦ ¹Þ¾ÒÀ¸¸é ±× Á¤º¸¸¦ ¹«½ÃÇÏ¸é ¾ÈµÈ´Ù. // ´Ù½Ã ÀÌ ÇÔ¼ö¸¦ ¶Ç ºÎ¸£¸é ±×¶§´Â not_cancel À̶ó°í ¸®ÅÏÇÒ °ÍÀÌ´Ù. (msg que °¡ ºñ¾úÀ¸¹Ç·Î) // rc = DHL_OS_ReceiveMessage(dmc_cancelQ, (char *)&msg, 0); if (rc == 0) { dprint(1, "!! cancel requested. cid %d\n", msg); doDmc_SetLastCancelId(msg); return TRUE; // cancel message received. } else return FALSE; // something err or not canceled. } //----------------------------------------------------------- // STATUS Dmc_SendCancelCommand(int cancelId) { UINT32 msg; //msg = doDmc_GetNewCancelId(); msg = cancelId; dprint(3, "Send cancel command, cid %d\n", msg); if (dmc_cancelQ) { return (STATUS)DHL_OS_SendMessage(dmc_cancelQ, &msg, sizeof(msg)); } return statusOutOfResource; // no cancel Q?? } STATUS Dmc_InitCancelQue(int nSizeQue) { if (dmc_cancelQ) return statusOK; dmc_cancelQ = DHL_OS_CreateMessageQueue("DmcCancelQ", 0, nSizeQue, sizeof(UINT32)); return dmc_cancelQ ? statusOK : statusOutOfResource; } void Dmc_DeleteCancelQue(void) { DHL_OS_DeleteMessageQueue(dmc_cancelQ); dmc_cancelQ = 0; } #if COMMENT _______PSI_Util________(){} #endif BOOL Dmc_CheckIfSamePat(MPEG_PAT *pat1, MPEG_PAT *pat2) { #if 0 // for reference typedef struct MPEG_PAT_program { UINT16 program_number; UINT16 program_map_PID; } MPEG_PAT_program; typedef struct MPEG_PAT { UINT16 transport_stream_id; UINT8 version_number; BOOLEAN current_next_indicator; UINT8 section_number; UINT8 last_section_number; BOOLEAN isWholePAT; /* FALSE if only a singe section of a PAT */ UINT16 numPrograms; BOOLEAN networkPIDPresent; /* TRUE if network_pid is valid */ UINT16 network_PID; MPEG_PAT_program *programs; } MPEG_PAT; #endif int i; if (!pat1 || !pat2 || pat1->transport_stream_id != pat2->transport_stream_id || pat1->numPrograms != pat2->numPrograms) return FALSE; // todo.. // ¼ø¼­¸¸ ´Þ¶óÁø °æ¿ì´Â equivalent pat·Î º¼ ¼ö Àִµ¥ // ±×°Í¿¡ ´ëÇÑ Ã¼Å© ÇÊ¿ä. for (i=0; inumPrograms; i++) if (pat1->programs[i].program_number != pat2->programs[i].program_number || pat1->programs[i].program_map_PID != pat2->programs[i].program_map_PID) return FALSE; return TRUE; } BOOL Dmc_CheckIfSamePmt(MPEG_PMT *pmt1, MPEG_PMT *pmt2) { // µÎ PMT¸¦ ºñ±³Çؼ­ °°Àº °ÍÀÎÁö ¾Æ´ÑÁö ºñ±³ÇÑ´Ù. // todo.. // ÁÖ·Î PsiEventProc¿¡¼­ ºÒ¸± °ÍÀε¥, tDHL_PSI_DataArray¸¦ Á÷Á¢ ºñ±³ÇÏ´Â °ÍÀº ¾î¶³±î? // // °°À¸¸é TRUE¸¦ ¸®ÅÏÇÑ´Ù. // ¹öÀü ¹øÈ£ (CRCµµ?) ´Â ºñ±³ÇÏÁö ¾Ê´Â´Ù. int i; if (!pmt1 || !pmt2 || pmt1->PID != pmt2->PID || pmt1->program_number != pmt2->program_number || pmt1->PCR_PID != pmt2->PCR_PID || pmt1->descriptor_length != pmt2->descriptor_length || pmt1->numStreams != pmt2->numStreams) return FALSE; if (pmt1->descriptors && pmt2->descriptors && pmt1->descriptor_length > 0) { if (memcmp(pmt1->descriptors, pmt2->descriptors, pmt1->descriptor_length)) return FALSE; } for (i=0; inumStreams; i++) { MPEG_PMT_stream *st1 = &pmt1->streams[i], *st2 = &pmt2->streams[i]; if (st1->stream_type != st2->stream_type || st1->elementary_PID != st2->elementary_PID || st1->descriptor_length != st2->descriptor_length) return FALSE; if (st1->descriptors && st2->descriptors && st1->descriptor_length > 0 && memcmp(st1->descriptors, st2->descriptors, st1->descriptor_length)) return FALSE; } return TRUE; } // Dmc_CheckPmtDifference // µÎ°³ÀÇ PMT¸¦ ºñ±³ÇÑ´Ù. // µÎ PMT¸¦ ºñ±³ÇÑ °á°ú, ¼­·Î µ¿ÀÏÇÏÁö ¾ÊÀ¸¸é non-Zero¸¦ ¸®ÅÏ. // int Dmc_CheckPmtDifference(MPEG_PMT *pmt1, MPEG_PMT *pmt2) { MPEG_PMT_stream *str1, *str2; int i, errbase; // if invalid PMTs are passed to this function, return valus is meaningless. if (pmt1 == NULL || pmt2 == NULL) return 1; if (pmt1->PID != pmt2->PID) return 2; if (pmt1->program_number != pmt2->program_number) return 3; if (pmt1->PCR_PID != pmt2->PCR_PID) return 4; if (pmt1->descriptor_length != pmt2->descriptor_length) return 5; if (pmt1->descriptor_length && memcmp(pmt1->descriptors, pmt2->descriptors, pmt1->descriptor_length)) return 6; if (pmt1->numStreams != pmt2->numStreams) return 7; for (i=0; inumStreams; i++) { str1 = &(pmt1->streams[i]); str2 = &(pmt2->streams[i]); errbase = (i+1)*10; if (str1->stream_type != str2->stream_type) return errbase+1; if (str1->elementary_PID != str2->elementary_PID) return errbase+2; if (str1->descriptor_length != str2->descriptor_length) return errbase+3; if (str1->descriptor_length && memcmp(str1->descriptors, str2->descriptors, str1->descriptor_length)) return errbase+4; // videoStreamDescriptor is NULL if not present if ((str1->videoStreamDescriptor && !str2->videoStreamDescriptor) || (!str1->videoStreamDescriptor && str2->videoStreamDescriptor)) // if only one of the two is NULL return errbase+5; if (str1->videoStreamDescriptor && // if both are non-NULL and, memcmp(str1->videoStreamDescriptor, str2->videoStreamDescriptor, sizeof(VideoStreamDescriptor))) // if contents are different return errbase+6; // VideoDecodeControlDescriptor has valid flag.. // compare whole contents including valid flag if (memcmp(&str1->videoDecodeControlDescriptor, &str2->videoDecodeControlDescriptor, sizeof(VideoDecodeControlDescriptor))) return errbase+7; } return FALSE; // meaning that two PMTs are same.. } #if COMMENT _______PSI_Util2_________(){} #endif // // VCT channel pointer·ÎºÎÅÍ major/minor °ªÀ» ÃßÃâÇÏ´Â ÇÔ¼ö // // major °ªÀÇ ¹üÀ§¸¦ Ã¼Å©ÇØ¼­ One Part Çü½ÄÀÏ °æ¿ì ÇØ´ç Çü½Ä¿¡ ¸Â°Ô º¯È¯ÇÑ´Ù. // UINT16 Dmc_GetMajorNumber(BOOL is_cvct, xvctChannelPtr_t ch) { if (is_cvct && IsOnePartChannelNumber(ch->major_channel_number)) { return ConvertToOnePartChannelNumber( (ch)->major_channel_number, (ch)->minor_channel_number); } return (ch)->major_channel_number; } UINT16 Dmc_GetMinorNumber(BOOL is_cvct, xvctChannelPtr_t ch) { if (is_cvct && IsOnePartChannelNumber(ch->major_channel_number)) { return ONE_PART_CHANNEL_INDICATOR; } return (ch)->minor_channel_number; } //=========================================================================== // // Debug // // from $6.7, Table 6.16 from ATSC A-65.A document // const char *Dmc_PsipDescriptorString(UINT8 d) { if (d == 0x80) return "Stuffing descriptor"; if (d == 0x81) return "AC-3 audio descriptor"; if (d == 0x86) return "Caption service descriptor"; if (d == 0x87) return "Content advisory descriptor"; if (d == 0xA0) return "Extended channel name descriptor"; if (d == 0xA1) return "Service location descriptor"; if (d == 0xA2) return "Time-shifted service descriptor"; if (d == 0xA3) return "Component name descriptor"; if (d >= 0xC0 && d <= 0xFE) return "User private"; return "Unknown"; } #if COMMENT ____PSILoad____(){} #endif // // ÇØ´ç program number¿¡ ÇØ´çÇÏ´Â PAT/PMT¸¦ ¼ö½ÅÇÑ´Ù. // // [IN] program_number, fnCheck // [INOUT] ppat, ppmt // // return value: // statusOK // statusInvalidPSI // statusNoPSI // statusCancelled // STATUS Dmc_GetPmtByProgramNumber(MPEG_PAT **ppat, MPEG_PMT **ppmt, UINT16 program_number, BOOL (*fnCheck)(void)) { // TVCT, CVCT ó¸® Áß¿¡ ºÒ¸°´Ù. // VCT¸¦ ¼ö½ÅÇϸ鼭 µ¿½Ã¿¡ PAT´Â ¹Þ¾ÆÁ® ÀÖ´Â °æ¿ì°¡ ´ëºÎºÐÀÌÁö¸¸, // ¸ø¹ÞÀº °æ¿ì¿¡´Â ´Ù½Ã ¹Þ´Â´Ù. // PMT´Â ¾È¹Þ¾ÆÁ® ÀÖ´Â°Ô º¸ÅëÀÌ´Ù. ÁöÁ¤µÈ program_number¿¡ ÇØ´çÇÏ´Â °ÍÀ» ¹Þ´Â´Ù. // ¹ÞÀº tableÀº ctx ÀúÀåµÇ¾î ¸®ÅϵȴÙ. // STATUS status, returnStatus = statusOK; int i; int _second = 1000; MPEG_PAT *pat; MPEG_PMT *pmt; if (ppat == NULL || ppmt == NULL) return statusInvalidArgument; pat = *ppat; pmt = *ppmt; dprint(2, "Dmc_GetPmtByProgramNumber(#%d):\n", program_number); if (pat && pmt) { if (pmt->program_number == program_number) { dprint(2, "\talready program number %d PMT received\n"); return statusOK; } else { dprint(2, "\tfree previous PMT.. program num %d\n", pmt->program_number); FreePMT(pmt); pmt = NULL; } } // PAT¸¦ ¼ö½ÅÇÑ´Ù. // if (pat == NULL) { dprint(2, "\tget new pat..\n"); status = Dmc_GetPAT(Dmc_GetCurrentTsd(), &pat, g_Timeout_PatLoading*_second/1000, fnCheck); if (status == statusCancelled) goto label_cancelled; else if (status) { dprint(1, "!! PAT load failed, %d\n", status); returnStatus = statusNoPSI; goto label_end_function; } if (fnCheck && fnCheck()) goto label_cancelled; dprint(2, "\tpat found. TSID %d, total %d programs\n", pat->transport_stream_id, pat->numPrograms); // MPEG_PAT } else { dprint(2, "\tpat %x already exist. TSID %d, %d programs\n", pat, pat->transport_stream_id, pat->numPrograms); } if (pat->numPrograms == 0 || pat->programs == NULL) { dprint(1, "!! invalid PSI.. no program in pat?\n"); returnStatus = statusInvalidPSI; goto label_end_function; } // ¿øÇÏ´Â ÇÁ·Î±×·¥À» ã´Â´Ù. // find 'the program' whose program number is 'progNumber'. // if not found, we report error directly. // for (i=0; inumPrograms; ++i) { if (pat->programs[i].program_number == program_number) break; } if (i >= pat->numPrograms) { dprint(1, "!! program number %d not found!\n", program_number); returnStatus = statusChannelNotFound; goto label_end_function; } dprint(2, "\tget pmt of program number #%d\n", pat->programs[i].program_number); status = Dmc_GetPMT(Dmc_GetCurrentTsd(), pat->programs[i].program_map_PID, pat->programs[i].program_number, &pmt, g_Timeout_PmtLoading*_second/1000, fnCheck); if (status == statusCancelled) goto label_cancelled; else if (status) { dprint(1, "!! PMT (#%d, pid %x) load failed, err %d\n", pat->programs[i].program_number, pat->programs[i].program_map_PID, status); returnStatus = statusNoPSI; goto label_end_function; } returnStatus = statusOK; goto label_end_function; label_cancelled: returnStatus = statusCancelled; label_end_function: *ppat = pat; *ppmt = pmt; return returnStatus; } // cafrii 060710 add // // vctÀÇ program number¿¡ ÇØ´çÇÏ´Â ÇÁ·Î±×·¥ÀÌ PAT¿¡ ¾ø´Â °æ¿ì, // vctÀÇ program numberÀÇ PMT°¡ ¼ö½ÅÀÌ ¾ÈµÇ´Â °æ¿ì, // vctÀÇ program number Á¤º¸°¡ À߸øµÈ °ÍÀ¸·Î °¡Á¤ÇÏ°í º¹±¸¸¦ ¼öÇàÇÑ´Ù. // µî·ÏµÈ ¸ðµç PMT¸¦ ¼ö½ÅÇØ¼­ °¡Àå ºñ½ÁÇÑ PMTÀÇ program number·Î ±³Ã¼ÇÑ´Ù. // // [IN] xvctChannelPtr_t channel : º¹±¸ÇÒ vct channel. // pat : ¹Ýµå½Ã ÀÖ¾î¾ß Çϸç, Á¦´ë·Î µÈ °ÍÀ̾î¾ß ÇÔ. // cancel check fn // // [INOUT] pmt list // STATUS Dmc_RecoverVctProgramNumber(xvctChannelPtr_t channel, MPEG_PAT *pat, // IN MPEG_PMT **pmtList, // INOUT int *pIndex, // OUT BOOL (*fnCheck)(void)) { STATUS status = statusError; int k; int _second = 1000; PidInfo pid1, pid2; if (channel == NULL) return statusInvalidArgument; dprint(2, "Dmc_RecoverVctProgramNumber(vct #%d):\n", channel->program_number); if (pat == NULL) return statusInvalidPSI; // PAT ¼ö½ÅÀ» ´õÀÌ»ó ½ÃµµÇÏÁö ¾Ê´Â´Ù. // ÀÌ ÇÔ¼ö°¡ ºÒ¸®´Â ´Ü°è¶ó¸é ÀÌ¹Ì ¸î ¹ø PAT ¼ö½Å¿¡ ½ÇÆÐÇÑ °æ¿ìÀÏ °ÍÀÓ. // if (pat->numPrograms == 0 || pat->programs == NULL) { dprint(1, "!! invalid PSI.. no program in pat?\n"); status = statusInvalidPSI; goto label_end_function; } memset(&pid1, 0, sizeof(pid1)); status = Dmc_GetInfoFromVctDesc(channel->descriptors, channel->descriptor_length, &pid1, NULL); if (status) { dprint(2, "!! vct pid info invalid. cannot recover\n"); return statusInvalidVCT; } for (k=0; knumPrograms; k++) { if (pmtList[k] && pat->programs[k].program_number == pmtList[k]->program_number) { // already downloaded. } else { dprint(2, "\t[%d] load pmt #%d..\n", k, pat->programs[k].program_number); if (pmtList[k]) FreePMT(pmtList[k]); // pnÀÌ pat°Í°ú ´Ù¸¥ °ÍÀ̹ǷΠ»èÁ¦ÈÄ ´Ù½Ã ¹ÞÀ½. status = Dmc_GetPMT(Dmc_GetCurrentTsd(), pat->programs[k].program_map_PID, pat->programs[k].program_number, &pmtList[k], g_Timeout_PmtLoading*_second/1000, fnCheck); if (status == statusCancelled) goto label_cancelled; else if (status) { dprint(2, "\t PMT[%d] load failed, %d\n", k, status); continue; } } // pmtÀÇ pid Á¤º¸¿Í, vctÀÇ pid Á¤º¸°¡ ÀÏÄ¡ÇÏ¸é ¼­·Î °°Àº programÀ¸·Î º¸°í // vctÀÇ program number¸¦ ¼öÁ¤ÇÏÀÚ! status = Dmc_GetPidInfoFromPMT(pmtList[k], &pid2); if (status) { dprint(2, "\t PMT[%d] pid info err %d\n", k, status); continue; } if (pid1.pcr == pid2.pcr && pid1.video == pid2.video && pid1.audio == pid2.audio) { dprint(2, "\tcorrect pmt found. recover vct #%d -> #%d\n", channel->program_number, pmtList[k]->program_number); channel->program_number = pmtList[k]->program_number; if (pIndex) *pIndex = k; status = statusOK; goto label_end_function; } } dprint(2, "\tproper pmt not found.\n"); status = statusNotFound; goto label_end_function; label_cancelled: status = statusCancelled; label_end_function: return status; } #if COMMENT ____PID____(){} #endif #define IS_VALID_PES_PID(p) ((p)>=0x10 && (p)<=0x1ffe) #define IS_VALID_PCR_PID(p) ((p)>=0x10 && (p)<=0x1ffe) STATUS Dmc_GetPidInfoFromSLD(serviceLocationDescriptorPtr_t sld, PidInfo *pPidInfo) { int i; BOOL bAudioPidFound = FALSE; // audio pid´Â óÀ½ ¹ß°ßµÇ´Â °Í Çϳª¸¸ »ç¿ë. if (pPidInfo == NULL) return statusInvalidArgument; pPidInfo->pcr = sld->PCR_PID; for(i=0; inumber_elements; i++) { if(sld->element[i].stream_type == StreamType_MPEG2Video) // MPEG-2 video { // ITU-T Rec.H.262 | ISO/IEC 13818-2 Video or // ISO/IEC 11172-2 constrained parameter video stream pPidInfo->video = sld->element[i].elementary_PID; dprint(3, " [%d] sld video pid %d (0x%x)\n", i, pPidInfo->video, pPidInfo->video); } else if (sld->element[i].stream_type == StreamType_AC3Audio) // ATSC A/53 audio { // ATSC A/53 Audio UINT32 lanCode; if (bAudioPidFound == FALSE) // ¸Ç óÀ½ ¹ß°ßµÇ´Â audio¸¸ ó¸®Çϵµ·Ï ÇÑ´Ù. pPidInfo->audio = sld->element[i].elementary_PID; lanCode = sld->element[i].ISO639_language_code; dprint(3, " [%d] sld audio pid %d (0x%x), Lang code (%c%c%c) %s\n", i, sld->element[i].elementary_PID, sld->element[i].elementary_PID, (lanCode>>16) & 0xff, (lanCode>>8) & 0xff, lanCode & 0xff, bAudioPidFound ? "ignored" : ""); bAudioPidFound = TRUE; } // cafrii 041203 add.. °­µ¿ ÄÉÀ̺í ä³Î¿¡¼­ MPEG-2 Audio ½ºÆ®¸²ÀÌ ³ª¿À°í ÀÖÀ½. else if (sld->element[i].stream_type == StreamType_MPEG1Audio || sld->element[i].stream_type == StreamType_MPEG2Audio) // MPEG audio { // MPEG 1 Audio, MPEG 2 Audio UINT32 lanCode; if (bAudioPidFound == FALSE) // ¸Ç óÀ½ ¹ß°ßµÇ´Â audio¸¸ ó¸®Çϵµ·Ï ÇÑ´Ù. pPidInfo->audio = sld->element[i].elementary_PID; lanCode = sld->element[i].ISO639_language_code; dprint(3, " [%d] sld audio pid %d (0x%x), MPEG%d audio, Lang code (%c%c%c) %s\n", i, sld->element[i].elementary_PID, sld->element[i].elementary_PID, sld->element[i].stream_type == StreamType_MPEG1Audio ? 1 : 2, (lanCode>>16) & 0xff, (lanCode>>8) & 0xff, lanCode & 0xff, bAudioPidFound ? "ignored" : ""); bAudioPidFound = TRUE; } else { dprint(3, " [%d] !! unknown stream type: 0x%x\n", i, sld->element[i].stream_type); } } return statusOK; } // PidInfo ´Â caller¿¡¼­ ÇÒ´çµÈ ¸Þ¸ð¸® ¿µ¿ªÀÇ Æ÷ÀÎÅÍÀ̰í, // pXcnd ´Â ÀÌ ÇÔ¼ö ³»ºÎ¿¡¼­ »õ·Î µ¿ÀûÀ¸·Î ÇÒ´çµÈ descriptor structure pointer ÀÌ´Ù. // // ÁÖÀÇ: // ¹ß°ßµÇÁö ¾Ê´Â stream type¿¡ ´ëÇØ¼­´Â pid update¸¦ ÇÏÁö ¾Ê°í ÀÖ´Ù. // µû¶ó¼­ caller¿¡¼­ ÃʱⰪÀ» ¸ÕÀú ÇÒ´çÇÑ »óÅ¿¡¼­ ºÒ·¯¾ß ÇÑ´Ù. (ex: 0) // STATUS Dmc_GetInfoFromVctDesc(UINT8 *desc, int desc_len, PidInfo *pPidInfo, extendedChannelNameDescriptorPtr_t *pXcnd) { UINT8* ptr; serviceLocationDescriptorPtr_t sld = NULL; //extendedChannelNameDescriptorPtr_t xcnd; // cafrii 050315 delete unused var. STATUS rval; int this_descriptor_len; int offset; dprint(2, "Dmc_GetInfoFromVctDesc:\n"); if (desc == NULL || desc_len == 0) { dprint(0, "!! GetInfoFromVctDesc: invalid desc\n"); return statusPSIPError; } if (pPidInfo) pPidInfo->bValid = FALSE; if (pXcnd) *pXcnd = NULL; ptr = desc; offset = 0; // Áö±Ý±îÁö parsingµÈ µ¥ÀÌÅÍ ±æÀÌ. while (TRUE) { // ptr[0] : descriptor tag. // ptr[1] : descriptor length. if (offset + 2 >= desc_len) // we need at least two bytes more to parse descriptor. break; this_descriptor_len = ptr[1] + 2; // include 'tag' and 'length' // cafrii 060707, remove unproper 'unsupported desc..' message if (ptr[0] == 0xA0) // extended channel name descriptor tag. { if (pXcnd) { rval = (STATUS)ParseExtendedChannelNameDescriptor (ptr, pXcnd); //if (rval != noError) if (IsError(rval)) // cafrii 050315 change { dprint(0, "!! parse ExtChNameDesc error %d\n", rval); *pXcnd = NULL; // cafrii 050315 add } else { dprint(2, " found ext.ch.name desc\n"); // descriptor´Â ¿©±â¼­ free ½ÃŰÁö ¾Ê°í, caller °¡ free ½Ã۵µ·Ï ÇÑ´Ù. } } } else if (ptr[0] == 0xA1) // SLD descriptor tag. { if (pPidInfo) { rval = (STATUS)ParseServiceLocationDescriptor(ptr, &sld); //if (rval != noError) if (IsError(rval)) // cafrii 050315 change { dprint(0, "!! parse sld error %d\n", rval); sld = NULL; // cafrii 050315 add } else { dprint(2, " found sld, pcr pid %d, %d streams\n", sld->PCR_PID, sld->number_elements); Dmc_GetPidInfoFromSLD(sld, pPidInfo); if (sld) FreeMpegDescriptor(sld); // cafrii 030716 sld = NULL; pPidInfo->bValid = TRUE; } } } else { // cafrii 030716, print more detail information.. // dprint(3, " unsupported descriptor, '%s' 0x%02x, len %d, skip!\n", Dmc_PsipDescriptorString(ptr[0]), ptr[0], this_descriptor_len); if (dprintable(3)) memdump(ptr, min(this_descriptor_len, desc_len - offset), 0); } // goto next descriptor. ptr += this_descriptor_len; offset += this_descriptor_len; } // while return statusOK; } // cafrii 060710 add // driverÀÇ ÇÔ¼ö¿¡ ÀÇÁ¸ÇÏÁö ¾Ê°í MW¿¡¼­ º°µµ·Î Á¦°øÇÑ´Ù. // GetElementaryPIDs ´ë½Å »ç¿ë. // STATUS Dmc_GetPidInfoFromPMT(MPEG_PMT *pmt, PidInfo *pPidInfo) { int i; if (pmt == NULL || pPidInfo == NULL) return statusInvalidArgument; memset(pPidInfo, 0, sizeof(PidInfo)); pPidInfo->pcr = IS_VALID_PCR_PID(pmt->PCR_PID) ? pmt->PCR_PID : 0; for (i=0; inumStreams; i++) { if (pmt->streams[i].stream_type == StreamType_MPEG2Video && pPidInfo->video == 0) { if (!IS_VALID_PES_PID(pmt->streams[i].elementary_PID)) { dprint(0, "!! pmt video pes pid %x invalid\n", pmt->streams[i].elementary_PID); continue; } pPidInfo->video = pmt->streams[i].elementary_PID; } // todo // StreamType_MPEG1Video Áö¿øÀº flag¿¡ µû¶ó¼­.. if (pmt->streams[i].stream_type == StreamType_AC3Audio && pPidInfo->audio == 0) { if (!IS_VALID_PES_PID(pmt->streams[i].elementary_PID)) { dprint(0, "!! pmt audio pes pid %x invalid\n", pmt->streams[i].elementary_PID); continue; } pPidInfo->audio = pmt->streams[i].elementary_PID; } // todo // StreamType_MPEG1Audio, StreamType_MPEG2Audio, // StreamType_AACAudio Áö¿øÀº flag¿¡ µû¶ó¼­.. } pPidInfo->bValid = TRUE; return statusOK; } STATUS Dmc_DecidePidInfo3(MPEG_PMT *pmt, xvctChannelPtr_t channel, PidInfo *pPidInfo, UINT32 flag) { if (channel == NULL) return Dmc_DecidePidInfo(pmt, NULL, pPidInfo, flag); else return Dmc_DecidePidInfo2(pmt, channel->descriptors, channel->descriptor_length, pPidInfo, flag); } STATUS Dmc_DecidePidInfo2(MPEG_PMT *pmt, UINT8 *descs, int descs_len, PidInfo *pPidInfo, UINT32 flag) { DHL_RESULT err = DHL_OK; STATUS status; serviceLocationDescriptorPtr_t sld = NULL; if (descs && descs_len > 0) { UINT8 *sld_desc; err = GetMpegDescriptor(descs, descs_len, service_location_tag, 0, &sld_desc); // 0xA1, SLD descriptor tag. if (!err) err = ParseServiceLocationDescriptor(sld_desc, &sld); } status = Dmc_DecidePidInfo(pmt, err ? NULL : sld, pPidInfo, flag); if (sld) FreeMpegDescriptor(sld); return status; } // cafrii 061114 add support multiple audio format // #define StreamTypeToAudioType(t) ( \ (t) == StreamType_AC3Audio ? eDHL_AUDIO_TYPE_AC3 : \ (t) == StreamType_MPEG2Audio ? eDHL_AUDIO_TYPE_MPEG_2 : \ (t) == StreamType_AACAudioADTS ? eDHL_AUDIO_TYPE_AAC_ADTS : \ (t) == StreamType_AACAudioLATM ? eDHL_AUDIO_TYPE_AAC_LATM : \ eDHL_AUDIO_TYPE_UNKNOWN ) #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 ) // // PSIP (VCT SLD)¿Í PMT Á¤º¸¸¦ ÀÌ¿ëÇÏ¿© PID¸¦ °áÁ¤ÇÑ´Ù. // // [IN] pmt, sld, flag // [OUT] pPidInfo // // °æ¿ì¿¡ µû¶ó¼­ vctChannelPtr_t, ¶Ç´Â sld ÇüÅ·Π¹Þ´Â°Ô ³ªÀ» ¼öµµ ÀÖÀ½. // STATUS Dmc_DecidePidInfo(MPEG_PMT *pmt, serviceLocationDescriptorPtr_t sld, PidInfo *pPidInfo, UINT32 flag) { #define MAX_PID_LIST 20 char buf[100]; UINT16 list_p[MAX_PID_LIST]; // candidate pid list from PMT UINT16 list_v[MAX_PID_LIST]; // candidate pid list from VCT int n_list_p, n_list_v; // number of candidate for each list int i, ip, iv; PidInfo pi; BOOL bVerbose = (flag & DMC_DPIF_SILENT) ? 0 : 1; tDHL_VideoCodingType vidType; tDHL_AudioCodingType audType; UINT32 vidCap, audCap; DHL_AV_Query(eDHL_AV_QUERY_VIDEO_CAP, &vidCap); DHL_AV_Query(eDHL_AV_QUERY_AUDIO_CAP, &audCap); if (bVerbose) //dprint(1, "%s: \n", __FUNCTION__); memset(&pi, 0, sizeof(pi)); // cafrii 060728 add // -------- VIDEO ------------ // Video pid from PMT memset(list_p, 0, sizeof(list_p)); n_list_p = 0; for (i=0; pmt && inumStreams; i++) { vidType = StreamTypeToVideoType(pmt->streams[i].stream_type); if (vidType == eDHL_VIDEO_TYPE_UNKNOWN) continue; if ((vidCap & (1<streams[i].elementary_PID)) { //dprint(0, "!! pmt video pes pid %x invalid\n", pmt->streams[i].elementary_PID); continue; } if (n_list_p >= MAX_PID_LIST) { //dprint(0, "!! pmt video pid too many\n"); break; } list_p[n_list_p++] = pmt->streams[i].elementary_PID; } // Video pid from VCT memset(list_v, 0, sizeof(list_v)); n_list_v = 0; for (i=0; sld && inumber_elements; i++) { vidType = StreamTypeToVideoType(sld->element[i].stream_type); if (vidType == eDHL_VIDEO_TYPE_UNKNOWN) continue; if ((vidCap & (1<element[i].elementary_PID)) { //dprint(0, "!! vct video pes pid %x invalid\n", sld->element[i].elementary_PID); continue; } if (n_list_v >= MAX_PID_LIST) { //dprint(0, "!! vct video pid too many\n"); break; } list_v[n_list_v++] = sld->element[i].elementary_PID; } // decide video pid using list of pmt and vct if ((list_v[0] != list_p[0] || dprintable(3)) && bVerbose) { if (list_v[0] != list_p[0] && n_list_p*n_list_v) // ÀÏÄ¡ÇÏÁö ¾Ê´Â °æ¿ì. // ¸¸¾à pmt³ª vct Áß Çϳª¸¸ ÁöÁ¤ÇÑ °æ¿ì¿£ °æ°í ¸Þ½ÃÁö Ãâ·ÂÇÏÁö ¸»ÀÚ. dprint(0, "!! Warning: pmt/vct video pid mismatch\n"); buf[0] = 0; //sprintf(buf, "vpid pmt(%d):", n_list_p); //for (i=0; i 0) // choose from list_pmt pi.video = list_p[0]; // it also may be zero else if (n_list_v > 0) // choose from list_vct pi.video = list_v[0]; // it also may be zero } // video pid·ÎºÎÅÍ video type ÃßÃâ. if (pi.video) { pi.videoType = eDHL_VIDEO_TYPE_UNKNOWN; for (i=0; pmt && inumStreams && pi.videoType==eDHL_VIDEO_TYPE_UNKNOWN; i++) { if (pmt->streams[i].elementary_PID == pi.video) pi.videoType = StreamTypeToVideoType(pmt->streams[i].stream_type); } for (i=0; sld && inumber_elements && pi.videoType==eDHL_VIDEO_TYPE_UNKNOWN; i++) { if (sld->element[i].elementary_PID == pi.video) pi.videoType = StreamTypeToVideoType(sld->element[i].stream_type); } DHL_ASSERT(pi.videoType != eDHL_VIDEO_TYPE_UNKNOWN, ""); } // -------- AUDIO ------------ // Audio pid from PMT memset(list_p, 0, sizeof(list_p)); n_list_p = 0; for (i=0; pmt && inumStreams; i++) { audType = StreamTypeToAudioType(pmt->streams[i].stream_type); if (audType == eDHL_AUDIO_TYPE_UNKNOWN) continue; if ((audCap & (1<streams[i].elementary_PID)) { dprint(0, "!! pmt audio pes pid %x invalid\n", pmt->streams[i].elementary_PID); continue; } if (n_list_p >= MAX_PID_LIST) { dprint(0, "!! pmt audio pid too many\n"); break; } list_p[n_list_p++] = pmt->streams[i].elementary_PID; } // Audio pid from VCT memset(list_v, 0, sizeof(list_v)); n_list_v = 0; for (i=0; sld && inumber_elements; i++) { audType = StreamTypeToAudioType(sld->element[i].stream_type); if (audType == eDHL_AUDIO_TYPE_UNKNOWN) continue; if ((audCap & (1<element[i].elementary_PID)) { dprint(0, "!! vct video pes pid %x invalid\n", sld->element[i].elementary_PID); continue; } if (n_list_v >= MAX_PID_LIST) { dprint(0, "!! vct video pid too many\n"); break; } list_v[n_list_v++] = sld->element[i].elementary_PID; } // decide Audio pid if ((list_v[0] != list_p[0] || dprintable(3)) && bVerbose) { if (list_v[0] != list_p[0] && pmt && sld) // ÀÏÄ¡ÇÏÁö ¾Ê´Â °æ¿ì. // ¸¸¾à pmt³ª vct Áß Çϳª¸¸ ÁöÁ¤ÇÑ °æ¿ì¿£ °æ°í ¸Þ½ÃÁö Ãâ·ÂÇÏÁö ¸»ÀÚ. dprint(0, "!! Warning: pmt/vct audio pid mismatch\n"); buf[0] = 0; //sprintf(buf, "apid pmt(%d):", n_list_p); //for (i=0; i 0) // choose from list_pmt pi.audio = list_p[0]; // it also may be zero if (n_list_v > 0) // choose from list_vct pi.audio = list_v[0]; // it also may be zero } // audio pid·ÎºÎÅÍ audio type ÃßÃâ. if (pi.audio) { pi.audioType = eDHL_AUDIO_TYPE_UNKNOWN; for (i=0; pmt && inumStreams && pi.audioType==eDHL_AUDIO_TYPE_UNKNOWN; i++) { if (pmt->streams[i].elementary_PID == pi.audio) pi.audioType = StreamTypeToAudioType(pmt->streams[i].stream_type); } for (i=0; sld && inumber_elements && pi.audioType==eDHL_AUDIO_TYPE_UNKNOWN; i++) { if (sld->element[i].elementary_PID == pi.audio) pi.audioType = StreamTypeToAudioType(sld->element[i].stream_type); } DHL_ASSERT(pi.audioType != eDHL_AUDIO_TYPE_UNKNOWN, ""); } // -------- check ------------ if (pi.video == 0 && pi.audio == 0){ dprint(0, "!! Warning: no valid pid\n"); return statusNotFound; } // -------- PCR ------------ pi.pcr = 0; if (1) { int pmt_pcr, sld_pcr; pmt_pcr = pmt ? pmt->PCR_PID : 0; sld_pcr = sld ? sld->PCR_PID : 0; if (pmt_pcr == sld_pcr && IS_VALID_PCR_PID(pmt_pcr)) pi.pcr = pmt_pcr; else { if (bVerbose && pmt && sld) // ¸¸¾à pmt³ª vct Áß Çϳª¸¸ ÁöÁ¤ÇÑ °æ¿ì¿£ °æ°í ¸Þ½ÃÁö Ãâ·ÂÇÏÁö ¸»ÀÚ. dprint(0, "!! Warning: pcr invalid, pmt %x, vct %x\n", pmt_pcr, sld_pcr); if (IS_VALID_PCR_PID(pmt_pcr)) pi.pcr = pmt_pcr; else if (IS_VALID_PCR_PID(sld_pcr)) pi.pcr = sld_pcr; else { if (IS_VALID_PCR_PID(pi.video)) pi.pcr = pi.video; else if (IS_VALID_PCR_PID(pi.audio)) pi.pcr = pi.audio; } } } pi.bValid = TRUE; if (pPidInfo) *pPidInfo = pi; return statusOK; } #if COMMENT _______Timing_Util________(){} #endif // Dmc_CheckIfFormatChanged // µÎ sequence header¸¦ ºñ±³ ºÐ¼®ÇÏ¿© »õ·Î¿î seq header¿¡¼­ display timingÀÌ // ¹Ù²î¾ú´ÂÁö üũÇÑ´Ù. // // º¯°æµÇ¾úÀ¸¸é TRUE¸¦ ¸®ÅÏÇÑ´Ù. // // ºÒ¸®´Â °÷: StartDigital (°¡Àå ¸¶Áö¸·ÀÇ seqHdr¿Í ºñ±³) // HandleImportantChange (video source°¡ Running changeµÈ °æ¿ìÀÓ) // BOOL Dmc_CheckIfFormatChanged(tDHL_VideoSeqHdr *newsh, tDHL_VideoSeqHdr *oldsh) { #if 0 // reference only. member of tDHL_VideoSeqHdr UINT32 generationNumber; /* Increments each time it changes */ UINT16 horizontal_size; /* incorporates horizontal_size_value and extension */ UINT16 vertical_size; /* incorporates vettical_size_value and extension */ MPEG_ASPECT_RATIO aspect_ratio_information; MPEG_FRAME_RATE frame_rate_code; FLOAT frame_rate; /* incorporates frame_rate_code, extension_n,_d */ UINT32 bit_rate; /* bit_rate_extension is added */ UINT32 vbv_buffer_size; /* Specified in bytes. (vbv_buffer_size_extension,value * 16/8 * 1024 */ BOOLEAN constrained_parameter_flag; BOOLEAN MPEG2; /* True if sequece_extension is present */ UINT8 profile_and_level_indication; BOOLEAN progressive_sequence; MPEG_CHROMA_FORMAT chroma_format; BOOLEAN low_delay; #endif if (newsh == NULL) return FALSE; // do not change. current seq hdr is invalid. if (oldsh == NULL) return TRUE; // newly generated. so changed!! // cafrii // ¼öÁ÷ ÇØ»óµµ 1080°ú 1088Àº °°Àº ÇØ»óµµ·Î °£ÁÖÇϵµ·Ï º¯°æ. // if (newsh->horizontal_size != oldsh->horizontal_size) return TRUE; // now we treat vertical line 1080 and 1088 as same format. if (newsh->vertical_size == 1080 || newsh->vertical_size == 1088) { if (oldsh->vertical_size != 1080 && oldsh->vertical_size != 1088) return TRUE; } else if (newsh->vertical_size != oldsh->vertical_size) return TRUE; if (newsh->aspect_ratio_information != oldsh->aspect_ratio_information || newsh->frame_rate_code != oldsh->frame_rate_code || newsh->progressive_sequence != oldsh->progressive_sequence) return TRUE; return FALSE; // no change in resolution/timing. } // Dmc_WhichATSCFormat // Sarnoff Stream ATSC_01 ~ ATSC_36 Áß¿¡¼­ ¾î¶² °Í¿¡ ÇØ´çµÇ´ÂÁö ¸®ÅÏ. // Á¤È®È÷ °°Àº°Ô ¾øÀ¸¸é 0À» ¸®ÅÏÇÑ´Ù. // int Dmc_WhichATSCFormat(tDHL_VideoSeqHdr *seq) { if (seq->horizontal_size == 1920 && (seq->vertical_size == 1080 || seq->vertical_size == 1088)) { if (seq->progressive_sequence) { return seq->frame_rate_code == FRAMERATE_23_976 ? 1 : seq->frame_rate_code == FRAMERATE_24 ? 2 : seq->frame_rate_code == FRAMERATE_29_97 ? 3 : seq->frame_rate_code == FRAMERATE_30 ? 4 : 0; } else { return seq->frame_rate_code == FRAMERATE_29_97 ? 5 : seq->frame_rate_code == FRAMERATE_30 ? 6 : 0; } } else if (seq->horizontal_size == 1280 && seq->vertical_size == 720) { return seq->frame_rate_code == FRAMERATE_23_976 ? 7 : seq->frame_rate_code == FRAMERATE_24 ? 8 : seq->frame_rate_code == FRAMERATE_29_97 ? 9 : seq->frame_rate_code == FRAMERATE_30 ? 10 : seq->frame_rate_code == FRAMERATE_59_94 ? 11 : seq->frame_rate_code == FRAMERATE_60 ? 12 : 0; } else if (seq->horizontal_size == 704 && seq->vertical_size == 480) { if (DHL_AV_IsWideoFormat(seq)) { // 16:9 if (seq->progressive_sequence) { return seq->frame_rate_code == FRAMERATE_23_976 ? 13 : seq->frame_rate_code == FRAMERATE_24 ? 14 : seq->frame_rate_code == FRAMERATE_29_97 ? 15 : seq->frame_rate_code == FRAMERATE_30 ? 16 : seq->frame_rate_code == FRAMERATE_59_94 ? 17 : seq->frame_rate_code == FRAMERATE_60 ? 18 : 0; } else { return seq->frame_rate_code == FRAMERATE_29_97 ? 19 : seq->frame_rate_code == FRAMERATE_30 ? 20 : 0; } } else { // 4:3 if (seq->progressive_sequence) { return seq->frame_rate_code == FRAMERATE_23_976 ? 21 : seq->frame_rate_code == FRAMERATE_24 ? 22 : seq->frame_rate_code == FRAMERATE_29_97 ? 23 : seq->frame_rate_code == FRAMERATE_30 ? 24 : seq->frame_rate_code == FRAMERATE_59_94 ? 25 : seq->frame_rate_code == FRAMERATE_60 ? 26 : 0; } else { return seq->frame_rate_code == FRAMERATE_29_97 ? 27 : seq->frame_rate_code == FRAMERATE_30 ? 28 : 0; } } } else if (seq->horizontal_size == 640 && seq->vertical_size == 480) { if (seq->progressive_sequence) { return seq->frame_rate_code == FRAMERATE_23_976 ? 29 : seq->frame_rate_code == FRAMERATE_24 ? 30 : seq->frame_rate_code == FRAMERATE_29_97 ? 31 : seq->frame_rate_code == FRAMERATE_30 ? 32 : seq->frame_rate_code == FRAMERATE_59_94 ? 33 : seq->frame_rate_code == FRAMERATE_60 ? 34 : 0; } else { return seq->frame_rate_code == FRAMERATE_29_97 ? 35 : seq->frame_rate_code == FRAMERATE_30 ? 36 : 0; } } return 0; } #if COMMENT ________(){} #endif #if DMW_REGISTER_DEBUG_SYMBOL static DHL_SymbolTable symbols[] = { }; #endif void RegisterChannelUtilSymbols(void) { #if DMW_REGISTER_DEBUG_SYMBOL DHL_DBG_RegisterSymbols(symbols, DHL_NUMSYMBOLS(symbols)); #endif }