📄 pbc_avpres.cpp
字号:
/* check for valid handle */
if (hPBC == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("pbcAvPresPlay: NULL handle!\n"));
return (PLAYCTRL_NULL_POINTER);
}
/* Halt the DR play queue so the DR status can't change */
DRQueueControl(hPBC->hDR, DR_STREAM_MAIN, DR_QUEUE_CMD_DISABLE);
/* find out context of the dr's current play */
DRGetStatus(hPBC->hDR, DR_STREAM_MAIN, DR_STATCMD_CONTEXT, (uint32 *)&pPIContext);
/* make sure the playlist hasn't changed */
PbcRegGetPSR(PLAYCTRL_PSR_PLAYLIST, &uiPlaylistID);
uiPlaylistID &= 0x0000ffff;
if (pPIContext->uiPlaylistID != uiPlaylistID)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s: WRONG PLAYLIST!\n", __FUNCTION__));
status = PLAYCTRL_FAILURE;
goto errout;
}
DBGPRINT(DBG_ON(DBG_TRACE), ("current speed: %i --- new speed: %i\n",
((hPBC->fReverse) ? -1 : 1) * hPBC->ulPlayRate, ((fReverse) ? -1 : 1) * ulNewSpeed));
/* If there's a change - do it. */
if ( (ulNewSpeed != hPBC->ulPlayRate) || (ulNewSpeed == 1) || (hPBC->fReverse != fReverse) )
{
PE_ISTREAMCTRL_PLAYRATE PlayRate;
PE_ISTREAMCTRL_PLAYRATE OldPlayRate;
PE_ISTREAMCTRL_DIRECTION PlayDirection;
uint16 uiNextPlayitemID = INVALID_PLAYITEM;
UBYTE ubNextRandomShuffleIndex = 0xff;
TIME45k time45k_PTS;
APPINFOPLAYLIST_TABLE *pAppInfoPL = NULL;
BOOLEAN fSendNext = TRUE;
PBC_WHICH_CONTEXT pwContext;
VDVD_CONNECT_COND connection = VDVD_CONNECTION_6;
BOOLEAN fStopCalled = FALSE;
/* rate changed: clear the old playitems out of the queue
* if something was removed, re-use that context */
if (DR_SUCCESS == DRQueueControl(hPBC->hDR, DR_STREAM_MAIN, DR_QUEUE_CMD_CLEAR))
{
pwContext = PBC_CURRENT;
}
else
{
pwContext = PBC_NEXT;
}
/* Get the Desired PE PlayRate configuration */
PlayDirection = (!fReverse) ? PE_ISTREAMCTRL_DIRECTION_FORWARD: PE_ISTREAMCTRL_DIRECTION_BACKWARD;
PEiStreamCtrlConfigPlayRateParam(hPBC->hPE, ulNewSpeed, PlayDirection, &PlayRate);
/* Get the Current PE PlayRate configuration */
PEiStreamCtrlGetRate(hPBC->hPE, &OldPlayRate);
/* Get playlist info */
if (MPLSGetAppInfo(&pAppInfoPL) != MPLS_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("pbcAvPresPlay: Failed to get playlist info!\n"));
status = PLAYCTRL_FAILURE;
goto errout;
}
/* If playlist is random/shuffle playback type, then restore random/shuffle status */
if ( (pAppInfoPL->PlayList_playback_type == MPLS_RANDOM_PLAYLIST) ||
(pAppInfoPL->PlayList_playback_type == MPLS_SHUFFLE_PLAYLIST) )
{
ubNextRandomShuffleIndex = PbcPLCtrlGetRandomShuffleIndex(hPBC);
}
/* if the rate change requires a change to the DR */
if ( (OldPlayRate.discontiguous == 1) || (PlayRate.discontiguous == 1) )
{
fSendNext = FALSE;
DBGPRINT(DBG_ON(DBG_TRACE), ("%s:%u - DR change required\n", __FUNCTION__, __LINE__));
/* C->D (same dir) */ /* @todo - this is a temporary change to simplify the trickmode cases ...
if this goes back in, will need to not set hPBC->fReverse here
(instead happens in BegStream)*/
if (0) //( (0 == OldPlayRate.discontiguous) && (1 == PlayRate.discontiguous) && ( hPBC->fReverse == fReverse ) )
{
/* find clean transition point */
if (DRBDROMStopAtPoint(hPBC->hDR, FALSE, (ULONG *)&time45k_PTS, (PVOID *)&pPIContext) != DR_FAILURE)
{
/* if we successfully found a change point in the current playitem,
* RE-SEND THE CURRENT playitem with the new speed, and starting at the change point */
DBGPRINT(DBG_ON(DBG_TRACE), ("successfuly found a speed change point in the clip\n"));
uiNextPlayitemID = pPIContext->uiPlayitemID;
}
else
{
/* if we don't successfully find a change point in the current playitem,
* SEND THE NEXT play item, with the correct speed and with the play item's
* listed start and end times. */
DBGPRINT(DBG_ON(DBG_TRACE), ("DID NOT find a speed change point in the clip\n"));
fSendNext = TRUE;
}
DBGPRINT(DBG_ON(DBG_VERBOSE), ("next play item id number: %u\n", uiNextPlayitemID));
}
/* D->C || D->D || C->D (opp dir) */
else
{
uint32 uiPlayitemID;
TIME45k time45k_STC;
/* pause the decoder */
if (PEiStreamCtrlPause(hPBC->hPE) != PE_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s:%u - FAILED to pause the decoder\n", __FUNCTION__, __LINE__));
status = PLAYCTRL_FAILURE;
goto errout;
}
/* stop feeding */
DRStop(hPBC->hDR);
/* get pts from decoder and use it to update location (guarantee we're exactly at the pause point) */
if (PEiStreamCtrlGetVidPTS(hPBC->hPE, &time45k_PTS, &time45k_STC) != PE_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s:%u - FAILED to get Video PTS\n", __FUNCTION__, __LINE__));
status = PLAYCTRL_FAILURE;
goto errout;
}
PbcPLCtrlUpdateLocation(hPBC, time45k_PTS);
OS_SemTake(hPBC->semRegisterMutex, OS_WAIT_FOREVER);
/* Get the playitem, and presentation time register values */
PbcRegGetPSR(PLAYCTRL_PSR_PLAYITEM, &uiPlayitemID);
uiNextPlayitemID = (uint16)(uiPlayitemID & 0x0000ffff);
PbcRegGetPSR(PLAYCTRL_PSR_PRES_TIME, &time45k_PTS);
OS_SemGive(hPBC->semRegisterMutex);
PEiStreamCtrlStopStream(hPBC->hPE, INPUT_MAIN, TRUE);
fStopCalled = TRUE;
connection = VDVD_CONNECTION_ABORT;
}
}
/* C->C case skips the above block */
/* the *next* playitem to be played is the one we're going to send */
if (fSendNext)
{
/* send the *next* playitem to the DR (replace what was cleared) */
uiNextPlayitemID = PbcPLCtrlGetNextPlayitem(hPBC, pPIContext->uiPlayitemID);
/* Get pointer to the playitem from the movie playlist database */
if (uiNextPlayitemID != INVALID_PLAYITEM)
{
if (MPLSGetPlayItem(uiNextPlayitemID, &pPlayItem) != MPLS_SUCCESS)
{
DbgAssert(0);
}
time45k_PTS = (!fReverse) ? pPlayItem->IN_time : pPlayItem->OUT_time;
}
/* If playlist is random/shuffle playback type, then restore random/shuffle status */
if ( (pAppInfoPL->PlayList_playback_type == MPLS_RANDOM_PLAYLIST) ||
(pAppInfoPL->PlayList_playback_type == MPLS_SHUFFLE_PLAYLIST) )
{
ubNextRandomShuffleIndex += (fReverse ? -1 : 1);
}
connection = VDVD_CONNECTION_UNDEF;
}
else
{
/* fixes a bug: the previous begOfStream is waiting and will be accepted
* once the next playitem begins. If we're calling another DRPlay()
* we need to clear this flag because it will be re-set by this
* DRPlay()s BegOfStream.
*/
hPBC->newpi.abort = TRUE;
if (PLAYCTRL_FAILURE == pbcEngineSendMessage(PBCENGINE_MSGTYPE_ABORT_COMPLETE, hPBC, 0, 0, 0, 0, 0, NULL))
{
/* @todo: handle this very bad case (though it *should* never happen) */
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcAvPres: PBCENGINE_MSGTYPE_ABORT_COMPLETE: pbcEngineSendMessage FAILED. FIX ME!!\n"));
}
}
/* set the pe rate */
PEiStreamCtrlSetRate(hPBC->hPE, &PlayRate);
/* restart the pe if necessary */
if (fStopCalled)
{
PEiStreamCtrlPrefill(hPBC->hPE, INPUT_MAIN, PE_ASYNC);
}
if (MPLSGetPlayItem(pPIContext->uiPlayitemID, &pPlayItem) != MPLS_SUCCESS)
{
DbgAssert(0);
}
if (!pPlayItem->PlayItem_random_access_flag)
{
pPIContext->PlayRate = PlayRate;
}
if ( (OldPlayRate.discontiguous == 1) && (0 == PlayRate.discontiguous) )
{
uint32 uiPGTextStn;
uint32 uiIGStn;
DBGPRINT(DBG_ON(DBG_TRACE), ("%s:%u - Reconfigure Demuxes\n", __FUNCTION__, __LINE__));
PbcRegGetPSR(PLAYCTRL_PSR_PG_AND_ST_STN, &uiPGTextStn);
uiPGTextStn &= 0x00000fff;
/* Configure PG and Text ST */
if (PbcPLCtrlConfigPGandTextST(hPBC, uiPlaylistID, pPIContext->uiPlayitemID, uiPGTextStn) != PLAYCTRL_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s: PbcPLCtrlConfigPGandTextST() FAILED!\n", __FUNCTION__));
}
PbcRegGetPSR(PLAYCTRL_PSR_IG_STN, &uiIGStn);
uiIGStn &= 0x000000ff;
if ( (pPlayItem->STN_table.number_of_IG_stream_entries > 0) &&
(pPlayItem->STN_table.IG_stream[uiIGStn - 1].stream_entry.type == 1) )
{
/* Configure IG */
if (PbcPLCtrlConfigIG(hPBC, uiPlaylistID, pPIContext->uiPlayitemID, uiIGStn) != PLAYCTRL_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s:: PbcPLCtrlConfigIG() FAILED!\n", __FUNCTION__));
}
}
}
else if ( (OldPlayRate.discontiguous == 0) && (1 == PlayRate.discontiguous) )
{
uint32 uiIGStn;
PbcRegGetPSR(PLAYCTRL_PSR_IG_STN, &uiIGStn);
uiIGStn &= 0x000000ff;
DBGPRINT(DBG_ON(DBG_TRACE), ("%s:%u - Remove Demuxes\n", __FUNCTION__, __LINE__));
PEiStreamCtrlDemuxRemovePG(hPBC->hPE);
if ( (pPlayItem->STN_table.number_of_IG_stream_entries > 0) &&
(pPlayItem->STN_table.IG_stream[uiIGStn - 1].stream_entry.type == 1) )
{
/* Get new value of stream number registers */
PEiStreamCtrlDemuxRemoveIG(hPBC->hPE);
}
}
/* and Send the DR playitem */
if (uiNextPlayitemID != INVALID_PLAYITEM)
{
ULONG ulSendSpeed = ulNewSpeed;
DBGPRINT(DBG_ON(DBG_TRACE), ("%s:%u - Send New DR Play Command\n", __FUNCTION__, __LINE__));
if (ulSendSpeed == 0)
{
/* We don't really want the BegStream code to know it's at "paused" speed.
Instead, we want it to know that the data is being sent in normal speed */
ulSendSpeed = 1000;
}
PbcPLCtrlPlayPlayitem(hPBC, pPIContext->uiPlayitemID, uiNextPlayitemID, time45k_PTS,
fReverse, ulSendSpeed, ubNextRandomShuffleIndex, FALSE, pwContext, connection, FALSE);
}
}
else
{
DBGPRINT(DBG_ON(DBG_TRACE), ("speed didn't change - nothing needed to happen\n"));
}
if (status == PLAYCTRL_SUCCESS)
{
/* Set the play rate and direction */
hPBC->ulPlayRate = ulNewSpeed;
hPBC->fReverse = fReverse;
hPBC->tState = (ulNewSpeed == 1) ? PLAYCTRL_STATE_PAUSE : PLAYCTRL_STATE_PLAY;
}
errout:
DRQueueControl(hPBC->hDR, DR_STREAM_MAIN, DR_QUEUE_CMD_ENABLE);
return (status);
}
/**
* PbcAvPresAudioChange -- Change presentation of audio to specified audio stream
*
* @param
* hPBC -- handle to playback control engine private data
* data1 -- audio stream number
* data2 -- not used
* data3 -- not used
*
* @retval
* PLAYCTRL_STATUS
*/
PLAYCTRL_STATUS PbcAvPresAudioChange(PBC_HANDLE *hPBC, ULONG data1, ULONG data2, ULONG data3)
{
uint32 uiPlayItemID = 0;
PLAYITEM *pPlayItem = NULL;
uint32 uiAudioStnCurrent;
uint32 uiAudioStnNew;
uint32 uiAudioStnNext;
PLAYCTRL_STATUS status = PLAYCTRL_SUCCESS;
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcAvPresAudioChange: audio stream = %d\n", data1));
/* check for valid handle */
if (hPBC == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcAvPresAudioChange: NULL handle!\n"));
return (PLAYCTRL_NULL_POINTER);
}
/* if we're currently stopped then just update the PSR */
if (hPBC->tState == PLAYCTRL_STATE_STOP)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcAvPrePbcAvPresAudioChange: JUST UPDATE PSR\n"));
/* update the current audio selection */
OS_SemTake(hPBC->semRegisterMutex, OS_WAIT_FOREVER);
PbcRegGetPSR(PLAYCTRL_PSR_AUDIO_STN, &uiAudioStnCurrent);
uiAudioStnCurrent &= 0xffffff00;
uiAudioStnCurrent |= (data1 & 0x000000ff);
PbcRegSetPSR(PLAYCTRL_PSR_AUDIO_STN, uiAudioStnCurrent);
OS_SemGive(hPBC->semRegisterMutex);
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcAvPresAudioChange: PSR = 0x%lx\n", uiAudioStnCurrent));
/* send event, notifying application of subtitle change */
if (hPBC->pCallback != NULL)
{
uint32 tmp_data1 = data1;
hPBC->pCallback(hPBC->pvCallbackContext, PLAYCTRL_EVENT_AUDIOCHANGE, &tmp_data1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -