
/**
 * @file        hv_mw_OsdTask.c
 * @brief       osd task c file.
 * @details     This file provides the following functions: \n
 *              (1) osd task init and task handle \n
 * @author      HiView SoC Software Team
 * @version     1.0.1
 * @date        2022-09-05
 * @copyright   Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par         History:
 * <table>
 * <tr><th>Author                        <th>Date         <th>Change Description
 * <tr><td>HiView SoC Software Team      <td>2022-08-25   <td>create
 * </table>
*/

#include "hv_vos_Comm.h"
#include "hv_comm_Event.h"
#include "hv_comm_Assert.h"
#include "hv_comm_Timer.h"
#include "hv_comm_DataBase.h"
#include "hv_mw_OsdLog.h"
#include "hv_mw_OsdOperation.h"
#include "hv_mw_SystemManager.h"
#include "hv_mw_EventHub.h"
#include "hv_mw_OsdTask.h"
#include "hv_mw_OsdEvent.h"
#include "hv_mw_OsdInit.h"
#include "hv_mw_OsdDraw.h"
#include "hv_app_Osd.h"
#include "hv_drv_Osd.h"
#include "hv_drv_Mailbox.h"
#include "hv_drv_Flash.h"
#include "hv_mw_StateMachine.h"
#include "hv_mw_UrgentTask.h"
#include "hv_chip_Config.h"

#define OSD_EVENT_CACHE_QUEUE   (10)

typedef enum  _OsdState
{
    OSD_STATE_IDLE,
    OSD_STATE_DRAWING,
    OSD_STATE_DRAW_DONE,
    OSD_STATE_SHOW_DONE,
    OSD_STATE_INVAILD,
} OsdState;

typedef struct _OsdStateMachine
{
    USHORT16        usAcceptStates;
    Status          (*pfActionHandle)(OsdEvent *pstEvent);
    OsdState        enNextContinueState;
    OsdState        enNextDoneState;
} OsdStateMachine;

static OsdEvent s_stOsdEventCacheQueue[OSD_EVENT_CACHE_QUEUE];
static UCHAR8 s_ucOsdEventCacheCount;
static Status s_uiOsdInited = HV_FAILURE;
static OsdState s_enCurrentOsdState = OSD_STATE_IDLE;


#ifdef HV_SCALER_DEBUG_VERSION
typedef struct _OsdDebugInfo
{
    UINT64          ullTick;
    OsdState        enOsdState;
    OsdLogoState    enLogoState;
    USHORT16        usEventId;
    USHORT16        usEventValue;
    USHORT16        usCurFocusing;
    UCHAR8          ucProc;     /* 0-normal, 1-cached, 2-droped */
    USHORT16        usProcTicks;
} OsdDebugInfo;

#define OSD_DEBUG_EVENT_QUEUE_NUM       (30)
#define OSD_DEBUG_TICK_COST_TOP_NUM     (3)

static OsdDebugInfo s_astOsdDebugFirstEventQueue[OSD_DEBUG_EVENT_QUEUE_NUM];
static USHORT16 s_usFirstEventCount = 0;
static OsdDebugInfo s_astOsdDebugLastEventQueue[OSD_DEBUG_EVENT_QUEUE_NUM];
static USHORT16 s_usLastEventCount = 0;
static UINT32 s_uiTotalEventNum = 0;
static UINT32 s_uiTotalDropedEventNum = 0;

static USHORT16 s_ausMaxTick[OSD_DEBUG_TICK_COST_TOP_NUM];
static USHORT16 s_ausMaxTickItem[OSD_DEBUG_TICK_COST_TOP_NUM];
static OsdEvent s_astMaxTickEvent[OSD_DEBUG_TICK_COST_TOP_NUM];
static USHORT16 s_usTickMinCnt = 0;

static VOID EventDebugQueueAppendProcTicks(OsdEvent *pstEvent, USHORT16 usItem, USHORT16 usTicks)
{
    HV_ASSERT_VALID_PTR_VOID(pstEvent);
    BOOL bFound = HV_FALSE;
    USHORT16 usCnt = 0;

    for (usCnt = 0; usCnt < OSD_DEBUG_TICK_COST_TOP_NUM; usCnt++)
    {
        if ((usItem == s_ausMaxTickItem[usCnt]) &&
            (pstEvent->usEventId == s_astMaxTickEvent[usCnt].usEventId) &&
            (pstEvent->usValue == s_astMaxTickEvent[usCnt].usValue))
        {
            bFound = HV_TRUE;
            break;
        }
    }

    if (!bFound)
    {
        usCnt = s_usTickMinCnt;
    }

    if (usTicks > s_ausMaxTick[usCnt])
    {
        s_ausMaxTickItem[usCnt] = usItem;
        s_ausMaxTick[usCnt] = usTicks;
        s_astMaxTickEvent[usCnt].usEventId = pstEvent->usEventId;
        s_astMaxTickEvent[usCnt].usValue = pstEvent->usValue;

        s_usTickMinCnt = 0;
        USHORT16 usMinTick = s_ausMaxTick[s_usTickMinCnt];
        for (usCnt = 0; usCnt < OSD_DEBUG_TICK_COST_TOP_NUM; usCnt++)
        {
            if (usMinTick > s_ausMaxTick[usCnt])
            {
                usMinTick = s_ausMaxTick[usCnt];
                s_usTickMinCnt = usCnt;
            }
        }
    }

    if (s_usFirstEventCount < OSD_DEBUG_EVENT_QUEUE_NUM)
    {
        s_astOsdDebugFirstEventQueue[s_usFirstEventCount - 1].usProcTicks = usTicks;
    }

    USHORT16 usLastCount = s_usLastEventCount;
    if (usLastCount == 0)
    {
        usLastCount = OSD_DEBUG_EVENT_QUEUE_NUM - 1;
    }
    else
    {
        usLastCount--;
    }
    s_astOsdDebugLastEventQueue[usLastCount].usProcTicks = usTicks;
}
#endif

static VOID Hv_Mw_Osd_DebugEventQueue(OsdEvent *pstEvent, UCHAR8 ucProc)
{
#ifdef HV_SCALER_DEBUG_VERSION
    HV_ASSERT_VALID_PTR_VOID(pstEvent);
    UINT64 ullCurTick = Hv_Vos_GetTick();
    OsdDebugInfo *pstDebugInfo = NULL;

    if (s_usFirstEventCount < OSD_DEBUG_EVENT_QUEUE_NUM)
    {
        pstDebugInfo = &s_astOsdDebugFirstEventQueue[s_usFirstEventCount];
        pstDebugInfo->ullTick = ullCurTick;
        pstDebugInfo->usEventId = pstEvent->usEventId;
        if (OSD_EVENT_SYNC != pstEvent->usEventId)
        {
            pstDebugInfo->enOsdState = s_enCurrentOsdState;
            pstDebugInfo->enLogoState = Hv_Mw_OsdGetLogoState();
            pstDebugInfo->usEventValue = pstEvent->usValue;
            pstDebugInfo->usCurFocusing = OSD_GET_FOCUSING();
            pstDebugInfo->ucProc = ucProc;
        }
        s_usFirstEventCount++;
    }

    pstDebugInfo = &s_astOsdDebugLastEventQueue[s_usLastEventCount];
    pstDebugInfo->ullTick = ullCurTick;
    pstDebugInfo->usEventId = pstEvent->usEventId;
    if (OSD_EVENT_SYNC != pstEvent->usEventId)
    {
        pstDebugInfo->enOsdState = s_enCurrentOsdState;
        pstDebugInfo->enLogoState = Hv_Mw_OsdGetLogoState();
        pstDebugInfo->usEventValue = pstEvent->usValue;
        pstDebugInfo->usCurFocusing = OSD_GET_FOCUSING();
        pstDebugInfo->ucProc = ucProc;
    }
    s_usLastEventCount++;
    if (s_usLastEventCount == OSD_DEBUG_EVENT_QUEUE_NUM)
    {
        s_usLastEventCount = 0;
    }

    s_uiTotalEventNum++;
    if (ucProc == 2)
    {
        s_uiTotalDropedEventNum++;
    }
#endif
}

VOID Hv_Mw_Osd_PrintDebugEventQueue(VOID)
{
#ifdef HV_SCALER_DEBUG_VERSION
    USHORT16 usId = 0;
    OsdDebugInfo *pstDebugInfo = NULL;
    const UCHAR8 aucProcName[3][10] = {"Processed", "Cached", "Dropped"};

    pstDebugInfo = s_astOsdDebugFirstEventQueue;
    OSD_LOG_INFO("*************** OSD DEBUG EVENT QUEUE ***************");
    OSD_LOG_INFO("Event total num = %d", s_uiTotalEventNum);
    OSD_LOG_INFO("Event total droped num = %d", s_uiTotalDropedEventNum);
    OSD_LOG_INFO("Current osd state = %d", s_enCurrentOsdState);
    OSD_LOG_INFO("Current logo state = %d", Hv_Mw_OsdGetLogoState());
    OSD_LOG_INFO("Proc: 0-handled, 1-cached, 2-droped");
    OSD_LOG_INFO("*************** OSD FIRST(%d) QUEUE ***************", OSD_DEBUG_EVENT_QUEUE_NUM);
    for (usId = 0; usId < MIN(s_usFirstEventCount, OSD_DEBUG_EVENT_QUEUE_NUM); usId++)
    {
        if (OSD_EVENT_SYNC == pstDebugInfo[usId].usEventId)
        {
            OSD_LOG_INFO("  Event[%d]: Tick-%llu, OsdState=%d, SYNC",
                         usId, pstDebugInfo[usId].ullTick, pstDebugInfo[usId].enOsdState);
        }
        else
        {
            OSD_LOG_INFO("  Event[%d]: Tick-%llu, OsdState=%d, LogoState=%d, %s(%d)-%d, CurFocusing=%s, cost:%d ticks [%s]",
                        usId,
                        pstDebugInfo[usId].ullTick,
                        pstDebugInfo[usId].enOsdState,
                        pstDebugInfo[usId].enLogoState,
                        Hv_Mw_OsdGetEventName(pstDebugInfo[usId].usEventId),
                        pstDebugInfo[usId].usEventId,
                        pstDebugInfo[usId].usEventValue,
                        ITEM_NAME(pstDebugInfo[usId].usCurFocusing),
                        pstDebugInfo[usId].usProcTicks,
                        aucProcName[pstDebugInfo[usId].ucProc]);
        }
    }

    pstDebugInfo = s_astOsdDebugLastEventQueue;
    OSD_LOG_INFO("*************** OSD LAST(%d) QUEUE ***************", OSD_DEBUG_EVENT_QUEUE_NUM);
    USHORT16 usIndex = 0;
    for (usId = 0; usId < OSD_DEBUG_EVENT_QUEUE_NUM; usId++)
    {
        if (s_uiTotalEventNum < (OSD_DEBUG_EVENT_QUEUE_NUM - usId))
        {
            continue;
        }
        usIndex = usId + s_usLastEventCount;
        if (usIndex >= OSD_DEBUG_EVENT_QUEUE_NUM)
        {
            usIndex -= OSD_DEBUG_EVENT_QUEUE_NUM;
        }
        if (OSD_EVENT_SYNC == pstDebugInfo[usIndex].usEventId)
        {
            OSD_LOG_INFO("  Event[%d]: Tick-%llu, OsdState=%d, SYNC",
                         s_uiTotalEventNum - (OSD_DEBUG_EVENT_QUEUE_NUM - usId), pstDebugInfo[usIndex].ullTick, pstDebugInfo[usIndex].enLogoState);
        }
        else
        {
            OSD_LOG_INFO("  Event[%d]: Tick-%llu, OsdState=%d, LogoState=%d, %s(%d)-%d, CurFocusing=%s, cost:%d ticks [%s]",
                        s_uiTotalEventNum - (OSD_DEBUG_EVENT_QUEUE_NUM - usId),
                        pstDebugInfo[usIndex].ullTick,
                        pstDebugInfo[usIndex].enOsdState,
                        pstDebugInfo[usIndex].enLogoState,
                        Hv_Mw_OsdGetEventName(pstDebugInfo[usIndex].usEventId),
                        pstDebugInfo[usIndex].usEventId,
                        pstDebugInfo[usIndex].usEventValue,
                        ITEM_NAME(pstDebugInfo[usIndex].usCurFocusing),
                        pstDebugInfo[usIndex].usProcTicks,
                        aucProcName[pstDebugInfo[usIndex].ucProc]);
        }
    }
    OSD_LOG_INFO("*************** OSD QUEUE END ***************");
    for (USHORT16 usCnt = 0; usCnt < OSD_DEBUG_TICK_COST_TOP_NUM; usCnt++)
    {
        OSD_LOG_INFO("MaxTick[%d] cost: %d ticks, focusing item: %s, event: %s-%d",
                     usCnt,
                     s_ausMaxTick[usCnt],
                     ITEM_NAME(s_ausMaxTickItem[usCnt]),
                     Hv_Mw_OsdGetEventName(s_astMaxTickEvent[usCnt].usEventId),
                     s_astMaxTickEvent[usCnt].usValue);
    }
    OSD_LOG_INFO("*********************************************");
#endif
}

static VOID Hv_Mw_BootupToPm(void);

Status Hv_Mw_Osd_TaskStartInit(VOID)
{
    HV_LOG_DEBUG(OSD, "##Hv_Mw_BootupToPm!");
    Hv_Mw_BootupToPm();
    if ((Hv_Mw_EventHub_GetPoweronReason()>>8 )== POWER_ON_REASON_TYPE_POWER_OFF)
    {
        return HV_FAILURE;
    }
    s_enCurrentOsdState = OSD_STATE_IDLE;
    s_ucOsdEventCacheCount = 0;

#ifdef HV_SCALER_DEBUG_VERSION
    for (USHORT16 usCnt = 0; usCnt < OSD_DEBUG_TICK_COST_TOP_NUM; usCnt++)
    {
        s_ausMaxTickItem[usCnt] = ITEM_NONE_ID;
        s_astMaxTickEvent[usCnt].usEventId = OSD_EVENT_MAX;
        s_astMaxTickEvent[usCnt].usValue = 0;
    }
    HV_MEMSET(s_ausMaxTick, 0, sizeof(s_ausMaxTick));
    s_usTickMinCnt = 0;
#endif

    if (Hv_Mw_OsdIsInited())
    {
        OSD_LOG_DEBUG("OSD Post Init");
        s_uiOsdInited =  Hv_Mw_OsdPostInit();
    }
    else
    {
        s_uiOsdInited = HV_FAILURE;
    }
    return s_uiOsdInited;
}

/**
 * @brief notify pm :risc has bootup.
 */
static VOID Hv_Mw_BootupToPm(void)
{
    HV_VOS_QUEUE_S *pstEventHubQueue = Hv_Mw_System_GetEventHubQueue();
    HV_ASSERT_VALID_PTR_VOID(pstEventHubQueue);
    Event stEvent = {0};
    stEvent.usEventId = EVENT_HUB_REV_MSG_ID_BOOTUP_TOPM;
    stEvent.usValue = 0;
    HV_ASSERT_TRUE_VOID(Hv_Vos_QueueSend(pstEventHubQueue, &stEvent));
    HV_COMMON_DATABASE_SET(TimeRec, ucPmPowerMode, POWER_STATE_NORMAL);
    Hv_Mw_DataBase_Sync();
    return;
}


static Status Hv_Mw_OsdEventHandle(OsdEvent *pstEvent)
{
    HV_ASSERT_VALID_PTR(pstEvent);
    Status uiRet = HV_FAILURE;
    USHORT16 usEventId = OSD_EVENT_MAX;
    HV_ASSERT_SUCCESS(s_uiOsdInited);

    /* 预处理Event事件消息：长按键，连续键，自动关闭/刷新 */
    Hv_Mw_OsdEventProc(pstEvent);

    /* 根据不同事件进行Osd绘制资源组织：菜单操作，弹框提示，用户设置 */
    Hv_App_Cb_OsdOperation(pstEvent);

    /* OSD执行绘制 */
    uiRet = Hv_Mw_OsdDraw(pstEvent);

    return uiRet;
}

static const OsdStateMachine s_astOsdStateMachine[] =
{
    {OSD_STATE_IDLE,            Hv_Mw_OsdEventHandle,   OSD_STATE_DRAWING,      OSD_STATE_DRAW_DONE},
    {OSD_STATE_DRAWING,         Hv_Mw_OsdDraw,          OSD_STATE_DRAWING,      OSD_STATE_DRAW_DONE},
    {OSD_STATE_DRAW_DONE,       Hv_Mw_OsdShow,          OSD_STATE_SHOW_DONE,    OSD_STATE_IDLE},
    {OSD_STATE_SHOW_DONE,       Hv_Mw_OsdShowDone,      OSD_STATE_IDLE,         OSD_STATE_IDLE},
};

BOOL Hv_Mw_OsdHasEventCached(USHORT16 usEventId)
{
    for (UCHAR8 ucIndex = 0; ucIndex < s_ucOsdEventCacheCount; ucIndex++)
    {
        if (s_stOsdEventCacheQueue[ucIndex].usEventId == usEventId)
        {
            return HV_TRUE;
        }
    }

    return HV_FALSE;
}

static VOID RunOsdStateMachine(OsdEvent *pstEvent)
{
    HV_ASSERT_VALID_PTR_VOID(pstEvent);
    Status uiRet = HV_FAILURE;
    BOOL bForceProced = HV_FALSE;
#ifdef HV_SCALER_DEBUG_VERSION
    UINT64 currTick = Hv_Vos_GetTick();
    USHORT16 usItem = OSD_GET_FOCUSING();
#endif

    /* 正在等待下一帧V-sync或正在显示logo时，缓存event，不丢失 */
    if (pstEvent->usEventId != OSD_EVENT_SYNC)
    {
        if (Hv_Mw_OsdGetLogoState() != OSD_LOGO_DONE)
        {
            if (Hv_Mw_OsdGetEventProp(pstEvent->usEventId, OSDEVT_LOGOING_PROCESS))
            {
                OSD_LOG_DEBUG("Process EventMsg-%d-%d during the logo show time", pstEvent->usEventId, pstEvent->usValue);
            }
            else
            {
                OSD_LOG_DEBUG("Logo not show done! Drop the EventMsg-%d-%d", pstEvent->usEventId, pstEvent->usValue);
                Hv_Mw_Osd_DebugEventQueue(pstEvent, 2);
                return;
            }
        }

        if (s_enCurrentOsdState != OSD_STATE_IDLE)
        {
            if (Hv_Mw_OsdGetEventProp(pstEvent->usEventId, OSDEVT_FORCE_PROCESS))
            {
                OSD_LOG_DEBUG("Force process EventMsg-%d-%d during osd busy time", pstEvent->usEventId, pstEvent->usValue);
                bForceProced = HV_TRUE;
            }
            else if (Hv_Mw_OsdGetEventProp(pstEvent->usEventId, OSDEVT_CACHABLE))
            {
                if (Hv_Mw_OsdGetEventProp(pstEvent->usEventId, OSDEVT_CACHABLE_ONCE) && (Hv_Mw_OsdHasEventCached(pstEvent->usEventId)))
                {
                    OSD_LOG_DEBUG("Drop the event: %s-%d", Hv_Mw_OsdGetEventName(pstEvent->usEventId), pstEvent->usValue);
                    Hv_Mw_Osd_DebugEventQueue(pstEvent, 2);
                }
                else
                {
                    /* push cache event */
                    if (s_ucOsdEventCacheCount < OSD_EVENT_CACHE_QUEUE)
                    {
                        OSD_LOG_DEBUG("OsdStateMachine state = %d, Cache EventMsg-%d-%d, count = %d",
                                    s_enCurrentOsdState, pstEvent->usEventId, pstEvent->usValue, s_ucOsdEventCacheCount);
                        HV_MEMCPY(&s_stOsdEventCacheQueue[s_ucOsdEventCacheCount], pstEvent, sizeof(OsdEvent));
                        s_ucOsdEventCacheCount++;
                        Hv_Mw_Osd_DebugEventQueue(pstEvent, 1);
                    }
                    else
                    {
                        OSD_LOG_WARN("OSD event cache queue full! Drop the EventMsg-%d-%d, OsdStateMachine state = %d",
                                    pstEvent->usEventId, pstEvent->usValue, s_enCurrentOsdState);
                        Hv_Mw_Osd_DebugEventQueue(pstEvent, 2);
                    }
                }
                return;
            }
            else
            {
                OSD_LOG_DEBUG("Drop the event: %s-%d", Hv_Mw_OsdGetEventName(pstEvent->usEventId), pstEvent->usValue);
                Hv_Mw_Osd_DebugEventQueue(pstEvent, 2);
                return;
            }
        }

        Hv_Mw_Osd_DebugEventQueue(pstEvent, 0);
    }

    if (bForceProced)
    {
        s_enCurrentOsdState = OSD_STATE_IDLE;
    }

    /* 执行OSD状态机 */
    OSD_LOG_DEBUG("OSD state = %d, EventMsg-%d-%d", s_enCurrentOsdState, pstEvent->usEventId, pstEvent->usValue);
    uiRet = s_astOsdStateMachine[s_enCurrentOsdState].pfActionHandle(pstEvent);
    if (HV_SUCCESS == uiRet)
    {
        s_enCurrentOsdState = s_astOsdStateMachine[s_enCurrentOsdState].enNextDoneState;
    }
    else if (HV_CONTINUE == uiRet)
    {
        s_enCurrentOsdState = s_astOsdStateMachine[s_enCurrentOsdState].enNextContinueState;
    }
    else
    {
        s_enCurrentOsdState = OSD_STATE_IDLE;
    }
    OSD_LOG_DEBUG("OSD state update to %d", s_enCurrentOsdState);

    if (s_enCurrentOsdState == OSD_STATE_IDLE)
    {
        /* check if need to close osd */
        if (Hv_Drv_OsdFrame_NeedCloseOsdClock())
        {
            OSD_LOG_DEBUG("close osd clock");
            Hv_Drv_OsdFrame_SetOsdClockEnable(HV_FALSE);
        }
    }

    /* 执行完成，重新发送缓存event，在下一轮处理 */
    if ((s_enCurrentOsdState == OSD_STATE_IDLE) && (s_ucOsdEventCacheCount > 0))
    {
        HV_VOS_QUEUE_S* pOsdQueue = Hv_Mw_System_GetOsdQueue();
        HV_ASSERT_VALID_PTR_VOID(pOsdQueue);
        /* 为了保证Event顺序，如果OsdQueue有新Event，则先取空 */
        OsdEvent stEventMsg = {0};
        while (Hv_Vos_QueueTimedRecv(pOsdQueue, (VOID*)&stEventMsg, 0))
        {
            if (s_ucOsdEventCacheCount < OSD_EVENT_CACHE_QUEUE)
            {
                if (Hv_Mw_OsdGetEventProp(stEventMsg.usEventId, OSDEVT_CACHABLE))
                {
                    if (Hv_Mw_OsdGetEventProp(stEventMsg.usEventId, OSDEVT_CACHABLE_ONCE) && (Hv_Mw_OsdHasEventCached(stEventMsg.usEventId)))
                    {
                        OSD_LOG_DEBUG("Cache once, drop the event: %s-%d", Hv_Mw_OsdGetEventName(stEventMsg.usEventId), stEventMsg.usValue);
                        Hv_Mw_Osd_DebugEventQueue(&stEventMsg, 2);
                    }
                    else
                    {
                        OSD_LOG_DEBUG("Cache new %s-%d, count = %d", Hv_Mw_OsdGetEventName(stEventMsg.usEventId), stEventMsg.usValue, s_ucOsdEventCacheCount);
                        HV_MEMCPY(&s_stOsdEventCacheQueue[s_ucOsdEventCacheCount], &stEventMsg, sizeof(OsdEvent));
                        s_ucOsdEventCacheCount++;
                    }
                }
                else
                {
                    OSD_LOG_DEBUG("Drop the event: %s-%d", Hv_Mw_OsdGetEventName(stEventMsg.usEventId), stEventMsg.usValue);
                    Hv_Mw_Osd_DebugEventQueue(&stEventMsg, 2);
                }
            }
            else
            {
                OSD_LOG_ERROR("OSD event cache queue full! Drop the event:%s-%d", Hv_Mw_OsdGetEventName(stEventMsg.usEventId), stEventMsg.usValue);
                Hv_Mw_Osd_DebugEventQueue(&stEventMsg, 2);
            }
        }
        /* 依序发送所有缓存的Event */
        OSD_LOG_DEBUG("Send event cache queue, num = %d", s_ucOsdEventCacheCount);
        for (UCHAR8 ucIndex = 0; ucIndex < s_ucOsdEventCacheCount; ucIndex++)
        {
            OSD_LOG_DEBUG("     Send CacheQueue[%d]: EventMsg-%d-%d", ucIndex,
                          s_stOsdEventCacheQueue[ucIndex].usEventId, s_stOsdEventCacheQueue[ucIndex].usValue);
            Hv_Vos_QueueSend(pOsdQueue, (VOID*)(&s_stOsdEventCacheQueue[ucIndex]));
        }
        s_ucOsdEventCacheCount = 0;
    }

#ifdef HV_SCALER_DEBUG_VERSION
    currTick = Hv_Vos_GetTick() - currTick;
    OSD_LOG_DEBUG("Osd run passed %llu ticks", currTick);
    EventDebugQueueAppendProcTicks(pstEvent, usItem, (USHORT16)currTick);
#endif
}

VOID Hv_Mw_OsdTaskHandle(VOID* arg)
{
    OsdEvent stEventMsg = {0};
    HV_VOS_QUEUE_S* pOsdQueue = Hv_Mw_System_GetOsdQueue();
    HV_ASSERT_VALID_PTR_VOID(pOsdQueue);
    s_uiOsdInited = Hv_Mw_Osd_TaskStartInit();
    for (;;)
    {
        #ifdef SW_DUMMY_DEBUG
        HV_WT32(SW_DUMMY_OSD_TASK, (HV_RD32(SW_DUMMY_OSD_TASK)+1));
        #endif
        OSD_LOG_DEBUG("Waiting Event...");

        if (Hv_Vos_QueueRecv(pOsdQueue, (VOID*)&stEventMsg))
        {
            OSD_LOG_DEBUG("Receive a EventMsg-%d-%d", stEventMsg.usEventId, stEventMsg.usValue);
            RunOsdStateMachine(&stEventMsg);
        }

        Hv_Vos_TaskYield();
    }
}
