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

📄 dvd_app.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*****************************************************************************
******************************************************************************
**                                                                          **
**  Copyright (c) 2002 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 dvd_app.cpp
 *
 * Application for playing DVDs
 *
 * $Id: dvd_app.cpp,v 1.181 2007/01/26 22:44:56 rbehe Exp $
 */

#include <string.h>
#include "vdvd_types.h"
#include "osapi.h"
#include "loader_app.h"
#include "dr_app.h"
#include "pe_app.h"
#include "nav_task.h"
#include "hw_init.h"
#include "parstask.h"
#include "timer.h"
#include "dvd_app.h"
#include "dvd_pgci.h"
#include "dvdnvpck.h"
#include "trickmode.h"
#include "dbgprint.h"
#include "utility.h"
#include "usrapi.h"
#include "dvd_prm.h"
#include "pgc_play.h"
#include "dvd_vmgi.h"
#include "dvd_vtsi.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif

#define DVDAPP_DEBUG DBG_ERROR
#define DBG_ON(x) (DVDAPP_DEBUG >= x)

#define MSQ_QUEUE_SIZE 320  /**< defines the number of ULONG */

#ifdef __cplusplus
extern "C" {
#endif
/*
 * GLOBALS
 ****************************************************************************/
LOADER_HANDLE       tLoader       = NULL;
DR_HANDLE           tDR           = NULL;
PE_HANDLE           tPE           = NULL;
OS_SEM_ID           nvpck_sem     = 0;
OS_SEM_ID           prm_sem       = 0;
OS_SEM_ID           semPlayrate   = 0;
BOOLEAN             fAngleReady   = FALSE;
BOOLEAN             fKillNavTasks = FALSE;
ULONG               ulNavTaskID   = 0;
OS_TIMER_ID         watchDogTimer = 0;
DVD_SYSTEM_PARAMS   dvd_system_params;
ULONG               prev_eltm     = 0;  /* Time of the previous, good navpack */

/*
 * EXTERNS
 ****************************************************************************/
#if LOADER_ERROR_RECOVER == TRUE
extern UBYTE  disc_error_count;
extern UBYTE  disc_error_flag;
extern ULONG  nv_pck_buf[];
#endif
#if REGION_CHECK == TRUE
extern UBYTE  invalid_region;
#endif
extern ULONG  nav_timer_counter;
extern UBYTE  WAIT_NEXT_CMD;
extern UBYTE  modify_video_mode;
extern UBYTE  TV_Type_Changed;
extern UBYTE  repeat_mode;
extern UBYTE  A_B_count;
extern UBYTE  clear_search;
extern ULONG  skip_expire;
extern UBYTE  skip_flag;
extern USHORT prev_ptt_count;
extern ULONG  valid_lbn_for_rsm;

extern UBYTE  nav_pack_abort;
extern UBYTE  nav_pack_suspend;
extern UBYTE  nv_pck_ready;
extern UBYTE  wait_first_nvpck;
extern UBYTE  during_search;
extern UBYTE  adjust_nv_tmr;

#ifdef __cplusplus
    }
#endif


/*
 * LOCALS
 ****************************************************************************/
static BOOLEAN fDVDAppStarted  = FALSE;

/*
 * PRIVATE FUNCTION PROTOTYPES
 ****************************************************************************/
static void      DvdAppSendNavPack(PVOID pDSIpayload, PVOID pPCIpayload);
static PE_STATUS dvdPEEventCallback(PVOID pContext, PE_EVENT_CODE event, PVOID pEventInfo);
static DR_ERROR  dvdDrEventCallback(PVOID context, DR_EVENT_CODE event, PVOID pvEventInfo);
static int       MapLanguageCode(UCHAR ucLangCode);

/**
 *
 */
DVDAPP_STATUS DvdAppInitialize(LOADER_HANDLE loader, DR_HANDLE dr, PE_HANDLE pe)
{
    ULONG ulEvents = PE_EVENT_END_OF_STREAM | PE_EVENT_BEG_OF_STREAM | PE_EVENT_DISCONTINUITY |
        PE_EVENT_ASYNC_PREFILL | PE_EVENT_NVPCK | PE_EVENT_DECODE_DONE;
    ULONG stacksize = 8*1024;

    tLoader = loader;
    tDR     = dr;
    tPE     = pe;

    DbgPrint(("%s, %s\n", VERSION_STRING, VERSION_DATE_STRING));

    /* initialize */
    fKillNavTasks  = FALSE;
    fParental_Play = FALSE;
    nav_state      = UNLOADED;
    pgc_domain     = FP_PGC;
    WAIT_NEXT_CMD  = 0;
    nvpck_sem     = 0;
    prm_sem       = 0;
    watchDogTimer = 0;
    fAngleReady   = FALSE;
    ulNavTaskID   = 0;
#if REGION_CHECK == TRUE
    invalid_region = 0;
#endif

    /* attach DR event handler */
    if (DRAttachEvent (tDR, dvdDrEventCallback, tDR) != DR_SUCCESS)
    {
        DbgPrint(("DRAttachEvent FAILED\n"));
        goto error_out;
    }

    /* attach iStrmCtrl event handler */
    if (PERegisterForEvents(tPE, dvdPEEventCallback, ulEvents, tPE) != PE_SUCCESS)
    {
        DbgPrint(("PEiStreamCtrlRegisterForEvents FAILED\n"));
        goto error_out;
    }

    /* Initialize dvd system params to default settings */
    dvd_system_params.video_mode            = 0;
    dvd_system_params.audio                 = 1;
    dvd_system_params.subtitle              = 1;
    dvd_system_params.dvd_menu_language     = 1;
    dvd_system_params.country               = 1;
    dvd_system_params.parental              = PARENTAL_OFF;
    dvd_system_params.video_mode2           = ASPECT_RATIO_16X9;
    dvd_system_params.background            = VIDEO_MUTE_BLACK_SCREEN;
    dvd_system_params.digital_out           = 0;
    dvd_system_params.dolby_digital         = 0;
    dvd_system_params.mpeg                  = 0;
    dvd_system_params.dts                   = 0;
    dvd_system_params.last_memo_on          = 1;
    dvd_system_params.scr_saver             = 0;

    /* init the sprm */
    sprm_init_from_system_params();

    /* create semaphores */
    nvpck_sem     = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_FULL);
    prm_sem       = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_FULL);
    semPlayrate   = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_FULL);

    DbgAssert(nvpck_sem != 0);
    DbgAssert(prm_sem != 0);

    /* Create message queues */
    queue_nav = OS_MsgQCreate(MSQ_QUEUE_SIZE/4, NAV_MSG_SIZE, OS_MSG_Q_FIFO);
    if (queue_nav == 0)
    {
        DbgPrint(("DvdAppInitialize: Failed to create msg q!\n"));
        goto error_out;
    }

    /* reset all expiration times */
    clear_all_timers();

    /* create timers */
    CreateNavCmdTimer();
    CreateNavTimer();
    if (OS_TimerCreate(&watchDogTimer, (OS_FUNCPTR)watchdog_timer) == OS_OK)
    {
        OS_TimerSetRepeatMsec(watchDogTimer, 100);
    }
    else
    {
        DbgPrint(("DvdAppInitialize: Failed to create watchdog timer!\n"));
        goto error_out;
    }

    /*
     * create tasks
     */
    ulNavTaskID = OS_TaskSpawnParam("NavTask", OS_TASK_NORMAL_PRIORITY, stacksize, nav_task, NULL, NULL);
    if (ulNavTaskID == (ULONG)OS_FAILURE)
    {
        DbgPrint(("DvdAppInitialize: Failed to create navtask!\n"));
        ulNavTaskID = 0;
        goto error_out;
    }

    /*
     * Set the graphics mode to DVD.
     */
    if (PEiStreamCtrlSetGraphicsMode(tPE, DVD_GRAPHICS_MODE) != PE_SUCCESS)
    {
        DbgPrint(("DvdAppInitialize: Failed to set graphics mode!\n"));
        goto error_out;
    }

    fDVDAppStarted = TRUE;

    return (DVDAPP_SUCCESS);

error_out:
    DvdAppUnInitialize();
    return (DVDAPP_FAILURE);
}

DVDAPP_STATUS DvdAppUnInitialize(void)
{
    ULONG msg[4];

    /* Reset flag */
    fDVDAppStarted = FALSE;

    /* stop the DR */
    if ( tDR != NULL )
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("DvdAppUnInitialize: Stop the DR\n"));
        DRStop(tDR);

        /* detach dr streams */
        DBGPRINT(DBG_ON(DBG_TRACE), ("DvdAppUnInitialize: Detach DR Stream\n"));
        DRDetachStream(tDR, DR_STREAM_MAIN);

        /* unregister dr events */
        DBGPRINT(DBG_ON(DBG_TRACE), ("DvdAppUnInitialize: Unregister DR Events\n"));
        DRDetachEvent(tDR);
        DRReset(tDR);
    }

    if ( tPE != NULL )
    {
        /* remove subpic demux */
        DBGPRINT(DBG_ON(DBG_TRACE), ("DvdAppUnInitialize: Remove SPU Demux\n"));
        PEiStreamCtrlDemuxRemoveSubpic(tPE);

        /* stop the PE */
        PEiStreamCtrlStop(tPE, FALSE);

        /* unregister iStreamCtrl events */
        DBGPRINT(DBG_ON(DBG_TRACE), ("DvdAppUnInitialize: Unregister PE Events\n"));
        PEDetachEvent(tPE, dvdPEEventCallback);
    }

    /* tell threads to terminate */
    fKillNavTasks  = TRUE;

    /* release wait states */
    if ( queue_nav != 0 )
    {
        msg[0] = NAV_TASK_EXIT;
        if (OS_MsgQSend(queue_nav, (char *)&msg[0], NAV_MSG_SIZE, OS_NO_WAIT, OS_MSG_PRI_URGENT) != OS_OK)
        {
            DBGPRINT(DVDAPP_DEBUG, ("OS_MsgQSend FAILED!, %s, %d", __FILE__, __LINE__));
        }
    }

    /* wait for threads to exit */
    if (ulNavTaskID != 0)
    {
        OS_TaskJoin(ulNavTaskID);
        OS_TaskDelete(ulNavTaskID);
        ulNavTaskID = 0;
    }

    /* delete timers */
    DeleteNavTimer();
    DeleteNavCmdTimer();

    if ( watchDogTimer != 0 )
    {
        OS_TimerDelete(watchDogTimer);
        watchDogTimer = 0;
    }

    if ( queue_nav != 0 )
    {
        /* delete message queues */
        OS_MsgQDelete(queue_nav);
        queue_nav = 0;
    }


    /* Delete semaphores */
    if ( nvpck_sem != 0 )
    {
        OS_SemDelete(nvpck_sem);
        nvpck_sem = 0;
    }

    if ( prm_sem != 0 )
    {
        OS_SemDelete(prm_sem);
        prm_sem   = 0;
    }

    if (semPlayrate != 0)
    {
        OS_SemDelete(semPlayrate);
        semPlayrate = 0;
    }

    /* set global pointers to NULL */
    tLoader         = NULL;
    tDR             = NULL;
    tPE             = NULL;

    return (DVDAPP_SUCCESS);
}

/**
 * Reads the Nav Pack cStream and sends the data to parse task for processing.
 *
 * @param NONE
 *
 * @return OS_STATUS
 */
void DvdAppSendNavPack(PVOID pDSIpayload, PVOID pPCIpayload)
{
    ULONG message[4];

    if (fKillNavTasks == TRUE)
    {
        return;
    }

    if (clear_search == 1)
    {
        clear_search   = 0;
        prev_ptt_count = 0;
        skip_flag      = 0;

        message[0] = VDVD_STATUS_RESUME_DISP;
        if (playback_mode == PG_SEQUENTIAL)
        {
            message[1] = 0;
        }
        else
        {
            message[1] = 1;
        }

        if (UsrEventHandler(message) != USR_SUCCESS)
        {
            DbgPrint(("\nUsrEventHandler FAILURE, %s, %d\n\n", __FILE__, __LINE__));
        }
    }

    if (0xffffffff != skip_expire)
    {
        return;
    }

    if (nav_pack_abort == 1)
    {
        return;
    }

    /* parse the navpack into the dvd nav's navpack structs */
    OS_SemTake(nvpck_sem, OS_WAIT_FOREVER);
    if (parse_nvpck((BYTE*)pPCIpayload, (BYTE*)pDSIpayload) != FAILURE)
    {
        /* Take down latest usable nv_pck_lbn for resume */
        if (nvpck[CURRENT].dsi_gi.vobu_1stref_ea || nvpck[CURRENT].dsi_gi.vobu_2ndref_ea || nvpck[CURRENT].dsi_gi.vobu_3rdref_ea)
        {
            valid_lbn_for_rsm = nvpck[CURRENT].dsi_gi.nv_pck_lbn;
            DBGPRINT(DBG_ON(DBG_VERBOSE), ("proc_nvpck: valid_lbn_for_rsm = %x\n", valid_lbn_for_rsm));
        }

#if LOADER_ERROR_RECOVER == TRUE
        /* if we're receiving good navpacks reset the error counter */
        if ( (disc_error_count > 0) && (nvpck[CURRENT].dsi_gi.nv_pck_lbn > nv_pck_buf[0]) )
        {
            disc_error_count = 0;
        }

        nv_pck_buf[0] = nvpck[CURRENT].dsi_gi.nv_pck_lbn;
        if ( (nvpck[CURRENT].vobu_sri[FWDI_2] & 0x3fffffff) != SRI_END_OF_CELL )
        {
            nv_pck_buf[0] = nvpck[CURRENT].dsi_gi.nv_pck_lbn + (nvpck[CURRENT].vobu_sri[FWDI_2] & 0x3fffffff);
        }

        nv_pck_buf[1] = nvpck[CURRENT].dsi_gi.nv_pck_lbn;
        if ( (nvpck[CURRENT].vobu_sri[FWDI_6] & 0x3fffffff) != SRI_END_OF_CELL )
        {
            nv_pck_buf[1] = nvpck[CURRENT].dsi_gi.nv_pck_lbn + (nvpck[CURRENT].vobu_sri[FWDI_6] & 0x3fffffff);
        }

        nv_pck_buf[2] = nvpck[CURRENT].dsi_gi.nv_pck_lbn;
        if ( (nvpck[CURRENT].vobu_sri[FWDI_10] & 0x3fffffff) != SRI_END_OF_CELL )
        {
            nv_pck_buf[2] = nvpck[CURRENT].dsi_gi.nv_pck_lbn + (nvpck[CURRENT].vobu_sri[FWDI_10] & 0x3fffffff);
        }

        nv_pck_buf[3] = nvpck[CURRENT].dsi_gi.nv_pck_lbn;
        if ( (nvpck[CURRENT].vobu_sri[FWDI_20] & 0x3fffffff) != SRI_END_OF_CELL )
        {
            nv_pck_buf[3] = nvpck[CURRENT].dsi_gi.nv_pck_lbn + (nvpck[CURRENT].vobu_sri[FWDI_20] & 0x3fffffff);
        }

        nv_pck_buf[4] = nvpck[CURRENT].dsi_gi.nv_pck_lbn;
        if ( (nvpck[CURRENT].vobu_sri[FWDI_60] & 0x3fffffff) != SRI_END_OF_CELL )
        {
            nv_pck_buf[4] = nvpck[CURRENT].dsi_gi.nv_pck_lbn + (nvpck[CURRENT].vobu_sri[FWDI_60] & 0x3fffffff);
        }
#endif

        /* notify navigator that a new navpack has been parsed */
        message[0] = NV_PCK_READY;
        if (OS_MsgQSend(queue_nav, (char *)&message[0], NAV_MSG_SIZE, OS_NO_WAIT, OS_MSG_PRI_NORMAL) != OS_OK)
        {
            DbgPrint(("\nOS_MsgQSend FAILURE, %s, %d\n\n", __FILE__, __LINE__));
        }
    }
    OS_SemGive(nvpck_sem);

    return;
}

/**
 * Map the command to a nav task and send message to nav task.
 *
 * @param
 *    ulCommand -- Command to be processed
 *    ulInfo    -- Information specific to the command
 *
 * @return DVDAPP_STATUS
 */
DVDAPP_STATUS DvdAppCommandHandler(ULONG ulCommand, ULONG ulInfo)
{
    BOOLEAN   bSendMsg = TRUE;
    ULONG     msg[4];

    /*
     * Map command to a nav task
     */
    switch (ulCommand)
    {
    case VDVD_COMMAND_RETURN:
        msg[0] = KEY_GOUP_PGC;
        break;

    case VDVD_COMMAND_PAUSE_ON:
    case VDVD_COMMAND_PAUSE_OFF:
        msg[0] = KEY_PAUSE;
        break;

    case VDVD_COMMAND_STILL_OFF:
        msg[0] = KEY_STILL_OFF;
        break;

    case VDVD_COMMAND_PLAY:
        msg[0] = KEY_PLAY;
        break;

    case VDVD_COMMAND_PLAY_LOCATION:
        msg[0] = KEY_PLAY_LOCATION;
        break;

    case VDVD_COMMAND_STOP:
        msg[0] = KEY_STOP;
        break;

    case VDVD_COMMAND_NEXT_CHAPTER:
        msg[0] = KEY_NEXT_PG;
        break;

    case VDVD_COMMAND_PREV_CHAPTER:
        msg[0] = KEY_PREV_PG;
        break;

    case VDVD_COMMAND_RESTART_CHAPTER:
        msg[0] = KEY_TOP_PG_SEARCH;
        break;

    case VDVD_COMMAND_FWD_PLAY:
        if (ulInfo == 1000)
        {
            msg[0] = KEY_PLAY;
        }
        else if (ulInfo > 1000)
        {
            msg[0] = KEY_FF;
        }
        else
        {
            msg[0] = KEY_SLOW_F;
        }
        break;

    case VDVD_COMMAND_BWD_PLAY:
        if (ulInfo > 1000)
        {
            msg[0] = KEY_FR;
        }
        else
        {
            bSendMsg = FALSE;
        }
        break;

    case VDVD_COMMAND_STEP_FWD:
        msg[0] = KEY_STEP;
        break;

    case VDVD_COMMAND_STEP_BWD:
        msg[0] = KEY_STEP_BACK;
        break;

    case VDVD_COMMAND_REPEAT:
        if ( (ulInfo == VDVD_INFO_REPEAT_A) || (ulInfo == VDVD_INFO_REPEAT_AB) )
        {
            msg[0] = KEY_A_B;
        }
        else
        {
            msg[0] = KEY_REPEAT;
        }
        break;

    case VDVD_COMMAND_ENTER:
        msg[0] = KEY_ACTIVATE_BUTTON;
        break;

    case VDVD_COMMAND_UP:
        msg[0] = KEY_UPPER_BUTTON_SELECT;
        break;

    case VDVD_COMMAND_DOWN:
        msg[0] = KEY_LOWER_BUTTON_SELECT;
        break;

    case VDVD_COMMAND_LEFT:
        msg[0] = KEY_LEFT_BUTTON_SELECT;
        break;

⌨️ 快捷键说明

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