Mstar方案CEC启动流程

Mstar方案CEC启动流程

  1. 开机启动:

在android系统启动起来会调用MSrv_Control_common.cpp(该类继承与msrv,子类有MSrv_Control)中的PostVideoInit()函数(暂不跟踪系统从哪里调用该方法)

Z:\msd358_AN8.0\vendor\mstar\supernova\projects\msrv\control\src\MSrv_Control_common.cpp

BOOL MSrv_Control_common::PostVideoInit()

{

#if (CEC_ENABLE == 1)

        CECStart();

#endif

    return TRUE;

}

调用了CECStart()函数:

MSrv_CEC * MSrv_Control_common::GetMSrvCEC(void)

{

    MSRV_CONTROL_COMMON_INFO("%s line %d\n", __PRETTY_FUNCTION__, __LINE__);

    MSrv_CEC *p = dynamic_cast<MSrv_CEC *>(m_pMSrvList[E_MSRV_CEC]);//获取对象指针

    ASSERT(p);

    return p;

}

 

void MSrv_Control_common::CECStart(void)

{

    pthread_attr_t attr2;

    pthread_attr_init(&attr2);

    pthread_attr_setdetachstate(&attr2, PTHREAD_CREATE_DETACHED);

    pthread_attr_setstacksize(&attr2, PTHREAD_STACK_SIZE);

 

    m_stCecThreadInfo.pclass = GetMSrvCEC();

 

    if(m_stCecThreadInfo.bActive == FALSE) //该结构体中存下MSrv_CEC的类和一个CEC线程是否启动的类

    {

        if(PTH_RET_CHK(pthread_create(&m_CECThread, &attr2, GetMSrvCEC()->CECMonitor, &m_stCecThreadInfo)) != 0) //创建并启动线程,调用CECMonitor函数

        {

            ASSERT(0);

        }

    }

}

现在我们来看一下主要实现代码的MSrv_CEC.cpp,只列出主要代码,并进行注释梳理:

Z:\msd358_AN8.0\vendor\mstar\supernova\projects\msrv\common\src\MSrv_CEC.cpp

void * MSrv_CEC::CECMonitor(void *arg)

{

 

    ST_THREAD_ARG_INFO *ptr = (ST_THREAD_ARG_INFO *)arg; //pthread_create的参数

    MSrv_CEC *c_ptr = (MSrv_CEC*)ptr->pclass; //从参数中获取到对象

 

    prctl(PR_SET_NAME, (unsigned long)"CECMonitor");//把当前线程命名为CECMonitor

 

    c_ptr->m_pCec = mapi_interface::Get_mapi_cec();

    if(c_ptr->m_pCec == NULL)

    {

        MSRV_CEC_ERROR("[CEC] mapi_interface::Get_mapi_cec() is NULL!\n");

    }

    else

    {

        pthread_cond_signal(&(c_ptr->m_CECCond)); //利用条件变量来唤醒阻塞线程

    }

 

    c_ptr->m_pCec->SetARC(FALSE);

    MS_CEC_SETTING CEC_Setting;

    memset(&CEC_Setting, 0, sizeof(CEC_Setting)); //清零

    c_ptr->GetCECConfiguration(&CEC_Setting);//从数据库中获取CEC的状态

    if( CEC_Setting.u8CECStatus == FALSE )

    {

        pthread_exit(NULL); //获取到CEC的状态为false,线程退出,函数结束

    }

    ptr->bActive = TRUE; //记录CEC的状态

    c_ptr->m_CECInfoExtend.fCecProtocolFirstInit=FALSE;

    c_ptr->CECInit();//初始化CEC相关数据

 

    while(ptr->bActive)

    {

        usleep(CEC_HANDLER_POLLING_TIME);

        MSrv_Control::GetMSrvCEC()->CECHandler();

    }

    mapi_interface::Get_mapi_cec()->CEC_Exit();

    c_ptr->Finalize();

    pthread_exit(NULL);

}

上述代码逻辑清晰:要注意的是,如果从数据库中获取的到CEC的状态为false,那么就会执行线程退出、函数结束。导致CEC初始化不能完整进行。那么再次使用CEC的话就会出问题。

上层app,主要调用MSrv_CEC中的SetCECConfiguration(MS_CEC_SETTING * CECSetting)来控制CEC、ARC,CECSetting参数中记录了详细的状态数据。

void MSrv_CEC::SetCECConfiguration(MS_CEC_SETTING * CECSetting)

{

    if(m_pCec == NULL)

    {  

        pthread_cond_wait(&m_CECCond, &m_CECMutex); //使用条件变量阻塞线程m_CECMutex,在CECMonitor有唤醒操作。

    }

    m_CECDatabase->SetCECSetting(CECSetting);//存到数据库中

 

    if((m_CECSetting.bCECLink == FALSE)&&(CECSetting->u8CECStatus == TRUE))

    {   printf("CEC_Setting.u8CECStatus2 =%d\n",CECSetting->u8CECStatus);

        ///CEC turn on

        if((m_pCec->CEC_GetMsgCnt()) != 0 )

        {

            m_pCec->CEC_SetFifoIdx((m_pCec->CEC_GetFifoIdx() + m_pCec->CEC_GetMsgCnt())%(m_pCec->Get_CEC_FIFO_CNT()));

            m_pCec->CEC_SetMsgCnt(0);

        }

        MSrv_Control::GetInstance()->CECStart(); //调用MSrv_Control_common.cpp中的CECStart()函数,就和上面逻辑一样,执行CECMonitor()方法,进行CEC初始化,注意这时候CEC的状态是true,所以不会执行线程退出动作!

    }

    else if(CECSetting->u8CECStatus == FALSE)

   {

        ///CEC turn off

        MSrv_Control::GetInstance()->CECStop();

    }

    if(OldARCStatus != NewARCStatus)

    {

PostEvent(0, EV_AUDIO_MUTE, 0, 0);// report ui to unmute  msg上传到上层

    }

}

之后会执行m_CECMutex线程所指向的函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值