📄 ig_parse.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 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 + -