sdpmdparse.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,366 行 · 第 1/3 页
CPP
1,366 行
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sdpmdparse.cpp,v 1.16.2.2 2004/07/09 02:05:16 hubbe Exp $
*
* Portions Copyright (c) 1995-2004 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 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the current version of the RealNetworks Community
* Source License (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.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL") in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your version of
* this file only under the terms of the GPL, and not to allow others
* to use your version of this file under the terms of either the RPSL
* or RCSL, indicate your decision by deleting the provisions above
* and replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient may
* use your version of this file under the terms of any one of the
* RPSL, the RCSL or the GPL.
*
* 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?