Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1407 lines
42 KiB

/////////////////////////////////////////////////////////////////////////////
// INTEL Corporation Proprietary Information
// This listing is supplied under the terms of a license agreement with Intel
// Corporation and many not be copied nor disclosed except in accordance
// with the terms of that agreement.
// Copyright (c) 1995, 1996 Intel Corporation.
//
//
// Module Name: h261rcv.cpp
// Environment: MSVC 4.0, OLE 2
/////////////////////////////////////////////////////////////////////////////////
// $Header: J:\rtp\src\ppm\h261rcv.cpv 1.43 29 May 1997 16:42:08 lscline $
#include "ppmerr.h"
#include "h261rcv.h"
#include "ippmcb.h"
#define H261_HDR_T int // for now
//////////////////////////////////////////////////////////////////////////////
// Private global data
#ifdef REBUILD_EXBITSTREAM
static const struct { DWORD dw[2]; } s_leadFragBitPatternQCIF =
{
MAKELONG(MAKEWORD(0, 1), MAKEWORD(0, 0)), // 4 bytes {0,1, 0,0}, big-endian
MAKELONG(MAKEWORD(0, 1), MAKEWORD(16, 0)) // 4 bytes {0,1,16,0}, big-endian
};
static const struct { DWORD dw[2]; } s_leadFragBitPatternCIF =
{
MAKELONG(MAKEWORD(0, 1), MAKEWORD(0, 40)), // 4 bytes {0,1, 0,40}, big-endian
MAKELONG(MAKEWORD(0, 1), MAKEWORD(16, 0)) // 4 bytes {0,1,16, 0}, big-endian
};
static const struct { char ch[4]; } s_nonLeadFragBitPattern = {0, 0, 0, 0};
#endif
/////////////////////////////////////////////////////////////////////////////
// H.261 utility function
/////////////////////////////////////////////////////////////////////////////
// getH261payloadType(): If successful, returns the payload type (QCIF or CIF)
// of H.261 buffer, otherwise returns unknown.
/////////////////////////////////////////////////////////////////////////////
// inline
RTPh261SourceFormat getH261payloadType(const void* pBuffer)
{
CBitstream bitstream(pBuffer);
// PSC
DWORD uResult = bitstream.getFixedBits(BITS_PICTURE_STARTCODE);
for (
int iLookAhead = 0;
(uResult != PSC_VALUE)
&& (iLookAhead <= MAX_LOOKAHEAD_NUMBER);
++ iLookAhead)
{
bitstream.getNextBit(uResult);
uResult &= GetBitsMask(BITS_PICTURE_STARTCODE);
}
if (uResult != PSC_VALUE)
{
return rtph261SourceFormatUnknown;
}
// Ignore BITS_TR (Temporal Reference)
bitstream.getFixedBits(BITS_TR);
// Ignore 3 bits of PTYPE (Picture Type)
bitstream.getFixedBits(3);
// Return source format. Only one bit, can't be invalid, unless we run
// out of buffer, which isn't checked for here.
return (RTPh261SourceFormat) bitstream.getFixedBits(1);
}
//////////////////////////////////////////////////////////////////////////////
// H261_ppmReceive implementation
H261_ppmReceive::H261_ppmReceive(IUnknown* pUnkOuter, IUnknown** ppUnkInner)
: ppmReceive(H261_PT, H261_BUFFER_SIZE, sizeof(unsigned long), pUnkOuter, ppUnkInner)
{
m_rtph261SourceFormat = rtph261SourceFormatUnknown;
m_GlobalLastMarkerBitIn = FALSE;
#ifdef REBUILD_EXBITSTREAM
m_ExtendedBitstream = TRUE;
#endif
// Allocate memory for the H261 headers;
// Note: We do not use ReadProfileHeaderSize for this, since this header structure
// contains padding so it can be in a FreeList; here we use the real padded size
HRESULT hr;
m_pH261Headers = new FreeList(
FREELIST_INIT_COUNT_RCV,
sizeof(H261_Header),
FREELIST_HIGH_WATER_MARK,
FREELIST_INCREMENT,
&hr); // Not really used here
if (! m_pH261Headers)
{
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::H261_ppmReceive: ERROR - m_pH261Headers == NULL"));
}
// Verify assumption made in H261_ppmReceive::BuildExtendedBitstream() wrt
// handling of underflow.
DWORD dwBufSize = 0;
int nLastEbit = 0;
ASSERT(
(((dwBufSize - 1) * BITSPERBYTE) +
(BITSPERBYTE - nLastEbit)) ==
(BITSPERBYTE * dwBufSize));
}
H261_ppmReceive::~H261_ppmReceive()
{
if (m_pH261Headers) {
delete m_pH261Headers;
m_pH261Headers = NULL;
}
}
IMPLEMENT_CREATEPROC(H261_ppmReceive);
//////////////////////////////////////////////////////////////////////////////
// ppmReceive Functions (Overrides)
//////////////////////////////////////////////////////////////////////////////
#ifdef REBUILD_EXBITSTREAM
//////////////////////////////////////////////////////////////////////////////////////////
// SetSession:
//////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP H261_ppmReceive::SetSession(PPMSESSPARAM_T* pSessparam)
{
// ccp - note unsafe downcast
m_ExtendedBitstream = ((H26XPPMSESSPARAM_T*) pSessparam)->ExtendedBitstream;
return ppmReceive::SetSession(pSessparam);
}
//////////////////////////////////////////////////////////////////////////////
// IPPMReceiveSession Functions (Overrides)
//////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
//GetResiliency: Gets the boolean for whether resiliency is on or off
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP H261_ppmReceive::GetResiliency(LPBOOL lpbResiliency)
{
if (!lpbResiliency) return E_POINTER;
*lpbResiliency = m_ExtendedBitstream;
return NOERROR;
}
////////////////////////////////////////////////////////////////////////////////////////
//SetResiliency: Sets the boolean for whether resiliency is on or off
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP H261_ppmReceive::SetResiliency(BOOL pbResiliency)
{
m_ExtendedBitstream = pbResiliency;
return NOERROR;
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// TimeToProcessMessages:
//////////////////////////////////////////////////////////////////////////////////////////
BOOL H261_ppmReceive::TimeToProcessMessages(FragDescriptor* pFragDescrip, MsgHeader* pMsgHdr)
{
return (pMsgHdr == m_pMsgHeadersHead);
}
//////////////////////////////////////////////////////////////////////////////////////////
// CheckMessageComplete:
//////////////////////////////////////////////////////////////////////////////////////////
BOOL H261_ppmReceive::CheckMessageComplete(MsgHeader* pMsgHdr)
{
// if there is no header then return false.
if (pMsgHdr == NULL)
{
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::CheckMessageComplete: ERROR - pMsgHdr == NULL"));
return FALSE;
}
// should there be a critical section in this function.
// check to make sure we have the first packet in the message.
if (pMsgHdr->m_pPrev == NULL) // if first message in list, then look at a variable
{
if (m_GlobalLastSeqNum != pMsgHdr->m_pFragList->FirstSeqNum()-1)
{
return FALSE;
}
}
else
{
if (pMsgHdr->m_pPrev->m_pFragList->LastSeqNum() != pMsgHdr->m_pFragList->FirstSeqNum()-1)
{
return FALSE;
}
}
// check to make sure we have the last packet in the message.
// For IETF compliance, marker bit must be set, but in H.225, the marker bit
// may optionally be omitted if setting it could cause additional end-to-end delay
// Thus, we check for the marker bit, but if it is not present, we also check to
// see if the next packet is in and has a different timestamp (ala generic).
if (! pMsgHdr->m_MarkerBitIn)
{
if (pMsgHdr->m_pNext == NULL) // if we don't have the next message,
{ // we don't know if the current message
// is done.
return FALSE;
}
if (pMsgHdr->m_pNext->m_pFragList->FirstSeqNum() !=
pMsgHdr->m_pFragList->LastSeqNum() + 1)
{
return FALSE;
}
}
// Check for a packet missing in the middle->
if ((int)pMsgHdr->m_pFragList->SeqNumSpan() != pMsgHdr->m_NumFragments)
{
return FALSE;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////////////
// PrepMessage: Sets H261 global variables, calls base PrepMessage. If any error
// checks are added, you MUST make a call to LeaveCriticalSection.
//////////////////////////////////////////////////////////////////////////////////////////
HRESULT H261_ppmReceive::PrepMessage(BOOL Complete)
{
EnterCriticalSection(&m_CritSec);
// Can't hurt to check although we should never get here if there is no head.
if (m_pMsgHeadersHead == NULL)
{
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::PrepMessage: ERROR - m_pMsgHeadersHead == NULL"));
LeaveCriticalSection(&m_CritSec);
return PPMERR(PPM_E_CORRUPTED);
}
// Save marker bit flag.
BOOL bMarkerBitIn = m_pMsgHeadersHead->m_MarkerBitIn;
LeaveCriticalSection(&m_CritSec);
HRESULT hErr = ppmReceive::PrepMessage(Complete);
// Update the H261 global variable.
m_GlobalLastMarkerBitIn = bMarkerBitIn;
DBG_MSG(DBG_TRACE,
("H261_ppmReceive::PrepMessage: m_GlobalLastMarkerBitIn=%d",
m_GlobalLastMarkerBitIn));
return hErr;
}
#ifdef REBUILD_EXBITSTREAM
//////////////////////////////////////////////////////////////////////////////////////////
// setBSInfoTrailer(): Inline helper to build EBS trailer.
//////////////////////////////////////////////////////////////////////////////////////////
void
setH261BSInfoTrailer(
BSINFO_TRAILER& rBS_trailer,
int iFrame,
DWORD dwBufSize,
int nNumFrags,
RTPh261SourceFormat rtph261SourceFormat)
{
// complete info for the trailer
rBS_trailer.dwVersion = H261_VERSION;
rBS_trailer.dwUniqueCode = H261_CODE;
rBS_trailer.dwFlags = 0;
if (iFrame)
rBS_trailer.dwFlags |= RTP_H26X_INTRA_CODED;
rBS_trailer.dwCompressedSize = dwBufSize;
rBS_trailer.dwNumberOfPackets = nNumFrags;
// Note: We may send unknown source format here if frame PSC was corrupt
// or missing, but we'll let the codec deal with that. Codec will
// typically just toss the frame, but sending unknown might facilitate
// more advanced error receover (i.e. attempting to deterimine source
// format from frame content). This would be more likely in an off-line
// (vs. real time) decoder. If codec doesn't support "unknown", it can
// use source format indicated by PSC
rBS_trailer.SourceFormat = rtph261SourceFormat;
// For H.261, we just put zeroes in these fields
rBS_trailer.TR = 0;
rBS_trailer.TRB = 0;
rBS_trailer.DBQ = 0;
}
#endif // REBUILD_EXBITSTREAM
// lsc - Note: we are not rebuilding the extended bitstream
// for complete frames.
// For now I am assuming that we only rebuild the extended bitstream for frames that
// have not received all packets (handled by PartialMessageHandler), and for complete
// frames we hand them up as usual. However, this routine is overridden to handle the
// data ORing for the byte overlap between packets.
#pragma optimize ( "", off ) // BUGBUG: Work around complier bug
//////////////////////////////////////////////////////////////////////////////////////////
// DataCopy: Copies data fragments into client's buffer. If any error checks with returns
// are added they MUST call LeaveCriticalSection.
//
//////////////////////////////////////////////////////////////////////////////////////////
HRESULT H261_ppmReceive::DataCopy(MsgHeader* const pMsgHdr)
{
if (pMsgHdr == NULL)
{
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::DataCopy: ERROR - pMsgHdr == NULL"));
return PPMERR(PPM_E_EMPTYQUE);
}
ASSERT(! pMsgHdr->m_pFragList->Is_Empty());
MsgDescriptor* pMsgDesc = DequeueBuffer(1); // Get a buffer to hold the message.
if (pMsgDesc == NULL)
{
FreeFragList(pMsgHdr);
FreeMsgHeader(pMsgHdr);
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::DataCopy: ERROR - Couldn't get a reassembly buffer"));
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_DROPFRAME, SEVERITY_NORMAL, NULL, 0);
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
EnterCriticalSection(&m_CritSec);
#ifdef GIVE_SEQNUM
// Do this before frag list exhausted below
pMsgDesc->m_TimeStamp = pMsgHdr->m_pFragList->LastSeqNum();
#else
pMsgDesc->m_TimeStamp = pMsgHdr->GetMsgID();
#endif
// Get payload type from PSC for BuildExtendedBitstream(). Do this even
// when not currently building the extended bitstream, since that mode can
// be toggled during the session.
RTPh261SourceFormat currentSourceFormat =
getH261payloadType(
((FragDescriptor*) pMsgHdr->m_pFragList->GetFirst())->m_pData);
if (currentSourceFormat != rtph261SourceFormatUnknown)
// Remember valid format for use by next frame.
m_rtph261SourceFormat = currentSourceFormat;
#ifdef REBUILD_EXBITSTREAM
BITSTREAM_INFO_H261* pEBS = NULL;
int nNumFrags = 0, nCurrentEBS = 0, iFrame = 0;
// Get local copy of extended bitstream flag to protect against
// possible change via H261_ppmReceive::SetSession() while building
// this frame. OK to change between frames.
BOOL bExtendedBitstream = m_ExtendedBitstream;
if (bExtendedBitstream)
{
nNumFrags = pMsgHdr->m_pFragList->SeqNumSpan();
// allocate structures for the extended bitstream information
pEBS = new BITSTREAM_INFO_H261[nNumFrags];
if (pEBS == NULL)
{
FreeFragList(pMsgHdr);
EnqueueBuffer(pMsgDesc);
FreeMsgHeader(pMsgHdr);
LeaveCriticalSection(&m_CritSec);
DBG_MSG(DBG_ERROR,
("H261_ppmReceive::DataCopy: ERROR - memory allocation failure"));
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_OUTOFMEMORY, SEVERITY_NORMAL, NULL, 0);
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
memset(pEBS, 0, nNumFrags * sizeof(*pEBS));
}
#endif
// Loop state variables
LPBYTE pbCurrentOffset = (LPBYTE) pMsgDesc->m_pBuffer; // start copying into front of buffer.
DWORD dwBufSize = 0;
UCHAR chLastByte = 0;
int nLastEbit = 0; // prior packet's ebit, for error checking
// There are three cases to check for overlapping bytes between
// packets:
// 1) There is overlap between packets, and this is first packet.
// 2) There is overlap between packets, and this is not first packet.
// 3) There is no overlap between packets.
// We'll check case 1 now, before getting into packet loop.
if (((H261_Header*)
(((FragDescriptor*) pMsgHdr->m_pFragList->GetFirst())->m_pProfileHeader)
)->sbit())
{
// First packet overlaps prior frame (case 1). Add a byte to hold
// first sbits. No need to clear byte now, since it'll be overwritten
// by chFirstByte below.
pbCurrentOffset++;
dwBufSize++;
}
// Process all rcvd packets
while (! pMsgHdr->m_pFragList->Is_Empty())
{
// get next fragment (const to prevent unintentional modification)
FragDescriptor* const pFragDesc = (FragDescriptor*)
pMsgHdr->m_pFragList->TakeFromList();
m_PacketsHold--;
// Verify that TakeFromList() didn't return NULL and that we
// won't overrun the buffer.
BOOL bExit;
#ifdef REBUILD_EXBITSTREAM
if (bExtendedBitstream && (pFragDesc != NULL))
{
bExit =
((dwBufSize +
pFragDesc->m_BytesOfData +
(nNumFrags * sizeof(*pEBS)) +
sizeof(BSINFO_TRAILER) +
offsetNextDword(pbCurrentOffset))
> pMsgDesc->m_Size);
}
else
#endif
{
bExit =
((pFragDesc == NULL) ||
(dwBufSize + pFragDesc->m_BytesOfData >= pMsgDesc->m_Size));
}
if (bExit)
{
FreeFragList(pMsgHdr);
EnqueueBuffer(pMsgDesc);
FreeMsgHeader(pMsgHdr);
#ifdef REBUILD_EXBITSTREAM
if (bExtendedBitstream)
{
if (pEBS) {
delete [] pEBS;
pEBS = NULL;
}
}
#endif
LeaveCriticalSection(&m_CritSec);
DBG_MSG(DBG_ERROR,
("H261_ppmReceive::DataCopy: ERROR - null pFragDesc or buffer overrun"));
if (pFragDesc != NULL)
{
// Release the CRTPSample to receive more data
m_pSubmitCallback->SubmitComplete(pFragDesc->m_pFragCookie,
NOERROR);
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_RECVSIZE, SEVERITY_NORMAL, NULL, 0);
// BUGBUG We are here because
// m_pFragList->Is_Empty() == FALSE
// then the pFragDesc should always be != NULL
if (pFragDesc->m_pProfileHeader)
FreeProfileHeader(pFragDesc->m_pProfileHeader);
FreeFragDescriptor(pFragDesc);
}
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
// Assign immutable reference to profile header
H261_Header& rProfileHdr =
*(H261_Header*) pFragDesc->m_pProfileHeader;
#ifdef REBUILD_EXBITSTREAM
if (bExtendedBitstream)
{
// Write BS struct for current packet. Do this _before_
// advancing dwBufSize.
pEBS[nCurrentEBS].dwFlags = 0;
if (rProfileHdr.sbit())
{
// Adjust EBS bit offset for this packet's sbits
pEBS[nCurrentEBS].dwBitOffset =
((dwBufSize - 1) * BITSPERBYTE)
+ rProfileHdr.sbit();
}
else
{
pEBS[nCurrentEBS].dwBitOffset = dwBufSize * BITSPERBYTE;
}
pEBS[nCurrentEBS].MBAP = rProfileHdr.mbap();
pEBS[nCurrentEBS].Quant = rProfileHdr.quant();
pEBS[nCurrentEBS].GOBN = rProfileHdr.gobn();
pEBS[nCurrentEBS].HMV = rProfileHdr.hmvd();
pEBS[nCurrentEBS].VMV = rProfileHdr.vmvd();
nCurrentEBS++;
}
#endif /* REBUILD_EXBITSTREAM */
if (rProfileHdr.sbit())
{
// This packet has missing sbits (case 1 or 2)
UCHAR chFirstByte =
*((LPBYTE) pFragDesc->m_pData)
& GetSMask(rProfileHdr.sbit());
// Either this is first packet (thus no ebits), or the prior
// and current packets had better overlap properly.
if ((nLastEbit != 0)
&& ((nLastEbit + rProfileHdr.sbit()) != BITSPERBYTE))
{
FreeFragList(pMsgHdr);
EnqueueBuffer(pMsgDesc);
FreeMsgHeader(pMsgHdr);
#ifdef REBUILD_EXBITSTREAM
if (bExtendedBitstream)
{
if (pEBS) {
delete [] pEBS;
pEBS = NULL;
}
}
#endif
LeaveCriticalSection(&m_CritSec);
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::DataCopy: ERROR - Received packets with sbit/ebit mismatch"));
if (pFragDesc != NULL)
{
// Release the CRTPSample to receive more data
m_pSubmitCallback->SubmitComplete(pFragDesc->m_pFragCookie,
NOERROR);
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_DROPFRAME, SEVERITY_NORMAL, NULL, 0);
// BUGBUG We are here because
// m_pFragList->Is_Empty() == FALSE
// then the pFragDesc should always be != NULL
if (pFragDesc->m_pProfileHeader)
FreeProfileHeader(pFragDesc->m_pProfileHeader);
FreeFragDescriptor(pFragDesc);
}
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
// combine sbits with ebits from prior packet
chFirstByte |= chLastByte;
// Copy packet to buffer
pbCurrentOffset[-1] = chFirstByte;
dwBufSize +=
copyAndAdvance(
pbCurrentOffset,
(LPBYTE) pFragDesc->m_pData + 1,
pFragDesc->m_BytesOfData - 1);
}
else
{
// This packet has no missing sbits (case 3).
if (nLastEbit != 0)
{
// Prior packet has missing ebits; possible encoding error.
FreeFragList(pMsgHdr);
EnqueueBuffer(pMsgDesc);
FreeMsgHeader(pMsgHdr);
#ifdef REBUILD_EXBITSTREAM
if (bExtendedBitstream)
{
if (pEBS) {
delete [] pEBS;
pEBS = NULL;
}
}
#endif
LeaveCriticalSection(&m_CritSec);
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::DataCopy: ERROR - Received packets with sbit/ebit mismatch"));
if (pFragDesc != NULL)
{
// Release the CRTPSample to receive more data
m_pSubmitCallback->SubmitComplete(pFragDesc->m_pFragCookie,
NOERROR);
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_DROPFRAME, SEVERITY_NORMAL, NULL, 0);
// BUGBUG We are here because
// m_pFragList->Is_Empty() == FALSE
// then the pFragDesc should always be != NULL
if (pFragDesc->m_pProfileHeader)
FreeProfileHeader(pFragDesc->m_pProfileHeader);
FreeFragDescriptor(pFragDesc);
}
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
// Copy packet to buffer
dwBufSize +=
copyAndAdvance(
pbCurrentOffset,
(LPBYTE) pFragDesc->m_pData,
pFragDesc->m_BytesOfData);
#ifdef REBUILD_EXBITSTREAM
if (bExtendedBitstream)
{
iFrame = rProfileHdr.i();
}
#endif
}
// Always shift the ignored bits out of the last byte and patch it
// back into the buffer, since there is no harm in doing so.
chLastByte =
(*((LPBYTE)pFragDesc->m_pData + pFragDesc->m_BytesOfData-1))
& GetEMask(rProfileHdr.ebit());
// Overwrite last byte in buffer
pbCurrentOffset[-1] = chLastByte;
// Save for packet misalignment detection.
nLastEbit = rProfileHdr.ebit();
// send the frag buffer back down to receive more data and free the frag header.
m_pSubmitCallback->SubmitComplete(pFragDesc->m_pFragCookie, NOERROR);
if (pFragDesc->m_pProfileHeader)
FreeProfileHeader(pFragDesc->m_pProfileHeader);
FreeFragDescriptor(pFragDesc);
} // End of packet processing loop
#ifdef REBUILD_EXBITSTREAM
if (bExtendedBitstream)
{
{
// Test if the buffer size is enough to avoid
// writing past the buffer size
unsigned char *ptr;
ptr = pbCurrentOffset +
offsetNextDword(pbCurrentOffset) +
nNumFrags * sizeof(*pEBS) +
sizeof(BSINFO_TRAILER);
if (ptr > ((unsigned char *)(pMsgDesc->m_pBuffer) +
pMsgDesc->m_Size) ) {
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_RECVSIZE, SEVERITY_NORMAL, NULL, 0);
#if DEBUG_FREELIST > 2
char str[128];
wsprintf(str,"DataCopy[0x%X]: "
"About to corrupt buffer "
"at: 0x%X size=%d, drop frame\n",
pMsgDesc->m_pBuffer, ptr-1, pMsgDesc->m_Size);
OutputDebugString(str);
#endif
if (pEBS)
delete [] pEBS;
// Drop frame
FreeFragList(pMsgHdr);
EnqueueBuffer(pMsgDesc);
FreeMsgHeader(pMsgHdr);
LeaveCriticalSection(&m_CritSec);
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
}
// Note that we don't increment dwBufSize here, since it doesn't include EBS or trailer.
// pad with zeros to next dword boundary
static const DWORD dwZero = 0;
copyAndAdvance(pbCurrentOffset, &dwZero, offsetNextDword(pbCurrentOffset));
// copy the extended bitstream structures into the buffer
copyAndAdvance(pbCurrentOffset, pEBS, nNumFrags * sizeof(*pEBS));
// Delete now to prevent erroneous late update
delete [] pEBS;
pEBS = NULL;
setH261BSInfoTrailer(
*(BSINFO_TRAILER*) pbCurrentOffset,
iFrame,
dwBufSize,
nNumFrags,
currentSourceFormat);
pbCurrentOffset += sizeof(BSINFO_TRAILER);
}
#endif /* REBUILD_EXBITSTREAM */
LeaveCriticalSection(&m_CritSec);
// When we are done. Call Client's submit with full Message
WSABUF tmpWSABUF[2];
tmpWSABUF[0].buf = (char*) pMsgDesc->m_pBuffer;
#ifdef REBUILD_EXBITSTREAM
if (bExtendedBitstream)
{
// we report the size including the extended bitstream + trailer + padding
tmpWSABUF[0].len = (ULONG) (pbCurrentOffset -
(LPBYTE) pMsgDesc->m_pBuffer);
}
else
#endif
{
tmpWSABUF[0].len = dwBufSize;
}
tmpWSABUF[1].buf = (char*) &(pMsgDesc->m_TimeStamp);
tmpWSABUF[1].len = sizeof(pMsgDesc->m_TimeStamp);
FreeMsgHeader(pMsgHdr);
HRESULT status =
m_pSubmit->Submit(
tmpWSABUF,
2,
pMsgDesc,
m_GlobalLastFrameDropped ? PPMERR(PPM_E_DROPFRAME) : NOERROR);
m_GlobalLastFrameDropped = FALSE;
if (FAILED(status))
{
#if DEBUG_FREELIST > 2
char str[128];
wsprintf(str,"DataCopy: Submit failed %d (0x%X)\n", status, status);
OutputDebugString(str);
#endif
// no SubmitComplete should be called, so take care of resources now
//pMsgDesc->m_Size = m_MaxBufferSize; // reset the data buffer size
//EnqueueBuffer(pMsgDesc);
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::DataCopy: ERROR - Client Submit failed"));
status = PPMERR(PPM_E_CLIENTERR);
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_CLIENTERR, SEVERITY_NORMAL, NULL, 0);
m_GlobalLastFrameDropped = TRUE;
}
return status;
}
#pragma optimize ( "", on ) // BUGBUG: Work around complier bug
#ifdef REBUILD_EXBITSTREAM
//////////////////////////////////////////////////////////////////////////////////////////
// initBitstreamInfoH261: Prepares bitstream info vector element. This function assumes
// that bitstream info vector was zero-filed on allocation, and that elements are never
// reused. If this turns out to be dangerous, this function should memset BS_info to zero.
//////////////////////////////////////////////////////////////////////////////////////////
inline void
initBitstreamInfoH261(BITSTREAM_INFO_H261& BS_info, DWORD dwBitOffset = 0)
{
BS_info.dwFlags = RTP_H26X_PACKET_LOST;
BS_info.dwBitOffset = dwBitOffset;
}
//////////////////////////////////////////////////////////////////////////////////////////
// BuildExtendedBitstream: build extended bitstream
//////////////////////////////////////////////////////////////////////////////////////////
HRESULT H261_ppmReceive::BuildExtendedBitstream(MsgHeader* const pMsgHdr)
{
MsgDescriptor* pMsgDesc = DequeueBuffer(1); // Get a buffer to hold the message.
if (pMsgDesc == NULL)
{
FreeFragList(pMsgHdr);
FreeMsgHeader(pMsgHdr);
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::BuildExtendedBitstream: ERROR - Couldn't get a reassembly buffer"));
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_DROPFRAME, SEVERITY_NORMAL, NULL, 0);
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
EnterCriticalSection(&m_CritSec);
#ifdef GIVE_SEQNUM
// Do this before frag list exhausted below
pMsgDesc->m_TimeStamp = pMsgHdr->m_pFragList->LastSeqNum();
#else
pMsgDesc->m_TimeStamp = pMsgHdr->GetMsgID();
#endif
int nExtraFrags = 0;
// Use presence/absence of valid picture start code to determine whether
// or not first fragment has been rcvd.
RTPh261SourceFormat currentSourceFormat =
getH261payloadType(
((FragDescriptor*) pMsgHdr->m_pFragList->GetFirst())->m_pData);
if (currentSourceFormat == rtph261SourceFormatUnknown)
{
nExtraFrags++;
}
else
{
// Remember valid format for use by next frame
m_rtph261SourceFormat = currentSourceFormat;
}
// Check for last packet missing; if so, add 1 to nNumFrags.
if (! pMsgHdr->m_MarkerBitIn)
{
nExtraFrags++;
}
// Compute frame fragment count (const for safety)
const int nNumFrags =
pMsgHdr->m_pFragList->SeqNumSpan() + nExtraFrags;
DBG_MSG(DBG_TRACE,
("H261_ppmReceive::BuildExtendedBitstream: "
"m_GlobalLastMarkerBitIn=%d, "
"m_GlobalLastSeqNum=%d",
m_GlobalLastMarkerBitIn,
m_GlobalLastSeqNum));
DBG_MSG(DBG_TRACE,
("H261_ppmReceive::BuildExtendedBitstream: "
"MsgHeader*=0x%08lx, FirstSeqNum()=%d",
pMsgHdr,
pMsgHdr->m_pFragList->FirstSeqNum()));
DBG_MSG(DBG_TRACE,
(" LastSeqNum()=%d, nNumFrags=%d",
pMsgHdr->m_pFragList->LastSeqNum(),
nNumFrags));
// allocate structures for the extended bitstream information
BITSTREAM_INFO_H261* pEBS = new BITSTREAM_INFO_H261[nNumFrags];
if (pEBS == NULL)
{
FreeFragList(pMsgHdr);
EnqueueBuffer(pMsgDesc);
FreeMsgHeader(pMsgHdr);
LeaveCriticalSection(&m_CritSec);
DBG_MSG(DBG_ERROR,
("H261_ppmReceive::BuildExtendedBitstream: ERROR - memory allocation failure"));
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_OUTOFMEMORY, SEVERITY_NORMAL, NULL, 0);
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
memset(pEBS, 0, nNumFrags * sizeof(*pEBS));
LPBYTE pbCurrentOffset = (LPBYTE) pMsgDesc->m_pBuffer; // start copying into front of buffer.
DWORD dwBufSize = 0;
int nCurrentEBS = 0; // EBS vector index
if (currentSourceFormat == rtph261SourceFormatUnknown)
{
// Source format is unknown, assume first packet is missing.
// Add EBS info for the lost first packet
initBitstreamInfoH261(pEBS[nCurrentEBS ++]);
// Add new padding values for lost first packet. Use PSC which
// corresponds to source format of last seen valid PSC.
if (m_rtph261SourceFormat == rtph261SourceFormatCIF)
{
dwBufSize +=
copyAndAdvance(
pbCurrentOffset,
&s_leadFragBitPatternCIF,
sizeof(s_leadFragBitPatternCIF));
}
else
{
// Either QCIF or unknown
dwBufSize +=
copyAndAdvance(
pbCurrentOffset,
&s_leadFragBitPatternQCIF,
sizeof(s_leadFragBitPatternQCIF));
}
}
// Loop state variables
UCHAR chLastByte = 0;
int iFrame = 0, nLastEbit = 0;
int nCurrentSeqNum = pMsgHdr->m_pFragList->FirstSeqNum();
// Process all rcvd packets
while (! pMsgHdr->m_pFragList->Is_Empty())
{
// get next fragment (const to prevent unintentional modification)
FragDescriptor* const pFragDesc = (FragDescriptor*)
pMsgHdr->m_pFragList->TakeFromList();
m_PacketsHold--;
// Note: remember that m_pFragList will be empty after the last
// iteration of this loop, so LList::methods which expect a
// non-empty list should not be called below.
// check to see if TakeFromList() returned NULL. Also, make sure
// we won't overrun the buffer (including extended bitstream,
// the trailer and any dword alignment bits that need to be added).
if ((pFragDesc == NULL) ||
((dwBufSize +
pFragDesc->m_BytesOfData +
(nNumFrags * sizeof(*pEBS)) +
sizeof(BSINFO_TRAILER) +
offsetNextDword(pbCurrentOffset))
> pMsgDesc->m_Size))
{
FreeFragList(pMsgHdr);
EnqueueBuffer(pMsgDesc);
FreeMsgHeader(pMsgHdr);
if (pEBS) {
delete [] pEBS;
pEBS = NULL;
}
LeaveCriticalSection(&m_CritSec);
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::BuildExtendedBitstream: ERROR - null pFragDesc or buffer overrun"));
if (pFragDesc != NULL)
{
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_RECVSIZE, SEVERITY_NORMAL, NULL, 0);
// BUGBUG We are here because
// m_pFragList->Is_Empty() == FALSE
// then the pFragDesc should always be != NULL
if (pFragDesc->m_pProfileHeader)
FreeProfileHeader(pFragDesc->m_pProfileHeader);
FreeFragDescriptor(pFragDesc);
}
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
DBG_MSG(DBG_TRACE,
("H261_ppmReceive::BuildExtendedBitstream: "
"FragDescriptor*=0x%08lx, "
"seq=%d, "
"ts=%lu, "
"frag[0-3]=%1X%1X%1X%1X",
pFragDesc,
pFragDesc->m_pRTPHeader->seq(),
pFragDesc->m_pRTPHeader->ts(),
((char*) pFragDesc->m_pData)[0],
((char*) pFragDesc->m_pData)[1],
((char*) pFragDesc->m_pData)[2],
((char*) pFragDesc->m_pData)[3]));
// see if packets are skipped; if so, put padding into buffer and add BS struct
#ifdef RTP_CLASS
for (; nCurrentSeqNum < pFragDesc->m_pRTPHeader->seq(); nCurrentSeqNum++)
#else
for (; nCurrentSeqNum < ntohs(pFragDesc->m_pRTPHeader->seq); nCurrentSeqNum++)
#endif
{
if (nCurrentEBS >= nNumFrags) { //ERROR, bail out
FreeFragList(pMsgHdr);
EnqueueBuffer(pMsgDesc);
FreeMsgHeader(pMsgHdr);
if (pEBS) {
delete [] pEBS;
pEBS = NULL;
}
LeaveCriticalSection(&m_CritSec);
DBG_MSG(DBG_ERROR, ("H263_ppmReceive::BuildExtendedBitstream: ERROR - buffer overrun"));
if (pFragDesc != NULL)
{
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_RECVSIZE, SEVERITY_NORMAL, NULL, 0);
// BUGBUG We are here because
// m_pFragList->Is_Empty() == FALSE
// then the pFragDesc should always be != NULL
if (pFragDesc->m_pProfileHeader)
FreeProfileHeader(pFragDesc->m_pProfileHeader);
FreeFragDescriptor(pFragDesc);
}
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
// If prior rcvd packet had missing ebits, adjust bit
// offset accordingly. The missing bits are added to the
// tail of the padding (by forcing bit offset of _next_
// segment to be byte-aligned). If there was no prior rcvd
// packet, or prior packet had no missing ebits, nLastEbit ==
// 0, so that the bit offset expression is equivalent to
// (dwBufSize * BITSPERBYTE).
initBitstreamInfoH261(
pEBS[nCurrentEBS++],
((dwBufSize - 1) * BITSPERBYTE)
+ (BITSPERBYTE - nLastEbit));
// we just consumed the last ebits (if any), and are now back
// to byte alignment.
nLastEbit = 0;
chLastByte = 0;
// for packets other than the first of the frame, we pad with 4
// bytes of zeroes
dwBufSize +=
copyAndAdvance(
pbCurrentOffset,
&s_nonLeadFragBitPattern,
sizeof(s_nonLeadFragBitPattern));
}
// Assign immutable reference to profile header
H261_Header& rProfileHdr =
*(H261_Header*) pFragDesc->m_pProfileHeader;
// Handle overlapping (shared byte) between current and prior
// between packets. There are three cases to deal with:
// 1) Current packet overlaps the prior packet, and the prior
// packet was received.
// 2) Current packet overlaps the prior packet, and this is first
// packet or prior packet was lost (there are no pending ebits).
// 3) Current packet doesn't overlap the prior packet.
if (rProfileHdr.sbit())
{
// This packet had missing sbits (case 1 or 2).
// Mask off missing sbits and combin with ebits from prior packet.
const UCHAR chFirstByte =
(*(LPBYTE) pFragDesc->m_pData
& GetSMask(rProfileHdr.sbit()))
| chLastByte;
if (nLastEbit == 0)
{
// Case 2: There are no pending ebits, so we need an
// extra byte into which to stuff the current packet's
// sbits. No need to clear the byte, since it'll be
// overwritten by chFirstByte below.
pbCurrentOffset++;
dwBufSize++;
}
else if (nLastEbit + rProfileHdr.sbit() != BITSPERBYTE)
{
// The prior and current packets don't overlap properly.
FreeFragList(pMsgHdr);
EnqueueBuffer(pMsgDesc);
FreeMsgHeader(pMsgHdr);
if (pEBS) {
delete [] pEBS;
pEBS = NULL;
}
LeaveCriticalSection(&m_CritSec);
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::BuildExtendedBitstream: ERROR - Received packets with sbit/ebit mismatch"));
if (pFragDesc != NULL)
{
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_DROPFRAME, SEVERITY_NORMAL, NULL, 0);
// BUGBUG We are here because
// m_pFragList->Is_Empty() == FALSE
// then the pFragDesc should always be != NULL
if (pFragDesc->m_pProfileHeader)
FreeProfileHeader(pFragDesc->m_pProfileHeader);
FreeFragDescriptor(pFragDesc);
}
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
pEBS[nCurrentEBS].dwBitOffset =
((dwBufSize - 1) * BITSPERBYTE)
+ rProfileHdr.sbit();
// Copy the packet to the frame buffer.
pbCurrentOffset[-1] = chFirstByte;
dwBufSize +=
copyAndAdvance(
pbCurrentOffset,
(LPBYTE) pFragDesc->m_pData + 1,
pFragDesc->m_BytesOfData - 1);
// dwBufSize now points to _next_ packet slot
}
else
{
// This packet doesn't overlap prior packet (case 3).
if (nLastEbit != 0)
{
// Prior packet has missing ebits; possible encoding error.
FreeFragList(pMsgHdr);
EnqueueBuffer(pMsgDesc);
FreeMsgHeader(pMsgHdr);
if (pEBS) {
delete [] pEBS;
pEBS = NULL;
}
LeaveCriticalSection(&m_CritSec);
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::BuildExtendedBitstream: ERROR - Received packets with sbit/ebit mismatch"));
if (pFragDesc != NULL)
{
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_DROPFRAME, SEVERITY_NORMAL, NULL, 0);
// BUGBUG We are here because
// m_pFragList->Is_Empty() == FALSE
// then the pFragDesc should always be != NULL
if (pFragDesc->m_pProfileHeader)
FreeProfileHeader(pFragDesc->m_pProfileHeader);
FreeFragDescriptor(pFragDesc);
}
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
pEBS[nCurrentEBS].dwBitOffset = dwBufSize * BITSPERBYTE;
// Copy the packet to the frame buffer.
dwBufSize +=
copyAndAdvance(
pbCurrentOffset,
pFragDesc->m_pData,
pFragDesc->m_BytesOfData);
// dwBufSize now points to _next_ packet slot
iFrame = rProfileHdr.i();
}
// We need to store the ebit for the last received packet to give the
// dwBitOffset for the last real packet if lost.
nLastEbit = rProfileHdr.ebit();
// Always shift the ignored bits out of the last byte and patch it
// back into the buffer, since there is no harm in doing so.
chLastByte =
(*((LPBYTE)pFragDesc->m_pData + pFragDesc->m_BytesOfData - 1))
& GetEMask(nLastEbit);
// Overwrite last byte to clear missing bits
pbCurrentOffset[-1] = chLastByte;
// Update BS struct for current packet and save off values for
// next lost packet
pEBS[nCurrentEBS].dwFlags = 0;
pEBS[nCurrentEBS].MBAP = rProfileHdr.mbap();
pEBS[nCurrentEBS].Quant = rProfileHdr.quant();
pEBS[nCurrentEBS].GOBN = rProfileHdr.gobn();
pEBS[nCurrentEBS].HMV = rProfileHdr.hmvd();
pEBS[nCurrentEBS].VMV = rProfileHdr.vmvd();
nCurrentEBS++;
nCurrentSeqNum++;
// Send the frag buffer back down to receive more data and free
// the frag header. always pass zero because we never allocated
// the buffers and therefore have no idea how big the buffers
// are.
m_pSubmitCallback->SubmitComplete(pFragDesc->m_pFragCookie, NOERROR);
if (pFragDesc->m_pProfileHeader)
FreeProfileHeader(pFragDesc->m_pProfileHeader);
FreeFragDescriptor(pFragDesc);
} // End of packet processing loop
{
// Test if the buffer size is enough to avoid
// writing past the buffer size
unsigned char *ptr;
ptr = pbCurrentOffset +
offsetNextDword(pbCurrentOffset) +
nNumFrags * sizeof(*pEBS) +
sizeof(BSINFO_TRAILER);
if (!pMsgHdr->m_MarkerBitIn)
ptr += sizeof(s_nonLeadFragBitPattern);
if ( ptr >
((unsigned char *)(pMsgDesc->m_pBuffer) + pMsgDesc->m_Size) ) {
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_DROPFRAME, SEVERITY_NORMAL, NULL, 0);
#if DEBUG_FREELIST > 2
char str[128];
wsprintf(str,"BuildExtendedBitstream[0x%X]: "
"About to corrupt buffer "
"at: 0x%X size=%d, drop frame\n",
pMsgDesc->m_pBuffer, ptr-1, pMsgDesc->m_Size);
OutputDebugString(str);
#endif
if (pEBS)
delete [] pEBS;
// Drop frame
FreeFragList(pMsgHdr);
EnqueueBuffer(pMsgDesc);
FreeMsgHeader(pMsgHdr);
LeaveCriticalSection(&m_CritSec);
m_GlobalLastFrameDropped = TRUE;
return PPMERR(PPM_E_DROPFRAME);
}
}
// check and handling for last packet if missing
if (! pMsgHdr->m_MarkerBitIn)
{
// Yes, it's last packet, but increment nCurrentEBS to trap
// unintentional reference later.
initBitstreamInfoH261(
pEBS[nCurrentEBS ++],
((dwBufSize - 1) * BITSPERBYTE) + (BITSPERBYTE - nLastEbit));
// for packets other than the first of the frame, we pad with
// 4 bytes of zeroes
dwBufSize +=
copyAndAdvance(
pbCurrentOffset,
&s_nonLeadFragBitPattern,
sizeof(s_nonLeadFragBitPattern));
}
// pad with zeros to next dword boundary
static const DWORD dwZero = 0;
copyAndAdvance(pbCurrentOffset, &dwZero, offsetNextDword(pbCurrentOffset));
// copy the extended bitstream structures into the buffer
copyAndAdvance(pbCurrentOffset, pEBS, nNumFrags * sizeof(*pEBS));
// Delete now to prevent erroneous late update
delete [] pEBS;
pEBS = NULL;
// Note that dwBufSize doesn't include the extended bitstream or the trailer.
setH261BSInfoTrailer(
*(BSINFO_TRAILER*) pbCurrentOffset,
iFrame,
dwBufSize,
nNumFrags,
m_rtph261SourceFormat);
pbCurrentOffset += sizeof(BSINFO_TRAILER);
LeaveCriticalSection(&m_CritSec);
// When we are done. Call Client's submit with full Message
// we report the size including the extended bitstream + trailer + padding
WSABUF tmpWSABUF[2];
tmpWSABUF[0].buf = (char*) pMsgDesc->m_pBuffer;
tmpWSABUF[0].len = (DWORD)(pbCurrentOffset - (LPBYTE) pMsgDesc->m_pBuffer);
tmpWSABUF[1].buf = (char*) &(pMsgDesc->m_TimeStamp);
tmpWSABUF[1].len = sizeof(pMsgDesc->m_TimeStamp);
// Make a callback into the app to let it know about this partial frame
// We also pass the timestamp of the frame
ppm::PPMNotification(
PPM_E_PARTIALFRAME,
SEVERITY_NORMAL,
(LPBYTE) tmpWSABUF[1].buf,
tmpWSABUF[1].len);
FreeMsgHeader(pMsgHdr);
HRESULT status =
m_pSubmit->Submit(tmpWSABUF, 2, pMsgDesc, PPMERR(PPM_E_PARTIALFRAME));
m_GlobalLastFrameDropped = FALSE;
if (FAILED(status))
{
// no SubmitComplete should be called, so take care of resources now
//pMsgDesc->m_Size = m_MaxBufferSize; // reset the data buffer size
//EnqueueBuffer(pMsgDesc);
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::BuildExtendedBitstream: ERROR - Client Submit failed"));
status = PPMERR(PPM_E_CLIENTERR);
// Make a callback into the app to let it know what happened.
ppm::PPMNotification(PPM_E_CLIENTERR, SEVERITY_NORMAL, NULL, 0);
m_GlobalLastFrameDropped = TRUE;
}
return status;
}
#endif // REBUILD_EXBITSTREAM
//////////////////////////////////////////////////////////////////////////////////////////
// PartialMessageHandler: deals with partial messages
//////////////////////////////////////////////////////////////////////////////////////////
HRESULT H261_ppmReceive::PartialMessageHandler(MsgHeader* pMsgHdr)
{
if (pMsgHdr == NULL)
{
DBG_MSG(DBG_ERROR, ("H261_ppmReceive::PartialMessageHandler: ERROR - pMsgHdr == NULL"));
return PPMERR(PPM_E_EMPTYQUE);
}
ASSERT(! pMsgHdr->m_pFragList->Is_Empty());
#ifdef REBUILD_EXBITSTREAM
if (m_ExtendedBitstream)
{
return BuildExtendedBitstream(pMsgHdr);
}
else
#endif /* REBUILD_EXBITSTREAM */
{
// Make a callback into the app to let it know about this dropped frame
// We also pass the timestamp of the frame
DWORD tmpTS = pMsgHdr->GetMsgID();
ppm::PPMNotification(
PPM_E_DROPFRAME,
SEVERITY_NORMAL,
(LPBYTE) &tmpTS,
sizeof(tmpTS));
m_GlobalLastFrameDropped = TRUE;
FreeFragList(pMsgHdr);
FreeMsgHeader(pMsgHdr);
return NOERROR;
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// InitProfileHeader: Given a buffer as type void, sets up a profile header. Does nothing
// for the Generic case. Intended for overrides for various payloads.
// Companion member function FreeProfileHeader provided so that if payload
// header memory is allocated in this function, it can be freed there.
//////////////////////////////////////////////////////////////////////////////////////////
void* H261_ppmReceive::InitProfileHeader(void* pBuffer)
{
// return new H261_Header ( (char*) pBuffer );
return new ( m_pH261Headers )H261_Header ( (char*) pBuffer );
}
//////////////////////////////////////////////////////////////////////////////////////////
// FreeProfileHeader: Given a buffer as type void, frees up a profile header. Does nothing
// for the Generic case. Intended for overrides for various payloads.
// Companion member function InitProfileHeader may allocate memory for
// payload header which needs to be freed here. No return value.
//////////////////////////////////////////////////////////////////////////////////////////
void H261_ppmReceive::FreeProfileHeader(void* pBuffer)
{
// delete (H261_Header*)pBuffer;
m_pH261Headers->Free( pBuffer );
return;
}
// [EOF]