📄 pg_parse.cpp
字号:
PGInfo.ParserPCS->VideoDesc.Height = MAKE_WORD(SegmentIndex+2);
PGInfo.ParserPCS->VideoDesc.FrameRate = ((*(SegmentIndex+4)) & 0xF0) >> 4;
SegmentIndex += SIZE_VIDEO_DESCRIPTOR;
if (PGInfo.RLEHalfWidth == 1)
{
if ((PGInfo.ParserPCS->VideoDesc.Width == 1920) && (PGInfo.ParserPCS->VideoDesc.Height == 1080))
{
DBGPRINT(DBG_ON(DBG_TRACE), ("PG - CoordsHalfWidth TRUE\n"));
PGInfo.CoordsHalfWidth = 1;
}
else
{
DBGPRINT(DBG_ON(DBG_TRACE), ("PG - CoordsHalfWidth FALSE\n"));
PGInfo.CoordsHalfWidth = 0;
}
}
else
{
PGInfo.CoordsHalfWidth = 0;
}
/* read in the composition descriptor */
PGInfo.ParserPCS->CompDesc.CompositionNumber = MAKE_WORD(SegmentIndex);
PGInfo.ParserPCS->CompDesc.CompositionState = ((*(SegmentIndex+2)) & 0xC0) >> 6;
SegmentIndex += SIZE_COMPOSITION_DESCRIPTOR;
/* account for epoch start, continue or acq points, if we haven't gotten one yet
* and this is our first then it's ok to decode again */
/* if the stream is not acquired yet, see if we got a ACQ Point or Epoch Start */
if (0 == PGInfo.StreamAcquired)
{
if ((PGInfo.ParserPCS->CompDesc.CompositionState == COMP_STATE_ACQUISITION_POINT) ||
(PGInfo.ParserPCS->CompDesc.CompositionState == COMP_STATE_EPOCH_START) ||
(PGInfo.ParserPCS->CompDesc.CompositionState == COMP_STATE_EPOCH_CONT))
{
/* we got a valid acquisition point now */
DBGPRINT(DBG_ON(DBG_TRACE), ("Stream Acquired\n"));
PGInfo.StreamAcquired = 1;
}
else
{
/* this PCS may reference old data, do NOT keep it */
DBGPRINT(DBG_ON(DBG_TRACE), ("Discard PCS\n"));
OS_MemFree(PGInfo.ParserPCS);
PGInfo.ParserPCS = NULL;
return PG_STATUS_SUCCESS;
}
}
/* if this is a new epoch, clear the screen and object buffers */
if (COMP_STATE_EPOCH_START == PGInfo.ParserPCS->CompDesc.CompositionState)
{
BYTE ScreenUpdate = 0;
/* NOTE:
BD SPEC section 8.8.3.1.5, On the DTS of Epoch Start we clear all buffers and
the Graphics plane, including what is on screen.
DON'T CHANGE this without a spec change.
*/
/* free the objects and palettes */
OS_SemTake(PGInfo.RenderLock, OS_WAIT_FOREVER);
PGGraphicsClearBuffer(&ScreenUpdate, 0);
if (ScreenUpdate)
{
OS_TimerSet(PGInfo.PGFlipTimer, 1);
OS_TaskYield();
}
if (PGInfo.RenderPCS)
{
ReleasePCS(PGInfo.RenderPCS);
PGInfo.RenderPCS = NULL;
}
PGFreeObjects();
OS_SemGive(PGInfo.RenderLock);
}
/* load the palette update flag */
PGInfo.ParserPCS->PaletteUpdateFlag = ((*SegmentIndex) & BIT7) >> 7;
/* get the palette id ref */
PGInfo.ParserPCS->PaletteIDRef = *(SegmentIndex+1);
/* get the number of composition objects */
PGInfo.ParserPCS->NumCompositionObjects = *(SegmentIndex+2);
SegmentIndex+=3;
if (PGInfo.ParserPCS->NumCompositionObjects > 0)
{
/* malloc some space for the composition objects */
PGInfo.ParserPCS->CompObjs =
(COMPOSITION_OBJECT *)OS_MemAlloc(PGInfo.ParserPCS->NumCompositionObjects * sizeof(COMPOSITION_OBJECT));
if (PGInfo.ParserPCS->CompObjs == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("couldn't malloc space for pcs->comp_objs\n"));
OS_MemFree(PGInfo.ParserPCS);
PGInfo.ParserPCS = NULL;
return PG_STATUS_ERROR;
}
/* load up the composition objects */
PGLoadPCSCompObjs(SegmentIndex, PGInfo.ParserPCS, &MovesBytes);
}
/* the PTS the packet came in on is it's render time, note it should be rendered by this time */
if ((PTS_ONLY == PTS_DTS_Flags) || (PTS_AND_DTS == PTS_DTS_Flags))
{
/* subtract 1 frame time from the pts, the flip should occur during this frame time */
PGInfo.ParserPCS->PTSDisplayTime = PTS;
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("\nERROR, there is no PTS time given to the PCS from PES header\n"));
PGInfo.ParserPCS->PTSDisplayTime = PGInfo.CurPTS; // render now
}
return (PG_STATUS_SUCCESS);
}
/**
* PGLoadPCSCompObjs - decodes data from the PGParseBuffer into our object lists
*
* @param BYTE *DataStart - pointer to the composition object data
* @param PCS *pcs - the Presentation Compostion Object we are working one
* @param ULONG *MovedBytes - return the number of bytes read in this ptr to caller
*
* @return PG_STATUS
*/
PG_STATUS PGLoadPCSCompObjs(BYTE *DataStart, PRESENTATION_COMPOSITION_SEGMENT *Pcs, ULONG *MovedBytes)
{
BYTE *ObjIndex = DataStart;
/* load all the composition objects */
for (int i=0; i<Pcs->NumCompositionObjects; i++)
{
Pcs->CompObjs[i].ObjectIDRef = MAKE_WORD(ObjIndex);
Pcs->CompObjs[i].WindowIDRef = *(ObjIndex+2);
Pcs->CompObjs[i].CroppedFlag = ((*(ObjIndex+3)) & BIT7) >> 7;
Pcs->CompObjs[i].ForcedOnFlag = ((*(ObjIndex+3)) & BIT6) >> 6;
Pcs->CompObjs[i].XPosition = MAKE_WORD(ObjIndex+4);
Pcs->CompObjs[i].YPosition = MAKE_WORD(ObjIndex+6);
/* if the image is cropped we will have a flag here */
if (Pcs->CompObjs[i].CroppedFlag)
{
/* load the cropping rectangle */
Pcs->CompObjs[i].Rect.X = MAKE_WORD(ObjIndex+8);
Pcs->CompObjs[i].Rect.Y = MAKE_WORD(ObjIndex+10);
Pcs->CompObjs[i].Rect.Width = MAKE_WORD(ObjIndex+12);
Pcs->CompObjs[i].Rect.Height = MAKE_WORD(ObjIndex+14);
/* move the size of a comp obj with a cropping rect (stream size not stored struct size) */
ObjIndex += SIZE_COMPOSITION_OBJECT;
}
else
{
/* move the size of a comp obj without a cropping rect (stream size not stored struct size) */
ObjIndex += SIZE_COMPOSITION_OBJECT - SIZE_CROPPING_RECTANGLE;
}
/* set the PCS forced flag so we know this PCS contains a forced composition */
if (Pcs->CompObjs[i].ForcedOnFlag)
{
Pcs->fPCSHasForced = 1;
}
/* checks for Composition Object Validity */
if (Pcs->CompObjs[i].ObjectIDRef > PG_MAX_ODS)
{
DbgPrint(("Invalid Composition Object, referencing ObjectId %d\n", Pcs->CompObjs[i].ObjectIDRef));
break;
}
if (Pcs->CompObjs[i].WindowIDRef > MAX_WINDOWS)
{
DbgPrint(("Invalid Composition Object, referencing WindowId %d\n", Pcs->CompObjs[i].WindowIDRef));
break;
}
}
*MovedBytes = ObjIndex - DataStart;
return PG_STATUS_SUCCESS;
}
/**
* PGLoadPalette - load a palette into the palettes array
*
* @param BYTE *DataStart - pointer to the start of the palette
* @param ULONG DataLength - size of DataStart in bytes
*
* @return PG_STATUS
*/
PG_STATUS PGLoadPalette(BYTE *DataStart, ULONG DataLength)
{
/* use the segment length to determine the number of colors */
BYTE *PalPtr = DataStart+2;
PALETTE *CurPal = NULL;
int PaletteNumber = *(DataStart);
int NumEntries;
BYTE fClearPalette=0;
if (PGInfo.CurrentState != PG_STATE_RUNNING)
{
return PG_STATUS_SUCCESS;
}
/* make sure this palette number doesn't overrun memory */
if (PaletteNumber >= PG_MAX_PALETTES)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("Invalid palette index, palette not parsed\n"));
return PG_STATUS_ERROR;
}
/* select the proper palette in the arrays */
CurPal = &PGPalettes[PaletteNumber];
/* load pg palette with this */
CurPal->PaletteVersion = *(DataStart+1);
/* calculate the number of entries, if the diviosion rounds data incorrectly the palette is
wrong anyway and we will miss some entries at the end */
NumEntries = (DataLength-2) / SIZE_PALETTE_ENTRY;
/* check that the palette entries are all filled up */
if (((DataLength-2) % SIZE_PALETTE_ENTRY) != 0)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("Palette entries not complete\n"));
return PG_STATUS_SUCCESS;
}
if (PGInfo.ParserPCS)
{
if (COMP_STATE_NORMAL == PGInfo.ParserPCS->CompDesc.CompositionState)
{
fClearPalette = 0;
}
else
{
fClearPalette = 1;
}
}
/* create the dfb palette */
if (PGGraphicsSetPaletteColors(PaletteNumber, PalPtr, NumEntries, fClearPalette, PGInfo.ColorSpace) != PG_STATUS_SUCCESS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("Failed to set palette colors in DFB Palette\n"));
return PG_STATUS_ERROR;
}
return PG_STATUS_SUCCESS;
}
/**
* PGLoadObject - load a object into the PGObjList
*
* @param BYTE *DataStart - pointer to the start of the object
* @param ULONG DataLength - size of DataStart in bytes
*
* @return PG_STATUS
*/
PG_STATUS PGLoadObject(BYTE *DataStart, ULONG DataLength)
{
int ObjectID = MAKE_WORD(DataStart);
int VersionNumber = *(DataStart + 2);
int OutputSize;
BYTE DoUpdate = 0;
BYTE *ObjStart = DataStart;
void *ImgData;
OBJECT_DEFINITION_SEGMENT *CurObj;
PG_STATUS status;
#ifdef ALLOW_PG_PROFILING
ULONG TickStart = 0;
#endif
if (PGInfo.CurrentState != PG_STATE_RUNNING)
{
return PG_STATUS_SUCCESS;
}
if (ObjectID >= PG_MAX_ODS)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGLoadObject: ObjectID to large %d\n", ObjectID));
return PG_STATUS_ERROR;
}
/* the current object for easy access */
CurObj = &PGObjList[ObjectID];
/* if the object is in use, check it's version number to see if we need an update */
if (CurObj->InUse)
{
if (CurObj->VersionNumber < VersionNumber)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("PGLoadObject: Update object new=%d, current=%d\n", VersionNumber, CurObj->VersionNumber));
DoUpdate = 1;
}
else
{
DBGPRINT(DBG_ON(DBG_TRACE), ("PG: PGLoadObject image has same or lower version number\n"));
return PG_STATUS_SUCCESS;
}
}
/*
load the object definition segment
*/
/* read the object id */
CurObj->VersionNumber = VersionNumber;
ObjStart+=3;
/* get sequence flags, these won't be accurate for mulitPES segments */
CurObj->SeqDesc.FirstInSequenceFlag = ((*ObjStart) & BIT7) >> 7;
CurObj->SeqDesc.LastInSequenceFlag = ((*ObjStart) & BIT6) >> 6;
ObjStart++;
/* read the object data fragment */
CurObj->ObjData.DataLength = (*ObjStart) << 16 | ((*(ObjStart+1)) << 8) | (*(ObjStart+2));
CurObj->ObjData.Width = MAKE_WORD(ObjStart+3); /* could add paranoia check here on do_update */
CurObj->ObjData.Height = MAKE_WORD(ObjStart+5); /* could add paranoia check here on do_update */
ObjStart+=7;
/* how big is the image? */
OutputSize = CurObj->ObjData.Width * CurObj->ObjData.Height;
/* is the output size bigger then the video size, if so error */
if (OutputSize > 1920*1080)
{
CurObj->VersionNumber = 0;
DBGPRINT(DBG_ON(DBG_ERROR), ("The Image Size is too large\n"));
return PG_STATUS_ERROR;
}
/* make sure we have the correct amount of data, (the DataLength - header = correct Object Data length)*/
if ((DataLength - 7) != CurObj->ObjData.DataLength)
{
DbgPrint(("PGLoadObject does not have the correct amount of data, Datalength-7 = %d Datalength = %d\n",
DataLength-7, CurObj->ObjData.DataLength));
CurObj->VersionNumber = 0;
return PG_STATUS_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -