📄 dr_prefetch_vcd.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 + -