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

📄 dr_prefetch_dvd.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
******************************************************************************
**                                                                          **
**  Copyright (c) 2005 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 dr_prefetch_dvd.cpp
 *
 * Prefetch class for the DR
 *
 * $Id: dr_prefetch_dvd.cpp,v 1.19 2007/01/26 20:47:06 rbehe Exp $
 */


#include <stdlib.h>
#include "vdvd_types.h"
#include "utility.h"

#include "loader_app.h"
#include "dr_types.h"
#include "dr_prefetch_dvd.h"
#include "css.h"

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


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



/* DVD Specific Defines */
#define MAX_SECTORS_PER_READ    16
#define PCI_PACKET_OFFSET       38
#define VOBU_SE_E_PTM_OFFSET    27
#define VOBU_S_PTM_OFFSET       19
#define PREU_FLAG               0x8000
#define ILVU_FLAG               0x4000
#define UNIT_START_FLAG         0x2000
#define UNIT_END_FLAG           0x1000




inline DR_ERROR drParseDSI(dsipkt_struct &dsi_packet, UCHAR *buf);
inline ULONG drGetVobuEndAddr(dsipkt_struct *dsi_packet, ULONG read_until_ref, ULONG ulNavPackLBN);





/**********************************************
 *
 * Implementations for DRPrefetch_DVD Derived Class
 *
 **********************************************/




/**
 * Private function used to send a timing packet to the PE.
 *
 * @param ulVobuCC          - The Vobu "count".
 * @param fIsVobuStill      - Flag to indicate that the player should pause at the end of this vobu.
 *
 * @retval DR_ERROR
 */
DR_ERROR DRPrefetch_DVD::drSendVobuInfo(ULONG ulVobuCC, BOOLEAN fIsVobuStill)
{
    DROUTPUTMESSAGE     streamMessage;
    cPayload            *pStreamPayload     = NULL;
    INFOPAYLOAD         *infoPayload;

    /* it's an info payload */
    streamMessage.fInfoPayload              = TRUE;

    /* Get a buffer from the stream */
    pStreamPayload = drGetPayload();

    if (pStreamPayload == NULL)
    {
        return (DR_FAILURE);
    }

    /* get the payload's write pointer */
    infoPayload = (INFOPAYLOAD*)pStreamPayload->get_base_ptr();

    /* set the type */
    infoPayload->bType = INFOTYPE_VOBUINFO;

    /* set the data */
    infoPayload->vobu.ulVobuCC     = ulVobuCC;
    infoPayload->vobu.fIsVobuStill = fIsVobuStill;

    /* send navpack id with the message */
    streamMessage.ulVobuCC         = m_ulVobuCC;
    streamMessage.fIsVobuStill     = fIsVobuStill;

    /* transfer the payload to the PE */
    drSendStream(streamMessage, pStreamPayload);

    /* delete the payload */
    delete pStreamPayload;
    pStreamPayload = NULL;

    return (DR_SUCCESS);
}



/**
 * dataRetrieve - retrieve data from the disk and put into the prefetch thread
 *
 * @param playcmd   - contains details for the data retrieval
 *
 * @retval none
 *
 * @remarks none.
 */
DR_ERROR DRPrefetch_DVD::dataRetrieve(PLAYCMD playcmd)
{
    BOOLEAN                 fReadOk                   = FALSE;
    ULONG                   ulCurrentSector;
    ULONG                   ulVobuEndAddr;
    ULONG                   ulSectorCount;
    ULONG                   ulNumSectors;
    ULONG                   ulLoopBuf;
    ULONG                   ulSectorsToRead;
    ULONG                   ulSectorsLeft;
    BYTE                    *pDataPtr                 = NULL;
    BOOLEAN                 fSeqEndDetected           = FALSE;
    ULONG                   ulNextSector;
    DROUTPUTMESSAGE         streamMessage;
    cPayload                *pStreamPayload           = NULL;
    BOOLEAN                 fSendTimeInfo             = TRUE;
    LOADER_ERR              ldrStatus;

    /* send beginning of stream for every play request */
    streamMessage.BegOfStream = TRUE;

    OS_SemGive(m_semPlayQueueEnabled);

    if (m_encryption_type == CSS)
    {
        drGetTitleKey(playcmd.dvd.ulStart);
    }

    /* check our queue type. If it is an abort the new data should always be
     * considered discontinuous from the previous */
    if ( (playcmd.dvd.queueType == DR_QUEUE_ABORT) || (playcmd.dvd.queueType == DR_QUEUE_NONSEAMLESS) )
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("discontinuity at beginning\n"));
        streamMessage.DiscontinuityAtBeginning = TRUE;
    }


    if (playcmd.dvd.playType == DR_TYPE_LBN)
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("DR_TYPE_LBN\n"));

        /* for LBN type playback we just play from the first to last sector with
         * no DVD navigation (ie. no nav pack parsing required) */
        m_ulNavPackLBN = 0;
        ulCurrentSector  = playcmd.dvd.ulStart;
        ulVobuEndAddr    = playcmd.dvd.ulEnd;
    }
    else
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("skip_vobu=%d, read_until_ref=%d\n", m_skip_vobu, m_read_until_ref));

        if ( (m_skip_vobu >= DR_BWDI_PREV) || (playcmd.dvd.queueType == DR_QUEUE_NONSEAMLESS) )
        {
            /* jump to last VOBU in cell */
            m_ulNavPackLBN     = playcmd.dvd.ulBegin;
            ulCurrentSector    = playcmd.dvd.ulBegin;
            ulVobuEndAddr      = playcmd.dvd.ulEnd;
        }
        else
        {
            m_ulNavPackLBN     = playcmd.dvd.ulStart;
            ulCurrentSector    = playcmd.dvd.ulStart;
            ulVobuEndAddr      = playcmd.dvd.ulEnd;
        }
    }

    DBGPRINT(DBG_ON(DBG_TRACE), ("DR_PLAY -- firstLBN=%x, lastLBN=%x, trickLBN=%x, NavPckLBN=%x\n",
        playcmd.dvd.ulStart, playcmd.dvd.ulEnd, playcmd.dvd.ulBegin, m_ulNavPackLBN));

    do                                /* while not up to the last sector */
    {
        /* release old payload */
        if (pStreamPayload != NULL)
        {
            delete pStreamPayload;
            pStreamPayload = NULL;
        }

        if (m_fAbort == TRUE)
        {
            DBGPRINT(DBG_ON(DBG_TRACE), ("DRDataProc() -- flush/abort\n"));
            break;
        }

        /* Get a buffer from the stream */
        pStreamPayload = drGetPayload();

        if (pStreamPayload == NULL)
        {
            break;
        }

        /* how many sector remain? */
        ulSectorCount = (playcmd.dvd.ulEnd - ulCurrentSector) + 1;

        /* how many sectors can fit in the buffer */
        ulNumSectors = (ULONG)((pStreamPayload->get_max_size()) / DVD_SECTOR_SIZE);

        /* make sure there are is at least 32K left to read */
        if (ulNumSectors > ulSectorCount)
        {
            DBGPRINT(DBG_ON(DBG_TRACE), ("DRDataProc() -- ulSectorCount=%d, ulNumSectors=%d\n", ulSectorCount, ulNumSectors));
            ulNumSectors = ulSectorCount;
        }

        /* Read enough data to fill the buffer */
        for (ulLoopBuf=0; ulLoopBuf < ulNumSectors; )
        {
            if (playcmd.dvd.playType == DR_TYPE_LBN)
            {
                ulSectorsToRead = ulNumSectors;
            }
            else
            {
                ulSectorsLeft   = ulNumSectors - ulLoopBuf;
                ulSectorsToRead = (ulSectorsLeft < MAX_SECTORS_PER_READ) ? ulSectorsLeft : MAX_SECTORS_PER_READ;
            }


            /* Grab the address we are about to read data into...
             * we need this so we can keep track of where we are in the buffer for nav pack parsing. */
            pDataPtr = (BYTE*)pStreamPayload->get_wr_ptr();

            ldrStatus = LoaderSectorReadAV(m_loader, ulCurrentSector, pDataPtr, ulSectorsToRead);

            if (ldrStatus == LOADER_SUCCESS)
            {
                /* check that the read begins with good data (program stream start code) */
                if (MAKE_DWORD(pDataPtr) != 0x000001ba)
                {
                    DbgPrint(("LoaderFileRead: bad data read from disk.\n"));
                    ldrStatus = LOADER_FAILURE;
                }
            }

            if (ldrStatus == LOADER_SUCCESS)
            {
                fReadOk = TRUE;

                /* Parse the DSI info */
                if (playcmd.dvd.playType != DR_TYPE_LBN)
                {
                    int i;

                    OS_SemTake(m_semAngleChg, OS_WAIT_FOREVER);

                    for (i=0; i<(int)ulSectorsToRead; i++)
                    {
                        /* DSI starts 1024 bytes later if this is a nav pack */
                        if (drParseDSI(m_dsi_packet, ((BYTE *)(KSEG1(pDataPtr)))+1024) == DR_SUCCESS )
                        {
                            /* Set cell position information of this vobu */
                            m_ulCellPosition = (m_dsi_packet.dsi_gi.vobu_vob_idn << 16);
                            m_ulCellPosition |= m_dsi_packet.dsi_gi.vobu_c_idn;

                            /* remember which sector this came from */
                            m_ulNavPackLBN = ulCurrentSector;

                            /* determine the VOBU end address */
                            ulVobuEndAddr = drGetVobuEndAddr(&m_dsi_packet, m_read_until_ref, m_ulNavPackLBN);

                            /* determine if VOBU contains a sequence end code by looking at the
                             * pci vobu_se_e_ptm value. A non-zero value indicates seq end exists */
                            fSeqEndDetected = (MAKE_DWORD(&( ((BYTE *)(KSEG1(pDataPtr)))[PCI_PACKET_OFFSET + VOBU_SE_E_PTM_OFFSET])) != 0);

                            /* send cell timing Info */
                            if (fSendTimeInfo == TRUE)
                            {
                                TIME45k startTime;
                                TIME45k stopTime;

                                /* Use the min of navpack scr from the DSI or the VOBU_S_PTM
                                 * if it's less than the navpack scr. This "should" never happen, but it does
                                 * on some "bad" content. */
                                startTime = MAKE_DWORD(&( ((BYTE *)(KSEG1(pDataPtr)))[PCI_PACKET_OFFSET + VOBU_S_PTM_OFFSET]))/2;
                                startTime = MIN(startTime, m_dsi_packet.dsi_gi.nv_pck_scr);

                                if (playcmd.dvd.fIsLastCell == FALSE)
                                {
                                    DBGPRINT(DBG_ON(DBG_TRACE), ("\n\nNOT LAST CELL\n\n"));
                                    stopTime = 0xffffffff;
                                }
                                else
                                {
                                    DBGPRINT(DBG_ON(DBG_TRACE), ("\n\nLAST CELL\n\n"));
                                    stopTime = m_dsi_packet.sml_pbi.vob_v_e_ptm/2;

                                    /* validate stop time */
                                    if (stopTime < startTime)
                                    {
                                        DBGPRINT(DBG_ON(DBG_TRACE), ("\n\nstopTime INVALID!\n\n"));
                                        stopTime = 0xffffffff;
                                    }
                                }

                                DBGPRINT(DBG_ON(DBG_TRACE), ("DR:dataRetrieve() -- startTime=0x%lx, stopTime=0x%lx\n",
                                    startTime, stopTime));

                                if (streamMessage.DiscontinuityAtBeginning == TRUE)
                                {
                                    drSendTimingInfo(1, VDVD_CONNECTION_1, startTime, stopTime, NULL);
                                }
                                else
                                {
                                    drSendTimingInfo(1, VDVD_CONNECTION_5, startTime, stopTime, NULL);
                                }

                                fSendTimeInfo = FALSE;
                            }

                            /* send vobu still and continuity count */
                            drSendVobuInfo(m_ulVobuCC++, playcmd.dvd.fIsVobuStill);
                        }
                        pDataPtr += DVD_SECTOR_SIZE;

⌨️ 快捷键说明

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