📄 sdpmdparse.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include "sdpmdparse.h"
#include "sdptypes.h"
#include "sdppyldinfo.h"
#include "rtptypes.h"
#include "nptime.h"
#include "rtsputil.h"
#include "safestring.h"
#include "chxfmtpparse.h"
#include "chxcharstack.h"
SDPMediaDescParser::SDPMediaDescParser(ULONG32 ulVersion) :
m_pContext(0),
m_pCCF(0),
m_ulVersion(ulVersion),
m_pFileHeader(0),
m_bDefiniteDuration(FALSE),
m_ulDefaultDuration(0)
{
}
SDPMediaDescParser::~SDPMediaDescParser()
{
HX_RELEASE(m_pCCF);
HX_RELEASE(m_pContext);
HX_RELEASE(m_pFileHeader);
clearStreamList();
}
HX_RESULT SDPMediaDescParser::Init(IUnknown* pContext)
{
HX_RESULT res = HXR_FAILED;
HX_RELEASE(m_pContext);
HX_RELEASE(m_pCCF);
if (pContext)
{
res = pContext->QueryInterface(IID_IHXCommonClassFactory,
(void**)&m_pCCF);
if (SUCCEEDED(res) && m_pCCF)
{
m_pContext = pContext;
m_pContext->AddRef();
}
}
return res;
}
HX_RESULT SDPMediaDescParser::Parse(IHXBuffer* pDescription,
REF(UINT16) nValues,
REF(IHXValues**) pValueArray)
{
HX_RESULT theErr = HXR_OK;
/*
* pDescription may not be NULL terminated, so don't do ->GetBuffer()
*/
char* pDescString = NULL;
UINT32 ulDescStringLen = 0;
theErr = pDescription->Get((BYTE*&)pDescString, ulDescStringLen);
if (HXR_OK == theErr)
theErr = fromExternalRep(pDescString, ulDescStringLen);
if (HXR_OK == theErr)
{
nValues = m_streams.GetCount() + 1;
IHXValues** ppHeaders = new IHXValues*[nValues];
ppHeaders[0] = m_pFileHeader;
ppHeaders[0]->AddRef();
CHXSimpleList::Iterator i;
UINT16 j=1;
for(i = m_streams.Begin();i != m_streams.End();++i,++j)
{
ppHeaders[j] = (IHXValues*)(*i);
ppHeaders[j]->AddRef();
TakeCareOfDefaults(ppHeaders[j]);
}
pValueArray = ppHeaders;
}
return theErr;
}
/* right now there is only ASMRuleBook */
void SDPMediaDescParser::TakeCareOfDefaults(IHXValues* pHeader)
{
HX_ASSERT(pHeader);
IHXBuffer* pBuf = NULL;
if (pHeader->GetPropertyCString("ASMRuleBook", pBuf) != HXR_OK)
{
// there is no asmrulebook...
UINT32 ul = 0;
if (pHeader->GetPropertyULONG32("AvgBitRate", ul) == HXR_OK)
{
AddRuleBook(pHeader, ul);
}
else
{
AddRuleBook(pHeader, 0);
// add 0 bandwidth...
pHeader->SetPropertyULONG32("AvgBitRate", 0);
}
}
HX_RELEASE(pBuf);
}
/* if ulBW is 0, we will assume TSD */
void SDPMediaDescParser::AddRuleBook(IHXValues* pHeader, UINT32 ulBW)
{
IHXBuffer* pBuf = NULL;
m_pCCF->CreateInstance(CLSID_IHXBuffer, (void**)&pBuf);
if (!pBuf)
{
// nothing we can do...
return;
}
if (ulBW)
{
char rulebook[256] = {0}; /* Flawfinder: ignore */
UINT32 ulBWHalf = ulBW / 2;
SafeSprintf(rulebook,256, "marker=0,AverageBandwidth=%d;marker=1,AverageBandwidth=%d;",
ulBW - ulBWHalf, ulBWHalf);
pBuf->Set((BYTE*)rulebook, strlen(rulebook) + 1);
}
else
{
pBuf->Set((const BYTE*)"marker=0,timestampdelivery=1;marker=1,timestampdelivery=1;", 59);
}
pHeader->SetPropertyCString("ASMRuleBook", pBuf);
HX_RELEASE(pBuf);
}
//
// This is to fix a problem that causes the optimized builds
// to cause the macintosh to crash!!!!!!!!!!!! <seanh>
//
#ifdef _MACINTOSH
#pragma peephole off
#pragma global_optimizer off
#pragma scheduling off
#endif
/*
* pData needs to be NULL terminated for we use strlen...
*/
HX_RESULT
SDPMediaDescParser::fromExternalRep(char* pData)
{
return fromExternalRep(pData, strlen(pData));
}
HX_RESULT
SDPMediaDescParser::fromExternalRep(char* pData, UINT32 ulDataLen)
{
const char* pCur = pData;
const char* pEnd = pData + ulDataLen;
ULONG32 nStreams = 0;
CHXString extraFields;
m_bDefiniteDuration = FALSE;
m_ulDefaultDuration = 0;
m_mediaType.Empty();
m_pFileHeader = CreateHeader();
IHXValues* pHdr = m_pFileHeader;
HX_RESULT res = (pHdr) ? HXR_OK : HXR_OUTOFMEMORY;
while((HXR_OK == res) && *pCur && (pCur < pEnd))
{
// Skip \n or '\r' characters
for(; *pCur && (pCur < pEnd) && strchr("\r\n", *pCur); pCur++)
;
if (*pCur && (pCur < pEnd))
{
char lineType = *pCur++;
if (*pCur == '=')
{
pCur++; // skip '='
IHXBuffer* pSDPLine = 0;
res = GetLine(pCur, pEnd, pSDPLine);
if (HXR_OK == res)
{
char* pLine = (char*)pSDPLine->GetBuffer();
//printf ("line %c '%s'\n", lineType, pLine);
switch(lineType) {
case 'v':
res = HandleVLine(pLine);
break;
case 'm':
if (!extraFields.IsEmpty())
{
AddString(pHdr, "SDPData",
(const char*)extraFields);
extraFields.Empty();
}
pHdr = CreateHeader();
m_streams.AddTail(pHdr);
AddULONG32(pHdr, "StreamNumber", nStreams);
nStreams++;
// Propagate default duration to new stream
if (0 != m_ulDefaultDuration)
{
AddULONG32(pHdr, "Duration", m_ulDefaultDuration);
}
res = HandleMLine(pLine, pHdr);
break;
case 'a':
res = HandleALine(pLine, pHdr);
break;
case 'c':
res = HandleCLine(pLine, pHdr);
break;
case 'b':
res = HandleBLine(pLine, pHdr);
break;
case 'i':
AddString(pHdr, "Information", pLine);
res = HXR_OK;
break;
case 'o':
case 's':
case 't':
// ignore these lines
res = HXR_OK;
break;
default:
res = HXR_NOT_SUPPORTED;
break;
};
if (HXR_NOT_SUPPORTED == res)
{
extraFields += lineType;
extraFields += '=';
extraFields += pLine;
extraFields += "\n";
res = HXR_OK;
}
pSDPLine->Release();
pSDPLine = 0;
}
}
else
{
res = HXR_FAILED;
}
}
}
if (HXR_OK == res)
{
if (!extraFields.IsEmpty())
{
AddString(pHdr, "SDPData",
(const char*)extraFields);
extraFields.Empty();
}
/* Only add StreamCount and LiveStream fields
* if we have at least 1 stream. This prevents
* the fields from appearing when we are using
* the SDP plugin to parse partial SDP chunks.
*/
if (nStreams)
{
AddULONG32(m_pFileHeader, "StreamCount", nStreams);
ULONG32 ulLive;
if (!m_bDefiniteDuration &&
(m_ulDefaultDuration == 0) &&
(!SUCCEEDED(m_pFileHeader->GetPropertyULONG32("LiveStream",
ulLive))))
{
AddULONG32(m_pFileHeader, "LiveStream", 1);
}
}
}
return res;
}
#ifdef _MACINTOSH
#pragma peephole reset
#pragma global_optimizer reset
#pragma scheduling reset
#endif
/*
* Payload table contains reserved/unassigned types as well. So, this func
* returns if the table contains a valid info
*/
BOOL
SDPMediaDescParser::IsPayloadTableValid(UINT32 ulPayloadType)
{
HX_ASSERT(SDPIsStaticPayload(ulPayloadType));
if (!SDPMapPayloadToEncodingName(ulPayloadType))
{
return FALSE;
}
return TRUE;
}
HX_RESULT
SDPMediaDescParser::getRTPMapInfo(const char* pMapInfo,
REF(CHXString) strMimeType,
IHXValues* pStream)
{
if (!pMapInfo || !strMimeType.GetLength() || !pStream)
{
return HXR_FAIL;
}
/*
* It could be either:
* EncodingName
* EncodingName/SamplesPerSecond
* EncodingName/SamplesPerSecond/Channels
*/
strMimeType += "/";
char* pTok = strchr((char*)pMapInfo, ' ');
if (pTok)
{
*pTok = '\0';
}
pTok = (char*)pMapInfo;
char* pTokNext = strchr(pTok, '/');
if (pTokNext)
{
*pTokNext++ = '\0';
strMimeType += pTok;
pTok = pTokNext;
pTokNext = strchr((char*)pTok, '/');
if (pTokNext)
{
*pTokNext++ = '\0';
AddULONG32(pStream, "SamplesPerSecond", strtol(pTok, 0, 10));
AddULONG32(pStream, "Channels", strtol(pTokNext, 0, 10));
}
else
{
AddULONG32(pStream, "SamplesPerSecond", strtol(pTok, 0, 10));
}
}
else
{
// this is just an encoding name
strMimeType += pMapInfo;
}
return HXR_OK;
}
/*
* Compare ulVersion against m_ulVersion. and returns HXR_FAIL iff
* ulVersion < m_ulVersion ---> need auto update.
*/
HX_RESULT
SDPMediaDescParser::checkVersion(UINT32 ulVersion)
{
HX_ASSERT(m_ulVersion);
UINT32 ulPluginMajor = HX_GET_MAJOR_VERSION(m_ulVersion);
UINT32 ulPluginMinor = HX_GET_MINOR_VERSION(m_ulVersion);
UINT32 ulDataMajor = HX_GET_MAJOR_VERSION(ulVersion);
UINT32 ulDataMinor = HX_GET_MINOR_VERSION(ulVersion);
if((ulDataMajor > ulPluginMajor) ||
(ulDataMajor == ulPluginMajor && ulDataMinor > ulPluginMinor))
{
return HXR_FAIL;
}
else
{
return HXR_OK;
}
}
void SDPMediaDescParser::clearStreamList()
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -