/** * @file Hv_Mw_Channel_SearchSource.c * @brief middlware channel Search source file. * @details This file provides the following functions: \n * (1) Initialization and de-initialization functions \n * (2) Start and stop functions \n * (3) Feed functions \n * * @author HiView SoC Software Team * @version 1.0.0 * @date 2022-08-23 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved. * @par History: * *
Author Date Change Description *
HiView SoC Software Team 2022-08-23 init *
*/ #include "hv_comm_DataBase.h" #include "hv_comm_Assert.h" #include "hv_drv_DpuCommon.h" #include "hv_mw_Channel_SearchSource.h" #include "hv_mw_InputPortManager.h" #include "hv_mw_SystemManager.h" #include "hv_mw_Video_TimingCheck.h" #ifdef CONFIG_USER_USB_OTA_ON #include "hv_mw_UsbTask.h" #endif static SearchStrategy s_astRealTimeMainSearchTable[] = { #if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID) {0, 0, 0}, #endif #if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID) {1, 0, 0}, #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID) {2, 0, 0}, #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID) {3, 0, 0}, #endif }; static SearchStrategy stRealTimeSubSearchTable[] = { #if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID) {0, 0, 0}, #endif #if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID) {1, 0, 0}, #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID) {2, 0, 0}, #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID) {3, 0, 0}, #endif }; static LinkPortIndex aenNosignalSearchPortTable[] = { #if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID) LINK_PORT_INDEX_HDMI_RX0, #endif #if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID) LINK_PORT_INDEX_HDMI_RX1, #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID) LINK_PORT_INDEX_DP_RX0, #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID) LINK_PORT_INDEX_DP_RX1, #endif }; static BOOL CheckPortOnUsing(ChannelType enCurrentSearch, LinkPortIndex enMwPortIndex) { const ChannelManager* pstChannelManager = Hv_Mw_Channel_GetManager(); HV_ASSERT_VALID_PTR_RET(pstChannelManager, HV_FALSE); #ifdef CONFIG_USER_DOUBLE_CHANNEL_ON /*PIP关闭,端口必然未被占用*/ if (0 == HV_COMMON_DATABASE_GET(UserData, ucPxPMode)) { return HV_FALSE; } #if (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY) else if (1 == HV_COMMON_DATABASE_GET(UserData, bMagnifyGlassSw)) { return HV_FALSE; } #endif #if (HV_CONFIG_ON == HV_PROJECT_CONFIG_DPU_BRIGHT_FRAME) else if (1 == HV_COMMON_DATABASE_GET(UserData, bBrightFrameEn)) { return HV_FALSE; } #endif else #endif { /*当前搜索的通道是主通道,那么需要检查该端口是否被辅通道占用*/ if (CHANNEL_TYPE_MAIN == enCurrentSearch) { #ifdef CONFIG_USER_DOUBLE_CHANNEL_ON return (enMwPortIndex == pstChannelManager->astChannelData[1].enChannelSrcLinkPortIndex); #else return HV_FALSE; #endif } else/*当前搜索的通道是辅通道,那么需要检查该端口是否被主通道占用*/ { return (enMwPortIndex == pstChannelManager->astChannelData[0].enChannelSrcLinkPortIndex); } } return HV_FALSE; } UCHAR8 Hv_Mw_Channel_ConvertMwToGuiPortIndex(LinkPortIndex enPortIndex) { UCHAR8 ucGuiPortIndex = 0; switch (enPortIndex) { #if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID) case LINK_PORT_INDEX_HDMI_RX0: { ucGuiPortIndex = 0; break; } #endif #if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID) case LINK_PORT_INDEX_HDMI_RX1: { ucGuiPortIndex = 1; break; } #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID) case LINK_PORT_INDEX_DP_RX0: { ucGuiPortIndex = 2; break; } #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID) case LINK_PORT_INDEX_DP_RX1: { ucGuiPortIndex = 3; break; } #endif default: { break; } } return ucGuiPortIndex; } LinkPortIndex Hv_Mw_Channel_ConvertGuiToMwPortIndex(UCHAR8 ucGuiPortIndex) { LinkPortIndex enPortIndex = LINK_PORT_INDEX_HDMI_RX0; switch (ucGuiPortIndex) { #if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID) case 0: { enPortIndex = LINK_PORT_INDEX_HDMI_RX0; break; } #endif #if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID) case 1: { enPortIndex = LINK_PORT_INDEX_HDMI_RX1; break; } #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID) case 2: { enPortIndex = LINK_PORT_INDEX_DP_RX0; break; } #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID) case 3: { enPortIndex = LINK_PORT_INDEX_DP_RX1; break; } #endif default: { break; } } return enPortIndex; } static Status SendTimingNotSuportToOsd(UINT32 uiCheckResult, ChannelType enChannelTye, LinkPortIndex enPortIndex) { HV_VOS_QUEUE_S *pOsdQueue = Hv_Mw_System_GetOsdQueue(); HV_ASSERT_VALID_PTR(pOsdQueue); OsdEvent stOsdEvent = {0}; stOsdEvent.usEventId = OSD_EVENT_SIGNAL_TIMING_NOT_SUPPORT; /*给OSD发NOT_SUPPORT消息分为NOT_SUPPORT和OUT_OF_RANGE两种,通过value区分*/ stOsdEvent.usValue |= uiCheckResult & 0x00FF; /*ERROR_RX_TIMING_FREQ_OUT_OF_RANGE 11, ERROR_RX_TIMING_UNSUPPORT 14*/ stOsdEvent.usValue |= (enChannelTye << 8) & 0x0F00; stOsdEvent.usValue |= (enPortIndex << 12) & 0xF000; HV_ASSERT_PEEK_TRUE(Hv_Vos_QueueSend(pOsdQueue, &stOsdEvent)); HV_LOG_DEBUG(CHANNEL, "send OSD_EVENT_SIGNAL_TIMING_NOT_SUPPORT to OsdTask success usValue=0x%x!!!", stOsdEvent.usValue); return HV_SUCCESS; } static UINT32 GetCurrentPortSearchTimes(ChannelData* pstChannelData) { if (Hv_Mw_InputPort_GetCableStatus(pstChannelData->enChannelSrcLinkPortIndex)) { return HV_PROJECT_CONFIG_CURRENT_PORT_SEARCHE_TIMES; } else { return HV_PROJECT_CONFIG_EACH_PORT_DISCONNECT_SEARCHE_TIMES; } } static UINT32 GetAllPortSearchTotalTimes(ChannelData* pstChannelData) { UINT32 uiAllPortSearchTotalTimes = 0; uiAllPortSearchTotalTimes += GetCurrentPortSearchTimes(pstChannelData); if (HV_TRUE == HV_COMMON_DATABASE_GET(UserData, bAutoVideoSrcSelSw)) { #if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID) if ((Hv_Mw_InputPort_GetCableStatus(LINK_PORT_INDEX_HDMI_RX0)) && (LINK_PORT_INDEX_HDMI_RX0 != pstChannelData->enChannelSrcLinkPortIndex)) { /*插线的端口搜索HV_PROJECT_CONFIG_EACH_PORT_SERARCH_MAX_TIMES*/ uiAllPortSearchTotalTimes += HV_PROJECT_CONFIG_EACH_PORT_SERARCH_MAX_TIMES; } else if (LINK_PORT_INDEX_HDMI_RX0 != pstChannelData->enChannelSrcLinkPortIndex) { /*插线的端口搜索HV_PROJECT_CONFIG_EACH_PORT_DISCONNECT_SEARCHE_TIMES*/ uiAllPortSearchTotalTimes += HV_PROJECT_CONFIG_EACH_PORT_DISCONNECT_SEARCHE_TIMES; } #endif #if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID) if ((Hv_Mw_InputPort_GetCableStatus(LINK_PORT_INDEX_HDMI_RX1)) && (LINK_PORT_INDEX_HDMI_RX1 != pstChannelData->enChannelSrcLinkPortIndex)) { uiAllPortSearchTotalTimes += HV_PROJECT_CONFIG_EACH_PORT_SERARCH_MAX_TIMES; } else if (LINK_PORT_INDEX_HDMI_RX1 != pstChannelData->enChannelSrcLinkPortIndex) { uiAllPortSearchTotalTimes += HV_PROJECT_CONFIG_EACH_PORT_DISCONNECT_SEARCHE_TIMES; } #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID) if ((Hv_Mw_InputPort_GetCableStatus(LINK_PORT_INDEX_DP_RX0)) && (LINK_PORT_INDEX_DP_RX0 != pstChannelData->enChannelSrcLinkPortIndex)) { uiAllPortSearchTotalTimes += HV_PROJECT_CONFIG_EACH_PORT_SERARCH_MAX_TIMES; } else if (LINK_PORT_INDEX_DP_RX0 != pstChannelData->enChannelSrcLinkPortIndex) { uiAllPortSearchTotalTimes += HV_PROJECT_CONFIG_EACH_PORT_DISCONNECT_SEARCHE_TIMES; } #endif #if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID) if ((Hv_Mw_InputPort_GetCableStatus(LINK_PORT_INDEX_DP_RX1)) && (LINK_PORT_INDEX_DP_RX1 != pstChannelData->enChannelSrcLinkPortIndex)) { uiAllPortSearchTotalTimes += HV_PROJECT_CONFIG_EACH_PORT_SERARCH_MAX_TIMES; } else if (LINK_PORT_INDEX_DP_RX1 != pstChannelData->enChannelSrcLinkPortIndex) { uiAllPortSearchTotalTimes += HV_PROJECT_CONFIG_EACH_PORT_DISCONNECT_SEARCHE_TIMES; } #endif } HV_LOG_DEBUG(CHANNEL, "uiAllPortSearchTotalTimes=%u, enChannelSrcLinkPortIndex=%u", uiAllPortSearchTotalTimes, pstChannelData->enChannelSrcLinkPortIndex); return uiAllPortSearchTotalTimes; } static Status FixSearchInputPort(ChannelData* pstChannelData) { HV_ASSERT_VALID_PTR(pstChannelData); LinkPortIndex enMwPortIndex = pstChannelData->enChannelSrcLinkPortIndex; /*绑定RX端口, for hdcp/mute/rxdpll*/ const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr(); pstInputPortManager->pfPreProcess(enMwPortIndex); Hv_Drv_DpuScaler_SetPortMux(pstChannelData->enChannelType, enMwPortIndex); pstInputPortManager->pfBindChannelPortIndex(pstChannelData->enChannelType, enMwPortIndex); /*固定搜索及时没有接RX也要绑定port,解决PXP只有一个信号时的交换源问题*/ if (Hv_Mw_InputPort_GetCableStatus(enMwPortIndex)) { if (HV_SUCCESS == pstInputPortManager->pfGetVideoPara(enMwPortIndex,pstChannelData)) { pstChannelData->uiErrorCode = Hv_Mw_Video_TimingCheck(enMwPortIndex,pstChannelData); if (HV_SUCCESS == pstChannelData->uiErrorCode) { /*端口timing check成功*/ HV_LOG_DEBUG(CHANNEL, "Fix Search Port %u Success on Channel=%u", enMwPortIndex, pstChannelData->enChannelType); return HV_SUCCESS; } else { /*失败发消息给OSD并停止搜索, 取消给osd发送,统一由channelmanager发送,否则会一直重复发*/ //SendTimingNotSuportToOsd(pstChannelData->uiErrorCode, pstChannelData->enChannelType, enMwPortIndex); HV_LOG_WARN(CHANNEL, "Fix Search Port %u fail on Channel %u,error code %u", enMwPortIndex, pstChannelData->enChannelType,pstChannelData->uiErrorCode); return HV_FAILURE; } } else { /*失败继续搜索*/ HV_LOG_DEBUG(CHANNEL, "Fix Get portIndex=%u timing parameter fail, ChannelType=%u!!!", enMwPortIndex, pstChannelData->enChannelType); } } else { pstInputPortManager->pfGetVideoPara(enMwPortIndex,pstChannelData); HV_LOG_DEBUG(CHANNEL, "Fix Cable not connect!!! portIndex = %u", enMwPortIndex); } return HV_CONTINUE; } /*信号源自动搜索方案: Hw_Mw_SearchTableInit 函数将备份端口设置为搜索的最高优先界级别(图像显示后每次都会更新备份端口)。 生成的表包含未插线端口。 自动搜索时,按照不插线跳过,插线端口搜索一定次数后,如果信号可以并且通过了check那么搜索结束。 否则继续搜索表中的下一个插线端口。 搜索一轮都结束后,清空搜索次数从新调用Hw_Mw_SearchTableInit,在继续搜索。在总搜索次数未超时前均执行以上策略 对于一个端口开始未插线跳过了,之后动态插线,在搜索完本轮已插线端口后下一轮会搜索到该端口。 */ static Status AutoSearchAllInputPort(ChannelData* pstChannelData) { SearchStrategy* pastSearchStrategy = NULL; USHORT16 usSearchTableSize = 0; UINT32 uiSearchCheckTimes = 0; HV_ASSERT_VALID_PTR(pstChannelData); if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType) { pastSearchStrategy = s_astRealTimeMainSearchTable; usSearchTableSize = ARRAY_SIZE(s_astRealTimeMainSearchTable); } else { pastSearchStrategy = stRealTimeSubSearchTable; usSearchTableSize = ARRAY_SIZE(stRealTimeSubSearchTable); } /*自动搜索时遍历RealTimeSearchTable*/ for (USHORT16 usLoopIndex = 0; usLoopIndex < usSearchTableSize; usLoopIndex++) { LinkPortIndex enMwPortIndex = Hv_Mw_Channel_ConvertGuiToMwPortIndex(pastSearchStrategy[usLoopIndex].ucGuiPortIndex); if (HV_TRUE == pastSearchStrategy[usLoopIndex].ucSearched)/*判决端口是否被search过,仅搜索未被search端口*/ { HV_LOG_INFO(CHANNEL, "port %u has been searched,quit", enMwPortIndex); pastSearchStrategy[usLoopIndex].usSearchTimes = 0; continue; } else/*端口没有被search过本次search该端口*/ { HV_LOG_DEBUG(CHANNEL, "ucGuiPortIndex %u ,enMwPortIndex = %u", pastSearchStrategy[usLoopIndex].ucGuiPortIndex,enMwPortIndex); if (Hv_Mw_InputPort_GetCableStatus(enMwPortIndex)) { #if (0 == HV_PROJECT_CONFIG_CHANNEL_USE_SAME_PORT) /*不允许使用相同端口*/ if (CheckPortOnUsing(pstChannelData->enChannelType, enMwPortIndex))/*判决该端口是否被其他通道占用*/ { HV_LOG_INFO(CHANNEL, "Other Channel is using portIndex=%u, current ChannelType=%u", enMwPortIndex, pstChannelData->enChannelType); pastSearchStrategy[usLoopIndex].ucSearched = HV_TRUE; continue;/*不允许主辅使用相同端口时,使用该端口正在被其他端口占用,跳过该端口的搜索*/ } #endif pastSearchStrategy[usLoopIndex].usSearchTimes++; /*设置DPU IP从哪个PORT接收数据*/ /*记录该端口用于判决端口占用,以及后续配置通路mux使用*/ const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr(); pstInputPortManager->pfPreProcess(enMwPortIndex); Hv_Drv_DpuScaler_SetPortMux(pstChannelData->enChannelType, enMwPortIndex); /*绑定RX端口, for hdcp*/ pstInputPortManager->pfBindChannelPortIndex(pstChannelData->enChannelType, enMwPortIndex); if (HV_SUCCESS == pstInputPortManager->pfGetVideoPara(enMwPortIndex,pstChannelData)) { pstChannelData->uiErrorCode = Hv_Mw_Video_TimingCheck(enMwPortIndex,pstChannelData); if (HV_SUCCESS == pstChannelData->uiErrorCode) { /*端口timing check成功*/ pstChannelData->enChannelSrcLinkPortIndex = enMwPortIndex; HV_LOG_DEBUG(CHANNEL, "Auto Search Port %u Success on Channel=%u", enMwPortIndex, pstChannelData->enChannelType); return HV_SUCCESS; } else { /*失败发消息给OSD并停止搜索, 取消给osd发送,统一由channelmanager发送,否则会一直重复发*/ //SendTimingNotSuportToOsd(pstChannelData->uiErrorCode, pstChannelData->enChannelType, enMwPortIndex); HV_LOG_WARN(CHANNEL, "Auto Search Port %u fail on Channel %u,error code %u", enMwPortIndex, pstChannelData->enChannelType,pstChannelData->uiErrorCode); return HV_FAILURE; } } else { /*失败继续搜索*/ HV_LOG_DEBUG(CHANNEL, "Auto Get portIndex=%u timing parameter fail, ChannelType=%u!!!", enMwPortIndex, pstChannelData->enChannelType); } if ((1 == HV_COMMON_DATABASE_GET(SystemData, bFactoryMode)) && (1 == HV_COMMON_DATABASE_GET(SystemData, bBurnInEnable))) { uiSearchCheckTimes = HV_PROJECT_CONFIG_BURN_IN_EACH_PORT_SEARCH_TIMES; } else { if(pstChannelData->enChannelSrcLinkPortIndex == enMwPortIndex) { uiSearchCheckTimes = GetCurrentPortSearchTimes(pstChannelData); /*UI菜单当前设置的通道,增加搜索次数,防止异常通道切换*/ } else { uiSearchCheckTimes = HV_PROJECT_CONFIG_EACH_PORT_SERARCH_MAX_TIMES; } } if (pastSearchStrategy[usLoopIndex].usSearchTimes > uiSearchCheckTimes) { HV_LOG_INFO(CHANNEL, "reach max search times!!! portIndex = %u, SearchTimes=%u", enMwPortIndex, uiSearchCheckTimes); pastSearchStrategy[usLoopIndex].usSearchTimes = 0; pastSearchStrategy[usLoopIndex].ucSearched = HV_TRUE; } /*每次只搜索一个PORT端口, 运行此处说明已经判断完该端口跳出循环*/ break; } else/*如果该端口未插线*/ { /*清除使用标志,清空搜索次数*/ HV_LOG_DEBUG(CHANNEL, "Auto Cable not connect!!! portIndex = %u", enMwPortIndex); pastSearchStrategy[usLoopIndex].usSearchTimes = 0; pastSearchStrategy[usLoopIndex].ucSearched = HV_FALSE; /*未插线更新一下stRxVideoTiming.bIsNoSignal*/ const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr(); pstInputPortManager->pfGetVideoPara(enMwPortIndex,pstChannelData); } } } /*判决是否完成一轮已插线端口的的搜索,如果完成了一轮的搜索,重新初始化search table,再继续搜索*/ BOOL bAllSearched = HV_TRUE; for (USHORT16 usLoopIndex = 0; usLoopIndex < usSearchTableSize; usLoopIndex++) { LinkPortIndex enMwPortIndex = Hv_Mw_Channel_ConvertGuiToMwPortIndex(pastSearchStrategy[usLoopIndex].ucGuiPortIndex); HV_LOG_DEBUG(CHANNEL, "enMwPortIndex[%u] searchTimes=%u,ChannelType=%u,", enMwPortIndex, pastSearchStrategy[usLoopIndex].usSearchTimes, pstChannelData->enChannelType); HV_LOG_DEBUG(CHANNEL, "cable state=%u ChannelType=%u, ucSearched=%u", Hv_Mw_InputPort_GetCableStatus(enMwPortIndex), pstChannelData->enChannelType, pastSearchStrategy[usLoopIndex].ucSearched); if (Hv_Mw_InputPort_GetCableStatus(enMwPortIndex) && (HV_FALSE == pastSearchStrategy[usLoopIndex].ucSearched)) { bAllSearched = HV_FALSE; } } if (bAllSearched) { HV_LOG_DEBUG(CHANNEL, "All Connect Port has searched,init table again!!! ChannelType=%u", pstChannelData->enChannelType); Hw_Mw_SearchTable_Init(pstChannelData); } return HV_CONTINUE; } VOID Hw_Mw_AudioPath_Mux(const ChannelData* pstChannelData,ChannelType enChannelType) { HV_ASSERT_VALID_PTR_VOID(pstChannelData); const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr(); UCHAR8 ucCurrentPortIndex = 0; SearchStrategy* pastSearchStrategy = NULL; USHORT16 usSearchTableSize = 0; BOOL bAudioFlag = HV_DISABLE; if (CHANNEL_TYPE_MAIN == enChannelType) { ucCurrentPortIndex = pstChannelData->enChannelSrcLinkPortIndex; pastSearchStrategy = s_astRealTimeMainSearchTable; usSearchTableSize = ARRAY_SIZE(s_astRealTimeMainSearchTable); if ((CHANNEL_TYPE_MAIN == HV_COMMON_DATABASE_GET(UserData, ucAudioSource))) { bAudioFlag = HV_ENABLE; } } #ifdef CONFIG_USER_DOUBLE_CHANNEL_ON else { ucCurrentPortIndex = pstChannelData->enChannelSrcLinkPortIndex; pastSearchStrategy = stRealTimeSubSearchTable; usSearchTableSize = ARRAY_SIZE(stRealTimeSubSearchTable); if ((CHANNEL_TYPE_SUB == HV_COMMON_DATABASE_GET(UserData, ucAudioSource))) { bAudioFlag = HV_ENABLE; } } #endif HV_ASSERT_TRUE_VOID(usSearchTableSize > 0); if(HV_ENABLE == bAudioFlag) { for (USHORT16 usLoopIndex = 0; usLoopIndex < usSearchTableSize; usLoopIndex++) { if(pastSearchStrategy[usLoopIndex].ucGuiPortIndex != Hv_Mw_Channel_ConvertMwToGuiPortIndex(ucCurrentPortIndex)) { HV_LOG_DEBUG(CHANNEL, "Stop port %u audio", Hv_Mw_Channel_ConvertGuiToMwPortIndex(pastSearchStrategy[usLoopIndex].ucGuiPortIndex)); pstInputPortManager->pfStopAudio(Hv_Mw_Channel_ConvertGuiToMwPortIndex(pastSearchStrategy[usLoopIndex].ucGuiPortIndex)); } else { if(LINK_PORT_INDEX_INVALID == pstChannelData->enChannelSrcLinkPortIndex) { HV_LOG_DEBUG(CHANNEL, "Stop port %u audio", Hv_Mw_Channel_ConvertGuiToMwPortIndex(pastSearchStrategy[usLoopIndex].ucGuiPortIndex)); pstInputPortManager->pfStopAudio(Hv_Mw_Channel_ConvertGuiToMwPortIndex(pastSearchStrategy[usLoopIndex].ucGuiPortIndex)); } } } } else { const ChannelManager* pstChannelManager = Hv_Mw_Channel_GetManager(); UCHAR8 ucAudioSource = HV_COMMON_DATABASE_GET(UserData, ucAudioSource); for (USHORT16 usLoopIndex = 0; usLoopIndex < usSearchTableSize; usLoopIndex++) { HV_LOG_DEBUG(CHANNEL, "Stop port %u audio", Hv_Mw_Channel_ConvertGuiToMwPortIndex(pastSearchStrategy[usLoopIndex].ucGuiPortIndex)); if(pastSearchStrategy[usLoopIndex].ucGuiPortIndex != pstChannelManager->astChannelData[ucAudioSource].enChannelSrcLinkPortIndex) { pstInputPortManager->pfStopAudio(Hv_Mw_Channel_ConvertGuiToMwPortIndex(pastSearchStrategy[usLoopIndex].ucGuiPortIndex)); } } } return; } /*辅助函数:交换两个元素*/ static VOID SwapObject(USHORT16 *usA, USHORT16 *usB) { USHORT16 usTemp = *usA; *usA = *usB; *usB = usTemp; } /*辅助函数:对数组进行排序(从小到大)*/ static VOID SortArray(USHORT16 ausArr[], USHORT16 usStart, USHORT16 usEnd) { for (int i = usStart; i < usEnd - 1; i++) { for (int j = usStart; j < usEnd - 1; j++) { if (ausArr[j] > ausArr[j + 1]) { SwapObject(&ausArr[j], &ausArr[j + 1]); } } } } static VOID CustomSortArr(USHORT16 ausPortArr[], USHORT16 usSearchTableSize) { USHORT16 usPivot = ausPortArr[0]; USHORT16 i, j; /* 分割数组*/ USHORT16 ausLeft[usSearchTableSize], ausRight[usSearchTableSize]; USHORT16 usLeftSize = 0, usRightSize = 0; for (i = 1; i < usSearchTableSize; i++) { if (ausPortArr[i] > usPivot) { ausRight[usRightSize++] = ausPortArr[i]; } else { ausLeft[usLeftSize++] = ausPortArr[i]; } } /*对分割后的数组进行排序*/ SortArray(ausRight, 0, usRightSize); SortArray(ausLeft, 0, usLeftSize); /*合并结果*/ USHORT16 usIndex = 1; for (i = 0; i < usRightSize; i++) { ausPortArr[usIndex++] = ausRight[i]; } for (i = 0; i < usLeftSize; i++) { ausPortArr[usIndex++] = ausLeft[i]; } } VOID Hw_Mw_SearchTable_Init(ChannelData* pstChannelData) { HV_ASSERT_VALID_PTR_VOID(pstChannelData); UCHAR8 ucCurrentPortIndex = 0; SearchStrategy* pastSearchStrategy = NULL; USHORT16 usSearchTableSize = 0; if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType) { ucCurrentPortIndex = pstChannelData->enChannelSrcLinkPortIndex; pastSearchStrategy = s_astRealTimeMainSearchTable; usSearchTableSize = ARRAY_SIZE(s_astRealTimeMainSearchTable); } #ifdef CONFIG_USER_DOUBLE_CHANNEL_ON else { ucCurrentPortIndex = pstChannelData->enChannelSrcLinkPortIndex; pastSearchStrategy = stRealTimeSubSearchTable; usSearchTableSize = ARRAY_SIZE(stRealTimeSubSearchTable); } #endif HV_ASSERT_TRUE_VOID(usSearchTableSize > 0); for (USHORT16 usLoopIndex = 0; usLoopIndex < usSearchTableSize; usLoopIndex++) { if(pastSearchStrategy[usLoopIndex].ucGuiPortIndex == ucCurrentPortIndex) { pastSearchStrategy[usLoopIndex].ucGuiPortIndex = pastSearchStrategy[0].ucGuiPortIndex; pastSearchStrategy[0].ucGuiPortIndex = ucCurrentPortIndex; break; } } USHORT16 ausPortArr[usSearchTableSize]; for (USHORT16 usLoopIndex = 0; usLoopIndex < usSearchTableSize; usLoopIndex++) { ausPortArr[usLoopIndex] = pastSearchStrategy[usLoopIndex].ucGuiPortIndex; } CustomSortArr(ausPortArr, usSearchTableSize); for (USHORT16 usLoopIndex = 0; usLoopIndex < usSearchTableSize; usLoopIndex++) { pastSearchStrategy[usLoopIndex].ucGuiPortIndex = ausPortArr[usLoopIndex]; } for (USHORT16 usLoopIndex = 0; usLoopIndex < usSearchTableSize; usLoopIndex++) { pastSearchStrategy[usLoopIndex].usSearchTimes = 0; pastSearchStrategy[usLoopIndex].ucSearched = HV_FALSE; } return; } #if (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY) static Status MagnifyGlassSearchSourceMode(ChannelData* pstChannelData) { HV_ASSERT_VALID_PTR(pstChannelData); const ChannelManager* pstChannelManager = Hv_Mw_Channel_GetManager(); const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr(); pstInputPortManager->pfGetVideoPara(pstChannelData->enChannelSrcLinkPortIndex, pstChannelData); /*放大镜使用PIP模式,辅通道的信号源使用主通道正常显示的信号源*/ if (CHANNEL_STATE_ACTIVE == pstChannelManager->astChannelData[0].enCurrentCHState) { LinkPortIndex enMwPortIndex = pstChannelManager->astChannelData[0].enChannelSrcLinkPortIndex; pstInputPortManager->pfPreProcess(enMwPortIndex); Hv_Drv_DpuScaler_SetPortMux(pstChannelData->enChannelType, enMwPortIndex); /*绑定RX端口, for hdcp*/ pstInputPortManager->pfBindChannelPortIndex(pstChannelData->enChannelType, enMwPortIndex); pstChannelData->enChannelSrcLinkPortIndex = enMwPortIndex; return HV_SUCCESS; } else { HV_LOG_DEBUG(CHANNEL, "sub magnify search, main not active."); /*do nothing*/ } return HV_CONTINUE; } #endif Status Hw_Mw_Channel_SearchSuitableSource(ChannelData* pstChannelData) { HV_ASSERT_VALID_PTR(pstChannelData); Status uiResult = HV_CONTINUE; pstChannelData->usTotalSearchTimes++; #ifdef CONFIG_USER_USB_OTA_ON if(USB_STATE_OTA_IN_PROCESSING == Hv_Mw_USB_GetUsbState()) { return HV_CONTINUE; } #endif if ((1 == HV_COMMON_DATABASE_GET(SystemData, bFactoryMode)) && (1 == HV_COMMON_DATABASE_GET(SystemData, bBurnInEnable))) { if (pstChannelData->usTotalSearchTimes > HV_PROJECT_CONFIG_MAX_SEARCH_TIMERS_BURN_IN) { /*老化模式,加速失败切换到NoSignal态*/ pstChannelData->usTotalSearchTimes = 0; return pstChannelData->uiErrorCode; } } else { if (pstChannelData->usTotalSearchTimes > GetAllPortSearchTotalTimes(pstChannelData)) { /*失败切换到NoSignal态*/ pstChannelData->usTotalSearchTimes = 0; return pstChannelData->uiErrorCode; } } #if (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY) /*开启了放大镜模式辅助通道强制需要等待主通道显示正常,并且直接使用主通道的信号源*/ if ((CHANNEL_TYPE_SUB == pstChannelData->enChannelType) && (PXP_MODE_MAGNIFY_GLASS_ENABLE == Hv_Mw_Channel_GetPxpMode())) { uiResult = MagnifyGlassSearchSourceMode(pstChannelData); } else /*非放大镜模式*/ #endif { if (HV_TRUE == HV_COMMON_DATABASE_GET(UserData, bAutoVideoSrcSelSw)) { if((PXP_MODE_CLOSE == Hv_Mw_Channel_GetPxpMode()) || (PXP_MODE_MAGNIFY_GLASS_ENABLE == Hv_Mw_Channel_GetPxpMode())) { uiResult = AutoSearchAllInputPort(pstChannelData); } else { uiResult = FixSearchInputPort(pstChannelData); } } else { uiResult = FixSearchInputPort(pstChannelData); } } return uiResult; } Status Hw_Mw_Channel_NoSignal_SearchPort(ChannelData* pstChannelData) { HV_ASSERT_VALID_PTR(pstChannelData); USHORT16 usPortLoopIndex = 0; Status uiResult = HV_CONTINUE; HV_LOG_DEBUG(CHANNEL, "Nosignal SearchPort ChannelType= %u, port:%u", pstChannelData->enChannelType, pstChannelData->enChannelSrcLinkPortIndex); if (HV_TRUE == HV_COMMON_DATABASE_GET(UserData, bAutoVideoSrcSelSw) && (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType)) { const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr(); for (usPortLoopIndex = 0; usPortLoopIndex < ARRAY_SIZE(aenNosignalSearchPortTable); usPortLoopIndex++) { if (CheckPortOnUsing(pstChannelData->enChannelType, aenNosignalSearchPortTable[usPortLoopIndex]))/*判决该端口是否被其他通道占用*/ { HV_LOG_INFO(CHANNEL, "Other Channel Is using portIndex=%u, current ChannelType=%u", aenNosignalSearchPortTable[usPortLoopIndex], pstChannelData->enChannelType); continue;/*不允许主辅使用相同端口时,使用该端口正在被其他端口占用,跳过该端口的搜索*/ } if (HV_SUCCESS == pstInputPortManager->pfGetVideoPara(aenNosignalSearchPortTable[usPortLoopIndex], pstChannelData)) { pstChannelData->uiErrorCode = Hv_Mw_Video_TimingCheck(aenNosignalSearchPortTable[usPortLoopIndex],pstChannelData); if (HV_SUCCESS == pstChannelData->uiErrorCode) { /*端口timing check成功*/ pstChannelData->enChannelSrcLinkPortIndex = aenNosignalSearchPortTable[usPortLoopIndex]; HV_LOG_DEBUG(CHANNEL, "Nosignal state Timing Check SUCCESS portIndex=%u ChannelType=%u",aenNosignalSearchPortTable[usPortLoopIndex], pstChannelData->enChannelType); return HV_SUCCESS; } else { /*失败发消息给OSD并停止搜索*/ //SendTimingNotSuportToOsd(pstChannelData->uiErrorCode, pstChannelData->enChannelType, aenNosignalSearchPortTable[usPortLoopIndex]); HV_LOG_INFO(CHANNEL, "Nosignal state TimingCheck Error!!! uiCheckResult %u,portIndex= %u", pstChannelData->uiErrorCode,aenNosignalSearchPortTable[usPortLoopIndex]); return HV_FAILURE; } } else { HV_LOG_DEBUG(CHANNEL, "get port status Error!!! portIndex= %u, ChannelType=%u", aenNosignalSearchPortTable[usPortLoopIndex], pstChannelData->enChannelType); } } } else { if (CHANNEL_TYPE_MAIN == pstChannelData->enChannelType) { uiResult = FixSearchInputPort(pstChannelData); } else { #if (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY) if (PXP_MODE_MAGNIFY_GLASS_ENABLE == Hv_Mw_Channel_GetPxpMode()) { uiResult = MagnifyGlassSearchSourceMode(pstChannelData); } else { uiResult = FixSearchInputPort(pstChannelData); } #else uiResult = FixSearchInputPort(pstChannelData); #endif } } return uiResult; }