📄 pbc_engine.cpp
字号:
}
/* clear the queue */
hPBC->newpi.abort = FALSE;
OS_MsgQReset(hPbcEngine->MsgQID);
return (PLAYCTRL_SUCCESS);
}
/**
* PbcEngineMapPBCFunctions -- Map commands to PBC functions through function pointers.
*
* @param
* none
*
* @retval
* PLAYCTRL_STATUS
*/
static PLAYCTRL_STATUS PbcEngineMapPBCFunctions(void)
{
if (hPbcEngine == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineMapPBCFunctions: pbc engine not created!\n"));
return (PLAYCTRL_FAILURE);
}
/* Set function pointers */
hPbcEngine->PbcFunc[PLAYCTRL_PLAYPLPLAYITEM] = PbcPbScenarioPlayPLPI;
hPbcEngine->PbcFunc[PLAYCTRL_LINKPI] = PbcPbScenarioLinkPI;
hPbcEngine->PbcFunc[PLAYCTRL_PLAYPLMARK] = PbcPbScenarioPlayPLMark;
hPbcEngine->PbcFunc[PLAYCTRL_LINKMARK] = PbcPbScenarioLinkMark;
hPbcEngine->PbcFunc[PLAYCTRL_PLAYPLTIME] = PbcPbScenarioPlayPLTime;
hPbcEngine->PbcFunc[PLAYCTRL_LINKTIME] = PbcPbScenarioLinkTime;
hPbcEngine->PbcFunc[PLAYCTRL_STOP] = PbcPbScenarioStop;
hPbcEngine->PbcFunc[PLAYCTRL_SUSPEND] = PbcPbScenarioSuspend;
hPbcEngine->PbcFunc[PLAYCTRL_RESUME] = PbcPbScenarioResume;
hPbcEngine->PbcFunc[PLAYCTRL_SKIPTONEXTPOINT] = PbcPbScenarioSkipNext;
hPbcEngine->PbcFunc[PLAYCTRL_SKIPTOPREVPOINT] = PbcPbScenarioSkipPrev;
hPbcEngine->PbcFunc[PLAYCTRL_RESTARTPOINT] = PbcPbScenarioRestartPoint;
hPbcEngine->PbcFunc[PLAYCTRL_REPEAT] = PbcPbScenarioRepeat;
hPbcEngine->PbcFunc[PLAYCTRL_PLAY] = NULL;
hPbcEngine->PbcFunc[PLAYCTRL_PAUSEON] = PbcAvPresPauseOn;
hPbcEngine->PbcFunc[PLAYCTRL_PAUSEOFF] = PbcAvPresPauseOff;
hPbcEngine->PbcFunc[PLAYCTRL_STILLON] = PbcAvPresStillOn;
hPbcEngine->PbcFunc[PLAYCTRL_STILLOFF] = PbcAvPresStillOff;
hPbcEngine->PbcFunc[PLAYCTRL_FORWARDPLAY] = PbcAvPresForwardPlay;
hPbcEngine->PbcFunc[PLAYCTRL_BACKWARDPLAY] = PbcAvPresBackwardPlay;
hPbcEngine->PbcFunc[PLAYCTRL_AUDIOCHANGE] = PbcAvPresAudioChange;
hPbcEngine->PbcFunc[PLAYCTRL_SECONDARYAUDIOCHANGE] = PbcAvPresSecondaryAudioChange;
hPbcEngine->PbcFunc[PLAYCTRL_SUBTITLECHANGE] = PbcAvPresSubtitleChange;
hPbcEngine->PbcFunc[PLAYCTRL_SUBTITLEDISPLAY] = PbcAvPresSubtitleDisplay;
hPbcEngine->PbcFunc[PLAYCTRL_ANGLECHANGE] = PbcAvPresAngleChange;
hPbcEngine->PbcFunc[PLAYCTRL_IGCHANGE] = PbcAvPresIGChange;
hPbcEngine->PbcFunc[PLAYCTRL_TEXTSUBTITLESTYLECHANGE] = PbcAvPresTextSTStyleChange;
hPbcEngine->PbcFunc[PLAYCTRL_GETNUMTEXTSUBTITLESTYLES] = PbcAvPresGetNumTextSTStyles;
hPbcEngine->PbcFunc[PLAYCTRL_SELECTBUTTONPAGE] = PbcIGSelectButtonPage;
hPbcEngine->PbcFunc[PLAYCTRL_POPUPON] = PbcIGPopUpOn;
hPbcEngine->PbcFunc[PLAYCTRL_POPUPOFF] = PbcIGPopUpOff;
hPbcEngine->PbcFunc[PLAYCTRL_ENABLEBUTTON] = PbcIGEnableButton;
hPbcEngine->PbcFunc[PLAYCTRL_DISABLEBUTTON] = PbcIGDisableButton;
hPbcEngine->PbcFunc[PLAYCTRL_MOVEUPSELECTEDBUTTON] = PbcIGMoveUpSelectedButton;
hPbcEngine->PbcFunc[PLAYCTRL_MOVEDOWNSELECTEDBUTTON] = PbcIGMoveDownSelectedButton;
hPbcEngine->PbcFunc[PLAYCTRL_MOVELEFTSELECTEDBUTTON] = PbcIGMoveLeftSelectedButton;
hPbcEngine->PbcFunc[PLAYCTRL_MOVERIGHTSELECTEDBUTTON] = PbcIGMoveRightSelectedButton;
hPbcEngine->PbcFunc[PLAYCTRL_SELECTBUTTON] = PbcIGSelectButton;
hPbcEngine->PbcFunc[PLAYCTRL_ACTIVATEBUTTON] = PbcIGActivateButton;
hPbcEngine->PbcFunc[PLAYCTRL_SELECTANDACTIVATEBUTTON] = PbcIGSelectAndActivateButton;
hPbcEngine->PbcFunc[PLAYCTRL_ACTIVATEBUTTON_COMPLETE] = PbcIGActivateButtonComplete;
hPbcEngine->PbcFunc[PLAYCTRL_RESET_USER_TIMEOUT] = PbcIGResetUserTimeout;
return (PLAYCTRL_SUCCESS);
}
/**
* PbcEngineDRCallback -- DR Callback Event handler.
*
* @param
* pContext -- context pointer that is registered with DR
* event -- DR event
* pEventInfo -- pointer to information associated with event
*
* @retval
* DR_ERROR
*/
static DR_ERROR PbcEngineDRCallback(PVOID pContext, DR_EVENT_CODE event, PVOID pEventInfo)
{
PBC_HANDLE *hPBC = (PBC_HANDLE *)pContext;
DR_ERROR tStatus = DR_SUCCESS;
PBCENGINE_MSGTYPE tMsgType = PBCENGINE_MSGTYPE_INVALID;
ULONG ulData0 = 0;
ULONG ulData1 = 0;
BOOLEAN fSendMsg = FALSE;
/* Check for valid context pointer */
if (pContext == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: Invalid context pointer!\n"));
return (DR_FAILURE);
}
/* Check for valid pbc engine module handle */
if (hPbcEngine == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: Invalid pbc engine handle!\n"));
return (DR_FAILURE);
}
/* Check for valid DR callback event */
if (event >= DR_EVENT_CODE_INVALID)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: Invalid DR Event callback!\n"));
return (DR_FAILURE);
}
/* Evaluate the DR callback event */
switch (event)
{
case DR_EVENT_BUFFER_EMPTY:
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcEngineDRCallback: DR_EVENT_BUFFER_EMPTY\n"));
break;
case DR_EVENT_COMMAND_BUFFER_EMPTY:
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcEngineDRCallback: DR_EVENT_COMMAND_BUFFER_EMPTY\n"));
break;
case DR_EVENT_ERROR:
switch ((ULONG)pEventInfo)
{
case DR_AACS_FAILURE:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_AACS_FAILURE\n"));
/* TODO: Add code to process this failure */
break;
default:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_ERROR\n"));
break;
}
break;
case DR_EVENT_COMMAND_ERROR:
switch ((ULONG)pEventInfo)
{
case DR_ATTACH_LOADER:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_ATTACH_LOADER\n"));
break;
case DR_ATTACH_STREAM:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_ATTACH_STREAM\n"));
break;
case DR_ATTACH_EVENT:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_ATTACH_EVENT\n"));
break;
case DR_IDENTIFY_TYPE:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_IDENTIFY_TYPE\n"));
break;
case DR_DETACH_STREAM:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_DETACH_STREAM\n"));
break;
case DR_PLAY_BDROM:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_PLAY_BDROM\n"));
break;
case DR_PLAY_DVD:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_PLAY_DVD\n"));
break;
case DR_PLAY_CD:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_PLAY_CD\n"));
break;
case DR_STOP:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_STOP\n"));
break;
case DR_STOP_STREAM:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_STOP_STREAM\n"));
break;
case DR_SET_DVD_SPEED:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_SET_DVD_SPEED\n"));
break;
case DR_SET_DVD_ANGLE:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_SET_DVD_ANGLE\n"));
break;
case DR_SET_BDROM_ANGLE:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_SET_BDROM_ANGLE\n"));
break;
case DR_QUEUE_CONTROL:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_QUEUE_CONTROL\n"));
break;
case DR_RESET:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, DR_RESET\n"));
break;
default:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: DR_EVENT_COMMAND_ERROR, UNSUPPORTED!!!\n"));
tStatus = DR_FAILURE;
break;
}
break;
default:
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: Unknown DR Event callback\n"));
tStatus = DR_FAILURE;
break;
}
/*
* If message should be sent to PBC engine task, then send message.
*
* NOTE: We do not take the PBC semaphore since that could lead to
* a deadlock.
*/
if (fSendMsg == TRUE)
{
PBCENGINE_MESSAGE msg;
/* Load message parameters */
msg.tMsgType = tMsgType;
msg.hPbc = hPBC;
msg.ulData0 = ulData0;
msg.ulData1 = ulData1;
msg.ulSemID = 0;
msg.pulRetVal = NULL;
/* Send message to be processed by the pbc engine task */
if (OS_MsgQSend(hPbcEngine->MsgQID, (char *)&msg, sizeof(PBCENGINE_MESSAGE), OS_NO_WAIT, OS_MSG_PRI_NORMAL) != OS_OK)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: Failure sending message!\n"));
tStatus = DR_FAILURE;
}
}
return (tStatus);
}
/**
* PbcEngineCallback -- PE Event Callback handler.
*
* @param
* pContext -- context pointer that is registered with PE
* event -- PE event
* pEventInfo -- pointer to information associated with event
*
* @retval
* PE_STATUS
*
* NOTE: This is called from the context of the PE
* You should NEVER call PE APIs from this function as this can lead to dead lock conditions
*/
static PE_STATUS PbcEnginePECallback(PVOID pContext, PE_EVENT_CODE event, PVOID pEventInfo)
{
PBC_HANDLE *hPBC = (PBC_HANDLE *)pContext;
PE_STATUS tStatus = PE_SUCCESS;
PBCENGINE_MSGTYPE tMsgType = PBCENGINE_MSGTYPE_INVALID;
ULONG ulData0 = 0;
ULONG ulData1 = 0;
ULONG ulData2 = 0;
BOOLEAN fSendMsg = FALSE;
/* Check for valid pbc engine module handle */
if (hPbcEngine == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEngineDRCallback: Invalid pbc engine handle!\n"));
return (DR_FAILURE);
}
/* Check for valid PE callback event */
if (event >= PE_EVENT_CODE_INVALID)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcEnginePEiStrmCtrlCallback: Invalid PE Event!\n"));
return (PE_FAILURE);
}
/* Evaluate the PE callback event */
switch (event)
{
case PE_EVENT_IDLE:
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcEnginePEiStrmCtrlCallback: PE_EVENT_IDLE\n"));
/* check the input */
if (pEventInfo == NULL)
{
return (PE_FAILURE);
}
if (((PE_IDLE_EVENT_INFO *)pEventInfo)->pContext == NULL)
{
return (PE_FAILURE);
}
/* Send beginning of stream msg to pbc msg queue. */
fSendMsg = TRUE;
tMsgType = PBCENGINE_MSGTYPE_BEG_STREAM;
ulData0 = (ULONG)(((PE_IDLE_EVENT_INFO *)pEventInfo)->pContext);
ulData1 = ((PE_IDLE_EVENT_INFO *)pEventInfo)->input;
ulData2 = (ULONG)FALSE;
break;
case PE_EVENT_BEG_OF_STREAM:
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcEnginePEiStrmCtrlCallback: PE_EVENT_BEG_OF_STREAM\n"));
PBC_PLAYITEM_CONTEXT *pPIContext;
/* check the input */
if (pEventInfo == NULL)
{
return (PE_FAILURE);
}
if (((PE_BEG_OF_STREAM_EVENT_INFO *)pEventInfo)->pContext == NULL)
{
return (PE_FAILURE);
}
/* set the context */
pPIContext = (PBC_PLAYITEM_CONTEXT *)(((PE_BEG_OF_STREAM_EVENT_INFO *)pEventInfo)->pContext);
if ( ((PE_BEG_OF_STREAM_EVENT_INFO *)pEventInfo)->input == INPUT_MAIN)
{
uint32 uiLastPlayitemID;
PE_ISTREAMCTRL_PLAYRATE CurrentPlayRate;
uint32 uiPlaylistID;
PLAYITEM *pCurrentPlayItem = NULL;
fSendMsg = TRUE;
/* Get Playlist, Last Playitem, and Current play rate */
PbcRegGetPSR(PLAYCTRL_PSR_PLAYLIST, &uiPlaylistID);
uiLastPlayitemID = hPBC->newpi.playitemID;
CurrentPlayRate = ((PE_BEG_OF_STREAM_EVENT_INFO *)pEventInfo)->pe_rate;
/*
* a new playitem is beginning. set the newpi informational flags.
*/
hPBC->newpi.marker_pts = 0;
if (uiLastPlayitemID != INVALID_PLAYITEM)
{
if (MPLSGetPlayItem( (uint16)(uiLastPlayitemID), &pCurrentPlayItem) == MPLS_SUCCESS)
{
hPBC->newpi.marker_pts = (!hPBC->fReverse) ? pCurrentPlayItem->OUT_time : pCurrentPlayItem->IN_time;
}
}
hPBC->newpi.playitemID = pPIContext->uiPlayitemID;
hPBC->newpi.fReverse = (pPIContext->PlayRate.direction == PE_ISTREAMCTRL_DIRECTION_FORWARD) ? 0: 1;
/* check the playlist is still valid */
if (pPIContext->uiPlaylistID == uiPlaylistID)
{
if ( ( pPIContext->connection == VDVD_CONNECTION_1 ) ||
( pPIContext->connection == VDVD_CONNECTION_NONSEAMLESS_ANGLE ) ||
( pPIContext->PlayRate.discontiguous != CurrentPlayRate.discontiguous ) )
{
/*
* Non-Seamless Case
*
* Need to check if there is a non-seamless connection between this new playitem
* and the previous playitem. If the connection is non-seamless, then this means that
* the pe will need re-configured. Since the PE needs reconfigured, it will need to
* be idle until the re-configuration is complete. So, we need to return an event status
* to the PE to tell it to stay idle until it is resumed. It will be resumed after it
* had been reconfigured by the PBC Engine.
*
* We also want to wait for decode to be done on the previous before processing beginning of stream.
*/
tStatus = PE_EVNT_IDLE | PE_EVNT_WAIT_FOR_DONE;
fSendMsg = FALSE;
}
else if ( ( pPIContext->connection == VDVD_CONNECTION_5 ) ||
( pPIContext->connection == VDVD_CONNECTION_6 ) )
{
/*
* Seamless Case
*
* get the playitem info for the currently playing playitem (PSR and newpi.playitemID are equal at this point)
* we want to know it's out point so that we can wait for it to complete
* before we transition the PSR values to the next playitem
*/
tStatus = PE_EVNT_WAIT_FOR_DONE;
}
else if ( pPIContext->connection == VDVD_CONNECTION_ABORT )
{
/*
* Abort Case
*
* This is the case where we're restarting playback. We'll go idle, but we won't wait for done
*
*/
tStatus = PE_EVNT_IDLE;
fSendMsg = FALSE;
}
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s:%u - Invalid Playlist!\n", __FILE__, __LINE__));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -