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

📄 pg_parse.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
******************************************************************************
**                                                                          **
**  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 pg_parse.cpp
 *
 * $Revision: 1.7 $ 
 *
 * Parse routines for the PG module
 *
 */
#include "vdvd_types.h"
#include "pg_api.h"
#include "pg_parse.h"
#include "pg_render.h"
#include "pg_util.h"
#include "pg_defs.h"
#include "utility.h"
#include "pg_graphics.h"
#include <directfb.h>

#define DEBUG_PG_PARSE  DBG_ERROR
#define DBG_ON(x)       (DEBUG_PG_PARSE >= x)

/* data declarations */
extern OBJECT_DEFINITION_SEGMENT PGObjList[PG_MAX_ODS];  /* our array of Objects (images) */
extern PALETTE PGPalettes[PG_MAX_PALETTES];
extern PGINFO PGInfo;
extern PGSTATS PGStats;
int gPGParserWaiting;

static PG_WINDOW PGWindows[MAX_WINDOWS]; /* our windows for images */

/* the amount of time between frames in relation to the FrameRate in the Video Descriptor,
    we use this to determine when to start a PCS rendering, these
    are in terms of 90khz clock */
int FrameTimes[16] = {0, 3754, 3750, 3600,
                      3003, 0, 3600, 3003,
                      0, 0, 0, 0,
                      0, 0, 0, 0};

/* local proto's */
static PG_STATUS PGLoadPCSCompObjs(BYTE *DataStart, PRESENTATION_COMPOSITION_SEGMENT *Pcs, ULONG *MovedBytes);
static PG_STATUS PGLoadPCS(BYTE *DataStart, ULONG DataLength, ULONG PTS, BYTE PTS_DTS_Flags);
static PG_STATUS PGLoadPalette(BYTE *DataStart, ULONG DataLength);
static PG_STATUS PGLoadObject(BYTE *DataStart, ULONG DataLength);
static PG_STATUS PGLoadWindows(BYTE *DataStart, ULONG DataLength);
static PG_STATUS PGDecodeData(PG_PARSE_MSG *ParseData);
static PG_STATUS PGWaitForDTS(ULONG DTS);


/**
 * PGParse - the parse task for the PG module
 *
 * @param PVOID pvParam - the parse queue we will use, this may change
 *
 * @return ULONG
 */
ULONG PGParse(PVOID pvParam)
{
    ULONG status = PG_STATUS_SUCCESS;
    PG_PARSE_MSG *pMessage = NULL;

    /* loop:
        read from queue
        process data
    */
    while (PG_FLAGS_EXIT != PGInfo.QuitFlags)
    {
        gPGParserWaiting = 1;
        /* Get a stream message */
        pMessage = (PG_PARSE_MSG *)PGInfo.PGParseQ->Read(OS_WAIT_FOREVER);

        gPGParserWaiting = 0;

        if (pMessage == NULL)
        {
            DBGPRINT(DBG_ON(DBG_TRACE), ("Null message in PGParse\n"));
            OS_TaskYield();
            continue;
        }

        if (PG_STATE_RUNNING != PGInfo.CurrentState)
        {
            /* release the message */
            PGInfo.PGParseQ->ReleaseMsg(pMessage);
            pMessage = NULL;
            continue;
        }

        /* decode the data */
        PGDecodeData(pMessage);

        /* release the message */
        PGInfo.PGParseQ->ReleaseMsg(pMessage);
        pMessage = NULL;
    }

    DBGPRINT(DBG_ON(DBG_TRACE), ("exit PGParse()\n"));

    OS_TaskExit();
    return (status);
}


/**
 * PGDecodeData - decodes data from the PGParseBuffer into our object lists
 *
 * @param PG_PARSE_DATA *ParseData - info about what to parse and how much data is there
 *
 * @return PG_STATUS
 */
PG_STATUS PGDecodeData(PG_PARSE_MSG *ParseData)
{
    ULONG SegmentLength;

    /* set start and end ptrs */
    BYTE *SegmentStart = ParseData->DataStart;
    BYTE *DataEnd = ParseData->DataStart + ParseData->DataLength;

    if (ParseData->DataStart < PGInfo.PGParseBuffer)
    {
        DbgPrint(("ERROR in parser, data start\n"));
        return PG_STATUS_ERROR;
    }

    if (DataEnd > PGInfo.PGParseBuffer + SIZE_PG_CODED_DATA_BUFFER)
    {
        DbgPrint(("ERROR in parser, data end\n"));
        return PG_STATUS_ERROR;
    }

    /*
        when we are called, we scoop up data from the start given in ParseData
        it gives a pointer and size and is assumed to be complete in that the
        data will be full segments, if it was a multipes packet segment
        the data will have been written to the queue such that no special handling is needed
    */

    /* while we still have data to process */
    while (SegmentStart < DataEnd)
    {
        /* look at the first byte in the sequence, if it is not a valid
        segment start code, skip the rest of the packet and return */

        /* check our quit flags */
        if (PG_STATE_RUNNING != PGInfo.CurrentState)
        {
            DBGPRINT(DBG_ON(DBG_TRACE), ("Leaving PGDecodeData() via flags\n"));

            /* update the read pointer */
            PGInfo.ParseReadPtr = (ULONG)DataEnd - (ULONG)PGInfo.PGParseBuffer;
            return PG_STATUS_SUCCESS;
        }

        /* the length of the segment is right after the first byte,
        unless this is a multipes segment, then there is only one object
        in this message it MUST be a ODS */

        SegmentLength = MAKE_WORD(SegmentStart+1);

        switch (*SegmentStart)
        {
            case PALETTE_DEFINITION:
                DBGPRINT(DBG_ON(DBG_TRACE), ("PG Parse: PAL wait for 0x%x CurPTS = 0x%x\n", ParseData->DTS, PGInfo.CurPTS));
                if (PGInfo.StreamAcquired)
                {
                    PGWaitForDTS(ParseData->DTS);   /* wait for the decode time we want */
                    PGLoadPalette(SegmentStart+3, SegmentLength);           /* feed start ptr as first byte after segment descriptor */
                }
                SegmentStart += SIZE_SEGMENT_DESCRIPTOR + SegmentLength;
            break;

            case OBJECT_DEFINITION:
                DBGPRINT(DBG_ON(DBG_TRACE), ("PG Parse: ODS, wait for 0x%x CurPTS 0x%x\n", ParseData->DTS, PGInfo.CurPTS));
                if (PGInfo.StreamAcquired)
                {
                    if (PGInfo.FrameDropping == 1)
                    {
                        /* if the display PTS has passed, we drop this */
                        if ((PGInfo.CurPTS <= PGInfo.ParserPCS->PTSDisplayTime) ||
                            (PGInfo.CurPTS < (ParseData->DTS + 3000)) )
                        {
                            PGWaitForDTS(ParseData->DTS); /* wait for it */
                            if (ParseData->MultiPES)
                            {
                                PGLoadObject(SegmentStart+3, ParseData->DataLength - 3);
                            }
                            else
                            {
                                PGLoadObject(SegmentStart+3, SegmentLength);
                            }
                        }
                        else
                        {
                            DBGPRINT(DBG_ON(DBG_ERROR), ("Dropping ODS: DTS: 0x%x PTS 0x%x PTSComp 0x%x, CurPTS 0x%x\n\n",
                                ParseData->DTS, ParseData->PTS, PGInfo.ParserPCS->PTSDisplayTime, PGInfo.CurPTS));
                            PGStats.PGTotalFrameDrops++;
                        }
                    }
                    else
                    {
                        /* not dropping frames, wait for time */
                        PGWaitForDTS(ParseData->DTS);
                        if (ParseData->MultiPES)
                        {
                            PGLoadObject(SegmentStart+3, ParseData->DataLength - 3);
                        }
                        else
                        {
                            PGLoadObject(SegmentStart+3, SegmentLength);
                        }
                    }
                }
                if (ParseData->MultiPES)
                {
                    SegmentStart = DataEnd;
                }
                else
                {
                    SegmentStart += SIZE_SEGMENT_DESCRIPTOR + SegmentLength;
                }
            break;

            case PRESENTATION_COMPOSITION:
                DBGPRINT(DBG_ON(DBG_TRACE), ("PG Parse: PCS, wait for 0x%x CurPTS is 0x%x\n", ParseData->DTS, PGInfo.CurPTS));

                /* reset the drop data flag and wait */
                PGWaitForDTS(ParseData->DTS);
                PGLoadPCS(SegmentStart+3, SegmentLength, ParseData->PTS, ParseData->PTS_DTS_Flags);
                SegmentStart += SIZE_SEGMENT_DESCRIPTOR + SegmentLength;
            break;

            case WINDOW_DEFINITION:
                DBGPRINT(DBG_ON(DBG_TRACE), ("PG Parse: WDS wait for 0x%x CurPTS is 0x%x\n", ParseData->DTS, PGInfo.CurPTS));
                if (PGInfo.StreamAcquired)
                {
                    if (PGInfo.ParserPCS == NULL)
                    {
                        DbgPrint(("GOT WDS WITHOUT A PCS!!!\n\n"));
                    }
                    PGWaitForDTS(ParseData->DTS);
                    PGLoadWindows(SegmentStart+3, SegmentLength);
                }
                SegmentStart += SIZE_SEGMENT_DESCRIPTOR + SegmentLength;
            break;

            case END_OF_DISPLAY_SET:
                DBGPRINT(DBG_ON(DBG_TRACE), ("PG Parse: EDS wait for 0x%x CurPTS is 0x%x\n", ParseData->DTS, PGInfo.CurPTS));
                PGWaitForDTS(ParseData->DTS);

                if (PGInfo.StreamAcquired)
                {
                    if (PGInfo.ParserPCS && (PGInfo.CurrentState == PG_STATE_RUNNING))
                    {
                        /* render this pcs */
                        OS_SemTake(PGInfo.RenderLock, OS_WAIT_FOREVER);

                        OS_SemTake(PGInfo.BlitLock, OS_WAIT_FOREVER);
                        RenderPCS(PGInfo.ParserPCS);
                        OS_SemGive(PGInfo.BlitLock);

                        OS_TimerSet(PGInfo.PGFlipTimer, 1);
                        OS_TaskYield();
                        OS_SemGive(PGInfo.RenderLock);

                        /* the renderer will free the memory, we DON'T free it here, just mark it
                        as not in use by the parser (NULL) */
                        PGInfo.ParserPCS = NULL;
                    }
                }

                /* we aren't guaranteed to get one of these after a pcs i don't think
                 * need to verify, if so, it would make a good signal to attach to
                 * the pcs so we know it's ok to render */
                SegmentStart += (SIZE_SEGMENT_DESCRIPTOR + SegmentLength);
            break;

            default:
                DBGPRINT(DBG_ON(DBG_ERROR), ("\n###ERROR: unsupported type of segment, 0x%x, datalength %d\n", *SegmentStart, ParseData->DataLength));
                PGStats.PGTotalParseMsgDrops++;
                goto errout;
        }
    }

    /* update the read pointer */
    PGInfo.ParseReadPtr = (ULONG)DataEnd - (ULONG)PGInfo.PGParseBuffer;
    return PG_STATUS_SUCCESS;

errout:

    DBGPRINT(DBG_ON(DBG_ERROR), ("ERROR OUT OF PG_DECODE\n"));

    /* update the read pointer */
    PGInfo.ParseReadPtr = (ULONG)DataEnd - (ULONG)PGInfo.PGParseBuffer;
    return PG_STATUS_ERROR;
}


/**
 * PGLoadPCS - decodes data from the PGParseBuffer into our object lists
 *
 * @param BYTE *DataStart - pointer to the buffer with data in it for decode
 * @param ULONG DataLength - the length of DataStart in bytes
 * @param ULONG PTS - Presentation Time Stamp of the PES packet this PCS came in
 * @param ULONG DTS - Decode Time Stamp of the PES packet this PCS came in
 * @param BYTE PTS_DTS_Flags - the PTS/DTS flags from the pes header (shifted down) (PTS_ONLY/PTS_AND_DTS)
 *
 * @return PG_STATUS
 */
PG_STATUS PGLoadPCS(BYTE *DataStart, ULONG DataLength, ULONG PTS, BYTE PTS_DTS_Flags)
{
    ULONG MovesBytes;
    BYTE *SegmentIndex = DataStart;

    if (PGInfo.CurrentState != PG_STATE_RUNNING)
    {
        return PG_STATUS_SUCCESS;
    }

    if (PGInfo.ParserPCS)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PGInfo.ParserPCS already exists\n"));
        ReleasePCS(PGInfo.ParserPCS);
        PGInfo.ParserPCS = NULL;
    }

    /* allocate space for a PCS */
    PGInfo.ParserPCS = (PRESENTATION_COMPOSITION_SEGMENT *)OS_MemAlloc(sizeof(PRESENTATION_COMPOSITION_SEGMENT));
    if (NULL == PGInfo.ParserPCS)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("Not Enough Memory for PCS\n"));
        return PG_STATUS_ERROR;
    }

    /* clear out the PCS object */
    memset(PGInfo.ParserPCS, 0, sizeof(PRESENTATION_COMPOSITION_SEGMENT));

    /* video descriptor */
    PGInfo.ParserPCS->VideoDesc.Width = MAKE_WORD(SegmentIndex);

⌨️ 快捷键说明

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