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

📄 trickmode.c

📁 这是DVD中伺服部分的核心代码
💻 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 + -