📄 sdpmdgen.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 "sdpmdgen.h"
#include "sdptypes.h"
#include "sdppyldinfo.h"
#include "hxstrutl.h"
#include "hxstring.h"
#include "nptime.h"
#include "netbyte.h"
#include "rtsputil.h"
#include "rtptypes.h"
//#include "hlxclib/stdio.h"
SDPMediaDescGenerator::SDPMediaDescGenerator(ULONG32 ulVersion) :
m_pContext(0),
m_pCCF(0),
m_pRegistry(0),
m_ulVersion(ulVersion),
m_bUseOldEOL(FALSE),
m_bUseSessionGUID(FALSE),
m_bUseAbsoluteURL(FALSE)
{}
SDPMediaDescGenerator::~SDPMediaDescGenerator()
{
HX_RELEASE(m_pCCF);
HX_RELEASE(m_pContext);
HX_RELEASE(m_pRegistry);
}
HX_RESULT SDPMediaDescGenerator::Init(IUnknown* pContext)
{
HX_RESULT res = HXR_FAILED;
HX_RELEASE(m_pContext);
HX_RELEASE(m_pCCF);
if (pContext)
{
pContext->QueryInterface(IID_IHXRegistry, (void**)&m_pRegistry);
res = pContext->QueryInterface(IID_IHXCommonClassFactory,
(void**)&m_pCCF);
if (SUCCEEDED(res) && m_pCCF)
{
m_pContext = pContext;
m_pContext->AddRef();
}
}
return res;
}
HX_RESULT SDPMediaDescGenerator::Generate(UINT16 nValues,
IHXValues** pValueArray,
REF(IHXBuffer*) pDescription)
{
CHXString mDesc;
char pszEOL[3]; /* Flawfinder: ignore */
HX_RESULT rc;
UINT32 propValue;
const char* pPropName = 0;
IHXBuffer* pPropBuffer = 0;
char psz256[256]; /* Flawfinder: ignore */
mDesc.SetMinBufSize(12000);
if (m_bUseOldEOL)
{
pszEOL[0] = '\n';
pszEOL[1] = '\0';
}
else
{
pszEOL[0] = '\r';
pszEOL[1] = '\n';
pszEOL[2] = '\0';
}
rc = SpecComplianceCheck(nValues, pValueArray);
if (HXR_OK != rc)
{
return rc;
}
// get local host address from registry
//HX_RESULT hresult;
IHXRegistry* pRegistry = 0;
/* XXX
* Interop: Our old system is expecting a media type in m= to be either
* "audio", "video", or "data" and anything else will be ignored.
* The spec dectates otherwise...It should be whatever the type of mimetype
* is. So, depending on the setting, we will have to change how we create
* m= line for interop and backward comp.
*
* by default, we will do the spec complient way.
*/
BOOL bUseOldSdp = FALSE;
IHXBuffer* pHostIBuf = NULL;
if(m_pRegistry)
{
m_pRegistry->GetStrByName("server.sdpconfig.hostaddr", pHostIBuf);
}
const char* pszHost = "";
if (pHostIBuf)
{
pszHost = (const char *)pHostIBuf->GetBuffer();
}
UINT32 ulHostAddr = HXinet_addr(pszHost);
/*
* default sessionID, else get LastModified from optional values
*/
char pszVersion[40]; /* Flawfinder: ignore */
UINT32 ulSessionIDBuffLen = 40;
IHXBuffer* pSessionGUIDBuff = NULL;
IHXBuffer* pControlStringBuff = NULL;
if(m_bUseSessionGUID && pValueArray[1])
{
rc = pValueArray[1]->GetPropertyCString("SessionGUID", pSessionGUIDBuff);
if((rc == HXR_OK) && pSessionGUIDBuff)
{
ulSessionIDBuffLen = pSessionGUIDBuff->GetSize();
}
}
NEW_FAST_TEMP_STR(pszSessionID, 256, ulSessionIDBuffLen);
// munge current time with IP
NPTime timeNow;
if (!pSessionGUIDBuff)
{
SafeSprintf(pszSessionID,ulSessionIDBuffLen,"%lu", ulHostAddr + timeNow.m_lMicroSecond);
}
SafeSprintf(pszVersion, 40, "%lu", timeNow.m_lMicroSecond);
IHXBuffer* pContentBase = NULL;
IHXBuffer* pQueryParams = NULL;
if(pValueArray[1])
{
ULONG32 ulLastMod;
rc = pValueArray[1]->GetPropertyULONG32("LastModified", ulLastMod);
SafeSprintf(pszVersion, 40,"%lu", ulLastMod);
if (pSessionGUIDBuff)
{
SafeSprintf(pszSessionID, ulSessionIDBuffLen, "%s",
pSessionGUIDBuff->GetBuffer());
}
else
{
SafeSprintf(pszSessionID, ulSessionIDBuffLen,"%lu", ulLastMod);
}
if (m_bUseAbsoluteURL)
{
rc = pValueArray[1]->GetPropertyCString("AbsoluteBaseURL",
pContentBase);
if (HXR_OK != rc)
{
HX_RELEASE(pContentBase);
}
rc = pValueArray[1]->GetPropertyCString("URLQueryParams",
pQueryParams);
if (HXR_OK != rc)
{
HX_RELEASE(pQueryParams);
}
}
rc = pValueArray[1]->GetPropertyCString("Control", pControlStringBuff);
if(rc != HXR_OK)
{
HX_RELEASE(pControlStringBuff);
}
}
NEW_FAST_TEMP_STR(pszTmpString, 256, strlen(pszSessionID) +
strlen(pszVersion) + strlen(pszHost) + 64);
SafeSprintf(pszTmpString, 256, "v=0%so=- %s %s IN IP4 %s%s",
pszEOL, pszSessionID, pszVersion, pszHost, pszEOL);
HX_RELEASE(pHostIBuf);
HX_RELEASE(pSessionGUIDBuff);
DELETE_FAST_TEMP_STR(pszSessionID);
mDesc = pszTmpString;
DELETE_FAST_TEMP_STR(pszTmpString);
char* pszTitle = NULL;
char* pszAuthor = NULL;
char* pszCopyright = NULL;
CHXString headerAttributes;
headerAttributes.SetMinBufSize(8192);
char* pszSDPData=NULL;
char* pszInfo=NULL;
char* pszConnAddr=NULL;
UINT32 avgBitRate = 0;
BOOL bFoundAvgBitRate = FALSE;
UINT32 connTTL = 0;
BOOL bFoundTTL = FALSE;
UINT32 connRange = 0;
BOOL bFoundRange = FALSE;
BOOL bAddToHeader = 0;
UINT32 ulDefaultDuration = 0;
BOOL bDefaultDurationFound = FALSE;
BOOL bIsLive = FALSE;
/*
* Add session-level a=control field only for clients that can handle
* interop SDP.
*/
// Figure out if the client can handle interop SDP
UINT32 ulSdpFileType = NONE_SDP;
if (HXR_OK == pValueArray[0]->GetPropertyULONG32("SdpFileType", ulSdpFileType))
{
// default for bUseOldSdp is FALSE
if (BACKWARD_COMP_SDP == ulSdpFileType)
{
bUseOldSdp = TRUE;
}
}
if(!bUseOldSdp)
{
if (!pControlStringBuff)
{
const char* pszFieldPrefix = "a=control:";
UINT32 ulBuffLen = 0;
if (pContentBase)
{
char *pszBaseURL = (char*)pContentBase->GetBuffer();
UINT32 ulBaseLen = strlen(pszBaseURL);
UINT32 ulBuffLen = strlen(pszFieldPrefix) + ulBaseLen +
((pQueryParams) ? pQueryParams->GetSize() : 0);
char cPathDelim = '\0';
// Strip off the trailing slash from the aggregate control URL
char *pszPathDelim = pszBaseURL + (ulBaseLen-1);
if (*pszPathDelim == '/')
{
cPathDelim = *pszPathDelim;
*pszPathDelim = '\0';
}
ulBuffLen += strlen(pszEOL) + 1;
NEW_FAST_TEMP_STR(pszSessionCtrl, 512, ulBuffLen);
SafeSprintf(pszSessionCtrl, ulBuffLen, "%s%s%s%s",
pszFieldPrefix, pszBaseURL,
(pQueryParams)?((char*)pQueryParams->GetBuffer()) : "",
pszEOL);
if (cPathDelim)
{
*pszPathDelim = cPathDelim;
}
headerAttributes += pszSessionCtrl;
DELETE_FAST_TEMP_STR(pszSessionCtrl);
}
else
{
ulBuffLen = strlen(pszFieldPrefix) + strlen(pszEOL) + 2;
NEW_FAST_TEMP_STR(pszSessionCtrl, 512, ulBuffLen);
SafeSprintf(pszSessionCtrl, ulBuffLen, "%s*%s", pszFieldPrefix, pszEOL);
headerAttributes += pszSessionCtrl;
DELETE_FAST_TEMP_STR(pszSessionCtrl);
}
}
else
{
UINT32 ulBuffLen = pControlStringBuff->GetSize();
ulBuffLen += (pContentBase) ? pContentBase->GetSize() : 0;
ulBuffLen += (pQueryParams) ? pQueryParams->GetSize() : 0;
ulBuffLen += 64;
NEW_FAST_TEMP_STR(pszControlString, 512, ulBuffLen);
SafeSprintf(pszControlString, ulBuffLen, "a=control:%s%s%s%s",
((pContentBase) ? ((char*)pContentBase->GetBuffer()) : ""),
pControlStringBuff->GetBuffer(),
(pQueryParams) ?((char*)pQueryParams->GetBuffer()) : "",
pszEOL);
headerAttributes += pszControlString;
DELETE_FAST_TEMP_STR(pszControlString);
}
}
rc = pValueArray[0]->GetFirstPropertyULONG32(pPropName, propValue);
while(rc == HXR_OK)
{
bAddToHeader = FALSE;
if(strcasecmp(pPropName, "MulticastTTL") == 0)
{
connTTL = propValue;
bFoundTTL = TRUE;
}
else if(strcasecmp(pPropName, "MulticastRange") == 0)
{
connRange = propValue;
bFoundRange = TRUE;
}
else if(strcasecmp(pPropName, "Duration") == 0)
{
// save this off, so we can add an appropriate a=range depending
// on the value in "SdpFileType"
ulDefaultDuration = propValue;
bDefaultDurationFound = TRUE;
}
else if(strcasecmp(pPropName, "LiveStream") == 0)
{
// is this live?
bIsLive = propValue;
bAddToHeader = TRUE;
}
else if(strcasecmp(pPropName, "AvgBitRate") == 0)
{
avgBitRate = propValue;
// we need this in kbps
avgBitRate = (UINT32)((double)avgBitRate / 1000.0 + 0.5);
bFoundAvgBitRate = TRUE;
// add it to attribute as well.
bAddToHeader = TRUE;
}
else if(strcasecmp(pPropName, "SdpFileType") == 0)
{
// don't add it to attribute.
bAddToHeader = FALSE;
}
else
{
bAddToHeader = TRUE;
}
if(bAddToHeader)
{
NEW_FAST_TEMP_STR(pszAttBuf, 256, strlen(pPropName) + 64);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -