📄 sdpmdparse.cpp
字号:
LISTPOSITION pos = m_streams.GetHeadPosition();
while(pos)
{
IHXValues* pStream = (IHXValues*)m_streams.GetNext(pos);
HX_RELEASE(pStream);
}
m_streams.RemoveAll();
}
IHXValues* SDPMediaDescParser::CreateHeader()
{
IHXValues* pRet = 0;
if (m_pCCF)
m_pCCF->CreateInstance(IID_IHXValues, (void**)&pRet);
return pRet;
}
void SDPMediaDescParser::AddULONG32(IHXValues* pHeader,
const char* pKey, ULONG32 ulValue)
{
pHeader->SetPropertyULONG32(pKey, ulValue);
}
void SDPMediaDescParser::AddString(IHXValues* pHeader,
const char* pKey,
const char* pValue)
{
if ((pKey == NULL) || (pValue == NULL))
{
return;
}
IHXBuffer* pBuf = CopyBuffer((const UINT8*)pValue, strlen(pValue) + 1);
if (pBuf)
pHeader->SetPropertyCString(pKey, pBuf);
HX_RELEASE(pBuf);
}
void SDPMediaDescParser::AddBuffer(IHXValues* pHeader,
const char* pKey,
const UINT8* pValue,
ULONG32 ulLength)
{
IHXBuffer* pBuf = CopyBuffer(pValue, ulLength);
if (pBuf)
pHeader->SetPropertyBuffer(pKey, pBuf);
HX_RELEASE(pBuf);
}
IHXBuffer* SDPMediaDescParser::CopyBuffer(const UINT8* pBuf, ULONG32 ulLength)
{
IHXBuffer* pRet = 0;
if (SUCCEEDED(m_pCCF->CreateInstance(IID_IHXBuffer, (void**)&pRet)))
pRet->Set(pBuf, ulLength);
return pRet;
}
HX_RESULT SDPMediaDescParser::GetLine(const char*& pData,
const char* pEnd,
IHXBuffer*& pLine) const
{
HX_RESULT res = HXR_OK;
CHXCharStack tok(m_pCCF);
BOOL bInQuote = FALSE;
BOOL bLastWasEscape = FALSE;
for (; (HXR_OK == res) && *pData && (pData < pEnd) && (bInQuote || !strchr("\r\n", *pData)); pData++)
{
if (bLastWasEscape)
{
bLastWasEscape = FALSE;
}
else
{
if (*pData == '"')
{
bInQuote = !bInQuote;
}
else if (*pData == '\\')
{
bLastWasEscape = TRUE;
}
}
res = tok.AddChar(*pData);
}
if (HXR_OK == res)
{
res = tok.Finish(pLine);
}
return res;
}
void SDPMediaDescParser::SkipSpaces(char*& pData) const
{
for (; *pData && *pData == ' '; pData++)
;
}
BOOL SDPMediaDescParser::ScanForDelim(char*& pData, char delim) const
{
BOOL bRet = FALSE;
while(*pData && !bRet)
{
if (*pData == delim)
{
bRet = TRUE;
}
else
{
pData++;
}
}
return bRet;
}
HX_RESULT SDPMediaDescParser::HandleVLine(char* pLine)
{
HX_RESULT res = HXR_FAILED;
char* pEnd = 0;
unsigned long version = strtoul(pLine, &pEnd, 10);
if (*pLine && !*pEnd && (version == 0))
{
res = HXR_OK;
}
return res;
}
HX_RESULT SDPMediaDescParser::HandleMLine(char* pLine, IHXValues* pHdr)
{
HX_RESULT res = HXR_FAILED;
if (*pLine)
{
int state = 0;
const char* pMediaType = pLine;
ULONG32 ulPort = 0;
ULONG32 ulPayloadType = 0;
if (ScanForDelim(pLine, ' '))
{
// Null terminate mimetype
*pLine++ = '\0';
// Save media type for later
m_mediaType = pMediaType;
res = HXR_OK;
}
while(*pLine && (HXR_OK == res))
{
char* pEnd = 0;
SkipSpaces(pLine);
if (*pLine)
{
switch(state) {
case 0:
// Grab port number
ulPort = strtoul(pLine, &pEnd, 10);
if (*pEnd == ' ')
{
pLine = pEnd;
state = 1;
}
else
{
// No transport field or
// invalid port character
res = HXR_FAILED;
}
break;
case 1:
// Skip transport. Usually RTP/AVP
if (ScanForDelim(pLine, ' '))
{
state = 2;
}
break;
case 2:
// Grab the first payload type
ulPayloadType = strtoul(pLine, &pEnd, 10);
if ((*pEnd == ' ') || !*pEnd )
{
state = 3;
}
else
{
// There was an unexpected character
// the the payload type
res = HXR_FAILED;
}
case 3:
// Consume the rest of the payload types
for (; *pLine; pLine++)
;
break;
}
}
}
if (state == 3)
{
AddULONG32(pHdr, "RTPPayloadType", ulPayloadType);
if (ulPort)
{
AddULONG32(pHdr, "Port", ulPort);
}
if (SDPIsStaticPayload(ulPayloadType))
{
if (IsPayloadTableValid(ulPayloadType))
{
if (!SDPIsTimestampDeliverable(ulPayloadType))
{
ULONG32 ulBitrate =
SDPMapPayloadToBitrate(ulPayloadType);
HX_ASSERT(ulBitrate);
// we have a bandwidth info in a table...
AddULONG32(pHdr, "AvgBitRate", ulBitrate);
}
// static payload type
AddString(pHdr, "MimeType",
SDPMapPayloadToMimeType(ulPayloadType));
AddULONG32(pHdr,
"RTPTimestampConversionFactor",
SDPMapPayloadToRTPFactor(ulPayloadType));
AddULONG32(pHdr,
"HXTimestampConversionFactor",
SDPMapPayloadToRMAFactor(ulPayloadType));
AddULONG32(pHdr,
"SamplesPerSecond",
SDPMapPayloadToSamplesPerSecond(ulPayloadType));
AddULONG32(pHdr,
"Channels",
(ULONG32)SDPMapPayloadToChannels(ulPayloadType));
// deal with opaque hack...
const BYTE* pOpaqueData = NULL;
ULONG32 ulOpaqueDataSize = 0;
switch(ulPayloadType)
{
case RTP_PAYLOAD_GSM:
pOpaqueData =
SDPMapPayloadToHeaderData(RTP_PAYLOAD_GSM,
ulOpaqueDataSize);
break;
}
if (pOpaqueData)
{
AddBuffer(pHdr, "OpaqueData",
pOpaqueData, ulOpaqueDataSize);
}
}
else
{
res = HXR_REQUEST_UPGRADE;
}
}
}
else if (HXR_OK == res)
{
res = HXR_FAILED;
}
}
return res;
}
HX_RESULT SDPMediaDescParser::HandleALine(char* pLine, IHXValues* pHdr)
{
HX_RESULT res = HXR_FAILED;
const char* pFieldName = pLine;
char* pFieldValue = 0;
FieldType fieldType = ftUnknown;
if (*pLine)
{
// Collect the field name
if (ScanForDelim(pLine, ':'))
{
char* pColon = pLine;
// Must be the key/value form
// a=foo:bar
// Null terminate field name by replacing ':' with '\0'
*pLine++ = '\0';
pFieldValue = pLine;
if ((HXR_OK == (res = ParseFieldValue(pFieldValue, fieldType))))
{
switch (fieldType) {
case ftUnknown:
res = HandleSpecialFields(pFieldName, pFieldValue, pHdr);
break;
case ftULONG32:
{
char* pEnd = 0;
ULONG32 ulValue = strtoul(pFieldValue, &pEnd, 10);
if (*pFieldValue && !*pEnd)
{
res = pHdr->SetPropertyULONG32(pFieldName, ulValue);
}
} break;
case ftString:
AddString(pHdr, pFieldName, pFieldValue);
res = HXR_OK;
break;
case ftBuffer:
{
int length = strlen(pFieldValue);
BYTE* pDecodeBuf = new BYTE[length];
INT32 decodeLen = BinFrom64(pFieldValue, length,
pDecodeBuf);
if( decodeLen != -1 )
{
AddBuffer(pHdr, pFieldName, pDecodeBuf, decodeLen);
}
res = HXR_OK;
delete [] pDecodeBuf;
}break;
}
}
if (HXR_OK != res)
{
// Put back the ':'
*pColon = ':';
}
}
else
{
// Must be the key only form
// a=foo
res = HXR_NOT_SUPPORTED;
}
}
return res;
}
HX_RESULT SDPMediaDescParser::HandleCLine(char* pLine, IHXValues* pHdr)
{
// Handles the following forms
// c=IN IP4 xxx.xxx.xxx.xxx
// c=IN IP4 xxx.xxx.xxx.xxx/xxx
// c=IN IP4 xxx.xxx.xxx.xxx/xxx/xx
HX_RESULT res = HXR_FAILED;
char* pCur = pLine;
if (ScanForDelim(pCur, ' '))
{
*pCur++ = '\0';
SkipSpaces(pCur);
char* pAddrType = pCur;
if (!strcasecmp(pLine, "IN") && ScanForDelim(pCur, ' '))
{
*pCur++ = '\0';
SkipSpaces(pCur);
if (!strcasecmp(pAddrType, "IP4") && *pCur)
{
char* pAddr = pCur;
if (ScanForDelim(pCur, '/'))
{
*pCur++ = '\0';
if (*pCur)
{
char* pEnd = 0;
ULONG32 ulTTL = strtoul(pCur, &pEnd, 10);
if (*pCur && ((*pEnd == '/') || (!*pEnd)))
{
AddULONG32(pHdr, "MulticastTTL", ulTTL);
res = HXR_OK;
pCur = pEnd;
if (*pCur)
{
pCur++; // skip '/'
ULONG32 ulRange = strtoul(pCur, &pEnd, 10);
if (*pCur && !*pEnd)
{
// c=IN IP4 xxx.xxx.xxx.xxx/xxx/xx
AddULONG32(pHdr, "MulticastRange", ulRange);
res = HXR_OK;
}
}
}
}
}
else
{
// c=IN IP4 xxx.xxx.xxx.xxx
res = HXR_OK;
}
if (HXR_OK == res)
{
AddString(pHdr, "MulticastAddress", pAddr);
}
}
}
}
return res;
}
HX_RESULT SDPMediaDescParser::HandleBLine(char* pLine, IHXValues* pHdr)
{
HX_RESULT res = HXR_FAILED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -