📄 pe_consumer_dvd.cpp
字号:
*
* @param StreamContext
*
* @return None
*/
PE_STATUS cPEConsumer_DVD::ProcessEndOfStream(PVOID StreamContext)
{
/*
* Do not do anything. The End Of Stream event will get processed from NavPackTask
* when the last vobu is being presented.
*/
return (PE_SUCCESS);
}
/**
* If active start consuming and presenting AV data.
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer_DVD::processData(PEINPUTMESSAGE *pInMessage)
{
BYTE *pbData = NULL;
ULONG ulSize = 0;
TCH_PAYLOAD(pInMessage->payload);
if (pInMessage->fInfoPayload)
{
return(PE_FAILURE);
}
/* get payload info */
pbData = (BYTE*)pInMessage->payload->get_rd_ptr();
ulSize = (ULONG)pInMessage->payload->get_size();
/* if the data is encrypted then decrypt it */
if (CSS == pInMessage->Encryption)
{
BYTE *pbSector;
int sector_cnt = ulSize/2048;
register int i;
for (i = 0; i < sector_cnt; i++)
{
pbSector = pbData + i*2048;
if ( CSSDescramble( pbSector, m_DecodeKey ) != CSS_SUCCESS )
{
DBGPRINT(DBG_ON(DBG_TRACE),("ERROR: CSSDescramble failed\n"));
}
m_FirstTitleKeyPack = FALSE;
}
}
/* send the payload to the psdemux
* this will in turn feed the decode playback */
SendStreamMsgToDemux(pInMessage->payload, pInMessage);
return (PE_SUCCESS);
}
/**
* Process an info payload
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer_DVD::processInfo(PEINPUTMESSAGE *pInMessage)
{
INFOPAYLOAD *infoPayload;
/* get payload info */
infoPayload = (INFOPAYLOAD*)pInMessage->payload->get_base_ptr();
/* Check for encryption key */
if (infoPayload->bType == INFOTYPE_CRYPTKEY)
{
BYTE *pbData = NULL;
ULONG ulSize = 0;
pbData = infoPayload->data_packet.data;
ulSize = infoPayload->data_packet.size;
/* The payload is an encryption key, we need to save this */
#if DBG_ON(DBG_TRACE)
{
ULONG i;
DbgPrint(("Decode Key: "));
for (i = 0; i < ulSize; i++)
{
DbgPrint((" %02x", pbData[i]));
}
DbgPrint(("\n"));
}
#endif
/* This is just a simple way of telling if we have a cleartext key or a key handle */
if (ulSize == 5)
{
memcpy(&m_DecodeKey, pbData, ulSize);
}
else if (ulSize == 4)
{
/* SDK: delete css key if the decoder API uses key handles */
m_FirstTitleKeyPack = TRUE;
}
goto exit;
}
/* check for VOBU packet */
if (infoPayload->bType == INFOTYPE_VOBUINFO)
{
if ( (m_playrate.rate == PLAY_RATE_STEP) && (m_playrate.direction == PE_ISTREAMCTRL_DIRECTION_BACKWARD) )
{
m_fPauseAfterVOBU = TRUE;
}
/* If we are in VOBU still mode then we wait here for the still to be released.
* This will hold off data from the decoder/spu/navpack tasks */
while (m_fPauseAfterVOBU == TRUE)
{
OS_TaskDelayMsec(100);
if (m_fAbort == TRUE)
{
m_fPauseAfterVOBU = FALSE;
goto exit;
}
}
/* now check if the next vobu is a vobu still */
if ( infoPayload->vobu.fIsVobuStill == TRUE )
{
m_fPauseAfterVOBU = TRUE;
}
else
{
m_fPauseAfterVOBU = FALSE;
}
goto exit;
}
/* check for INFOTYPE_TIMEPACK packet */
if (infoPayload->bType == INFOTYPE_TIMEPACK )
{
pInMessage->semMsgDone = m_semPSDemxMsgSync;
}
/* send the info payload to the psdemux
* this will in turn send it to all of the output pins */
SendStreamMsgToDemux(pInMessage->payload, pInMessage);
exit:
return (PE_SUCCESS);
}
/**
* cPEConsumer_DVD::NavPackAVSync
*
* @return PE_STATUS
*/
void cPEConsumer_DVD::NavPackAVSync(TIME90k time90k_NavPackPTS, ULONG ulLastTickCount, BOOLEAN fVideoExists)
{
VDVD_ERROR error = VDVD_SUCCESS;
static TIME90k time90k_PrevPTS = 0;
TIME90k time90k_PTS = 0;
TIME90k time90k_STC = 0;
TIME45k time45k_PTS;
TIME45k time45k_STC;
int offset = 0;
BOOLEAN PrevPTSValid = FALSE;
DECODE_STATUS_TYPE d_status;
if (m_NvPckSyncState == PE_NVPCK_SYNC_FIRST)
{
return;
}
DBGPRINT(DBG_ON(DBG_NVPCK), ("NavPackAVSync - STARTING - nvpckPTS=%ld, VideoExist=%d\n",
time90k_NavPackPTS, fVideoExists));
while (FALSE == m_fFlushNavPacks)
{
if (m_playrate.discontiguous == FALSE)
{
if (m_videoDecode[0] != NULL)
{
/* TODO-SDK - Get the current PTS and STC of the decoder. */
error = m_videoDecode[0]->GetStatus(&d_status);
}
else if (m_videoDecode[1] != NULL)
{
error = m_videoDecode[1]->GetStatus(&d_status);
}
else if (m_audioDecode[0] != NULL)
{
/* TODO-SDK - Get the current PTS and STC of the decoder. */
error = m_audioDecode[0]->GetStatus(&d_status);
}
else if (m_audioDecode[1] != NULL)
{
error = m_audioDecode[1]->GetStatus(&d_status);
}
if (fVideoExists == TRUE)
{
/* use video pts & scr when it exists */
time45k_PTS = d_status.video_pts;
time45k_STC = d_status.video_stc;
}
else
{
/* use audio pts & scr since there is not video in this VOBU */
time45k_PTS = d_status.audio_pts;
time45k_STC = d_status.audio_stc;
}
/* navpack PTS is 90k so scale 45k value to 90k
* Note: keep bit0 so that values of 0x0 and 0xffffffff are still possible */
time90k_PTS = (time45k_PTS * 2) | (time45k_PTS & 0x00000001);
time90k_STC = (time45k_STC * 2) | (time45k_STC & 0x00000001);
}
else
{
time90k_PTS = 0;
time90k_STC = 0;
}
DBGPRINT(DBG_ON(DBG_NVPCK), ("NavPackAVSync: decoder info: PTS:%d, STC:%d\n",time45k_PTS,time45k_STC ));
/*
* if this is the first navpack then send it right away
*/
if (m_E_STD_Active == FALSE)
{
if ( (time90k_NavPackPTS == 0) && (m_playrate.direction == PE_ISTREAMCTRL_DIRECTION_FORWARD) )
{
DBGPRINT(DBG_ON(DBG_NVPCK), ("NavPackAVSync: first navpack\n"));
break;
}
}
/*
* If the data is contiguous use timestamps
*/
if (m_playrate.discontiguous == FALSE)
{
/*
* slow/normal and IP-FF playrate
*/
/* the STC is only useful for normal playrate */
if ( (m_playrate.rate == PLAY_RATE_NORMAL) || (fVideoExists == FALSE) )
{
if (m_E_STD_Active == TRUE)
{
/* get delta between current time and offset */
m_E_STD_Time = (LONG)time90k_STC - (LONG)m_E_STD_Offset;
if ((m_E_STD_Time >= m_E_STD_StartPTM) ||
((m_E_STD_RolledOver == TRUE) && (m_E_STD_Time < 0)) )
{
/* also we need to be sure the decoder has actually transitioned, that means
* waiting for a PTS that is in the next VOBU */
if ((time90k_PTS >= m_E_STD_StartPTM) && (time90k_PTS < (m_E_STD_StartPTM + 90000)))
{
/* as soon as we roll over, turn off the estd */
DBGPRINT(DBG_ON(DBG_NVPCK), ("Turn OFF ESTD 1\n"));
m_E_STD_Active = FALSE;
m_E_STD_Offset = 0;
m_E_STD_Time = 0;
m_E_STD_RolledOver = FALSE;
}
}
/* if the clock becomes positive and we haven't already sent the 0 time
* navpack send it now */
if ((m_E_STD_Time >= 0) && (m_time90k_NavPackPTS != 0))
{
DBGPRINT(DBG_ON(DBG_NVPCK), ("Kick out navpack during ESTD\n"));
m_E_STD_RolledOver = TRUE;
break;
}
/* we are in a still and ESTD mode, we have a valid last pts and it's equal to current,
* we check active here because we may have just turned E_STD active off */
if ((time90k_PTS == time90k_PrevPTS) && (PrevPTSValid == TRUE) && (m_E_STD_Active == TRUE))
{
/* if we are in a still and still using the old clocking during an estd transition
* base the time on the stc offset from the previous navpack */
offset = ((OS_GetTicks() - ulLastTickCount) / (OS_GetTickRate() / 1000)) * 90;
if (m_time90k_NavPackPTS + offset > time90k_NavPackPTS)
{
DBGPRINT(DBG_ON(DBG_NVPCK), ("Turn off estd KICK STILL ESTD time %lu\n\n", m_time90k_NavPackPTS + offset));
m_E_STD_Active = FALSE;
m_E_STD_Offset = 0;
m_E_STD_Time = 0;
m_E_STD_RolledOver = FALSE;
break;
}
}
}
else
{
/* if video does not exist then calculate the amount of time that has passed
* since the last navpack was sent. This is only valid for normal playrate */
if ( (fVideoExists == FALSE) && (m_playrate.rate == PLAY_RATE_NORMAL) )
{
if ((time90k_PTS == time90k_PrevPTS) && (PrevPTSValid == TRUE))
{
/* determine how much time has passed since the last navpack was sent */
offset = ((OS_GetTicks() - ulLastTickCount) / (OS_GetTickRate() / 1000)) * 90;
if (m_time90k_NavPackPTS + offset > time90k_NavPackPTS + 9000)
{
DBGPRINT(DBG_ON(DBG_NVPCK), ("NavPackAVSync: USING LAST NVPACK PTS\n"));
break;
}
}
}
/* don't use the STC if AVSync appears to be out */
if ( (m_NvPckSyncState == PE_NVPCK_SYNC_NORMAL) ||
((time90k_STC < time90k_PTS + 15000) && (time90k_PTS < time90k_STC + 15000)) )
{
offset = ((OS_GetTicks() - ulLastTickCount) / (OS_GetTickRate() / 1000)) * 90;
/* base sending navpacks on previous navpack send time and the offset between
* the current time and that one */
if (m_time90k_NavPackPTS + offset > time90k_NavPackPTS)
{
DBGPRINT(DBG_ON(DBG_NVPCK), ("NavPackAVSync: USING STC OFFSET\n"));
break;
}
}
else if ((time90k_PTS == time90k_PrevPTS) && (fVideoExists == TRUE))
{
/* if the pts isn't moving (we are at a still probably) and we have video
* use an offset based on the last navpack and the ticks since then */
offset = ((OS_GetTicks() - ulLastTickCount) / (OS_GetTickRate() / 1000)) * 90;
if (m_time90k_NavPackPTS + offset > time90k_NavPackPTS)
{
DBGPRINT(DBG_ON(DBG_NVPCK), ("NavPackAVSync: USING STC 2\n"));
break;
}
}
}
}
else
{
/* if we are in the E_STD active zone handle the rollover cases to kick out */
if (m_E_STD_Active == TRUE)
{
/* get delta between current time and offset */
m_E_STD_Time = (LONG)time90k_PTS - (LONG)m_E_STD_Offset;
/* if we hit the start time of the next vobu turn off estd, also turn it
* off if we have already rolled over and the time appears to have gone negative (in
* this case the low pts value and the high E_STD_offset make the time < 0) */
if ((m_E_STD_Time >= m_E_STD_StartPTM) ||
((m_E_STD_RolledOver == TRUE) && (m_E_STD_Time < 0)) )
{
DBGPRINT(DBG_ON(DBG_NVPCK), ("Turn off ESTD 2\n\n\n"));
m_E_STD_Active = FALSE;
m_E_STD_Offset = 0;
m_E_STD_Time = 0;
m_E_STD_RolledOver = FALSE;
}
/* if we hit the estd time and havent sent the 0 navpack, send it now
* Q: does this properly handle non-zero estd transitions? is that possible? */
if ((m_E_STD_Time >= 0) && (m_time90k_NavPackPTS != 0))
{
DBGPRINT(DBG_ON(DBG_NVPCK), ("NavPackAVSync: Send navpack after estd2\n"));
m_E_STD_RolledOver = TRUE;
break;
}
}
else
{
offset = time90k_PTS - m_LastPTS;
if (m_time90k_NavPackPTS + offset > time90k_NavPackPTS)
{
DBGPRINT(DBG_ON(DBG_NVPCK), ("NavPackAVSync: USING STC 2\n"));
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -