📄 pbc_plcontrol.cpp
字号:
/*****************************************************************************
******************************************************************************
** **
** Copyright (c) 2005-2006 Videon Central, Inc. **
** All rights reserved. **
** **
** The computer program contained herein contains proprietary information **
** which is the property of Videon Central, Inc. The program may be used **
** and/or copied only with the written permission of Videon Central, Inc. **
** or in accordance with the terms and conditions stipulated in the **
** agreement/contract under which the programs have been supplied. **
** **
******************************************************************************
*****************************************************************************/
/**
* @file pbc_plcontrol.cpp
*
* PlayList Control module of the Playback Control Engine.
* The PlayList Control module is responsible for starting and stopping playlist
* playback, as well as handling transitions between playitems in a playlist.
* This API is intended to be private and used by other Playback
* Control Engine modules only.
*
* $Id: pbc_plcontrol.cpp,v 1.184 2007/01/26 22:27:29 rbehe Exp $
*/
#include <stdlib.h>
#include <time.h>
#include "vdvd_types.h"
#include "utility.h"
#include "pbc_plcontrol.h"
#include "playctrl.h"
#include "pbc_types.h"
#include "pbc_engine.h"
#include "pbc_register.h"
#include "pbc_stnselect.h"
#include "../mvplaylistdb.h"
#include "dr_app.h"
#include "pe_app.h"
#include "dbgprint.h"
#include "usrapi.h"
#include "clpinfodb.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
/* Debug macros */
#define DBG_PLCONTROL DBG_ERROR
#define DBG_ON(x) (DBG_PLCONTROL >= x)
/* Data for shuffle play */
typedef struct tagRANDOM_PLAY
{
USHORT usCount;
USHORT usCurrentIndex;
USHORT usNumberAvailable;
USHORT usAvailableList[MAX_NUMBER_PLAYITEMS];
USHORT usPlayedList[MAX_NUMBER_PLAYITEMS];
} RANDOM_PLAY;
/**
* Local variables
*/
static RANDOM_PLAY RandomShuffle;
static RANDOM_PLAY RandomShuffleBackup;
static ULONG prevPlayitemPlayRate = 1000;
/**
* Local functions
*/
static PLAYCTRL_STATUS pbcplctrlConfigVideo(PBC_HANDLE *hPBC, uint32 uiPlaylistID, uint16 uiPlayitemID, ULONG ulVideoStn);
static PLAYCTRL_STATUS pbcplctrlConfigSecondaryAudio(PBC_HANDLE *hPBC, uint32 uiPlaylistID, uint16 uiPlayitemID, ULONG ulSecondaryAudioStn);
static PLAYCTRL_STATUS pbcPLCtrlGetAudioAttributes(STREAM_ATTRIBUTES *pAttributes, PE_ISTREAMCTRL_AUDIO_TYPE *pAudioType,
PE_ISTREAMCTRL_AUDIO_SAMPLING_FREQUENCY *pSamplingFrequency, PE_ISTREAMCTRL_AUDIO_CHANNELS *pChannels);
static BOOLEAN pbcPLCtrlIsSameClip(PBC_HANDLE *hPBC, PBC_STREAM_ENTRY_TYPE StreamEntryType, uint16 uiNewPlayitemID,
uint16 uiNewStn, uint16 uiOldPlayitemID, uint16 uiOldStn);
static uint16 pbcPLCtrlGetNumberOfClips(void);
/**
* PbcPLCtrlStartPL -- Start playback of a playlist.
*
* @param
* hPBC -- handle to playback control engine private data
* playlistID -- playlist id to start playback of
* playitemID -- start playback at this playitem
* ulStartTimestamp -- start playback at this presentation time within a playitem's clip
*
* @retval
* PLAYCTRL_STATUS
*/
PLAYCTRL_STATUS PbcPLCtrlStartPL(PBC_HANDLE *hPBC, uint32 playlistID, uint16 playitemID, TIME45k time45k_StartTime,
UBYTE ubRandomShuffleIndex, BOOLEAN fNewPlaylist)
{
uint32 uiChapterNumber;
PLAYLISTMARK_TABLE *pPLMark = NULL;
uint32 uiPrevPlayitemID;
uint8 uiApplicationType;
DBGPRINT(DBG_ON(DBG_TRACE), ("PbcPLCtrlStartPL: ENTER\n"));
/* Reset still flag and pending playlist complete flag */
hPBC->ulStillTime = 0;
hPBC->fPLCompletePending = FALSE;
/* Set the state information */
hPBC->fReverse = 0;
hPBC->ulPlayRate = 1000;
hPBC->tState = PLAYCTRL_STATE_PLAY;
hPBC->newpi.doneState = PBC_DECDONE_STATE_INACTIVE;
hPBC->newpi.playitemID = INVALID_PLAYITEM;
/* Notify if the playrate has changed */
PbcPLCtrlNotifyPlayRateChange(hPBC->ulPlayRate);
/* get playmark table */
MPLSGetPlayMark(&pPLMark);
DbgAssert(pPLMark != NULL);
/*
* If current title is interactive, then chapter has not meaning, so set chapter PSR to 0xFFFF.
* Otherwise, Calculate chapter number based on start playitem and pts.
* Note: Since this is the start of playback in a playlist,
* we should set the PSRs for Playlist, Playitem, and Chapter NOW, instead of waiting
* until the beginning of stream is received. This will prevent race
* conditions where the application starts the playlist, then checks these PSRs right away,
* and the PSRs have not been set because the beginning of stream wasn't received yet.
*/
if (hPBC->fInteractiveTitle == TRUE)
{
uiChapterNumber = 0xFFFF;
}
else
{
/* calculate the chapter number */
uiChapterNumber = PbcPLCtrlCalculatePLMark(pPLMark, playitemID, time45k_StartTime, ENTRY_MARK);
}
/* Get current PSR value for playitem ID so we know what the playitem was last played */
PbcRegGetPSR(PLAYCTRL_PSR_PLAYITEM, &uiPrevPlayitemID);
uiPrevPlayitemID &= 0x0000ffff;
/* Take register mutex semaphore */
OS_SemTake(hPBC->semRegisterMutex, OS_WAIT_FOREVER);
/* Set playlist, playitem, and chapter player register */
PbcRegSetPSR(PLAYCTRL_PSR_PLAYLIST, playlistID);
PbcRegSetPSR(PLAYCTRL_PSR_PLAYITEM, playitemID);
PbcRegSetPSR(PLAYCTRL_PSR_CHAPTER, uiChapterNumber);
PbcRegSetPSR(PLAYCTRL_PSR_PRES_TIME, time45k_StartTime);
/* Give register mutex semaphore */
OS_SemGive(hPBC->semRegisterMutex);
/*
* Set playmark id here. We do not want to think that we are crossing over a play mark
* when we get the first vsync and send a playmark change event, so we want to set the playmark
* id to the mark where playback will start from, even though it hasn't started yet. There
* is a test on JTD300 that was failing because we were sending the PlaybackMarkEvent anytime we
* started playback of a playlist. This fix will allow the test to pass.
*/
hPBC->usCurPLMarkID = (USHORT)(PbcPLCtrlCalculatePLMark(pPLMark, playitemID, time45k_StartTime, ENTRY_MARK | LINK_POINT));
/* Notify application of playitem change */
if (hPBC->pCallback != NULL)
{
uint32 tmp_playitemID = playitemID;
hPBC->pCallback(hPBC->pvCallbackContext, PLAYCTRL_EVENT_PLAYITEMCHANGE, &tmp_playitemID);
}
/* Enable the DR play queue */
DRQueueControl(hPBC->hDR, DR_STREAM_MAIN, DR_QUEUE_CMD_ENABLE);
/*
* If this is a new playlist, then stop the PE, and reconfigure the video.
* Also, load clip info.
*/
if (fNewPlaylist == TRUE)
{
uint16 uiNumPlayitems;
uint16 uiNumSubpaths;
PLAYITEM *pPlayitem = NULL;
SUBPATH *pSubpath = NULL;
uint16 uiNumClips;
uint16 i, j, k;
PEiStreamCtrlStop(hPBC->hPE, FALSE);
/*
* Configure video after loading clip info, since we need information from clipinfo
* to configure the video.
*/
/* count how many clips there are in this playlist */
uiNumClips = pbcPLCtrlGetNumberOfClips();
/*
* If there are enough clips to cause a delay while loading clip info, then
* send notification that we are loading a title.
*/
if (uiNumClips > MAX_CLIPS_QUICKLOAD)
{
ULONG out_msg[4];
out_msg[0] = VDVD_STATUS_LOADING;
out_msg[1] = VDVD_LOADING_TITLE;
UsrEventHandler(out_msg);
}
/*
* Preload all clip info for this entire playlist. Do this now so that
* clipinfo does not need to be loaded during playitem transitions.
*/
/* First, unload any previously loaded clip info */
ClpInfoMgrUnload();
/* Get number of playitems in this playlist */
if (MPLSGetNumberOfPlayItems(&uiNumPlayitems) != MPLS_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlStartPL: MPLSGetNumberOfPlayItems() FAILED!\n"));
goto errout;
}
/* Get number of subpaths in this playlist */
if (MPLSGetNumberOfSubPaths(&uiNumSubpaths) != MPLS_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlStartPL: MPLSGetNumberOfSubPaths() FAILED!\n"));
goto errout;
}
/* Load clip info for all playitems */
for (i = 0; i < uiNumPlayitems; i++)
{
/* get playitem info */
if (MPLSGetPlayItem(i, &pPlayitem) != MPLS_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlStartPL: MPLSGetPlayItem() FAILED!\n"));
goto errout;
}
/* Load clip info of the default angle clip for the playitem */
if (ClpInfoMgrLoad(GET_INT_FROM_ASCII5(pPlayitem->Clip_Information_file_name) ) != CLPINFO_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlStartPL: ClpInfoMgrLoad() FAILED!\n"));
goto errout;
}
/* Load clip info of other angle clips for the playitem */
if (pPlayitem->is_multi_angle == 1)
{
for (j = 1; j < pPlayitem->number_of_angles; j++)
{
/* Load clip info of the angle clip */
if (ClpInfoMgrLoad(GET_INT_FROM_ASCII5(pPlayitem->multi_clip_entry[j - 1].Clip_Information_file_name) ) != CLPINFO_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlStartPL: ClpInfoMgrLoad() FAILED!\n"));
goto errout;
}
}
}
}
/* Load clip info for all subpaths */
for (i = 0; i < uiNumSubpaths; i++)
{
/* get subpath info */
if (MPLSGetSubPath( (uint8)(i), &pSubpath) != MPLS_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("MPLSGetSubPath: MPLSGetSubPath() FAILED!\n"));
goto errout;
}
/* Load clip info for all sub-playitems of this subpath */
for (j = 0; j < pSubpath->number_of_SubPlayItems; j++)
{
/* Load clip info of the main clip for the sub-playitem */
if (ClpInfoMgrLoad(GET_INT_FROM_ASCII5(pSubpath->SubPlayItem[j].Clip_Information_file_name) ) != CLPINFO_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlStartPL: ClpInfoMgrLoad() FAILED!\n"));
goto errout;
}
/* Load clip info of sub-clips for the sub-playitem */
if (pSubpath->SubPlayItem[j].is_multi_Clip_entries == 1)
{
for (k = 1; k < pSubpath->SubPlayItem[j].number_of_Clip_entries; k++)
{
/* Load clip info of the angle clip */
if (ClpInfoMgrLoad(GET_INT_FROM_ASCII5(pSubpath->SubPlayItem[j].multi_clip_entry[k - 1].Clip_Information_file_name) ) != CLPINFO_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlStartPL: ClpInfoMgrLoad() FAILED!\n"));
goto errout;
}
}
}
}
}
/*
* If there are enough clips to cause a delay while loading clip info, then
* send notification that we are done loading a title.
*/
if (uiNumClips > MAX_CLIPS_QUICKLOAD)
{
ULONG out_msg[4];
out_msg[0] = VDVD_STATUS_LOAD_COMPLETE;
out_msg[1] = VDVD_LOADING_TITLE;
UsrEventHandler(out_msg);
}
/* Configure Video */
if (pbcplctrlConfigVideo(hPBC, playlistID, playitemID, 0) != PLAYCTRL_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PbcPLCtrlStartPL: pbcplctrlConfigVideo() FAILED!\n"));
goto errout;
}
}
/*
* Get application type for the playlist.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -