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

📄 pe_consumer_dvd.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

/*****************************************************************************
******************************************************************************
**                                                                          **
**  Copyright (c) 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 pe_consumer_dvd.cpp
 *
 * $Revision: 1.27 $ 
 *
 * PE Consumer DVD Derived Class Definition
 * The PE Consumer moves data from an input stream to a decoder or demux.
 *
 */

#include <stdlib.h>
#include "decoder.h"
#include "vdvd_types.h"
#include "osapi.h"
#include "dbgprint.h"
#include "pe_app.h"

#include "pe_consumer.h"
#include "pe_consumer_dvd.h"
#include "pe_types.h"
#include "spu_app.h"
#include "css.h"
#include "utility.h"

#define DEBUG_PE_CONSUMER_DVD   DBG_ERROR
#define DBG_NVPCK               DBG_VERBOSE
#define DBG_SUBPIC              DBG_VERBOSE
#define DBG_ON(x)               (DEBUG_PE_CONSUMER_DVD >= x)

#define PE_CONSUMER_DVD_PROC_PRIORITY   OS_TASK_NORMAL_PRIORITY
#define PE_CONSUMER_PROC_STACK_SIZE (16 * 1024)


/* number of messages accepted by the PSDemux before it blocks
 * this is kept at a minimum because the prefetch buffer is maintained in the DR */
#define INPUT_STREAM_DEPTH      1

/* number of messages accepted by spu before it blocks
 * the max bitrate for one stream is 3.36 Mbps, the SPU decoder does not buffer SPUs so the
 * buffer is maintained in the cStream. The number of messages required is ((3.36Mbps / 8) / 2048)
 * because each message holds 2048 of data. */
#define SUBPIC_NUM_MESSAGES     215

/* number of messages accepted by the bypass stream before it blocks
 * this is one because the buffering is in the decoder */
#define BYPASS_NUM_MESSAGES     1

/* number of messages accepted by the navpack stream before it blocks
 * PCI and DSI packets share the same message so this equates to 2 full navpacks
 * This allows us to feed 3 VOBU to the decoder before the PSDemux blocks */
#define NVPACK_NUM_MESSAGES     2


const UCHAR PCI_STRT[] = {0x00, 0x00, 0x01, 0xBF, 0x03, 0xD4, 0x00};
const UCHAR DSI_STRT[] = {0x00, 0x00, 0x01, 0xBF, 0x03, 0xFA, 0x01};


/**
 * peConsumerNavPackTaskCaller
 *
 * @return ULONG
 */
static ULONG peConsumerNavPackTaskCaller(PVOID pvParam)
{
    PE_STATUS status = PE_SUCCESS;

    if (NULL != pvParam)
    {
        status = ( (cPEConsumer_DVD*)pvParam )->NavPackTask(pvParam);
    }

    OS_TaskExit();

    return (status);
}

/**
 * peConsumerPlaybackTaskCaller
 *
 * @return ULONG
 */
static ULONG peConsumerPlaybackTaskCaller(PVOID pvParam)
{
    PE_STATUS status = PE_SUCCESS;

    if (NULL != pvParam)
    {
        status = ( (cPEConsumer_DVD*)pvParam )->PlaybackTask(pvParam);
    }

    OS_TaskExit();

    return (status);
}

/**
 * peConsumerDVDSubpicSyncCallback
 *
 * @return SPU_ERR
 */
static SPU_ERR peConsumerDVDSubpicSyncCallback(PVOID pContext, TIME90k time90k_TargPTS, TIME90k *ptime90k_CurrSTC)
{
    if ( ((cPEConsumer_DVD*)(pContext))->SubpicSyncCallback(time90k_TargPTS, ptime90k_CurrSTC) == PE_SUCCESS)
    {
        return (SPU_SUCCESS);
    }
    else
    {
        return (SPU_FAILURE);
    }

} /* end peConsumerDVDSubpicSyncCallback() */

/**
 * cPEConsumer_DVD::Configure
 *
 * @return PE_STATUS
 */
PE_STATUS cPEConsumer_DVD::Configure(PE_CONSUMER_CONFIG_INFO *pConfigInfo)
{
    PE_STATUS status;

    DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_DVD::Configure()\n"));

    /* base class does work required by all consumers */
    status = cPEConsumer::Configure(pConfigInfo);

    if (status == PE_SUCCESS)
    {
        /* Create and initialize cStreams */
        DBGPRINT(DBG_ON(DBG_VERBOSE), ("cPEConsumer_DVD::Configure() - create cStreams\n"));
        if (CreateStreams() != PE_SUCCESS)
        {
            DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer_DVD::Configure() - Could not create cStreams\n"));
            goto error_out;
        }

        /* Create and initialize a program stream demux
         * This will be used to demux the subpicture and navpack data */
        DBGPRINT(DBG_ON(DBG_VERBOSE), ("cPEConsumer_DVD::Configure() - create PSDemux\n"));
        if (CreatePSDemux() != PE_SUCCESS)
        {
            DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer_DVD::Configure() - Could not create PSDemux\n"));
            goto error_out;
        }

        /* DVD needs to demux navpacks */
        DBGPRINT(DBG_ON(DBG_VERBOSE), ("cPEConsumer_DVD::Configure() - Start navpack demux\n"));
        if (pcDemux->AttachOutputStream(0xBF, 0, DEMUX_ANY, NVPCK, m_pNvPckStream) != DEMUX_PASS)
        {
            DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer_DVD::Configure() - Could not start Navpack Demux\n"));
            goto error_out;
        }

        /* Create a task to read navpacks from psdemux and syncronize them to the scr */
        task_navpack = OS_TaskSpawnParam("PENavPck", PE_CONSUMER_DVD_PROC_PRIORITY, PE_CONSUMER_PROC_STACK_SIZE,
            peConsumerNavPackTaskCaller, this, NULL);

        /* Create send date task */
        task_playback = OS_TaskSpawnParam("PEPbcTsk", PE_CONSUMER_DVD_PROC_PRIORITY, PE_CONSUMER_PROC_STACK_SIZE,
            peConsumerPlaybackTaskCaller, this, NULL);
    }


    return (status);

error_out:
    return (PE_FAILURE);
}

/**
 * cPEConsumer_DVD::Reset
 *
 * @return PE_STATUS
 */
PE_STATUS cPEConsumer_DVD::Reset(void)
{
    PE_STATUS          status;
    DEMUXOUTPUTMESSAGE *pMessage = NULL;

    if (m_ConsumerState == PE_CONSUMER_STATE_UNREALIZED)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer_DVD::Reset() - PE_INVALID_STATE (%d)\n", m_ConsumerState));
        return (PE_INVALID_STATE);
    }

    /* clear prefill since we are going to stop state */
    m_fPrefill        = FALSE;
    m_fSuspend        = FALSE;
    m_fPauseAfterVOBU = FALSE;

    /* start flushing */
    DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_DVD::Reset() - start flushing\n"));
    m_fFlushNavPacks  = TRUE;
    m_fFlushPlayback  = TRUE;

    if ( (IS_PECONSUMER_STATE_RUNNING(m_ConsumerState) == TRUE) && (m_fStop == FALSE) )
    {
        PEINPUTMESSAGE *pInMessage = NULL;

        m_fStop  = TRUE;
        m_fAbort = TRUE;

        /* kick the dataProc so it won't wait */
        pInMessage = (PEINPUTMESSAGE*)m_InputStream->GetMsg(OS_NO_WAIT);
        if (pInMessage != NULL)
        {
            m_InputStream->Write(pInMessage);
        }

        /* stop the PSDemux */
        DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_DVD::Reset() - stop the PSDemux\n"));
        pcDemux->Stop();

        /* Flush the spu decoder
         * NOTE: disable forced subpics so the the current spu doesn't get displayed during the flush */
        DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_DVD::Reset() - SPUStop\n"));
        if (m_spu_decoder != NULL)
        {
            ULONG ulSPDStatus;
            SPUGetStatus(m_spu_decoder, &ulSPDStatus);
            if ((ulSPDStatus & SPU_STATE_MASK) != SPU_STATE_STOPPED)
            {
                DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer_DVD::Reset() stop spu decoder, pids %d %d\n", m_spu_pesID, m_spu_subID));
                SPUDisableForced(m_spu_decoder);
                SPUStop(m_spu_decoder);
            }
        }

        /* wait for transition to stopped state */
        DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_DVD::Reset() - Wait for stopped state\n"));
        while (m_fStop == TRUE)
        {
            OS_TaskYield();
        }
    }

    /* send termination messages to the PSDemux output streams */
    pMessage = (DEMUXOUTPUTMESSAGE*)m_pNvPckStream->GetMsg(OS_WAIT_1S);
    if (pMessage != NULL)
    {
        pMessage->fTerminate = TRUE;
        m_pNvPckStream->Write(pMessage);
    }
    pMessage = (DEMUXOUTPUTMESSAGE*)m_pBypassStream->GetMsg(OS_WAIT_1S);
    if (pMessage != NULL)
    {
        pMessage->fTerminate = TRUE;
        m_pBypassStream->Write(pMessage);
    }

    /* use the base clase to terminate the main consumer task */
    DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_DVD::Reset() - base clase terminate\n"));
    status = cPEConsumer::Reset();

    /* wait until the dvd consumer tasks have terminated */
    DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_DVD::Reset() - wait until tasks have terminated\n"));
    OS_TaskJoin(task_navpack);
    OS_TaskJoin(task_playback);
    OS_TaskDelete(task_navpack);
    OS_TaskDelete(task_playback);

    if (m_spu_decoder != NULL)
    {
        ULONG ulSPDStatus = 0;

        /* if the subpic stop is still in progress wait for it to complete */
        SPUGetStatus(m_spu_decoder, &ulSPDStatus);
        while ((ulSPDStatus & SPU_STATE_MASK) == SPU_STATE_STOPPING)
        {
            OS_TaskDelayMsec(100);
            SPUGetStatus(m_spu_decoder, &ulSPDStatus);
        }

        /* detach stream from spu before we delete it */
        SPUDetachInputStream(m_spu_decoder);
        m_spu_pesID = -1;
        m_spu_subID = -1;
    }

    /* cleanup the ps demux */
    if (pcDemux != NULL)
    {
        /* detach the navpack stream from the demux */
        DBGPRINT(DBG_ON(DBG_TRACE), ("DeletePSDemux: detach the navpack stream from the demux\n"));
        pcDemux->DetachOutputStream(m_pNvPckStream);

        /* delete the ps demux */
        DeletePSDemux();
    }

    /* delete any streams we've created */
    DeleteStreams();

    return (status);

} /* end cPEConsumer_DVD::Reset() */

/**
 * Private function that creates a PSDemux class and the input stream used to feed it data.
 *
 * @param None
 *
 * @return PE_STATUS.
 */
PE_STATUS cPEConsumer_DVD::CreatePSDemux(void)
{
    /* Create the program stream demux */
    pcDemux = new cDemux;
    if (NULL == pcDemux)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("%s: Could not create cDemux\n", __FUNCTION__));
        goto error_out;
    }

    /* create semaphore used for message synchronization */
    m_semPSDemxMsgSync = OS_SemBCreateNamed(OS_SEM_Q_FIFO, OS_SEM_EMPTY, "semDmxMsg");
    if (m_semPSDemxMsgSync == 0)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("%s: Could not create semDmxMsg\n", __FUNCTION__));
        goto error_out;
    }

    /* create semaphore used for message synchronization */
    m_semNavPackState = OS_SemBCreateNamed(OS_SEM_Q_FIFO, OS_SEM_FULL, "semNVpckState");
    if (m_semNavPackState == 0)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("%s: Could not create semNVpckState\n", __FUNCTION__));
        goto error_out;
    }

    /* Attach the Demux input stream */
    if (pcDemux->AttachInputStream(m_pDemuxInStream) != DEMUX_PASS)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("%s: Could not attach input stream\n", __FUNCTION__));
        goto error_out;
    }

    /* Create the demux task */
    if (pcDemux->Create("PSDemux", DEMUX_MPEG2) != DEMUX_PASS)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("%s: Could not create PSDemux\n", __FUNCTION__));
        goto error_out;
    }

    /* attach a bypass output stream to feed the playback */
    if (pcDemux->AttachOutputStream(0, 0, DEMUX_ANY, BYPASS, m_pBypassStream) != DEMUX_PASS)
    {
        DbgPrint(("%s, %d, FAILED TO ADD BYPASS DEMUX\n", __FILE__, __LINE__));
        goto error_out;
    }

    return (PE_SUCCESS);

error_out:
    DBGPRINT(DBG_ON(DBG_ERROR), ("CreatePSDemux: FAILED\n"));
    return (PE_FAILURE);
}

/**
 * Private function that deletes the PSDemux class and the input stream used to feed it data.
 *
 * @param None
 *
 * @return PE_STATUS
 */
PE_STATUS cPEConsumer_DVD::DeletePSDemux(void)
{
    DBGPRINT(DBG_ON(DBG_TRACE), ("DeletePSDemux: Delete the program stream demux\n"));

    /* Delete the program stream demux */
    if (NULL != pcDemux)
    {
        /* detach the bypass stream from the demux */
        DBGPRINT(DBG_ON(DBG_TRACE), ("DeletePSDemux: detach the bypass stream from the demux\n"));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -