⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pbc_plcontrol.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*****************************************************************************
******************************************************************************
**                                                                          **
**  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 + -