📄 trickmode.c
字号:
/******************************************************************************
*******************************************************************************
** **
** 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 trickmode.c
*
* Helper functions for configuring DVD trick modes.
*
* $Id: trickmode.c,v 1.62 2007/01/26 22:50:56 rbehe Exp $
*/
#include "vdvd_types.h"
#include "spu_con.h"
#include "pgc_play.h"
#include "dvdnvpck.h"
#include "pe_app.h"
#include "dr_app.h"
#include "trickmode.h"
#include "dbgprint.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
#include "qa.h" /* for qa automation */
#define DEBUG_TRICKMODE DBG_ERROR
#define DBG_ON(x) (DEBUG_TRICKMODE >= x)
ULONG trick_resume_offset = 0;
extern PE_HANDLE tPE;
extern DR_HANDLE tDR;
extern int timeout_wait_next_cmd;
extern UBYTE WAIT_NEXT_CMD;
extern UBYTE trick_rsm;
extern UBYTE angle_change;
extern OS_SEM_ID semPlayrate;
/**
* TMCalcSkipVOBU - Determines the correct DR skip VOBU mode for the desired trick mode.
*
* @param read_skip - The number of VOBUs to skip between reads.
* @param direction - The target playback direction
*
* @return NONE
*/
DR_SRI TMCalcSkipVOBU(ULONG read_skip, PE_ISTREAMCTRL_DIRECTION direction)
{
DR_SRI skip_vobu;
/* we need DR_FWDI_2 to skip one vobu, etc
* this is an easy was to make sure we pick the correct mode */
if (read_skip > 0)
read_skip++;
if (direction == PE_ISTREAMCTRL_DIRECTION_FORWARD)
{
if (read_skip <= 15)
{
skip_vobu = (DR_SRI)(DR_FWDI_NEXT - read_skip);
}
else if (read_skip < 20)
{
skip_vobu = DR_FWDI_20;
}
else if (read_skip < 60)
{
skip_vobu = DR_FWDI_60;
}
else if (read_skip < 120)
{
skip_vobu = DR_FWDI_120;
}
else
{
skip_vobu = DR_FWDI_240;
}
}
else
{
if (read_skip <= 15)
{
skip_vobu = (DR_SRI)(DR_BWDI_PREV + read_skip);
}
else if (read_skip < 20)
{
skip_vobu = DR_BWDI_20;
}
else if (read_skip < 60)
{
skip_vobu = DR_BWDI_60;
}
else if (read_skip < 120)
{
skip_vobu = DR_BWDI_120;
}
else
{
skip_vobu = DR_BWDI_240;
}
}
DBGPRINT(DBG_ON(DBG_TRACE), ("TMCalcSkipVOBU: skip_vobu = %d\n", skip_vobu));
return (skip_vobu);
}
static void TMPlay(ULONG ulRate, PE_ISTREAMCTRL_DIRECTION direction)
{
PE_ISTREAMCTRL_PLAYRATE OldPlayRate;
PE_ISTREAMCTRL_PLAYRATE NewPlayRate;
QAPrintOutput2(ulRate, "SPEED"); /* for qa automation */
/* get current playrate settings */
PEiStreamCtrlGetRate(tPE, &OldPlayRate);
/* get new playrate settings */
PEiStreamCtrlConfigPlayRateParam(tPE, ulRate, direction, &NewPlayRate);
/* if the data will change directions or from discrete modes then we need to flush */
if ( (OldPlayRate.direction != NewPlayRate.direction) ||
(OldPlayRate.discontiguous != NewPlayRate.discontiguous) ||
( (NewPlayRate.discontiguous == TRUE) && (NewPlayRate.read_skip != OldPlayRate.read_skip) ) )
{
OS_SemTake(semPlayrate, OS_WAIT_FOREVER);
/* hold the current frame */
PEiStreamCtrlPause(tPE);
timeout_wait_next_cmd = 0;
WAIT_NEXT_CMD = 2;
/* send abort to the disc task */
if (DRStop(tDR) == DR_SUCCESS)
{
/* flush the decoder */
PEiStreamCtrlStop(tPE, TRUE);
/* set the decoder playrate */
PEiStreamCtrlSetRate(tPE, &NewPlayRate);
OS_SemGive(semPlayrate);
/* put the DR into trick mode */
if (NewPlayRate.discontiguous == FALSE)
{
DRSetDVDSpeed(tDR, TMCalcSkipVOBU(NewPlayRate.read_skip, NewPlayRate.direction), DR_NORMAL_PLAYBACK);
}
else
{
DRSetDVDSpeed(tDR, TMCalcSkipVOBU(NewPlayRate.read_skip, NewPlayRate.direction), DR_UNTIL_1STREF_EA);
}
/* restart the PE */
PEiStreamCtrlPrefill(tPE, INPUT_MAIN, FALSE);
/* restart the nav at the point we left off
* NOTE: The restart point is recorded by proc_nvpck() */
if ( (angle_change & 0x0F) == 0 )
{
trick_rsm = 1;
}
else
{
trick_rsm = 2;
}
cell_play(1);
if ( (OldPlayRate.rate == PLAY_RATE_STEP) && (OldPlayRate.direction == PE_ISTREAMCTRL_DIRECTION_BACKWARD) &&
(NewPlayRate.rate == PLAY_RATE_STEP) && (NewPlayRate.direction == PE_ISTREAMCTRL_DIRECTION_FORWARD ) )
{
/* set the decoder playrate */
PEiStreamCtrlSetRate(tPE, &NewPlayRate);
}
}
else
{
OS_SemGive(semPlayrate);
}
}
else
{
/* just apply the trick mode since no flush is required */
PEiStreamCtrlSetRate(tPE, &NewPlayRate);
}
/* for FF/REW disable SPU decode */
if ( (ulRate > PLAY_RATE_NORMAL) || (NewPlayRate.discontiguous == TRUE) )
{
stop_spu_decode();
}
/* for slow/normal reenable SPU decode */
else if ( (direction == PE_ISTREAMCTRL_DIRECTION_FORWARD) && (ulRate <= PLAY_RATE_NORMAL) && (NewPlayRate.discontiguous == FALSE) )
{
if (spu_is_decode_on() == 0)
{
start_spu();
}
}
}
/**
* TMForwardPlay - Handles all forward trick commands.
*
* @param ulRate - The target playback rate
*
* @return NONE
*/
void TMForwardPlay(ULONG ulRate)
{
TMPlay(ulRate, PE_ISTREAMCTRL_DIRECTION_FORWARD);
}
/**
* TMBackwardPlay - Handles all backward trick commands.
*
* @param ulRate - The target playback rate
*
* @return NONE
*/
void TMBackwardPlay(ULONG ulRate)
{
TMPlay(ulRate, PE_ISTREAMCTRL_DIRECTION_BACKWARD);
}
/**
* TMGetPlayRate - Get the play rate
*
* @param none
*
* @return playrate
*/
int32 TMGetPlayRate()
{
PE_ISTREAMCTRL_PLAYRATE playrate;
OS_SemTake(semPlayrate, OS_WAIT_FOREVER);
/* Get playrate from PE */
if (PEiStreamCtrlGetRate(tPE, &playrate) != PE_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("TMGetPlayRate -- PEiStreamCtrlGetRate() failed!\n"));
playrate.rate = 0;
}
OS_SemGive(semPlayrate);
return ((int32)playrate.rate * ((playrate.direction == PE_ISTREAMCTRL_DIRECTION_BACKWARD) ? -1 : 1));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -