📄 dr_prefetch_dvd.cpp
字号:
/* Have we reached the end of the current VOBU?
* NOTE: we play up and including this sector so increment after check */
if (ulCurrentSector++ == ulVobuEndAddr)
{
if (fSeqEndDetected == TRUE)
{
/* the seq end flag is indicated at the beginning of the vobu
* so we need to wait until we've actually read the vobu before
* we send the sequence end flag */
if (m_dsi_packet.dsi_gi.vobu_2ndref_ea == 0)
{
/* if there is no 2ndref then this is an I-Frame only */
streamMessage.SequenceEnd = 0x03;
}
else
{
streamMessage.SequenceEnd = 0x01;
}
streamMessage.DiscontinuityAtEnd = TRUE;
}
/* determine the next sector */
ulNextSector = drGetNextSectorAddr(&m_dsi_packet, playcmd.dvd.ulStart, playcmd.dvd.ulEnd, ulVobuEndAddr, m_ulNavPackLBN);
/* if we are in a discontinuous read mode and this was the last sector
* then stop here and send it to the decoder */
if (m_read_until_ref != DR_NORMAL_PLAYBACK)
{
/* we are skipping data so mark the discontinuity
* and send this off to the PE */
streamMessage.DiscontinuityAtEnd = TRUE;
}
/*
* throw away the rest of the sectors
* We will start reading from the new address calculated above.
* Since we want to include the current sector add one to the current count.
*/
ulCurrentSector = ulNextSector;
ulSectorsToRead = i + 1;
break;
}
}
OS_SemGive(m_semAngleChg);
}
else /* lbn playback */
{
ulCurrentSector += ulSectorsToRead;
}
}
else
{
/* ERROR RECOVERY */
DbgPrint(("\nLoaderSectorReadAV Error, sector = %lx\n\n", (long)ulCurrentSector));
/* if a event callback is registered then send an error notification */
if (m_event != NULL)
{
m_event(m_pContext, DR_EVENT_ERROR, NULL);
}
/* The dvd nav handles error recovery in VOBU or CELL mode */
if (playcmd.dvd.playType == DR_TYPE_LBN)
{
ulCurrentSector += ulSectorsToRead;
ulSectorsToRead = 0;
}
else
{
/* so we don't report errors reading the same sector again */
m_fAbort = TRUE;
}
fReadOk = FALSE;
}
/* Update the write pointer */
if (TRUE == fReadOk)
{
pStreamPayload->add_data(ulSectorsToRead * DVD_SECTOR_SIZE);
}
/* make sure we kick out if we hit the end */
if (ulCurrentSector > playcmd.dvd.ulEnd)
{
ulCurrentSector = SRI_END_OF_CELL;
break;
}
ulLoopBuf += ulSectorsToRead;
if (ulCurrentSector == SRI_END_OF_CELL)
{
break;
}
if (streamMessage.DiscontinuityAtEnd == TRUE)
{
break;
}
/* if a flush is requested just drop everything */
if (m_fAbort == TRUE)
{
break;
}
}
/* force the EndOfStream flag */
if ((ulCurrentSector > playcmd.dvd.ulEnd) || /* playing fwd reached end of sectors */
(ulCurrentSector < playcmd.dvd.ulStart)) /* playing rev reached beg of sectors */
{
streamMessage.EndOfStream = TRUE;
}
streamMessage.StreamContext = playcmd.dvd.pvContext;
/* send navpack id with the message */
streamMessage.ulVobuCC = m_ulVobuCC;
streamMessage.fIsVobuStill = playcmd.dvd.fIsVobuStill;
/* transfer the payload to the PE */
drSendStream(streamMessage, pStreamPayload);
delete pStreamPayload;
pStreamPayload = NULL;
if (streamMessage.SequenceEnd != FALSE)
{
/* reset flags */
streamMessage.SequenceEnd = FALSE;
fSeqEndDetected = FALSE;
}
/* reset flags */
streamMessage.DiscontinuityAtBeginning = FALSE;
streamMessage.DiscontinuityAtEnd = FALSE;
streamMessage.EndOfStream = FALSE;
streamMessage.BegOfStream = FALSE;
/* for rewind */
if ( (m_skip_vobu > DR_FWDI_NEXT) && (ulCurrentSector < playcmd.dvd.ulStart) )
{
break;
}
} while (ulCurrentSector <= playcmd.dvd.ulEnd);
return(DR_SUCCESS);
}
/**
* drGetTitleKey - get the title key for the current sector
*
* @param ulSector - the current sector
*
* @retval none
*
* @remarks none.
*/
DR_ERROR DRPrefetch_DVD::drGetTitleKey(ULONG ulSector)
{
cPayload *pStreamPayload = NULL;
DROUTPUTMESSAGE streamMessage;
DR_ERROR status = DR_FAILURE;
streamMessage.fInfoPayload = TRUE;
/* Get a payload buffer to work with */
pStreamPayload = drGetPayload();
if (NULL != pStreamPayload)
{
BYTE *pbData;
INFOPAYLOAD *infoPayload;
infoPayload = (INFOPAYLOAD*)pStreamPayload->get_base_ptr();
infoPayload->bType = INFOTYPE_CRYPTKEY;
pbData = infoPayload->data_packet.data;
/* Scan for the first sector with a title key.
* Give up if not found in first 16 sectors */
for (int i=0; i<16; i++)
{
if (LoaderSectorRead(m_loader, ulSector, pbData, 1) != LOADER_SUCCESS)
{
/* ERROR RECOVERY */
DbgPrint(("\nLoaderSectorRead Error while retrieving title key, sector = %lx\n\n", (long)ulSector));
/* if a event callback is registered then send an error notification */
if (m_event != NULL)
{
m_event(m_pContext, DR_EVENT_ERROR, NULL);
}
status = DR_FAILURE;
break;
}
else
{
/* determine if sector is encrypted */
if (MAKE_DWORD(pbData) == 0x000001BA)
{
if ( (((BYTE*)(KSEG1(pbData)))[20] & 0x30) &&
( ((BYTE*)(KSEG1(pbData)))[17] != 0xbd) )
{
DBGPRINT(DBG_ON(DBG_TRACE), ("DRCommandProc() -- DR_TITLE_KEY sector = %lx\n", (long)ulSector));
status = DR_SUCCESS;
break;
}
}
ulSector++;
}
if (m_fAbort == TRUE)
{
break;
}
}
if (DR_SUCCESS == status)
{
BYTE bDataSize;
/* bDataSize is used in case we need to pass encrypted or unencrypted keys or something else entirely */
if (CSSGetTitleKey(m_loader, ulSector, &pbData[0], &bDataSize) == CSS_FAILURE)
{
/* return an error */
DbgPrint((" ERROR, CANNOT GET TITLE KEY\n"));
status = DR_FAILURE;
}
else
{
/* we've got the title key, send it to the PE */
infoPayload->data_packet.size = (ULONG)bDataSize;
/* send navpack id with the message */
streamMessage.ulVobuCC = m_ulVobuCC;
streamMessage.fIsVobuStill = FALSE;
/* transfer the payload to the PE */
if (drSendStream(streamMessage, pStreamPayload) != DR_SUCCESS)
{
/* return an error */
status = DR_FAILURE;
}
}
}
else
{
DbgPrint(("DRCommandProc: DR_TITLE_KEY -- COULD NOT FIND TITLE KEY!!!\n"));
}
/* delete the payload */
delete pStreamPayload;
}
/* Done getting title key, transition to IDLE */
DBGPRINT(DBG_ON(DBG_TRACE), ("DRCommandProc: DR_TITLE_KEY -- Done getting title key\n"));
return (status);
}
/**
* drParseDSI - parse the DSI packet
*
* @param dsi_packet - output: the dsi packet as a struct
* @param buf - the buffer containing the dsi packet information
*
* @retval none
*
* @remarks none.
*/
const UCHAR DSI_STRT[] = {0x00, 0x00, 0x01, 0xBF, 0x03, 0xFA, 0x01};
inline DR_ERROR drParseDSI(dsipkt_struct &dsi_packet, UCHAR *buf)
{
USHORT n;
USHORT i;
//DbgAssert(dsi_packet != NULL);
DbgAssert(buf != NULL);
/* check that we have proper header else bomb */
for (n = 0; n < 7; n++)
{
if (buf[n] != DSI_STRT[n])
{
return (DR_FAILURE);
}
}
/* parse the DSI_GI for a total of 32 bytes */
n = 7;
/* get NV_PCK_SCR */
dsi_packet.dsi_gi.nv_pck_scr = MAKE_DWORD(&buf[n]);
n += 4;
/* get NV_PCK_LBN */
dsi_packet.dsi_gi.nv_pck_lbn = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_EA */
dsi_packet.dsi_gi.vobu_ea = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_1STREF_EA */
dsi_packet.dsi_gi.vobu_1stref_ea = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_2NDREF_EA */
dsi_packet.dsi_gi.vobu_2ndref_ea = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_3RDREF_EA */
dsi_packet.dsi_gi.vobu_3rdref_ea = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_VOB_IDN */
dsi_packet.dsi_gi.vobu_vob_idn = MAKE_WORD(&buf[n]);
n += 3; /* reserved byte follows VOBU_VOB_IDN */
/* get VOBU_C_IDN */
dsi_packet.dsi_gi.vobu_c_idn = buf[n];
n += 1;
/* dump Cell Elapse Time on the floor */
n += 4;
/* next parse the SML_PBI for a total of 148 bytes */
/* starting with VOBU_SML_CAT */
dsi_packet.sml_pbi.vobu_sml_cat = MAKE_WORD(&buf[n]);
n += 2; /* skip reserved byte */
/* get ILVU_EA */
dsi_packet.sml_pbi.ilvu_ea = MAKE_DWORD(&buf[n]);
n += 4;
/* get NXT_ILVU_SA */
dsi_packet.sml_pbi.nxt_ilvu_sa = MAKE_DWORD(&buf[n]);
n += 4;
/* get NXT_ILVU_SZ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -