/**
* @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;
}