📄 dvd_app.cpp
字号:
/*****************************************************************************
******************************************************************************
** **
** 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 + -