📄 pg_api.cpp
字号:
/* clear pes header info */
memset(&PGInfo.CurPesInfo, 0, sizeof(PES_HDR_INFO));
return PG_STATUS_SUCCESS;
}
/* bytes left in start code */
TempCodeBytesLeft--;
StartCodeBase++;
}
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("UNHANDLED CASE IN PGScanForStartCode\n"));
/* TODO: edge case
we got a really small packet after the end of a pes packet, test what can be tested
*/
}
}
/* spin and find the start code in the data */
while (Index < SearchSize)
{
/* we Only accept private stream one data */
if (PRIVATE_STREAM_1_START_CODE == MAKE_DWORD(&Buffer[Index]))
{
*Offset = Index+4;
/* clear pes header info */
memset(&PGInfo.CurPesInfo, 0, sizeof(PES_HDR_INFO));
return PG_STATUS_SUCCESS;
}
/* next byte in buffer */
Index++;
}
/* if we got here we didn't find a start code and need to save the data */
memcpy(PGInfo.CurPesInfo.StartCodeBuff, &Buffer[Index], Size-Index);
PGInfo.CurPesInfo.StartCodeBuffSize = (BYTE)(Size-Index);
return PG_STILL_SCANNING_SC;
}
/**
* PGReadPESHeader - 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 *PESStart - the start of the PES header data
* @param PES_HDR_INFO *Info - state information about the header
*
* @return PG_STATUS
*/
PG_STATUS PGReadPESHeader(BYTE *PESStart)
{
PGInfo.CurPesInfo.PacketSize = MAKE_WORD(PESStart);
PGInfo.CurPesInfo.SegAligned = PESStart[2] & BIT2; /* is the segment aligned? */
PGInfo.CurPesInfo.PTSDTSFlags = (PESStart[3] & (BIT6|BIT7)) >> 6; /* value 2 is PTS_ONLY, value 3 is PTS_DTS */
PGInfo.CurPesInfo.PesHeaderLen = PESStart[4]; /* length of the pes header */
PGInfo.CurPesInfo.ESRemaining = PGInfo.CurPesInfo.PacketSize - PGInfo.CurPesInfo.PesHeaderLen - 3;
if (PGInfo.CurPesInfo.SegAligned == 0)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("!!!!!!Segment not aligned\n"));
}
if (PTS_ONLY == PGInfo.CurPesInfo.PTSDTSFlags)
{
/* get the PTS */
PGInfo.CurPesInfo.PTS = MAKE_WORD(&PESStart[6]) >> 1;
PGInfo.CurPesInfo.PTS = PGInfo.CurPesInfo.PTS << 14 | MAKE_WORD(&PESStart[8]) >> 2;
PGInfo.CurPesInfo.PTS |= ((ULONG)(PESStart[5] & 0xe)) << 28;
PGInfo.CurPesInfo.DTS = 0;
}
else if (PTS_AND_DTS == PGInfo.CurPesInfo.PTSDTSFlags)
{
/* get the PTS and DTS */
PGInfo.CurPesInfo.PTS = MAKE_WORD(&PESStart[6]) >> 1;
PGInfo.CurPesInfo.PTS = PGInfo.CurPesInfo.PTS << 14 | MAKE_WORD(&PESStart[8]) >> 2;
PGInfo.CurPesInfo.PTS |= ((ULONG)(PESStart[5] & 0xe)) << 28;
PGInfo.CurPesInfo.DTS = MAKE_WORD(&PESStart[11]) >> 1;
PGInfo.CurPesInfo.DTS = PGInfo.CurPesInfo.DTS << 14 | MAKE_WORD(&PESStart[13]) >> 2;
PGInfo.CurPesInfo.DTS |= ((ULONG)(PESStart[10] & 0xe)) << 28;
}
else
{
/* no pts or dts till given */
PGInfo.CurPesInfo.DTS = 0;
PGInfo.CurPesInfo.PTS = 0;
}
PGInfo.CurPesInfo.HeaderComplete = 1;
return PG_STATUS_SUCCESS;
}
/**
* PGWaitForSpaceAvail - see if there is linear space in the PGParseBuffer for Size bytes of data
*
* @param ULONG Size - number of bytes we need to be contiguous
*
* @return PG_STATUS
*/
PG_STATUS PGWaitForSpaceAvail(ULONG Size)
{
/* check the current write pointer, if we are going to wrap then wrap */
if ((PGInfo.PESWritePtr + Size) >= SIZE_PG_CODED_DATA_BUFFER)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("Wrap1 rp=%d wp=%d size =%d\n", PGInfo.ParseReadPtr, PGInfo.PESWritePtr, Size));
if (PGInfo.ParseReadPtr < PGInfo.PESWritePtr)
{
/* on wrap we would walk past read ptr, wait for read pointer to wrap */
while ((PGInfo.ParseReadPtr <= (Size+1)) && (PGInfo.CurrentState == PG_STATE_RUNNING))
{
OS_TaskYield();
}
}
else if (PGInfo.ParseReadPtr > PGInfo.PESWritePtr)
{
ULONG RP = PGInfo.ParseReadPtr;
/* on wrap we would walk past read ptr, wait for read pointer to wrap */
if ((PGInfo.PESWritePtr + Size) > PGInfo.ParseReadPtr)
{
/* wait for read pointer to wrap around here */
while ((PGInfo.ParseReadPtr >= RP) && (PGInfo.CurrentState == PG_STATE_RUNNING))
{
OS_TaskYield();
}
/* on wrap we would walk past read ptr, wait for read pointer to wrap */
while ((PGInfo.ParseReadPtr <= (Size+1)) && (PGInfo.CurrentState == PG_STATE_RUNNING))
{
OS_TaskYield();
}
}
}
else
{
DBGPRINT(DBG_ON(DBG_TRACE), ("PGWaitForSpaceAvail: buffer empty\n"));
}
/* wrap the write pointer */
PGInfo.PESWritePtr = 1;
}
if (PGInfo.PESWritePtr < PGInfo.ParseReadPtr)
{
/* crossing over read boundry */
if ((PGInfo.PESWritePtr + Size) >= PGInfo.ParseReadPtr)
{
/* wait for space in the parse buffer */
while (((PGInfo.PESWritePtr + Size) >= PGInfo.ParseReadPtr) && (PGInfo.CurrentState == PG_STATE_RUNNING))
{
OS_TaskYield();
/* if the read pointer gets lower than the write pointer, it must have wrapped */
if (PGInfo.ParseReadPtr < PGInfo.PESWritePtr)
{
/* spin wait for the read pointer to allow at least Size bytes in the buffer */
while ((PGInfo.ParseReadPtr < Size) && (PGInfo.CurrentState == PG_STATE_RUNNING))
{
OS_TaskYield();
}
break;
}
}
}
}
//DBGPRINT(DBG_ON(DBG_TRACE), ("read %d write %d size %d\n", PGInfo.ParseReadPtr, PGInfo.PESWritePtr, Size));
return PG_STATUS_SUCCESS;
}
/**
* PGAssemblePesHeader - Try to read in a whole PES header worth of dat into our pes header parse buffer
*
* @param BYTE *Buffer - the data buffer with pes data
* @param ULONG Size - the size of Buffer in bytes
* @param USHORT *BytesRead - how many bytes we read from the buffer
*
* @return PG_STATUS
*/
PG_STATUS PGAssemblePesHeader(BYTE *Buffer, ULONG Size, USHORT *ReadBytes)
{
ULONG BytesRead = 0;
ULONG BytesLeft = Size;
/*
NOTE: to start off PES header parsing we Require 5 bytes of data to start, until we get
that much we just copy into the temp buffer. Once that data is available we can
read out the size of the PES header, then we request the rest of the bytes to complete the
header
*/
while (PGInfo.CurPesInfo.HeaderNeedBytes)
{
/* try to get the number of bytes requested */
if (PGInfo.CurPesInfo.HeaderNeedBytes <= BytesLeft)
{
//DBGPRINT(DBG_ON(DBG_TRACE), ("copying needed bytes %d\n", PGInfo.CurPesInfo.HeaderNeedBytes));
memcpy(&PGInfo.CurPesInfo.PesHdrBuff[PGInfo.CurPesInfo.PesHdrIndex], &Buffer[BytesRead], PGInfo.CurPesInfo.HeaderNeedBytes);
PGInfo.CurPesInfo.PesHdrIndex += PGInfo.CurPesInfo.HeaderNeedBytes; /* buffer index up */
BytesLeft -= PGInfo.CurPesInfo.HeaderNeedBytes; /* less bytes left */
BytesRead += PGInfo.CurPesInfo.HeaderNeedBytes; /* more bytes read */
//DBGPRINT(DBG_ON(DBG_TRACE), ("pes index is now %d\n", PGInfo.CurPesInfo.PesHdrIndex));
}
else
{
/* buffer is too small, copy what we can and mark down the HeaderNeedBytes field */
DBGPRINT(DBG_ON(DBG_TRACE), ("buffer too small copy %d of %d\n", PGInfo.CurPesInfo.HeaderNeedBytes, PGInfo.CurPesInfo.PesHeaderLen));
memcpy(&PGInfo.CurPesInfo.PesHdrBuff[PGInfo.CurPesInfo.PesHdrIndex], &Buffer[BytesRead], BytesLeft);
PGInfo.CurPesInfo.PesHdrIndex += (USHORT)(BytesLeft);
PGInfo.CurPesInfo.HeaderNeedBytes -= (BYTE)(BytesLeft);
*ReadBytes = (USHORT)(BytesRead);
return PG_MORE_DATA;
}
/* now analyze the data, do we have just 5 bytes? */
if (PGInfo.CurPesInfo.PesHdrIndex == 5)
{
/* we need the rest of the pes header length */
PGInfo.CurPesInfo.HeaderNeedBytes = PGInfo.CurPesInfo.PesHdrBuff[4]; /* this is the pes header length */
PGInfo.CurPesInfo.PesHeaderLen = PGInfo.CurPesInfo.PesHdrBuff[4];
//DBGPRINT(DBG_ON(DBG_TRACE), ("Pes Header Len is %d\n", PGInfo.CurPesInfo.PesHeaderLen));
}
else
{
/* we have more, is it the whole pes packet? */
if ((5 + PGInfo.CurPesInfo.PesHeaderLen) == PGInfo.CurPesInfo.PesHdrIndex)
{
/* we have the whole header */
PGInfo.CurPesInfo.HeaderNeedBytes = 0;
*ReadBytes = (USHORT)(BytesRead);
return PG_STATUS_SUCCESS;
}
else
{
//DBGPRINT(DBG_ON(DBG_TRACE), ("we need more, header len is %d\n", PGInfo.CurPesInfo.PesHeaderLen));
/* no we need more */
continue;
}
}
}
DBGPRINT(DBG_ON(DBG_ERROR), ("\nExited Assemble PES header incorrectly\n"));
return PG_STATUS_ERROR;
}
/**
* PGAssembleSegmentData - Try to get the requested amount of segment bytes in the buffer
*
* @param BYTE *Buffer - the data buffer with pes data
* @param ULONG Size - the size of Buffer in bytes
* @param USHORT *BytesRead - how many bytes we read from the buffer
*
* @return PG_STATUS
*/
PG_STATUS PGAssembleSegmentData(BYTE *Buffer, ULONG Size, USHORT *ReadBytes)
{
/* try to get the requested number of bytes for the segment header, if we can't get
all the data return PG_MORE_DATA after copying what we can and updating pointers */
if (PGInfo.CurPesInfo.NeedSegmentBytes <= Size)
{
/* get the number of bytes requested */
memcpy(&(PGInfo.CurPesInfo.SegmentTemp[PGInfo.CurPesInfo.SegmentIndex]), Buffer, PGInfo.CurPesInfo.NeedSegmentBytes);
PGInfo.CurPesInfo.SegmentIndex += PGInfo.CurPesInfo.NeedSegmentBytes; /* buffer index up */
*ReadBytes = PGInfo.CurPesInfo.NeedSegmentBytes;
PGInfo.CurPesInfo.NeedSegmentBytes = 0; /* we read all that was requested */
return PG_STATUS_SUCCESS;
}
else
{
/* buffer is too small, copy what we can and mark down the HeaderNeedBytes field */
DBGPRINT(DBG_ON(DBG_TRACE), ("Segment data buffer too small copy %d bytes\n", Size));
memcpy(&PGInfo.CurPesInfo.SegmentTemp[PGInfo.CurPesInfo.SegmentIndex], &Buffer[0], Size);
PGInfo.CurPesInfo.SegmentIndex += (BYTE)(Size);
PGInfo.CurPesInfo.NeedSegmentBytes -= (BYTE)(Size);
*ReadBytes = (USHORT)(Size);
return PG_MORE_DATA;
}
}
/**
* PGAddParseMessage - Queue a message to the PGParse task for it to decode segment data
*
* @param BYTE *BufferStart - pointer to the segment data
* @param ULONG BufferLength - the size of BufferStart in bytes
*
* @return PG_STATUS
*/
PG_STATUS PGAddParseMessage(ULONG BufferStart, ULONG BufferLength, ULONG DTS, ULONG PTS, ULONG Flags, BYTE MultiPES)
{
PG_PARSE_MSG *pMessage = NULL;
/* get a message */
while (pMessage == NULL)
{
pMessage = (PG_PARSE_MSG*)PGInfo.PGParseQ->GetMsg(OS_NO_WAIT);
if (PGInfo.CurrentState != PG_STATE_RUNNING)
{
if (pMessage)
{
PGInfo.PGParseQ->ReleaseMsg(pMessage);
pMessage = NULL;
}
return PG_STATUS_SUCCESS;
}
if (pMessage == NULL)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("PGAddParseMessage(): Couldn't get message, there are %d in Q\n", PGInfo.PGParseQ->FullStatus()));
OS_TaskYield();
}
}
/* fill it */
pMessage->PTS = PTS;
pMessage->DTS = DTS;
pMessage->PTS_DTS_Flags = (BYTE)(Flags);
pMessage->DataStart = &PGInfo.PGParseBuffer[BufferStart];
pMessage->DataLength = BufferLength;
pMessage->MultiPES = MultiPES;
/* send it off */
if (PGInfo.PGParseQ->Write(pMessage, OS_NO_WAIT) != OS_OK)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("Msg add failed, release message (Parser can't keep up)\n"));
/* toss the message back */
PGInfo.PGParseQ->ReleaseMsg(pMessage);
pMessage = NULL;
return PG_STATUS_ERROR;
}
return PG_STATUS_SUCCESS;
}
/**
* PGSendEmptyMessageToStream - send an empty message to a stream, used to wake up threads
*
* @param cStream *Stream - pointer to the stream that will get a blank message (ParseQ or RenderQ)
*
* @return void
*/
void PGSendEmptyMessageToStream(cStream *Stream)
{
if (Stream == PGInfo.PGParseQ)
{
PG_PARSE_MSG *pMessage = NULL;
/* send an empty message to the parse Q */
if (PGInfo.PGParseQ)
{
pMessage = (PG_PARSE_MSG*)PGInfo.PGParseQ->GetMsg(OS_WAIT_FOREVER);
if (pMessage)
{
if (PGInfo.PGParseQ->Write(pMessage, OS_NO_WAIT) != OS_OK)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("Failed to write blank message to PGPARSEQ\n"));
return;
}
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("Failed to get message on PGSendEmptyMessageToStream() Parse\n"));
}
}
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("!!!\n\nPGSendEmptyMessageToStream() - invalid stream type\n"));
}
}
/**
* PGClearAddDataVars - Clear out state vars related to AddData(), this is called on AddData errors
*
* @return void
*/
void PGClearAddDataVars()
{
/* clear data vars, not all of them, keep the write ptr, but put it back to before any data was received */
PGInfo.CurPTS = 0;
PGInfo.CopyingPES = 0;
PGInfo.CopyingMultiPES = 0;
PGInfo.SequenceDesc = 0;
PGInfo.fGotStartPtr = 0;
/* put the pes write pointer back to where it was before
we received packet data for a pes packet. */
if (PGInfo.PESWriteStart != 0)
{
PGInfo.PESWritePtr = PGInfo.PESWriteStart;
}
PGInfo.PESWriteStart = 1;
memset(&PGInfo.CurPesInfo, 0, sizeof(PES_HDR_INFO));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -