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

📄 dr_prefetch_vcd.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.cpp
 *
 * Prefetch class for the DR
 *
 * $Id: dr_prefetch_vcd.cpp,v 1.5 2007/01/04 23:45:25 rbehe Exp $
 */

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

#include "loader_app.h"
#include "dr_types.h"
#include "dr_prefetch_vcd.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




/**********************************************
 *
 * Implementations for DRPrefetch_VCD Derived Class
 *
 **********************************************/

/**
 * 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_VCD::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;
    cPayload                *pTempPayload             = NULL;
    DROUTPUTMESSAGE         streamMessage;
    ULONG                   i, j;
    BYTE                    *pbSrc;
    BYTE                    *pbDest;
    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;
        case DR_CD_SECTOR_MODE1:
            ulSectorSize = CD_MODE1_USER_DATA;
            dataselect = LOADER_CDDS_USER;
            break;
        case DR_CD_SECTOR_MODE2:
            ulSectorSize = CD_MODE2_USER_DATA;
            dataselect = LOADER_CDDS_USER;
            break;
        case DR_CD_SECTOR_MODE2_FORM1:
            ulSectorSize = CD_MODE2_FORM1_USER_DATA;
            dataselect = LOADER_CDDS_USER;
            break;
        case DR_CD_SECTOR_MODE2_FORM2:
            ulSectorSize = CD_ALLHDR_USER_ECC_SIZE;
            dataselect = LOADER_CDDS_ALLHDR_USER_ECC;
            pTempPayload   = drGetPayload();
            if (pTempPayload == NULL)
            {
                return (DR_FAILURE);
            }
            break;
        default:
            DbgPrint(("Sector Type doesn't exist\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);

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

        if (playcmd.cd.sectorType != DR_CD_SECTOR_MODE2_FORM2)
        {
            pTempPayload   = pStreamPayload;
        }

        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*)pTempPayload->get_wr_ptr(),
                         (ULONG)(pTempPayload->get_max_size())) != LOADER_SUCCESS)
        {
            /* ERROR RECOVERY */
            DbgPrint(("\n\nDR: LoaderSectorRead Error, sector = 0x%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;
            }
        }

        /* Special case for VCD playback */
        if (playcmd.cd.sectorType == DR_CD_SECTOR_MODE2_FORM2)
        {
            pbSrc  = (BYTE*)pTempPayload->get_rd_ptr();
            pbDest = (BYTE*)pStreamPayload->get_wr_ptr();

            ulWriteSize = 0;
            j=0;
            for (i=0; i<ulSectorsToRead; i++)
            {
                /* if it's not an empty sector */
                if (!( (  pbSrc[i*CD_ALLHDR_USER_ECC_SIZE + 6] == 0x20   ) ||
                       ( (pbSrc[i*CD_ALLHDR_USER_ECC_SIZE + 5] == 0x00) && 
                         (pbSrc[i*CD_ALLHDR_USER_ECC_SIZE + 7] == 0x1F)  )  )  )
                {
                    /* check for important flags in the non-user data */
                    streamMessage.SequenceEnd = (pbSrc[i*CD_ALLHDR_USER_ECC_SIZE + 6] & 0x81) ? pbSrc[i*CD_ALLHDR_USER_ECC_SIZE + 5] : 0;
                    streamMessage.AutoPause   = (pbSrc[i*CD_ALLHDR_USER_ECC_SIZE + 6] & 0x10) ? 1 : 0;

                    /* copy the user data to the stream payload */
                    memcpy(&pbDest[j*CD_MODE2_FORM2_USER_DATA], &pbSrc[i*CD_ALLHDR_USER_ECC_SIZE + 12], CD_MODE2_FORM2_USER_DATA);
                    ulWriteSize += CD_MODE2_FORM2_USER_DATA;
                    j++;
                }
                else
                {
                    DBGPRINT(DBG_ON(DBG_VERBOSE), ("DR: empty sector\n"));
                }

                if (streamMessage.AutoPause || streamMessage.SequenceEnd)
                {
                    DBGPRINT(DBG_ON(DBG_TRACE), ("\nfAutoPause: %u\n", streamMessage.AutoPause));
                    DBGPRINT(DBG_ON(DBG_TRACE), ("fSendSeqEnd: %u\n", streamMessage.SequenceEnd));
                    DBGPRINT(DBG_ON(DBG_TRACE), ("currentsector: %u\n\n", ulCurrentSector+i));
                    i++;
                    break;
                }
            }
            ulCurrentSector += i;
        }
        /* NORMAL IS HERE */
        else
        {
            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;
        }

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

    if (playcmd.cd.sectorType == DR_CD_SECTOR_MODE2_FORM2)
    {
        delete pTempPayload;
        pTempPayload = NULL;
    }

    return (DR_SUCCESS);
}



⌨️ 快捷键说明

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