📄 pg_api.cpp
字号:
if (0xFFFF == PGInfo.CurPesInfo.PacketSize)
{
PGInfo.CurPesInfo.NeedSegmentBytes = ODS_HEADER_SIZE;
PGInfo.CurPesInfo.SegmentIndex = 0;
}
else
{
/* else: not full packet and we aren't currently coping multipes so can't be multipes */
/* make sure we have room for the packet */
PGWaitForSpaceAvail(PGInfo.CurPesInfo.PacketSize);
if (PGInfo.CurrentState != PG_STATE_RUNNING)
{
OS_SemGive(PGInfo.StateLock);
return PG_STATUS_ERROR;
}
}
}
else
{
/* we are already copying multipes, we need to look instead for the last in sequence flag,
we don't care if the packet is a full 0xffff or not, last_in_sequence will tell us we are done */
PGInfo.CurPesInfo.NeedSegmentBytes = ODS_HEADER_SIZE_NO_FRAGMENT;
PGInfo.CurPesInfo.SegmentIndex = 0;
}
/* move ahead */
BytesRead += AssembleBytesRead;
BytesLeft -= AssembleBytesRead;
AssembleBytesRead = 0;
}
else if (PG_MORE_DATA == RetCode)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("Need more data\n"));
/* need more data to finish pes header */
#ifdef ALLOW_PG_PROFILING
if (1 == PGStats.Profiling)
{
PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(PGInfo.StateLock);
return PG_STATUS_SUCCESS;
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("pg error adddata\n"));
/* error */
PGClearAddDataVars();
#ifdef ALLOW_PG_PROFILING
if (1 == PGStats.Profiling)
{
PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(PGInfo.StateLock);
return PG_STATUS_ERROR;
}
}
/* we have a multipes segment to handle, get all the bytes of a segment header and buffer
them, don't continue until we have enough to parse */
if (PGInfo.CurPesInfo.NeedSegmentBytes)
{
RetCode = PGAssembleSegmentData(&Buffer[BytesRead], BytesLeft, &AssembleBytesRead);
if (PG_STATUS_SUCCESS == RetCode)
{
/* we got the whole segment, make sure it's an object defintion segment */
if (OBJECT_DEFINITION != PGInfo.CurPesInfo.SegmentTemp[0])
{
DBGPRINT(DBG_ON(DBG_TRACE), ("This data is incorrect, the data must be a Object Definition Segment, skip data to sync\n"));
/* clear the pes header */
PGClearAddDataVars();
#ifdef ALLOW_PG_PROFILING
if (1 == PGStats.Profiling)
{
PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(PGInfo.StateLock);
return PG_STATUS_SUCCESS; // we got data but it wrong, who's error? and we shouldn't stop so no error
}
}
else if (PG_MORE_DATA == RetCode)
{
/* we need more data */
BytesRead -= AssembleBytesRead;
#ifdef ALLOW_PG_PROFILING
if (1 == PGStats.Profiling)
{
PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(PGInfo.StateLock);
return PG_STATUS_SUCCESS;
}
/*
if we get here we have a full segment buffer
*/
/* grab the sequence descriptor */
PGInfo.SequenceDesc = PGInfo.CurPesInfo.SegmentTemp[6];
/* we haven't copied the first of a multipes packet yet */
if (FIRST_IN_SEQUENCE & PGInfo.SequenceDesc)
{
/*
this is the first in a seqence of pes packets
*/
/* if this occurs while we are waiting for a last in sequence,
we will lose the previous data which is what we want since
there must have been some data corruption anyway... */
/* now the size of the object, we need linear space for this */
ObjectDataSize = (PGInfo.CurPesInfo.SegmentTemp[7] << 16) |
(PGInfo.CurPesInfo.SegmentTemp[8] << 8) |
PGInfo.CurPesInfo.SegmentTemp[9];
/* copy the whole header - 4 bytes for width and height of ODS */
ObjectDataSize += ODS_HEADER_SIZE - 4;
/* get space for this data */
PGWaitForSpaceAvail(ObjectDataSize);
if (PGInfo.CurrentState != PG_STATE_RUNNING)
{
OS_SemGive(PGInfo.StateLock);
return PG_STATUS_ERROR;
}
/* copy over the segment header data to the PGParseBuffer */
memcpy(&PGInfo.PGParseBuffer[PGInfo.PESWritePtr], &Buffer[BytesRead], PGInfo.CurPesInfo.SegmentIndex);
PGInfo.PESWriteStart = PGInfo.PESWritePtr;
PGInfo.PESWritePtr += PGInfo.CurPesInfo.SegmentIndex;
/* we are now copying multipes data */
PGInfo.CopyingMultiPES = 1;
PGInfo.fGotStartPtr = 1;
}
/* say that we read the data */
PGInfo.CurPesInfo.ESRemaining -= PGInfo.CurPesInfo.SegmentIndex;
PGInfo.CurPesInfo.SegmentIndex = 0; /* segment header is read */
/* how much we read from the current packet must be removed from what's left */
BytesLeft -= AssembleBytesRead;
BytesRead += AssembleBytesRead;
/* now copy out the data in the PES buffer, as much as we can, either the
rest of the PES packet or the rest of the AddData buffer */
LeftToCopy = MIN(PGInfo.CurPesInfo.ESRemaining, BytesLeft);
/* copy what ES data we can here */
memcpy(&PGInfo.PGParseBuffer[PGInfo.PESWritePtr], &Buffer[BytesRead], LeftToCopy);
PGInfo.PESWritePtr += LeftToCopy; /* push up the write pointer */
PGInfo.CurPesInfo.ESRemaining -= LeftToCopy; /* remove some byte from esremaining */
BytesLeft -= LeftToCopy; /* less bytes left */
BytesRead += LeftToCopy; /* more bytes read */
/* very very edge case that for some reason there was a full
PES packet 0xffff but the first and last in sequence flags were still set */
if (0 == PGInfo.CurPesInfo.ESRemaining)
{
if (LAST_IN_SEQUENCE & PGInfo.SequenceDesc)
{
//DBGPRINT(DBG_ON(DBG_TRACE), ("@@Multi-pes got last in sequence, start 0x%x, size %d\n", PGInfo.PESWriteStart, PGInfo.PESWritePtr - PGInfo.PESWriteStart));
/* tell the parser to start decoding a segment */
PGAddParseMessage( PGInfo.PESWriteStart,
PGInfo.PESWritePtr - PGInfo.PESWriteStart,
PGInfo.CurPesInfo.DTS,
PGInfo.CurPesInfo.PTS,
PGInfo.CurPesInfo.PTSDTSFlags,
1);
/* not copying a pes packet right now */
PGInfo.CopyingPES = 0;
PGInfo.CopyingMultiPES = 0;
PGInfo.fGotStartPtr = 0;
}
}
else
{
continue; /* not done yet */
}
}
else /* this is the rest of some ES data, could be multipes packets */
{
LeftToCopy = MIN(PGInfo.CurPesInfo.ESRemaining, BytesLeft);
/* copy a packet, it may or may not be all here */
memcpy(&PGInfo.PGParseBuffer[PGInfo.PESWritePtr], &Buffer[BytesRead], LeftToCopy);
/* if we haven't gotten the start ptr yet get it */
if (0 == PGInfo.fGotStartPtr)
{
/* if we are just continuing a copy we don't reget the write ptr */
PGInfo.PESWriteStart = PGInfo.PESWritePtr; /* data start */
PGInfo.fGotStartPtr = 1;
}
/* update pointers */
PGInfo.PESWritePtr += LeftToCopy; /* bump the write ptr */
BytesRead += LeftToCopy; /* we read this much data */
BytesLeft -= LeftToCopy; /* we read this much data */
PGInfo.CurPesInfo.ESRemaining -= LeftToCopy; /* copied ES data */
/* are we done with the PES packet */
if (PGInfo.CurPesInfo.ESRemaining)
{
//DBGPRINT(DBG_ON(DBG_TRACE), ("EsRemain is %d, copying pes %d, multipes %d, BytesRead %d BytesLeft %d, PES Size %d, ParsePacketSize %d\n",
// PGInfo.CurPesInfo.ESRemaining, PGInfo.CopyingPES, PGInfo.CopyingMultiPES,
// BytesRead, BytesLeft, PGInfo.CurPesInfo.PacketSize, PGInfo.PESWritePtr - PGInfo.PESWriteStart));
continue; /* no we need more */
}
else /* yes */
{
if (0 == PGInfo.CopyingMultiPES)
{
/* tell the parser to start decoding a segment */
PGAddParseMessage( PGInfo.PESWriteStart,
PGInfo.PESWritePtr - PGInfo.PESWriteStart,
PGInfo.CurPesInfo.DTS,
PGInfo.CurPesInfo.PTS,
PGInfo.CurPesInfo.PTSDTSFlags,
0);
/* not copying a pes packet right now */
PGInfo.CopyingPES = 0;
PGInfo.fGotStartPtr = 0;
}
else
{
if (LAST_IN_SEQUENCE & PGInfo.SequenceDesc)
{
/* tell the parser to start decoding a segment */
PGAddParseMessage( PGInfo.PESWriteStart,
PGInfo.PESWritePtr - PGInfo.PESWriteStart,
PGInfo.CurPesInfo.DTS,
PGInfo.CurPesInfo.PTS,
PGInfo.CurPesInfo.PTSDTSFlags,
1);
/* not copying a pes packet right now */
PGInfo.CopyingPES = 0;
PGInfo.CopyingMultiPES = 0;
PGInfo.fGotStartPtr = 0;
}
}
}
}
} /* copyingpes */
/*
2. look for sync
*/
if (PG_STATUS_SUCCESS != PGScanForStartCode(&Buffer[BytesRead], BytesLeft, &StartCodeOffset))
{
/* couldn't get sync on the rest of the packet */
#ifdef ALLOW_PG_PROFILING
if (1 == PGStats.Profiling)
{
PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(PGInfo.StateLock);
return PG_STATUS_SUCCESS;
}
/* assemble the PES header, we need 5 bytes to start */
PGInfo.CurPesInfo.HeaderNeedBytes = 5;
PGInfo.CopyingPES = 1;
BytesLeft -= StartCodeOffset;
BytesRead += StartCodeOffset;
}
#ifdef ALLOW_PG_PROFILING
if (1 == PGStats.Profiling)
{
PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(PGInfo.StateLock);
return PG_STATUS_SUCCESS;
}
/**
* PGSetColorSpace - set the color space for PG to 601 or 709
*
* @param IG_HANDLE handle - handle to the PG module
* @param int ColorSpace - number indicating colorspace
*
* @return IG_STATUS
*/
PG_STATUS PGSetColorSpace(PG_HANDLE handle, int ColorSpace)
{
if (handle != (PVOID)PG_HANDLE_VALUE)
{
return (PG_STATUS_INVALID_HANDLE);
}
/* store the color space */
if (ColorSpace == 0)
{
PGInfo.ColorSpace = REC_601;
}
else
{
PGInfo.ColorSpace = REC_709;
}
return PG_STATUS_SUCCESS;
}
/**
* PGUpdateTimeStamp - Queue a message to the PGParse task for it to decode segment data
*
* @param PG_HANDLE handle - handle to the PG module
* @param ULONG PTS - The current Presentation Time Stamp
* @param ULONG SCR - The current System Clock Reference
*
* @return PG_STATUS
*/
PG_STATUS PGUpdateTimeStamp(PG_HANDLE handle, ULONG PTS, ULONG SCR)
{
if (handle != (PVOID)PG_HANDLE_VALUE)
{
return PG_STATUS_INVALID_HANDLE;
}
if (PG_STATE_RUNNING != PGInfo.CurrentState)
{
return PG_STATUS_NOT_RUNNING;
}
if (PTS == 0xFFFFFFFF)
{
//DbgPrint(("PGUpdateTimeStamp: Invalid PTS\n"));
return PG_STATUS_ERROR;
}
PGInfo.CurPTS = PTS;
/* Renderer waiting? */
if (PGInfo.RenderWait.WaitTime.Enabled)
{
if (PGInfo.CurPTS >= PGInfo.RenderWait.WaitTime.WaitPTS)
{
OS_SemGive(PGInfo.RenderWait.WaitSem);
}
}
/* Parser waiting? */
if (PGInfo.ParseWait.WaitTime.Enabled)
{
if (PGInfo.CurPTS >= PGInfo.ParseWait.WaitTime.WaitPTS)
{
//DBGPRINT(DBG_ON(DBG_TRACE), ("PGUpdateTimeStamp Kick ParseWait() 0x%x\n", PGInfo.CurPTS));
OS_SemGive(PGInfo.ParseWait.WaitSem);
}
}
return PG_STATUS_SUCCESS;
}
/**
* PGScanForStartCode - scan the buffer given for a start code, if a start code overlaps
* the buffer we save the last few bytes of the previous so we can find it
*
* @param BYTE *Buffer - Data buffer to search
* @param ULONG Size - Size of the Buffer in bytes
* @param ULONG *Offset - Offset index into the Buffer where data is found, this is always the first
* byte after the start code
*
*
* @return PG_STATUS
*/
PG_STATUS PGScanForStartCode(BYTE *Buffer, ULONG Size, ULONG *Offset)
{
int Index=0;
int SearchSize = Size-SIZE_START_CODE+1;
/* scan for the 4 byte pes header private stream 1 and return the index into the buffer where
it was found, if it was across two buffer boundries then mark the EndOfCode flag as 1 and
return in the Offset the byte right after the start code
*/
/* if we were in the middle of scanning for start codes lets finish */
if (PGInfo.CurPesInfo.StartCodeBuffSize > 0)
{
int TempCodeBytesLeft = PGInfo.CurPesInfo.StartCodeBuffSize;
int StartCodeBase = 0;
/* we have a 6 byte copy buffer for start codes, copy x bytes from the param Buffer
into a logical ending place in the gTempStartCode buffer and create and test
a start code, if it's good, mark the EndOfCode flag and return the Offset
as the byte after the start code */
if (Size >= (SIZE_START_CODE-1))
{
/* copy a few bytes from the front of the new buffer to the temp buffer and look
for a start code */
memcpy(&PGInfo.CurPesInfo.StartCodeBuff[PGInfo.CurPesInfo.StartCodeBuffSize], Buffer, 3);
for (int i=PGInfo.CurPesInfo.StartCodeBuffSize; i > 0; i--)
{
/* a start code across buffer boundries ? */
if (PRIVATE_STREAM_1_START_CODE == MAKE_DWORD(&PGInfo.CurPesInfo.StartCodeBuff[StartCodeBase]))
{
DBGPRINT(DBG_ON(DBG_TRACE), ("Found start code across boundry\n"));
*Offset = SIZE_START_CODE-TempCodeBytesLeft;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -