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

📄 ig_parse.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*****************************************************************************
******************************************************************************
**                                                                          **
**  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 ig_parse.cpp
 *
 * $Revision: 1.6 $ 
 *
 * Parse routines for the IG module
 *
 */

#include "vdvd_types.h"
#include "osapi.h"
#include "ig_api.h"
#include "ig_render.h"
#include "ig_util.h"
#include "ig_defs.h"
#include "ig_graphics.h"
#include "ig_parse.h"
#include "utility.h"

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

/* data declarations */
extern OBJECT_DEFINITION_SEGMENT IGObjList[IG_MAX_ODS];  /* our array of Objects (images) */
extern PALETTE IGPalettes[IG_MAX_PALETTES];
extern IGINFO IGInfo;
extern IGSTATS IGStats;
int gIGDecodedObjectBuffUsed=0;
int gIGParserWaiting = 0;

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

/* local proto's */
static IG_STATUS IGLoadPalette(BYTE *DataStart, ULONG DataLength);
static IG_STATUS IGLoadObject(BYTE *DataStart, ULONG DataLength);
static IG_STATUS IGDecodeData(IG_PARSE_MSG *ParseData);
static IG_STATUS IGLoadICS(BYTE *DataStart, ULONG DataLength, ULONG PTS, BYTE PTS_DTS_Flags);
static IG_STATUS IGLoadICSPages(BYTE *DataStart, BYTE NumPages, PAGE *Pages, ULONG *MovedBytes);
static IG_STATUS IGLoadICSPageEffects(BYTE *DataStart, EFFECT_SEQUENCE *Eff, ULONG *MovedBytes);
static IG_STATUS IGLoadICSPageBogs(BYTE *DataStart, PAGE *Page, ULONG *MovedForward);
static IG_STATUS IGLoadICSPageBogsButtons(BYTE *DataStart, BUTTON* Buttons, BYTE NumButtons, ULONG *MovedForward);
static IG_STATUS IGWaitForDTS(ULONG DTS);
static void IGFreeObjects();
static void IGClearPalettes();

/**
 * IGParse - the parse task for the IG module
 *
 * @param PVOID pvParam - the parse queue we will use, this may change
 *
 * @return ULONG
 */
ULONG IGParse(PVOID pvParam)
{
    ULONG status = IG_STATUS_SUCCESS;
    IG_PARSE_MSG *pMessage = NULL;

    /* loop:
        read from queue
        process data
    */
    while (IG_FLAGS_EXIT != IGInfo.QuitFlags)
    {
        gIGParserWaiting = 1;

        /* Get a stream message */
        pMessage = (IG_PARSE_MSG *)IGInfo.IGParseQ->Read(OS_WAIT_FOREVER);

        gIGParserWaiting = 0;

        if (pMessage == NULL)
        {
            DBGPRINT(DBG_ON(DBG_ERROR), ("IGParse(): Null Message from RenderQ\n"));
            OS_TaskYield();
            continue;
        }

        if (IG_STATE_RUNNING == IGInfo.CurrentState)
        {
            /* take the lock for the parse task */
            OS_SemTake(IGInfo.ParseLock, OS_WAIT_FOREVER);

            /* decode the data */
            IGDecodeData(pMessage);
            IGInfo.IGParseQ->ReleaseMsg(pMessage);
            pMessage = NULL;

            /* give the lock back */
            OS_SemGive(IGInfo.ParseLock);
        }
        else
        {
            if (pMessage != NULL)
            {
                IGInfo.IGParseQ->ReleaseMsg(pMessage);
                pMessage = NULL;
            }
        }
    }

    DBGPRINT(DBG_ON(DBG_TRACE), ("IGParse(): Leaving Task\n"));

    OS_TaskExit();
    return (status);
}


/**
 * IGDecodeData - decodes data from the IGParseBuffer into our object lists
 *
 * @param IG_PARSE_DATA *ParseData - info about what to parse and how much data is there
 *
 * @return IG_STATUS
 */
IG_STATUS IGDecodeData(IG_PARSE_MSG *ParseData)
{
    uint32 SegmentLength;

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

    /* check boundries */
    if (ParseData->DataStart < IGInfo.IGParseBuffer)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("ERROR in parser, data start\n"));
        return IG_STATUS_ERROR;
    }

    if (DataEnd > IGInfo.IGParseBuffer + SIZE_IG_CODED_DATA_BUFFER)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("ERROR in parser, data end\n"));
        return IG_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)
    {
        /* check our quit flags */
        if ((IG_FLAGS_STOP == IGInfo.QuitFlags) || (IG_FLAGS_EXIT == IGInfo.QuitFlags))
        {
            DBGPRINT(DBG_ON(DBG_TRACE), ("IGDecodeData(): Quit via top loop\n"));
            IGInfo.ParseReadPtr = (ULONG)DataEnd - (ULONG)IGInfo.IGParseBuffer; 
            return IG_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);

        /* 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 */
        switch (*SegmentStart)
        {
            case PALETTE_DEFINITION:
                DBGPRINT(DBG_ON(DBG_TRACE), ("IGDecodeData(): PAL\n"));
                IGWaitForDTS(ParseData->DTS);   /* wait for the decode time we want */
                if (IGInfo.StreamAcquired)
                {
                    IGLoadPalette(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), ("IGDecodeData(): ODS 0x%x\n", ParseData->DTS));
                if (ParseData->MultiPES)  /* there can be only one object */
                {
                    DBGPRINT(DBG_ON(DBG_TRACE), ("IGDecodeData(): MULTI-PES\n"));
                    if (IGInfo.StreamAcquired)
                    {
                        IGWaitForDTS(ParseData->DTS); /* wait for it */
                        IGLoadObject(SegmentStart+3, SegmentLength);  /* load a ODS, either multipes or single pes */
                    }

                    SegmentStart = DataEnd;
                }
                else
                {
                    if (IGInfo.StreamAcquired)
                    {
                        IGWaitForDTS(ParseData->DTS); /* wait for it */
                        IGLoadObject(SegmentStart+3, SegmentLength);  /* load a ODS, either multipes or single pes */
                    }

                    SegmentStart += SIZE_SEGMENT_DESCRIPTOR + SegmentLength;
                }
            break;

            case INTERACTIVE_COMPOSITION:
                DBGPRINT(DBG_ON(DBG_TRACE), ("IGDecodeData(): ICS 0x%x\n", ParseData->DTS));
                if (ParseData->MultiPES)  /* there can be only one object */
                {
                    DBGPRINT(DBG_ON(DBG_TRACE), ("IGDecodeData(): ICS MULTI-PES\n"));
                    IGWaitForDTS(ParseData->DTS);
                    IGLoadICS(SegmentStart+3, SegmentLength, ParseData->PTS, ParseData->PTS_DTS_Flags);
                    SegmentStart = DataEnd;
                    break;
                }
                else
                {
                    IGWaitForDTS(ParseData->DTS);
                    IGLoadICS(SegmentStart+3, SegmentLength, ParseData->PTS, ParseData->PTS_DTS_Flags);
                    SegmentStart += SIZE_SEGMENT_DESCRIPTOR + SegmentLength;
                }

            break;

            case END_OF_DISPLAY_SET:
                DBGPRINT(DBG_ON(DBG_TRACE), ("IGDecodeData(): EDSS\n"));

                IGWaitForDTS(ParseData->DTS);
                /*  attach the ics to the renderer now ??
                    NOTE: this should help us through menu's since
                    the PTS is not being updated, once that is fixed we should be able to get
                    rid of this */

                /* write the message to the renderer */
                if (IGInfo.StreamAcquired)
                {
                    if (IGInfo.pICSMessage != NULL)
                    {
                        if (IGInfo.IGRenderQ->Write(IGInfo.pICSMessage, OS_NO_WAIT) != OS_OK)
                        {
                            DBGPRINT(DBG_ON(DBG_ERROR), ("IGDecodeData(): Failed to write message to Render Queue\n"));

                            IGFreeICS(IGInfo.pICSMessage->ICS);

                            /* and toss the message back */
                            IGInfo.IGRenderQ->ReleaseMsg(IGInfo.pICSMessage);
                            IGInfo.pICSMessage = NULL;

                            goto errout;
                        }

                        /* yield so renderer can run */
                        OS_TaskYield();
                    }

                    // it was written
                    IGInfo.pICSMessage = NULL;
                }

                SegmentStart += SIZE_SEGMENT_DESCRIPTOR + SegmentLength;
            break;

            default:
                DBGPRINT(DBG_ON(DBG_ERROR), ("IGDecodeData(): unsupported type of segment, 0x%x\n", *SegmentStart));
                goto errout;
        }
    }

    IGInfo.ParseReadPtr = (ULONG)DataEnd - (ULONG)IGInfo.IGParseBuffer; 
    return IG_STATUS_SUCCESS;

errout:

    DBGPRINT(DBG_ON(DBG_ERROR), ("IGDecodeData(): errout\n"));
    IGInfo.ParseReadPtr = (ULONG)DataEnd - (ULONG)IGInfo.IGParseBuffer; 
    return IG_STATUS_ERROR;
}


/**
 * IGLoadICS - decodes data from the IGParseBuffer 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 ICS came in
 * @param ULONG DTS - Decode Time Stamp of the PES packet this ICS came in
 * @param BYTE PTS_DTS_Flags - the PTS/DTS flags from the pes header (shifted down) (PTS_ONLY/PTS_AND_DTS)
 *
 * @return IG_STATUS
 */
IG_STATUS IGLoadICS(BYTE *DataStart, ULONG DataLength, ULONG PTS, BYTE PTS_DTS_Flags)
{
    BYTE *SegmentIndex = DataStart;
    ULONG BytesMoved=0;

    /* not running now? */
    if (IGInfo.CurrentState != IG_STATE_RUNNING)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("IGLoadICS(): NOT_RUNNING\n"));
        return IG_STATUS_ERROR;
    }

    /* make sure we don't have a message already */
    if (IGInfo.pICSMessage != NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("IGLoadICS(): already had a ICS?, possible data corruption, drop old ICS\n"));

        if (IGInfo.pICSMessage->ICS != NULL)
        {
            IGFreeICS(IGInfo.pICSMessage->ICS);
        }

        /* release the message */
        IGInfo.IGRenderQ->ReleaseMsg(IGInfo.pICSMessage);
        IGInfo.pICSMessage = NULL;
    }

    /* get a message from the renderQ */
    while (IGInfo.pICSMessage == NULL)
    {
        IGInfo.pICSMessage = (IG_RENDER_MSG*)IGInfo.IGRenderQ->GetMsg(OS_WAIT_FOREVER);
        if ((IG_FLAGS_STOP == IGInfo.QuitFlags) || (IG_FLAGS_EXIT == IGInfo.QuitFlags))
        {
            if (IGInfo.pICSMessage)
            {
                IGInfo.IGRenderQ->ReleaseMsg(IGInfo.pICSMessage);
                IGInfo.pICSMessage = NULL;
            }
            return IG_STATUS_SUCCESS;
        }
    }

    /* did we get a message? */
    if (IGInfo.pICSMessage == NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("IGLoadICS(): Returning from IGLoadICS without parsing ICS\n"));
        return IG_STATUS_ERROR;
    }

⌨️ 快捷键说明

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