⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pbc_engine.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*****************************************************************************
******************************************************************************
**                                                                          **
**  Copyright (c) 2005-2006 Videon Central, Inc.                            **
**  All rights reserved.                                                    **
**                                                                          **
**  The computer program contained herein contains proprietary information  **
**  which is the property of Videon Central, Inc.  The program may be used  **
**  and/or copied only with the written permission of Videon Central, Inc.  **
**  or in accordance with the terms and conditions stipulated in the        **
**  agreement/contract under which the programs have been supplied.         **
**                                                                          **
******************************************************************************
*****************************************************************************/
/**
 * @file pbc_engine.cpp
 *
 * Playback Control Engine core module.
 * This module contains the playback control engine task.
 * This API is intended to be private and used by other Playback
 * Control Engine modules only.
 *
 * $Id: pbc_engine.cpp,v 1.96 2007/01/26 22:31:59 rbehe Exp $
 */

#include "vdvd_types.h"
#include "utility.h"
#include "pbc_engine.h"
#include "playctrl.h"
#include "pbc_types.h"
#include "pbc_pbscenario.h"
#include "pbc_avpres.h"
#include "pbc_ig.h"
#include "pbc_register.h"
#include "pbc_plcontrol.h"
#include "dr_app.h"
#include "pe_app.h"
#include "../mvplaylistdb.h"
#include "../sounddb.h"
#include "osapi.h"
#include "dbgprint.h"

#ifdef DMALLOC
#include "dmalloc.h"
#endif

/* Debug macros */
#define DBG_PBCENGINE   DBG_ERROR
#define DBG_ON(x)       (DBG_PBCENGINE >= x)

/* Local constants */
#define PBCENGINE_MSG_QUEUE_DEPTH   20


/**
 * PBC Engine Message
 */
typedef struct tagPBCENGINE_MESSAGE
{
    PBCENGINE_MSGTYPE   tMsgType;
    PBC_HANDLE          *hPbc;
    ULONG               ulData0;
    ULONG               ulData1;
    ULONG               ulData2;
    ULONG               ulData3;
    ULONG               ulSemID;
    ULONG*              pulRetVal;
} PBCENGINE_MESSAGE;

/**
 * PBC Engine data
 */
typedef struct tagPBC_ENGINE
{
    ULONG           ulTaskId;
    OS_MSG_Q_ID     MsgQID;
    OS_SEM_ID       semMsgSynch;
    OS_TIMER_ID     NavTimer;
    PBC_FUNC_PTR    PbcFunc[PLAYCTRL_INVALID_COMMAND];
} PBC_ENGINE;



/**
 * Local variables
 */
PBC_ENGINE  *hPbcEngine = NULL;

/**
 * Local functions
 */
static PLAYCTRL_STATUS  PbcEngineMapPBCFunctions(void);
static DR_ERROR         PbcEngineDRCallback(PVOID pContext, DR_EVENT_CODE event, PVOID pEventInfo);
static PE_STATUS        PbcEnginePECallback(PVOID pContext, PE_EVENT_CODE event, PVOID pEventInfo);
static void             PbcEngineNavTimerCallback(PVOID pvParam);
static PLAYCTRL_STATUS  PbcEngineTimerUpdate(PBC_HANDLE *hPBC);
static PLAYCTRL_STATUS  PbcEnginePlayButtonSound(PBC_HANDLE *hPBC, uint32 sound_id);
static ULONG            PbcEngineTask(PVOID pvParam);



/**
 * PbcEngineCreate -- Create the playback control engine task and message queue.
 *
 * @param
 *      hPBC -- handle to playback control engine private data
 *
 * @retval
 *      PLAYCTRL_STATUS
 */
PLAYCTRL_STATUS PbcEngineCreate(PBC_HANDLE *hPBC)
{
    ULONG ulPEevents = 0;

    if (hPBC == NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: NULL handle!\n"));
        return (PLAYCTRL_NULL_POINTER);
    }

    /* Attach DR event handler */
    if (DRAttachEvent(hPBC->hDR, PbcEngineDRCallback, hPBC) != DR_SUCCESS)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failed to attach DR events handler!\n"));
        goto errout;
    }

    /* Set PE Events to register for */
    ulPEevents = PE_EVENT_END_OF_STREAM | PE_EVENT_BEG_OF_STREAM | PE_EVENT_DISCONTINUITY |
                 PE_EVENT_ASYNC_PREFILL | PE_EVENT_VSYNC | PE_EVENT_ICS_VALID | PE_EVENT_ICS_INVALID |
                 PE_EVENT_SELECT_PAGE | PE_EVENT_SELECT_BUTTON | PE_EVENT_ACTIVATE_BUTTON | PE_EVENT_DECODE_DONE |
                 PE_EVENT_PROCESS_BOBJ | PE_EVENT_AM_LEVEL_CHG | PE_EVENT_AM_PANNING_CHG | PE_EVENT_AM_STOP_SOUND |
                 PE_EVENT_AM_CLOSE_SOUND | PE_EVENT_IDLE;

    /* Attach the PE event handler */
    if (PERegisterForEvents(hPBC->hPE, PbcEnginePECallback, ulPEevents, hPBC) != PE_SUCCESS)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failed to register for PEiStrmCtrl Events!\n"));
        goto errout;
    }

    /* Create pbc engine data handle */
    hPbcEngine = (PBC_ENGINE *)OS_MemAlloc(sizeof(PBC_ENGINE) );
    if (hPbcEngine == NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure creating local handle!\n"));
        goto errout;
    }

    /* intialize params */
    hPbcEngine->ulTaskId    = 0;
    hPbcEngine->MsgQID      = 0;
    hPbcEngine->semMsgSynch = 0;
    hPbcEngine->NavTimer    = 0;

    /* Map commands to playback control functions */
    if (PbcEngineMapPBCFunctions() != PLAYCTRL_SUCCESS)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure mapping functions!\n"));
        goto errout;
    }

    /* Create semaphore used for synchronous message processing */
    hPbcEngine->semMsgSynch = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_EMPTY);
    if (hPbcEngine->semMsgSynch == 0)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure creating semaphore!\n"));
        goto errout;
    }

    /* Create the pbc engine message queuee */
    hPbcEngine->MsgQID = OS_MsgQCreate(PBCENGINE_MSG_QUEUE_DEPTH, sizeof(PBCENGINE_MESSAGE), OS_MSG_Q_FIFO);
    if (hPbcEngine->MsgQID == 0)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure creating msg queue!\n"));
        goto errout;
    }

    /* Create pbc engine task */
    hPbcEngine->ulTaskId = OS_TaskSpawnParam("PbcEngineTask", OS_TASK_HIGH_PRIORITY, 4096, PbcEngineTask, NULL, NULL);
    if (hPbcEngine->ulTaskId == (ULONG)OS_FAILURE)
    {
        hPbcEngine->ulTaskId = 0;
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure spawning task!\n"));
        goto errout;
    }

    /* Create nav timer */
    if (OS_TimerCreateParam(&hPbcEngine->NavTimer, (OS_FUNCPTR_PARAM)PbcEngineNavTimerCallback, hPBC) != OS_OK)
    {
        hPbcEngine->NavTimer = 0;
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure creating nav timer!\n"));
        goto errout;
    }

    /* Set nav timer to fire every second */
    if (OS_TimerSetRepeat(hPbcEngine->NavTimer, OS_WAIT_1S) != OS_OK)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineCreate: Failure setting repeat nav timer!\n"));
        goto errout;
    }

    return (PLAYCTRL_SUCCESS);

errout:

    /* Perform un-initialization routines */
    PbcEngineDelete(hPBC);

    return (PLAYCTRL_FAILURE);
}

/**
 * PbcEngineDelete -- Delete the playback control engine task and message queue.
 *
 * @param
 *      hPBC -- handle to playback control engine private data
 *
 * @retval
 *      PLAYCTRL_STATUS
 */
PLAYCTRL_STATUS PbcEngineDelete(PBC_HANDLE *hPBC)
{
    if (hPbcEngine != NULL)
    {
        if (hPBC == NULL)
        {
            DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDelete: NULL handle!\n"));
            return (PLAYCTRL_NULL_POINTER);
        }

        if (hPbcEngine->NavTimer != 0)
        {
            /* Stop and delete the nav timer */
            OS_TimerStop(hPbcEngine->NavTimer);
            OS_TimerDelete(hPbcEngine->NavTimer);
            hPbcEngine->NavTimer = 0;
        }

        if (hPbcEngine->ulTaskId != 0)
        {
            PBCENGINE_MESSAGE msg;

            /* Send an exit message to the PBC engine task */
            msg.tMsgType    = PBCENGINE_MSGTYPE_EXIT;
            msg.ulSemID     = 0;
            msg.pulRetVal   = NULL;
            OS_MsgQSend(hPbcEngine->MsgQID, (char *)&msg, sizeof(PBCENGINE_MESSAGE), OS_WAIT_FOREVER, OS_MSG_PRI_NORMAL);

            /* Wait for task to exit then delete the task */
            OS_TaskJoin(hPbcEngine->ulTaskId);
            OS_TaskDelete(hPbcEngine->ulTaskId);
            hPbcEngine->ulTaskId = 0;
        }

        if (hPbcEngine->MsgQID != 0)
        {
            /* Delete the msg queue */
            OS_MsgQDelete(hPbcEngine->MsgQID);
            hPbcEngine->MsgQID = 0;
        }

        if (0 != hPbcEngine->semMsgSynch)
        {
            OS_SemDelete(hPbcEngine->semMsgSynch);
            hPbcEngine->semMsgSynch = 0;
        }

        /* Detach PE Event handler */
        PEDetachEvent(hPBC->hPE, PbcEnginePECallback);

        /* Detach DR event handler */
        DRDetachEvent(hPBC->hDR);

        /* Delete local handle */
        OS_MemFree(hPbcEngine);
        hPbcEngine = NULL;
    }
    else
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDelete: Not created!\n"));
        return (PLAYCTRL_FAILURE);
    }

    return (PLAYCTRL_SUCCESS);
}

/**
 * PbcEngineProcessCmd -- Add a command to the playback control engine message queue
 *                        to be processed in the pbc engine task.
 *
 * @param
 *      hPBC -- playback control engine handle
 *      tCmd -- command to be processed
 *      data1 -- data parameter
 *      data2 -- data parameter
 *      data3 -- data parameter
 *      fSynch -- flag to indicate whether or not to process the message synchronously
 *                if true, process the message synchronously, o.w. asynchronous
 *
 * @retval
 *      PLAYCTRL_STATUS
 */
PLAYCTRL_STATUS PbcEngineProcessCmd(PBC_HANDLE *hPBC, PLAYCTRL_COMMAND tCmd, ULONG data1, ULONG data2, ULONG data3, BOOLEAN fSynch)
{
    PBCENGINE_MESSAGE   msg;
    ULONG               ulRetVal;
    PLAYCTRL_STATUS     status;

    if (hPbcEngine == NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineProcessCmd: HDMV Module not created!\n"));
        return (PLAYCTRL_FAILURE);
    }

    /* Check that message queue is created */
    if (hPbcEngine->MsgQID == 0)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineProcessCmd: Msg queue not created!\n"));
        return (PLAYCTRL_FAILURE);
    }

    /* Load message parameters */
    msg.tMsgType    = PBCENGINE_MSGTYPE_PBC_CMD;
    msg.hPbc        = hPBC;
    msg.ulData0     = (ULONG)tCmd;
    msg.ulData1     = data1;
    msg.ulData2     = data2;
    msg.ulData3     = data3;

    /*
     * If synch flag is set, attach semaphore so message is processed sychronously.
     * Otherwise, do not attach a semaphore to the message.
     */
    if (fSynch == TRUE)
    {
        msg.ulSemID   = (ULONG)hPbcEngine->semMsgSynch;
        msg.pulRetVal = &ulRetVal;
    }
    else
    {
        msg.ulSemID   = 0;
        msg.pulRetVal = NULL;
    }

    /* Send message to be processed by the pbc engine task */
    if (OS_MsgQSend(hPbcEngine->MsgQID, (char *)&msg, sizeof(PBCENGINE_MESSAGE), OS_WAIT_FOREVER, OS_MSG_PRI_NORMAL) != OS_OK)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineProcessCmd: Failure sending message!\n"));
        status = PLAYCTRL_FAILURE;
    }
    else
    {
        /*
         * If message is being processed synchronously, then
         * wait for message processing to complete.
         */
        if (fSynch == TRUE)
        {
            OS_SemTake(hPbcEngine->semMsgSynch, OS_WAIT_FOREVER);
            status = *msg.pulRetVal;
        }
        else
        {
            status = PLAYCTRL_SUCCESS;
        }
    }

    return (status);
}

/*
 * Empty the Playback Control Engines Message Queue
 */
PLAYCTRL_STATUS PbcEngineClearCmdQueue(PBC_HANDLE *hPBC)
{
    if (hPbcEngine == NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineProcessCmd: HDMV Module not created!\n"));
        return (PLAYCTRL_FAILURE);
    }

    /* Check that message queue is created */
    if (hPbcEngine->MsgQID == 0)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineProcessCmd: Msg queue not created!\n"));
        return (PLAYCTRL_FAILURE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -