📄 ig_api.cpp
字号:
"IGTotalCreateSurfaceTime: %u.%u\nIGTotalAddDataTime: %u.%u\nIGTotalFrameDrops: %u\nIGTotalParseMsgDrops: %u\n"
"IGTotalRLEFailures: %u\nIGPixelDecodeRate: %u.%u\n\n",
IGStats.TotalBlitTicks/TickRate, IGStats.TotalBlitTicks%TickRate,
IGStats.TotalFlipTicks/TickRate, IGStats.TotalFlipTicks%TickRate,
IGStats.TotalRLETicks/TickRate, IGStats.TotalRLETicks%TickRate,
IGStats.TotalCreateSurfaceTicks/TickRate, IGStats.TotalCreateSurfaceTicks%TickRate,
IGStats.TotalAddDataTicks/TickRate, IGStats.TotalAddDataTicks%TickRate,
IGStats.TotalFrameDrops,
IGStats.TotalParseMsgDrops,
IGStats.TotalRLEFailures,
PixelsPerSec,
PixelsRemain));
}
#endif
OS_SemGive(IGInfo.StateLock);
}
else if (IG_STATE_INITIALIZED == IGInfo.CurrentState)
{
/* we should already be stopped */
OS_SemTake(IGInfo.StateLock, OS_WAIT_FOREVER);
IGInfo.CurrentState = IG_STATE_STOPPED;
OS_SemGive(IGInfo.StateLock);
}
else
{
return IG_STATUS_ERROR;
}
return IG_STATUS_SUCCESS;
}
/**
* IGAddData - adds data to the IG module, once this call ends the data given can
* be free'd. Note we don't just copy the data, we inspect the PES headers
* a bit to pull out ES data and drop it in the parse buffer. Then fire
* a message to the IGParse task so it can parse the new data.
*
* @param IG_HANDLE handle - handle to the IG module
* @param BYTE *Buffer - data buffer to add to module
* @param ULONG Size - size of Buffer in bytes
*
* @return IG_STATUS - IG_STATUS_SUCCESS if data copied successfully
* - IG_STATUS_NOT_RUNNING if we are not in the Run State
*/
IG_STATUS IGAddData(IG_HANDLE handle, BYTE *Buffer, ULONG Size)
{
IG_STATUS Status;
ULONG BytesRead=0;
ULONG RetCode;
ULONG LeftToCopy=0;
USHORT AssembleBytesRead=0;
ULONG ObjectDataSize=0;
ULONG BytesLeft=0;
ULONG StartCodeOffset=0;
#ifdef ALLOW_IG_PROFILING
ULONG TickStart = 0;
#endif
/* this routine should copy the data given into our IG parse buffer */
OS_SemTake(IGInfo.StateLock, OS_WAIT_FOREVER);
/* this routine will just copy data to the buffer looking for full PES
packets, when it receives full PES packets it will signal the IG parser
task to go and use the data, if there is a storm of data we should be able to
copy to our buffer and signal the IG parser one at a time when it has finished
with the data, to do that we should just mark each point in the buffer that
contains the start of a PES packet and put it in a list, the IG parser
should be able to just read from that list (or queue) and run with the data,
NOTE: WATCH for data wrap arounds, DON'T STORE data in a non contiguous fashion
in the buffer, make sure there is enough room to work with it in place without wrapping
the copies
NOTE 2: the data is dword filled memory the size given to this call is
NOT the size of the valid data but the size of the chunk, we will need to parse
PES headers and track whats needed in order to get the correct amount of data */
// this one has ics which can also be multiPES so watch
#ifdef ALLOW_IG_PROFILING
if (IGStats.Profiling == 1)
{
TickStart = OS_GetTicks();
}
#endif
if (handle != (PVOID)IG_HANDLE_VALUE)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("IGAddData(): IG_STATUS_INVALID_HANDLE\n"));
#ifdef ALLOW_IG_PROFILING
if (IGStats.Profiling == 1)
{
IGStats.TotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(IGInfo.StateLock);
return IG_STATUS_INVALID_HANDLE;
}
if (IG_STATE_RUNNING != IGInfo.CurrentState)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("IGAddData(): IG_STATUS_NOT_RUNNING\n"));
#ifdef ALLOW_IG_PROFILING
if (IGStats.Profiling == 1)
{
IGStats.TotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(IGInfo.StateLock);
return IG_STATUS_NOT_RUNNING;
}
DBGPRINT(DBG_ON(DBG_VERBOSE), ("--IGAddData 0x%p, size=%d\n", Buffer, Size));
/* loop
{
1. finish current pes packet (if any)
2. look for sync
}*/
/* this is how much is left in the packet */
BytesLeft = Size;
/* loop over the whole buffer */
while (BytesLeft > 0)
{
if ((IG_FLAGS_STOP == IGInfo.QuitFlags) || (IG_FLAGS_EXIT == IGInfo.QuitFlags))
{
DBGPRINT(DBG_ON(DBG_ERROR), ("IGAddData(): Called while in Stop State!\n"));
#ifdef ALLOW_IG_PROFILING
if (IGStats.Profiling == 1)
{
IGStats.TotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(IGInfo.StateLock);
return IG_STATUS_ERROR;
}
/*
1. finish current pes packet (if any)
*/
if (IGInfo.CopyingPES)
{
/* header not complete */
if (0 == IGInfo.CurPesInfo.HeaderComplete)
{
/* if we ran out of data we will wait till the next adddata to finish the header */
RetCode = IGAssemblePesHeader(&Buffer[BytesRead], BytesLeft, &AssembleBytesRead);
if (IG_STATUS_SUCCESS == RetCode)
{
/* packet assembled, read the pes header */
if (IG_STATUS_SUCCESS != IGReadPESHeader(IGInfo.CurPesInfo.PesHdrBuff))
{
/* something is wrong with this pes header, don't try to figure it out
drop data and hope we catch up */
DBGPRINT(DBG_ON(DBG_ERROR), ("IGAddData(): Error in pes header\n"));
IGClearAddDataVars();
#ifdef ALLOW_IG_PROFILING
if (IGStats.Profiling == 1)
{
IGStats.TotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(IGInfo.StateLock);
return IG_STATUS_ERROR;
}
/* are we copying a multipes segment already */
if (0 == IGInfo.CopyingMultiPES)
{
/* is this packet full (multipes)? */
if (0xFFFF == IGInfo.CurPesInfo.PacketSize)
{
/* NOTE: here we make an assumption that we need a minimum of the largest sized header
we will process which is the ICS header + 3 bytes for it's size, If the segment is
really a ICS we will already have the min if we have ICS_HEADER_SIZE */
IGInfo.CurPesInfo.NeedSegmentBytes = ICS_HEADER_SIZE;
IGInfo.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 */
IGWaitForSpaceAvail(IGInfo.CurPesInfo.PacketSize);
if (IGInfo.CurrentState != IG_STATE_RUNNING)
{
OS_SemGive(IGInfo.StateLock);
return IG_STATUS_SUCCESS;
}
}
}
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 */
if (OBJECT_DEFINITION == IGInfo.SegmentType)
{
IGInfo.CurPesInfo.NeedSegmentBytes = ODS_HEADER_SIZE_NO_FRAGMENT;
}
else if (INTERACTIVE_COMPOSITION == IGInfo.SegmentType)
{
IGInfo.CurPesInfo.NeedSegmentBytes = ICS_HEADER_SIZE_MULTIPES;
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("IGAddData(): Illegal segment type on rest of MultiPES packet\n"));
/* clear and reset here */
IGClearAddDataVars();
#ifdef ALLOW_IG_PROFILING
if (IGStats.Profiling == 1)
{
IGStats.TotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(IGInfo.StateLock);
return IG_STATUS_ERROR;
}
IGInfo.CurPesInfo.SegmentIndex = 0;
}
/* move ahead */
BytesRead += AssembleBytesRead;
BytesLeft -= AssembleBytesRead;
AssembleBytesRead = 0;
}
else if (IG_MORE_DATA == RetCode)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("IGAddData(): Need more data\n"));
#ifdef ALLOW_IG_PROFILING
if (IGStats.Profiling == 1)
{
IGStats.TotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(IGInfo.StateLock);
return IG_STATUS_SUCCESS;
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("IGAddData(): IG error adddata\n"));
IGClearAddDataVars();
#ifdef ALLOW_IG_PROFILING
if (IGStats.Profiling == 1)
{
IGStats.TotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(IGInfo.StateLock);
return IG_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 (IGInfo.CurPesInfo.NeedSegmentBytes)
{
RetCode = IGAssembleSegmentData(&Buffer[BytesRead], BytesLeft, &AssembleBytesRead);
if (IG_STATUS_SUCCESS == RetCode)
{
/* we got ODS_HEADER_SIZE bytes of data in, make sure it's a ODS or ICS
NOTE that if it's an ICS we have a few bytes extra in the SegmentTemp buffer
on the first in seqence */
switch(IGInfo.CurPesInfo.SegmentTemp[0])
{
case OBJECT_DEFINITION:
IGInfo.SegmentType = IGInfo.CurPesInfo.SegmentTemp[0]; /* keep track of what kind this is */
IGInfo.SequenceDesc = IGInfo.CurPesInfo.SegmentTemp[6];
break;
case INTERACTIVE_COMPOSITION:
IGInfo.SegmentType = IGInfo.CurPesInfo.SegmentTemp[0]; /* keep track of what kind this is */
IGInfo.SequenceDesc = IGInfo.CurPesInfo.SegmentTemp[11];
break;
default:
DBGPRINT(DBG_ON(DBG_ERROR), ("IGAddData(): This data is incorrect, the data must be a Object Definition Segment, skip data to sync\n"));
/* clear pes parsing structures and state info and return */
IGClearAddDataVars();
#ifdef ALLOW_IG_PROFILING
if (IGStats.Profiling == 1)
{
IGStats.TotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(IGInfo.StateLock);
return IG_STATUS_ERROR; /* we got wrong data */
}
}
else if (IG_MORE_DATA == RetCode)
{
/* we need more data */
DBGPRINT(DBG_ON(DBG_TRACE), ("IGAddData(): IG MORE DATA\n"));
BytesRead -= AssembleBytesRead;
#ifdef ALLOW_IG_PROFILING
if (IGStats.Profiling == 1)
{
IGStats.TotalAddDataTicks += OS_GetTicks() - TickStart;
}
#endif
OS_SemGive(IGInfo.StateLock);
return IG_STATUS_SUCCESS;
}
/* we haven't copied the first of a multipes packet yet */
if (FIRST_IN_SEQUENCE & IGInfo.SequenceDesc)
{
DBGPRINT(DBG_ON(DBG_VERBOSE), ("First in seq %d\n", IGInfo.SequenceDesc));
/*
this is the first in a seqence of pes packets
*/
if (OBJECT_DEFINITION == IGInfo.SegmentType)
{
/* now the size of the object, we need linear space for this */
ObjectDataSize = (IGInfo.CurPesInfo.SegmentTemp[7] << 16) |
(IGInfo.CurPesInfo.SegmentTemp[8] << 8) |
IGInfo.CurPesInfo.SegmentTemp[9];
/* copy the whole header - 4 bytes for width and height of ODS */
ObjectDataSize += ODS_HEADER_SIZE - 4;
/* do we have space for all this data */
IGWaitForSpaceAvail(ObjectDataSize);
if (IGInfo.CurrentState != IG_STATE_RUNNING)
{
OS_SemGive(IGInfo.StateLock);
return IG_STATUS_SUCCESS;
}
/* copy over the segment header data to the IGParseBuffer (this includes some extra bytes) */
memcpy(&IGInfo.IGParseBuffer[IGInfo.PESWritePtr], &Buffer[BytesRead], AssembleBytesRead);
IGInfo.PESWriteStart = IGInfo.PESWritePtr;
IGInfo.PESWritePtr += AssembleBytesRead;
/* copy some ES data */
BytesLeft -= AssembleBytesRead;
BytesRead += AssembleBytesRead;
IGInfo.CurPesInfo.ESRemaining -= AssembleBytesRead;
IGInfo.CurPesInfo.SegmentIndex = 0; /* segment header is read */
}
else if (INTERACTIVE_COMPOSITION == IGInfo.SegmentType)
{
if (IGInfo.CurPesInfo.SegmentIndex == ICS_HEADER_SIZE)
{
/* calc the size of the ICS */
ObjectDataSize = (IGInfo.CurPesInfo.SegmentTemp[12] << 16) |
(IGInfo.CurPesInfo.SegmentTemp[13] << 8) |
IGInfo.CurPesInfo.SegmentTemp[14];
/* copy the whole header - 4 bytes for width and height of ODS */
ObjectDataSize += ICS_HEADER_SIZE;
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("IGAddData(): Error with data size of first ICS in Segment Data\n"));
IGClearAddDataVars();
#ifdef ALLOW_IG_PROFILING
if (IGStats.Profiling == 1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -