📄 pbc_plcontrol.cpp
字号:
uiApplicationType = PlayCtrlGetCurrentApplicationType();
/* Notify application of application type */
if (hPBC->pCallback != NULL)
{
hPBC->pCallback(hPBC->pvCallbackContext, PLAYCTRL_EVENT_APPLICATION_TYPE, &uiApplicationType);
}
/* play the desired playitem */
PbcPLCtrlPlayPlayitem(hPBC, (uint16)(uiPrevPlayitemID), playitemID, time45k_StartTime, hPBC->fReverse, hPBC->ulPlayRate,
ubRandomShuffleIndex, fNewPlaylist, PBC_NEXT, VDVD_CONNECTION_ABORT, TRUE);
/* Put the Decoder in the normal run state */
PEiStreamCtrlResume(hPBC->hPE);
return (PLAYCTRL_SUCCESS);
errout:
/* Stop Playback */
PbcPLCtrlStopPL(hPBC, FALSE);
return (PLAYCTRL_FAILURE);
}
/**
* PbcPLCtrlStopPL -- Stop playback of a playlist.
*
* @param
* hPBC -- handle to playback control engine private data
*
* @retval
* PLAYCTRL_STATUS
*/
PLAYCTRL_STATUS PbcPLCtrlStopPL(PBC_HANDLE *hPBC, BOOLEAN fHoldPicture)
{
int i;
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcPLCtrlStopPL: ENTER\n"));
/* check for valid handle */
if (hPBC == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlStopPL: NULL handle!\n"));
return (PLAYCTRL_NULL_POINTER);
}
/* Stop Playback */
DRStop(hPBC->hDR);
/*
* Flush the decoder. Do not actually stop the PE so that the out-of-mux IG and
* TextST does not get flushed.
*/
for (i = 0; i < MAX_PE_INPUTS; i++)
{
PEiStreamCtrlFlush(hPBC->hPE, (PE_ISTREAMCTRL_INPUT)i);
}
/* If pop-up menu is on, turn it off */
if (PEiStreamCtrlIsPopupOn(hPBC->hPE) == TRUE)
{
PE_ISTREAMCTRL_IG_PARAM ig_param;
/* send pop-up off command to the PE */
ig_param.cmd = PE_IG_POPUP_OFF;
if (PEiStreamCtrlSendIGCmd(hPBC->hPE, &ig_param) != PE_SUCCESS)
{
return (PLAYCTRL_FAILURE);
}
}
/* cancel any trick modes
* fixes pause -> eject -> play */
PEiStreamCtrlResume(hPBC->hPE);
hPBC->ulPlayRate = 0;
hPBC->fReverse = 0;
hPBC->tState = PLAYCTRL_STATE_STOP;
hPBC->newpi.doneState = PBC_DECDONE_STATE_INACTIVE;
hPBC->newpi.playitemID = INVALID_PLAYITEM;
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"));
}
/* Clear repeat info */
memset(&hPBC->RepeatBlock, 0, sizeof(hPBC->RepeatBlock));
/* Reset flags that indicate waiting for prefills */
for (i = 0; i < MAX_PE_INPUTS; i++)
{
hPBC->fWaitingPrefill[i] = FALSE;
}
return (PLAYCTRL_SUCCESS);
}
/**
* PbcPLCtrlPlaylistComplete -- Playlist playback complete, stop playlist and send
* callback to notify playback complete.
*
* @param
* hPBC -- handle to playback control engine private data
* fError -- set if playback was terminated due to an error
*
* @retval
* PLAYCTRL_STATUS
*/
void PbcPLCtrlPlaylistComplete(PBC_HANDLE *hPBC, BOOLEAN fError)
{
PLAYCTRL_EVENT_CODE event;
/*
* If playlist playback is active then stop the pbc engine.
*/
if (hPBC->tState != PLAYCTRL_STATE_STOP)
{
/* stop the playlist */
if (PbcPLCtrlStopPL(hPBC, FALSE) != PLAYCTRL_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlPlaylistComplete: Failed to stop playlist\n"));
}
/* enter the stop state */
hPBC->tState = PLAYCTRL_STATE_STOP;
}
/* set event to send to callback */
event = (fError == TRUE) ? PLAYCTRL_EVENT_ERROR_PLAYLIST_TERMINATED : PLAYCTRL_EVENT_PLAYLIST_COMPLETE;
/*
* Send a callback event to notify the application environment that
* playback of a playlist is complete.
*/
if (hPBC->pCallback != NULL)
{
hPBC->pCallback(hPBC->pvCallbackContext, event, NULL);
}
DRQueueControl(hPBC->hDR, DR_STREAM_MAIN, DR_QUEUE_CMD_DISABLE);
}
/**
* PbcPLCtrlBegStream -- Handle the beginning of stream event from the PE.
*
* @param
* hPBC -- handle to playback control engine private data
* pPIContext -- pointer to playitem context of current playitem
* tInput -- PE Input pin that is at the beginning of stream
*
* @retval
* PLAYCTRL_STATUS
*/
PLAYCTRL_STATUS PbcPLCtrlBegStream(PBC_HANDLE *hPBC, PBC_PLAYITEM_CONTEXT *pPIContext, PE_ISTREAMCTRL_INPUT tInput, BOOLEAN fRepeatCall)
{
PLAYCTRL_STATUS status = PLAYCTRL_SUCCESS;
PLAYITEM *pCurrentPlayItem = NULL;
APPINFOPLAYLIST_TABLE *pPLAppInfo = NULL;
uint16 uiNextPlayitemID;
uint32 uiPlaylistID;
uint32 uiAngleNumber;
PE_ISTREAMCTRL_PLAYRATE OldPlayRate;
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcPLCtrlBegStream PI %u\n", pPIContext->uiPlayitemID));
/* verify input */
if ( (hPBC == NULL) || (pPIContext == NULL) )
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlBegStream: NULL pointer!\n"));
status = PLAYCTRL_NULL_POINTER;
goto errout;
}
/* make sure the playlist hasn't changed */
PbcRegGetPSR(PLAYCTRL_PSR_PLAYLIST, &uiPlaylistID);
if (pPIContext->uiPlaylistID != uiPlaylistID)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlBegStream: WRONG PLAYLIST!\n"));
status = PLAYCTRL_FAILURE;
goto errout;
}
/* Check which PE input pin hit beginning of stream */
if (tInput == INPUT_MAIN)
{
TIME45k time45k_StartTime;
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcPLCtrlBegStream PI %u: INPUT_MAIN\n", pPIContext->uiPlayitemID));
/* gives us a way out in the case where user changes playback before we hit the new playitem */
if (hPBC->newpi.abort == TRUE)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcPLCtrlBegStream PI %u: ABORTED\n", pPIContext->uiPlayitemID));
status = PLAYCTRL_SUCCESS;
goto out;
}
/* Only on first time through: */
if (!fRepeatCall && (VDVD_CONNECTION_ABORT != pPIContext->connection) )
{
if (hPBC->newpi.doneState == PBC_DECDONE_STATE_ACTIVE)
{
hPBC->newpi.doneState = PBC_DECDONE_STATE_INACTIVE;
}
else
{
SET_BIT(hPBC->newpi.doneState, PBC_DECDONE_STATE_WAITING_BOS);
}
}
/*
* --The Wait Loop--
* if the playitem hasn't transitioned, loop
*/
if ( GET_BIT(hPBC->newpi.doneState, PBC_DECDONE_STATE_WAITING_BOS) && (VDVD_CONNECTION_ABORT != pPIContext->connection) )
{
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcPLCtrlBegStream PI %u: rejected. haven't actually reached BOS\n", pPIContext->uiPlayitemID));
TIME45k time45k_CurrPTS;
static TIME45k time45k_PrevPTS = 0xffffffff;
PbcRegGetPSR(PLAYCTRL_PSR_PRES_TIME, &time45k_CurrPTS);
if ( ( (VDVD_CONNECTION_SEAMLESS_ANGLE == pPIContext->connection) &&
(time45k_CurrPTS >= pPIContext->ptsInTime ) ) ||
( (VDVD_CONNECTION_NONSEAMLESS_ANGLE == pPIContext->connection) &&
(time45k_CurrPTS == time45k_PrevPTS ) ) )
{
DBGPRINT(DBG_ON(DBG_ALL), ("PbcPLCtrlBegStream PI %u: Angle Change Catch - Angle edge detected\n", pPIContext->uiPlayitemID));
CLR_BIT(hPBC->newpi.doneState, PBC_DECDONE_STATE_WAITING_BOS);
}
else
{
time45k_PrevPTS = time45k_CurrPTS;
OS_TaskDelayMsec(100);
return (PLAYCTRL_RETRY);
}
}
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcPLCtrlBegStream: accepted for playitem %u. do BOS processing\n", pPIContext->uiPlayitemID));
hPBC->fReverse = (pPIContext->PlayRate.direction == PE_ISTREAMCTRL_DIRECTION_FORWARD) ? 0: 1;
hPBC->ulPlayRate = pPIContext->PlayRate.rate;
/*** ***/
/*** SET UP FOR CURRENTLY STARTING PLAYITEM ***/
/*** ***/
/*** this section sets the playitem and angle ***/
/*** registers to the current play and ***/
/*** configures the pe for the current play ***/
/* Get playlist info */
if (MPLSGetAppInfo(&pPLAppInfo) != MPLS_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlBegStream: MPLSGetAppInfo() Failed!\n"));
status = PLAYCTRL_FAILURE;
goto errout;
}
/*
* If playback type is random/shuffle then update the
* random/shuffle status information.
*/
if ( (pPLAppInfo->PlayList_playback_type == MPLS_RANDOM_PLAYLIST) ||
(pPLAppInfo->PlayList_playback_type == MPLS_SHUFFLE_PLAYLIST) )
{
/* Set current playitem index */
RandomShuffle.usCurrentIndex = pPIContext->ubRandomShuffleIndex;
if (RandomShuffle.usCount == RandomShuffle.usCurrentIndex)
{
/* Add this playitem to the list of played playitems */
RandomShuffle.usPlayedList[RandomShuffle.usCurrentIndex] = pPIContext->uiPlayitemID;
/* Increment count of played playitems */
RandomShuffle.usCount++;
/* If shuffle mode, then update list of available playitems */
if (pPLAppInfo->PlayList_playback_type == MPLS_SHUFFLE_PLAYLIST)
{
/* Look for this playitem in the list */
for (UBYTE i = 0; i < RandomShuffle.usNumberAvailable; i++)
{
/* If playitem is found, then remove it from list of available playitems */
if (RandomShuffle.usAvailableList[i] == pPIContext->uiPlayitemID)
{
/* Replace this playitem with playitem from end of list and shorten list by 1 */
RandomShuffle.usAvailableList[i] = RandomShuffle.usAvailableList[RandomShuffle.usNumberAvailable - 1];
RandomShuffle.usAvailableList[RandomShuffle.usNumberAvailable - 1] = 0xff;
RandomShuffle.usNumberAvailable--;
break;
}
}
}
}
}
/* get the playitem info for this playitem */
if (MPLSGetPlayItem(pPIContext->uiPlayitemID, &pCurrentPlayItem) != MPLS_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s:%u - MPLSGetPlayItem: Failed to get playitem!\n", __FILE__, __LINE__));
goto errout;
}
/* Get current value of the angle number register */
PbcRegGetPSR(PLAYCTRL_PSR_ANGLE, &uiAngleNumber);
uiAngleNumber &= 0x000000ff;
/*
* If the currently selected angle number is invalid, then set the angle number to 1.
*/
if (uiAngleNumber > pCurrentPlayItem->number_of_angles)
{
uiAngleNumber = 1;
if (pCurrentPlayItem->is_multi_angle == 1)
{
PbcRegSetPSR(PLAYCTRL_PSR_ANGLE, uiAngleNumber);
/* Send angle change event in callback */
if (hPBC->pCallback != NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -