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

📄 dr_prefetch_cdda.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
字号:
/*****************************************************************************
******************************************************************************
**                                                                          **
**  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_cdda.cpp
 *
 * Prefetch class for the DR
 *
 * $Id: dr_prefetch_cdda.cpp,v 1.8 2007/01/05 02:02:54 rbehe Exp $
 */

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

#include "loader_app.h"
#include "dr_types.h"
#include "dr_prefetch_cdda.h"

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

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


/* CD Specific Defines */
#define CD_TRICK_NUM_SECTORS    16
#define CD_SECTORS_PER_PAYLOAD  2





/**********************************************
 *
 * Implementations for DRPrefetch_CDDA Derived Class
 *
 **********************************************/


/**
 * Private function used to send a QData 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_CDDA::drSendQData(void)
{
    DR_ERROR        drStatus = DR_SUCCESS;
    DROUTPUTMESSAGE streamMessage;
    cPayload        *pStreamPayload = NULL;
    INFOPAYLOAD     *infoPayload    = NULL;
    BYTE            *pSubChannData  = NULL;

    /* 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_CDDA_QDATA;

    pSubChannData = (BYTE *)&(infoPayload->data_packet.data)[0];

    if (LoaderReadSubChannel(m_loader, TRUE, TRUE, 0x01, 0x00, pSubChannData, 12) != LOADER_SUCCESS)
    {
        DbgPrint(("\n\nDR: LoaderReadSubChannel Error\n"));
        drStatus = DR_FAILURE;
        goto errout;
    }

    /* set the data */
    infoPayload->data_packet.size   = 12;
    infoPayload->data_packet.offset = 0;

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

errout:

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

    return (drStatus);
}


/**
 * 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_CDDA::dataRetrieve(PLAYCMD playcmd)
{
    BOOLEAN                 fDataOk                   = FALSE;
    BOOLEAN                 fReadErr                  = FALSE;
    ULONG                   ulCurrentSector           = 0;
    ULONG                   ulSectorSize              = 1;
    ULONG                   ulWriteSize               = 0;
    ULONG                   ulSectorCount             = 0;
    ULONG                   ulNumSectors              = 0;
    ULONG                   ulSectorsToRead           = 0;
    LOADER_CD_DATA_SELECT   dataselect                = LOADER_CDDS_NONE;
    cPayload                *pStreamPayload           = NULL;
    DROUTPUTMESSAGE         streamMessage;
    ULONG                   ulHighBound, ulLowBound;

    OS_SemGive(m_semPlayQueueEnabled);

    if (playcmd.cd.playType == DR_TYPE_VOB)
    {
        return (DR_INVALID_PARAM);
    }

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

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

    if (playcmd.cd.playType == DR_TYPE_MSF)
    {
        /* translate addresses to lbn */
        playcmd.cd.ulStart = MSFUL_TO_LBA(playcmd.cd.ulStart);
        playcmd.cd.ulEnd  = MSFUL_TO_LBA(playcmd.cd.ulEnd);
    }

    /*
     * from here on, all addresses are in lbn
     */


    /* start at the beginning */
    ulCurrentSector  = playcmd.cd.ulStart - ((playcmd.cd.sSpeed < 0) ? CD_TRICK_NUM_SECTORS : 0);

    switch(playcmd.cd.sectorType)
    {
        case DR_CD_SECTOR_CDDA:
            ulSectorSize = CDDA_SECTOR_SIZE;
            dataselect = LOADER_CDDS_USER;
            break;
        default:
            DbgPrint(("Sector Type doesn't exist for CDDA playback\n"));
            return(DR_FAILURE);
            break;
    }

    DBGPRINT(DBG_ON(DBG_TRACE), ("DR_PLAY -- firstLBN=%x, lastLBN=%x, startLBN=%x\n", playcmd.cd.ulStart, playcmd.cd.ulEnd, ulCurrentSector));

    /* determine edge conditions of the read */
    ulLowBound  = (playcmd.cd.sSpeed > 0) ? playcmd.cd.ulStart : playcmd.cd.ulEnd;
    ulHighBound = (playcmd.cd.sSpeed > 0) ? playcmd.cd.ulEnd   : playcmd.cd.ulStart;

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

        /* if we should stop, then stop */
        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;
        }


        if (playcmd.cd.sSpeed == 1)
        {   /* normal forward play */

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

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

            /* Use the defined number of sectors only if it fits within the payload */
            if (CD_SECTORS_PER_PAYLOAD <= ulNumSectors)
            {
                ulNumSectors = CD_SECTORS_PER_PAYLOAD;
            }

            /* if we're at the end, only read what's left */
            if (ulNumSectors > ulSectorCount)
            {
                DBGPRINT(DBG_ON(DBG_TRACE), ("DRDataProc() -- ulSectorCount=%d, ulNumSectors=%d\n", ulSectorCount, ulNumSectors));
                ulNumSectors = ulSectorCount;
            }
        }
        else
        {   /* trick play */
            ulNumSectors = CD_TRICK_NUM_SECTORS;
        }

        /* set the user data to the starting location */
        if (playcmd.cd.playType == DR_TYPE_MSF)
        {
            pStreamPayload->set_user_data(LBA_TO_MSF(ulCurrentSector));
        }
        else
        {
            pStreamPayload->set_user_data(ulCurrentSector);
        }

        /* if the previous run had a read error, use the same ulSectorsToRead value */
        if (fReadErr == FALSE)
        {
            ulSectorsToRead = ulNumSectors;
        }

        fDataOk   = TRUE;
        fReadErr  = FALSE;

        /* do the read - loop until successful */
        while (LoaderCDRead(m_loader, ulCurrentSector, ulSectorsToRead,
                         (LOADER_CD_SECTOR_TYPE)playcmd.cd.sectorType, dataselect,
                         (BYTE*)pStreamPayload->get_wr_ptr(),
                         (ULONG)(pStreamPayload->get_max_size())) != LOADER_SUCCESS)
        {
            /* ERROR RECOVERY */
            DbgPrint(("\n\nDR: LoaderSectorRead Error, sector = %lx\n", (long)ulCurrentSector));
            ulWriteSize = 0;
            fReadErr    = TRUE;

            /* if an event callback is registered then send an error notification */
            if (m_event != NULL)
            {
                m_event(m_pContext, DR_EVENT_ERROR, NULL);
            }

            if (ulSectorsToRead > 1)
            {
                ulSectorsToRead /= 2;
            }
            else
            {
                /* the sector at ulCurrentSector is unreadable */
                fDataOk = FALSE;
                ulSectorsToRead = 0;

                /* leap ahead to look for a good sector */
                ulCurrentSector += 150;
            }
        }

        ulWriteSize = ulSectorsToRead * ulSectorSize;
        ulCurrentSector += ulSectorsToRead;

        /* for trick modes (in normal play this statement has no effect) */
        ulCurrentSector += (CD_TRICK_NUM_SECTORS * (playcmd.cd.sSpeed-1) );

        /* Update the write pointer */
        if (TRUE == fDataOk)
        {
            pStreamPayload->add_data(ulWriteSize);
        }

        /* force the EndOfStream flag */
        if ( (ulCurrentSector >  ulHighBound)  ||  /* playing fwd reached end of sectors */
             (ulCurrentSector <  ulLowBound )   )  /* playing rev reached beg of sectors */
        {
            streamMessage.EndOfStream = TRUE;
        }

        /* Send the Q-data for the last sector that was read from the loader */
        drSendQData();

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

        delete pStreamPayload;
        pStreamPayload = NULL;

        /* reset flags */
        streamMessage.BegOfStream              = FALSE;
        streamMessage.SequenceEnd              = FALSE;
        streamMessage.EndOfStream              = FALSE;
        streamMessage.DiscontinuityAtBeginning = FALSE;

    } while ( (ulCurrentSector <= ulHighBound) && (ulCurrentSector >= ulLowBound) );

    return(DR_SUCCESS);
}



⌨️ 快捷键说明

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