sdpmdgen.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:51k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: sdpmdgen.cpp,v 1.14.2.1 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 "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] = ' ';
- }
- else
- {
- pszEOL[0] = 'r';
- pszEOL[1] = 'n';
- pszEOL[2] = ' ';
- }
- 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 = ' ';
- // Strip off the trailing slash from the aggregate control URL
- char *pszPathDelim = pszBaseURL + (ulBaseLen-1);
- if (*pszPathDelim == '/')
- {
- cPathDelim = *pszPathDelim;
- *pszPathDelim = ' ';
- }
- 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);
- SafeSprintf(pszAttBuf, 256,"a=%s:integer;%d%s", pPropName, propValue,
- pszEOL);
- headerAttributes += pszAttBuf;
- DELETE_FAST_TEMP_STR(pszAttBuf);
- }
- /* make sure to reset SdpFileType header */
- if (strcasecmp(pPropName, "SdpFileType") == 0)
- {
- pValueArray[0]->SetPropertyULONG32(pPropName, NONE_SDP);
- }
- rc = pValueArray[0]->GetNextPropertyULONG32(pPropName,
- propValue);
- }
- /*
- * 3GPP compliance: session-level "b=" parameter is required. If we
- * it's not in the file header, then compute it from component streams.
- */
- if (!bFoundAvgBitRate)
- {
- UINT32 ulSessionBitRate = 0;
- UINT32 ulStreamBitRate = 0;
-
- for(UINT16 i=2 ; i < nValues; ++i)
- {
- if (pValueArray[i])
- {
- if (HXR_OK == pValueArray[i]->GetPropertyULONG32("AvgBitRate",
- ulStreamBitRate))
- {
- bFoundAvgBitRate = TRUE;
- ulSessionBitRate += ulStreamBitRate;
- }
- }
- }
- if (bFoundAvgBitRate)
- {
- // Convert bits/sec -> Kbits/sec (round up to nearest whole num)
- avgBitRate = (UINT32) ((double)ulSessionBitRate / 1000.0 + 0.5);
- }
- }
- rc = pValueArray[0]->GetFirstPropertyBuffer(pPropName, pPropBuffer);
- while(rc == HXR_OK)
- {
- INT32 dataSize = pPropBuffer->GetSize();
- char* pString = (char*) pPropBuffer->GetBuffer();
- bAddToHeader = TRUE; // add it to attribute by default
- if (dataSize > 0 && pString != NULL && *pString != ' ')
- {
- if(strcasecmp(pPropName, "Title") == 0)
- {
- pszTitle = new char [ dataSize + 1 ];
- memcpy(pszTitle, (const char*)pPropBuffer->GetBuffer(), dataSize); /* Flawfinder: ignore */
- pszTitle[dataSize] = ' ';
- }
- else if(strcasecmp(pPropName, "Author") == 0)
- {
- pszAuthor = new char [ dataSize + 1 ];
- memcpy(pszAuthor, (const char*)pPropBuffer->GetBuffer(), dataSize); /* Flawfinder: ignore */
- pszAuthor[dataSize] = ' ';
- }
- else if(strcasecmp(pPropName, "Copyright") == 0)
- {
- pszCopyright = new char [ dataSize + 1 ];
- memcpy(pszCopyright, (const char*)pPropBuffer->GetBuffer(), dataSize); /* Flawfinder: ignore */
- pszCopyright[dataSize] = ' ';
- }
- if (bAddToHeader)
- {
- NEW_FAST_TEMP_STR(pszAttBuf, 4096, dataSize * 2 + strlen(pPropName)
- + 64);
- NEW_FAST_TEMP_STR(pszPropString, 4096, dataSize * 2 + 64);
- (void)BinTo64((const BYTE*)pPropBuffer->GetBuffer(),
- dataSize, pszPropString);
- SafeSprintf(pszAttBuf, 4096, "a=%s:buffer;"%s"%s",pPropName,
- pszPropString, pszEOL);
- headerAttributes += pszAttBuf;
- DELETE_FAST_TEMP_STR(pszPropString);
- DELETE_FAST_TEMP_STR(pszAttBuf);
- }
- }
- HX_RELEASE(pPropBuffer);
- rc = pValueArray[0]->GetNextPropertyBuffer(pPropName,
- pPropBuffer);
- }
- rc = pValueArray[0]->GetFirstPropertyCString(pPropName,
- pPropBuffer);
- while(rc == HXR_OK)
- {
- char* pString = (char*) pPropBuffer->GetBuffer();
- char* pszData=NULL;
- BOOL bDeleteString=FALSE;
- bAddToHeader = FALSE;
- INT32 dataSize = pPropBuffer->GetSize();
- if (dataSize > 0 && pString != NULL && *pString != ' ')
- {
- if(strcasecmp(pPropName, "Title") == 0)
- {
- pszTitle = EscapeBuffer(pString, pPropBuffer->GetSize());
- pszData = pszTitle;
- bAddToHeader = TRUE;
- }
- else if(strcasecmp(pPropName, "Author") == 0)
- {
- pszAuthor = EscapeBuffer(pString, pPropBuffer->GetSize());
- pszData = pszAuthor;
- bAddToHeader = TRUE;
- }
- else if(strcasecmp(pPropName, "Copyright") == 0)
- {
- pszCopyright = EscapeBuffer(pString, pPropBuffer->GetSize());
- pszData = pszCopyright;
- bAddToHeader = TRUE;
- }
- else if(strcasecmp(pPropName, "MulticastAddress") == 0)
- {
- pszConnAddr = EscapeBuffer(pString, pPropBuffer->GetSize());
- }
- else if(strcasecmp(pPropName, "SDPData") == 0)
- {
- pszSDPData = new char [ dataSize + 1 ];
- memcpy(pszSDPData, (const char*)pPropBuffer->GetBuffer(), dataSize); /* Flawfinder: ignore */
- pszSDPData[dataSize] = ' ';
- RemoveASLine(pszSDPData, dataSize);
- }
- else if(strcasecmp(pPropName, "Information") == 0)
- {
- // "i="
- pszInfo = EscapeBuffer(pString, pPropBuffer->GetSize());
- }
- else
- {
- pszData = EscapeBuffer(pString, pPropBuffer->GetSize());
- bAddToHeader = TRUE;
- bDeleteString = TRUE;
- }
- if(bAddToHeader)
- {
- HX_ASSERT(pszData);
- NEW_FAST_TEMP_STR(pszAttBuf, 4096, dataSize +
- strlen(pPropName) + 64);
- SafeSprintf(pszAttBuf, 4096,"a=%s:string;"%s"%s", pPropName,
- pszData, pszEOL);
- headerAttributes += pszAttBuf;
- DELETE_FAST_TEMP_STR(pszAttBuf);
- }
- if (bDeleteString)
- {
- HX_VECTOR_DELETE(pszData);
- }
- }
-
- HX_RELEASE(pPropBuffer);
- rc = pValueArray[0]->GetNextPropertyCString(pPropName,
- pPropBuffer);
- }
- /*
- * Things in headerAttributes that depend on the value in "SdpFileType"
- */
- if (!bIsLive)
- {
- if (bDefaultDurationFound)
- {
- NPTime npTime(ulDefaultDuration);
- const char* pszTime = (const char*)npTime;
- headerAttributes += "a=range:npt=0-";
- headerAttributes += pszTime;
- headerAttributes += pszEOL;
- }
- else
- {
- /*
- * error case - SpecComplianceCheck() should be taking care of it.
- *
- * let's just treat it as live. When file is done, RTCP_BYE
- * will be sent, and client TEARDOWN
- */
- if (bUseOldSdp)
- {
- SafeSprintf(psz256, 256, "a=range:npt=0-0%s", pszEOL);
- headerAttributes += psz256;
- }
- else
- {
- SafeSprintf(psz256, 256,"a=range:npt=0-%s", pszEOL);
- headerAttributes += psz256;
- }
- }
- }
-
- if (!pszTitle)
- {
- SafeSprintf(psz256, 256,"s=<No title>%s", pszEOL);
- mDesc += psz256;
- }
- else
- {
- NEW_FAST_TEMP_STR(pszTmpStr, 256, strlen(pszTitle) + 64);
- SafeSprintf(pszTmpStr, 256, "s=%s%s", pszTitle, pszEOL);
- mDesc += pszTmpStr;
- DELETE_FAST_TEMP_STR(pszTmpStr);
- }
- if (pszInfo)
- {
- NEW_FAST_TEMP_STR(pszTmpStr, 256, strlen(pszInfo) + 64);
- SafeSprintf(pszTmpStr, 256,"i=%s%s", pszInfo, pszEOL);
- mDesc += pszTmpStr;
- DELETE_FAST_TEMP_STR(pszTmpStr);
- HX_VECTOR_DELETE(pszInfo);
- pszInfo = NULL;
- }
- else
- {
- const char* pszDefaultAuthor = "<No author>";
- const char* pszDefaultCopyright = "<No copyright>";
- UINT32 len = 64;
- len += pszAuthor ? strlen(pszAuthor) : 16;
- len += pszCopyright ? strlen(pszCopyright) : 16;
- NEW_FAST_TEMP_STR(pszTmpString, 512, len);
- SafeSprintf(pszTmpString, 256, "i=%s %s%s",
- pszAuthor ? pszAuthor : pszDefaultAuthor,
- pszCopyright ? pszCopyright : pszDefaultCopyright,
- pszEOL);
- mDesc += pszTmpString;
- DELETE_FAST_TEMP_STR(pszTmpString);
- }
- if (pszTitle)
- HX_VECTOR_DELETE(pszTitle);
- if (pszAuthor)
- HX_VECTOR_DELETE(pszAuthor);
- if (pszCopyright)
- HX_VECTOR_DELETE(pszCopyright);
- /* Format the connection line only if MulticastAddress and MulticastTTL
- * exist in the file header
- */
- if (pszConnAddr && strlen(pszConnAddr) && bFoundTTL)
- {
- NEW_FAST_TEMP_STR(pszTmpString, 256, strlen(pszConnAddr) + 64);
- if (bFoundRange)
- {
- SafeSprintf(pszTmpString,256, "c=IN IP4 %s/%d/%d%s",
- pszConnAddr, connTTL, connRange, pszEOL);
- }
- else
- {
- SafeSprintf(pszTmpString, 256, "c=IN IP4 %s/%d%s",
- pszConnAddr, connTTL, pszEOL);
- }
- mDesc += pszTmpString;
- DELETE_FAST_TEMP_STR(pszTmpString);
- }
- else if (!bUseOldSdp)
- {
- // we still need a c= line with a NULL value (RFC 2326 C.1.7)
- // XXXGo
- // Since adding this line w/o TTL (i.e. 0.0.0.0/ttl) will cause
- // older sdpplin to skip the next line (due to a wrong parsing),
- // add this only when we are using new sdp type.
- mDesc += "c=IN IP4 0.0.0.0";
- mDesc += pszEOL;
- }
- if (bFoundAvgBitRate)
- {
- SafeSprintf(psz256, 256, "b=AS:%u%s", avgBitRate, pszEOL);
- mDesc += psz256;
- bFoundAvgBitRate = FALSE;
- }
- mDesc += "t=0 0";
- mDesc += pszEOL;
- /* add sdpplin version */
- SafeSprintf(psz256, 256, "a=SdpplinVersion:%u%s", m_ulVersion, pszEOL);
- mDesc += psz256;
-
- mDesc += headerAttributes;
- // expand SDPData if it's there...
- if (pszSDPData)
- {
- mDesc += pszSDPData;
- HX_VECTOR_DELETE(pszSDPData);
- pszSDPData = NULL;
- }
- for(UINT16 i=2;i<nValues;++i)
- {
- if(pValueArray[i])
- {
- CHXString streamAttributes;
- streamAttributes.SetMinBufSize(8192);
- UINT32 streamNumber = 0;
- BOOL bStreamNumberFound=FALSE;
- UINT32 duration = 0;
- BOOL bDurationFound = FALSE;
- UINT32 rtpPayloadType = 0;
- BOOL bRtpPayloadTypeFound=FALSE;
- UINT32 samplesPerSecond = 0;
- BOOL bSamplesPerSecondFound=FALSE;
- UINT32 nChannels = 0;
- BOOL bChannelsFound=FALSE;
- UINT32 port = 0;
- UINT32 ulPayloadType = 0;
- BOOL bFoundRTCPRR = FALSE;
- UINT32 ulRTCPRR = 0;
- BOOL bFoundRTCPSR = FALSE;
- UINT32 ulRTCPSR = 0;
- BOOL bFoundPreDecBufSize = FALSE;
- UINT32 ulPreDecBufSize = 0;
- BOOL bFoundPreDecBufPeriod = FALSE;
- UINT32 ulPreDecBufPeriod = 0;
- BOOL bFoundPostDecBufPeriod = FALSE;
- UINT32 ulPostDecBufPeriod = 0;
- BOOL bFoundDecByteRate = FALSE;
- UINT32 ulDecByteRate = 0;
- char* pszMimeType=NULL;
- char* pszMimeFirst=NULL;
- UINT32 ulMimeFirstBufLen = 0;
- char* pszMimeLast=NULL;
-
- UINT32 ptime=0;
- BOOL bPtimeFound=FALSE;
- char* pszFmtp=NULL;
- // Reuse connection strings from file header
- if (pszConnAddr)
- {
- HX_VECTOR_DELETE(pszConnAddr);
- pszConnAddr = NULL;
- }
- bFoundTTL = FALSE;
- bFoundRange = FALSE;
- port = 0;
-
- rc = pValueArray[i]->GetFirstPropertyULONG32(pPropName, propValue);
- while(rc == HXR_OK)
- {
- bAddToHeader = FALSE;
- if(strcasecmp(pPropName, "StreamNumber") == 0)
- {
- streamNumber = propValue;
- bStreamNumberFound = TRUE;
- }
- else if(strcasecmp(pPropName, "Duration") == 0)
- {
- // don't use if 0 ( XXXJC we used to assert if the
- // prop was not present).
- if (0 != propValue)
- {
- duration = propValue;
- bDurationFound = TRUE;
- }
- }
- else if(strcasecmp(pPropName, "RTPPayloadType") == 0)
- {
- rtpPayloadType = propValue;
- bRtpPayloadTypeFound = TRUE;
- }
- else if(strcasecmp(pPropName, "SamplesPerSecond") == 0)
- {
- samplesPerSecond = propValue;
- bSamplesPerSecondFound = TRUE;
- }
- else if(strcasecmp(pPropName, "Channels") == 0)
- {
- nChannels = propValue;
- bChannelsFound = TRUE;
- }
- else if(strcasecmp(pPropName, "MulticastTTL") == 0)
- {
- connTTL = propValue;
- bFoundTTL = TRUE;
- }
- else if(strcasecmp(pPropName, "MulticastRange") == 0)
- {
- connRange = propValue;
- bFoundRange = TRUE;
- }
- else if(strcasecmp(pPropName, "Port") == 0)
- {
- port = propValue;
- }
- else if(strcasecmp(pPropName, "ptime") == 0)
- {
- ptime = propValue;
- bPtimeFound = 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, "RtcpRRRate") == 0)
- {
- bFoundRTCPRR = TRUE;
- ulRTCPRR = propValue;
- }
- else if(strcasecmp(pPropName, "RtcpRSRate") == 0)
- {
- bFoundRTCPSR = TRUE;
- ulRTCPSR = propValue;
- }
- else if(strcasecmp(pPropName, "PreDecBufSize") == 0)
- {
- bFoundPreDecBufSize = TRUE;
- ulPreDecBufSize = propValue;
- }
- else if(strcasecmp(pPropName, "InitPreDecBufPeriod") == 0)
- {
- bFoundPreDecBufPeriod = TRUE;
- ulPreDecBufPeriod = propValue;
- }
- else if(strcasecmp(pPropName, "InitPostDecBufPeriod") == 0)
- {
- bFoundPostDecBufPeriod = TRUE;
- ulPostDecBufPeriod = propValue;
- }
- else if(strcasecmp(pPropName, "DecByteRate") == 0)
- {
- bFoundDecByteRate = TRUE;
- ulDecByteRate = propValue;
- }
- else
- {
- bAddToHeader = TRUE;
- }
-
- if (bAddToHeader)
- {
- NEW_FAST_TEMP_STR(pszAttBuf, 4096, strlen(pPropName) + 64);
- SafeSprintf(pszAttBuf, 4096, "a=%s:integer;%d%s", pPropName,
- propValue, pszEOL);
- streamAttributes += pszAttBuf;
- DELETE_FAST_TEMP_STR(pszAttBuf);
- }
-
- /* make sure to reset SdpFileType header */
- if (strncasecmp(pPropName, "SdpFileType", 11) == 0)
- {
- pValueArray[i]->SetPropertyULONG32(pPropName, NONE_SDP);
- }
- rc = pValueArray[i]->GetNextPropertyULONG32(pPropName,
- propValue);
- }
- rc = pValueArray[i]->GetFirstPropertyBuffer(pPropName, pPropBuffer);
- while(rc == HXR_OK)
- {
- INT32 dataSize = pPropBuffer->GetSize();
- NEW_FAST_TEMP_STR(pszAttBuf, 4096, dataSize * 2 +
- strlen(pPropName) + 64);
- NEW_FAST_TEMP_STR(pszPropString, 4096, dataSize * 2 + 64);
- (void)BinTo64((const BYTE*)pPropBuffer->GetBuffer(),
- dataSize, pszPropString);
- SafeSprintf(pszAttBuf, 4096, "a=%s:buffer;"%s"%s", pPropName,
- pszPropString, pszEOL);
- streamAttributes += pszAttBuf;
- DELETE_FAST_TEMP_STR(pszPropString);
- DELETE_FAST_TEMP_STR(pszAttBuf);
- HX_RELEASE(pPropBuffer);
- rc = pValueArray[i]->GetNextPropertyBuffer(pPropName,
- pPropBuffer);
- }
- rc = pValueArray[i]->GetFirstPropertyCString(pPropName,
- pPropBuffer);
- while(rc == HXR_OK)
- {
- char* pString = (char*) pPropBuffer->GetBuffer();
- char* pszData=NULL;
- BOOL bDeleteString = FALSE;
- int len = pPropBuffer->GetSize();
- bAddToHeader = FALSE;
- if(strcasecmp(pPropName, "MimeType") == 0)
- {
- pszMimeType = EscapeBuffer(pString, pPropBuffer->GetSize());
- pszMimeLast = strchr(pszMimeType, '/');
- if(pszMimeLast)
- {
- int MFLen = pszMimeLast-pszMimeType;
- pszMimeLast++;
- pszMimeFirst = new char [ MFLen+1 ];
- ulMimeFirstBufLen = MFLen + 1;
- memcpy(pszMimeFirst, pszMimeType, MFLen); /* Flawfinder: ignore */
- pszMimeFirst[MFLen] = ' ';
- }
- else
- {
- // mimetype is not in the right format...
- }
- }
- else if(strcasecmp(pPropName, "MulticastAddress") == 0)
- {
- pszConnAddr = EscapeBuffer(pString, pPropBuffer->GetSize());
- }
- else if(strcasecmp(pPropName, "Control") == 0)
- {
- if (pControlStringBuff)
- {
- HX_RELEASE(pControlStringBuff);
- pControlStringBuff = pPropBuffer;
- pControlStringBuff->AddRef();
- }
- }
- else if(strcasecmp(pPropName, "PayloadParameters") == 0)
- {
- pszFmtp = EscapeBuffer(pString, pPropBuffer->GetSize());
- }
- else if(strcasecmp(pPropName, "SDPData") == 0)
- {
- pszSDPData = new char [ len + 1 ];
- memcpy(pszSDPData, (const char*)pPropBuffer->GetBuffer(), len); /* Flawfinder: ignore */
- pszSDPData[len] = ' ';
- RemoveASLine(pszSDPData, len);
- }
- else if(strcasecmp(pPropName, "Information") == 0)
- {
- // "i="
- HX_ASSERT(!pszInfo);
- pszInfo = EscapeBuffer(pString, pPropBuffer->GetSize());
- }
- else
- {
- pszData = EscapeBuffer(pString, pPropBuffer->GetSize());
- bDeleteString = TRUE;
- bAddToHeader = TRUE;
- }
-
- if(bAddToHeader)
- {
- NEW_FAST_TEMP_STR(pszAttBuf, 4096, strlen(pszData) +
- strlen(pPropName) + 64);
- SafeSprintf(pszAttBuf, 4096,"a=%s:string;"%s"%s", pPropName,
- pszData, pszEOL);
- streamAttributes += pszAttBuf;
- DELETE_FAST_TEMP_STR(pszAttBuf);
- }
- if (bDeleteString)
- {
- HX_VECTOR_DELETE(pszData);
- }
- HX_RELEASE(pPropBuffer);
- rc = pValueArray[i]->GetNextPropertyCString(pPropName,
- pPropBuffer);
- }
- if(!bRtpPayloadTypeFound)
- {
- ulPayloadType = RTP_PAYLOAD_RTSP;
- }
- else
- {
- ulPayloadType = rtpPayloadType;
- }
- if (bUseOldSdp)
- {
- // our old sdpplin expects m= to have either "audio",
- // "video", or "data", and anything else would be BAD!
- if (strcmp(pszMimeFirst, "audio") && strcmp(pszMimeFirst, "video"))
- {
- SafeStrCpy(pszMimeFirst, "data", ulMimeFirstBufLen);
- }
- }
- else if (!pszMimeFirst)
- {
- pszMimeFirst = new char [ 5 ];
- strcpy(pszMimeFirst, "data"); /* Flawfinder: ignore */
- }
- // m=
- NEW_FAST_TEMP_STR(pszTmpString, 256, strlen(pszMimeFirst) + 128);
- SafeSprintf(pszTmpString, 256, "m=%s %d RTP/AVP %d%s",
- pszMimeFirst, port, ulPayloadType, pszEOL);
- mDesc += pszTmpString;
- DELETE_FAST_TEMP_STR(pszTmpString);
- // i=
- if (pszInfo)
- {
- NEW_FAST_TEMP_STR(pszTmpStr, 256, strlen(pszInfo) + 64);
- SafeSprintf(pszTmpStr, 256,"i=%s%s", pszInfo, pszEOL);
- mDesc += pszTmpStr;
- DELETE_FAST_TEMP_STR(pszTmpStr);
- HX_VECTOR_DELETE(pszInfo);
- pszInfo = NULL;
- }
- /* Format the connection line only if MulticastAddress and
- * MulticastTTL exist in the stream header
- */
- if (pszConnAddr && strlen(pszConnAddr) && bFoundTTL)
- {
- NEW_FAST_TEMP_STR(pszTmpString, 256, strlen(pszConnAddr) + 128);
- if (bFoundRange)
- {
- SafeSprintf(pszTmpString, 256,"c=IN IP4 %s/%d/%d%s",
- pszConnAddr, connTTL, connRange, pszEOL);
- }
- else
- {
- SafeSprintf(pszTmpString, 256,"c=IN IP4 %s/%d%s",
- pszConnAddr, connTTL, pszEOL);
- }
- mDesc += pszTmpString;
- DELETE_FAST_TEMP_STR(pszTmpString);
- }
- // b=
- if (bFoundAvgBitRate)
- {
- SafeSprintf(psz256, 256,"b=AS:%u%s", avgBitRate, pszEOL);
- mDesc += psz256;
- bFoundAvgBitRate = FALSE;
- }
- if (bFoundRTCPRR)
- {
- SafeSprintf(psz256, 256,"b=RR:%u%s", ulRTCPRR, pszEOL);
- mDesc += psz256;
- bFoundRTCPRR = FALSE;
- }
-
- if (bFoundRTCPSR)
- {
- SafeSprintf(psz256, 256,"b=RS:%u%s", ulRTCPSR, pszEOL);
- mDesc += psz256;
- bFoundRTCPSR = FALSE;
- }
-
- // a=control
- if (pControlStringBuff)
- {
- char* pString = (char*) pControlStringBuff->GetBuffer();
- char* pszData=NULL;
- pszData = EscapeBuffer(pString, pControlStringBuff->GetSize());
- if (pContentBase || pQueryParams)
- {
- UINT32 ulBuffLen = strlen(pszData);
- ulBuffLen += (pContentBase) ? pContentBase->GetSize() : 0;
- ulBuffLen += (pQueryParams) ? pQueryParams->GetSize() : 0;
- ulBuffLen +=64;
- NEW_FAST_TEMP_STR(pszControlString, 512, ulBuffLen);
- SafeSprintf(pszControlString, 512, "a=control:%s%s%s%s",
- (pContentBase)? ((char*)pContentBase->GetBuffer()) : "",
- pControlStringBuff->GetBuffer(),
- (pQueryParams)?((char*)pQueryParams->GetBuffer()) : "",
- pszEOL);
-
- mDesc += pszControlString;
- DELETE_FAST_TEMP_STR(pszControlString);
- }
- else
- {
- UINT32 ulBuffLen = strlen(pszData) + 64;
- NEW_FAST_TEMP_STR(pszControlString, 512, ulBuffLen);
- SafeSprintf(pszControlString,512,"a=control:%s%s", pszData,
- pszEOL);
-
- mDesc += pszControlString;
- DELETE_FAST_TEMP_STR(pszControlString);
- }
- HX_VECTOR_DELETE(pszData);
- }
- else if (bStreamNumberFound)
- {
- if (pContentBase || pQueryParams)
- {
- const char* pszFieldPrefix = "a=control:";
- const char* pszStreamLabel = "streamid=";
- UINT32 ulBuffLen = strlen(pszFieldPrefix) +
- strlen(pszStreamLabel);
- ulBuffLen += (pContentBase) ? (pContentBase->GetSize()) : 0;
- ulBuffLen += (pQueryParams) ? (pQueryParams->GetSize()) : 0;
- ulBuffLen += 1;
- NEW_FAST_TEMP_STR(pszControlField, 256, ulBuffLen);
- SafeSprintf(pszControlField, 256,"%s%s%s%d%s%s",
- pszFieldPrefix,
- (pContentBase)? ((char*)pContentBase->GetBuffer()) : "",
- pszStreamLabel, streamNumber,
- (pQueryParams)? ((char*)pQueryParams->GetBuffer()) : "",
- pszEOL);
- mDesc += pszControlField;
- DELETE_FAST_TEMP_STR(pszControlField);
- }
- else
- {
- SafeSprintf(psz256, 256,"a=control:streamid=%d%s", streamNumber, pszEOL);
- mDesc += psz256;
- }
- }
- // a=length && a=range
- if (bDurationFound)
- {
- NPTime npTime(duration);
- if (!bIsLive)
- {
- SafeSprintf(psz256,256, "a=range:npt=0-%s%s", (const char*)npTime, pszEOL);
- mDesc += psz256;
- }
-
- SafeSprintf(psz256, 256, "a=length:npt=%s%s", (const char*)npTime, pszEOL);
- mDesc += psz256;
- }
- else if (bDefaultDurationFound)
- {
- // take it from file header
- NPTime npTime(ulDefaultDuration);
- if (!bIsLive)
- {
- SafeSprintf(psz256, 256,"a=range:npt=0-%s%s", (const char*)npTime, pszEOL);
- mDesc += psz256;
- }
- SafeSprintf(psz256,256, "a=length:npt=%s%s", (const char*)npTime,pszEOL);
- mDesc += psz256;
- }
- else
- {
- // if we put ntp=0-, old sdpplin is gonna freak out.
- if (bUseOldSdp)
- {
- if (!bIsLive)
- {
- SafeSprintf(psz256, 256,"a=range:npt=0-0%s", pszEOL);
- mDesc += psz256;
- }
- SafeSprintf(psz256, 256,"a=length:npt=0%s", pszEOL);
- mDesc += psz256;
- }
- else
- {
- if (!bIsLive)
- {
- SafeSprintf(psz256, 256,"a=range:npt=0-%s", pszEOL);
- mDesc += psz256;
- }
- SafeSprintf(psz256, 256,"a=length:npt=0%s", pszEOL);
- mDesc += psz256;
- }
- }
-
- // a=rtpmap:
- if (!pszMimeLast)
- {
- goto bail;
- }
-
- SafeSprintf(psz256, 256, "a=rtpmap:%d %s", ulPayloadType, pszMimeLast);
- mDesc += psz256;
- if (SDPIsStaticPayload(ulPayloadType))
- {
- if (!bSamplesPerSecondFound)
- {
- samplesPerSecond =
- SDPMapPayloadToSamplesPerSecond(ulPayloadType);
- if (samplesPerSecond)
- {
- bSamplesPerSecondFound = TRUE;
- }
- }
- if (!bChannelsFound)
- {
- nChannels = SDPMapPayloadToChannels(ulPayloadType);
- if (nChannels)
- {
- bChannelsFound = TRUE;
- }
- }
- }
- if (bSamplesPerSecondFound)
- {
- SafeSprintf(psz256, 256,"/%d", samplesPerSecond);
- mDesc += psz256;
- }
- else
- {
- mDesc += "/1000";
- }
- if (bChannelsFound)
- {
- SafeSprintf(psz256, 256,"/%d", nChannels);
- mDesc += psz256;
- }
- mDesc += pszEOL;
-
- // a=fmtp
- if (pszFmtp)
- {
- SafeSprintf(psz256, 256, "a=fmtp:%d %s%s", ulPayloadType, pszFmtp, pszEOL);
- mDesc += psz256;
- HX_VECTOR_DELETE(pszFmtp);
- }
- else if (!bUseOldSdp)
- {
- // 3GPP requires an fmtp field in every SDP file
- // Include this only if the client supports interop SDP
- // and SDPData doesn't already contain a=fmtp:
- SafeSprintf(psz256, 256,"a=fmtp:%d ", ulPayloadType);
- if (!pszSDPData || !strstr(pszSDPData, psz256))
- {
- SafeSprintf(psz256,256, "a=fmtp:%d %s", ulPayloadType, pszEOL);
- mDesc += psz256;
- }
- }
- // a=ptime
- if (bPtimeFound)
- {
- SafeSprintf(psz256,256, "a=ptime:%d%s", ptime, pszEOL);
- mDesc += psz256;
- }
- if (pszMimeType)
- {
- // a=mimetype:string;xxx
- NEW_FAST_TEMP_STR(pszTmpStr, 256, strlen(pszMimeType) + 128);
- SafeSprintf(pszTmpString, 256, "a=mimetype:string;"%s"%s", pszMimeType, pszEOL);
- mDesc += pszTmpString;
- DELETE_FAST_TEMP_STR(pszTmpStr);
-
- HX_VECTOR_DELETE(pszMimeType);
- }
- // 3GPP AnnexG values
- if (bFoundPreDecBufSize)
- {
- SafeSprintf(psz256, 256, "a=X-predecbufsize:%u%s",
- ulPreDecBufSize, pszEOL);
- mDesc += psz256;
- }
- if (bFoundPreDecBufPeriod)
- {
- SafeSprintf(psz256, 256, "a=X-initpredecbufperiod:%u%s",
- ulPreDecBufPeriod, pszEOL);
- mDesc += psz256;
- }
- if (bFoundPostDecBufPeriod)
- {
- SafeSprintf(psz256, 256, "a=X-initpostdecbufperiod:%u%s",
- ulPostDecBufPeriod, pszEOL);
- mDesc += psz256;
- }
- if (bFoundDecByteRate)
- {
- SafeSprintf(psz256, 256, "a=X-decbyterate:%u%s",
- ulDecByteRate, pszEOL);
- mDesc += psz256;
- }
- if (pszMimeFirst)
- {
- HX_VECTOR_DELETE(pszMimeFirst);
- }
- mDesc += streamAttributes;
- // expand SDPData if it's there...
- if (pszSDPData)
- {
- mDesc += pszSDPData;
- HX_VECTOR_DELETE(pszSDPData);
- pszSDPData = NULL;
- }
- }
- }
- bail:
- if (pszConnAddr)
- HX_VECTOR_DELETE(pszConnAddr);
- HX_RELEASE(pControlStringBuff);
- HX_RELEASE(pContentBase);
- HX_RELEASE(pQueryParams);
- if (mDesc.IsEmpty())
- {
- pDescription = NULL;
- return HXR_FAIL;
- }
- IHXBuffer* pBuffer = NULL;
- m_pCCF->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
- pBuffer->Set((BYTE*)(const char*)mDesc, mDesc.GetLength());
- pDescription = pBuffer;
- return HXR_OK;
- }
- BOOL SDPMediaDescGenerator::GetUseOldEOL() const
- {
- return m_bUseOldEOL;
- }
- void SDPMediaDescGenerator::SetUseOldEOL(BOOL bUseOldEOL)
- {
- m_bUseOldEOL = bUseOldEOL;
- }
- /*
- * If there is no Duration in a file header and all streams have the same
- * duration, put it in a file header.
- * If live, it is 0.
- */
- HX_RESULT
- SDPMediaDescGenerator::SpecComplianceCheck(UINT16 nValues,
- IHXValues** ppValueArray)
- {
- HX_RESULT theErr;
- UINT32 ulDuration;
- // sanity check
- if (nValues < 3 || !ppValueArray)
- {
- HX_ASSERT(!"unexpected headers");
- return HXR_UNEXPECTED;
- }
-
- theErr = ppValueArray[0]->GetPropertyULONG32("Duration", ulDuration);
- if (SUCCEEDED(theErr))
- {
- return HXR_OK;
- }
-
- UINT32 ulTmp = 0;
- ulDuration = 0;
-
- /* find out if this is a live session */
- theErr = ppValueArray[0]->GetPropertyULONG32("LiveStream", ulTmp);
- if (SUCCEEDED(theErr) && 1 == ulTmp)
- {
- ppValueArray[0]->SetPropertyULONG32("Duration", 0);
- return HXR_OK;
- }
-
- for (UINT16 i = 2; i < nValues; ++i)
- {
- theErr =
- ppValueArray[i]->GetPropertyULONG32("Duration", ulTmp);
- if (SUCCEEDED(theErr))
- {
- // take the largest
- if (ulDuration < ulTmp)
- {
- ulDuration = ulTmp;
- }
- }
- }
-
- if (ulDuration)
- {
- ppValueArray[0]->SetPropertyULONG32("Duration", ulDuration);
- }
- return HXR_OK;
- }
- char*
- SDPMediaDescGenerator::EscapeBuffer(const char* pBuffer, UINT32 len)
- {
- UCHAR* buf;
- UINT32 newlen;
- UINT32 i = 0;
- UCHAR* tmp;
- UCHAR* newbuf;
- if(!pBuffer)
- {
- return 0;
- }
- buf = (UCHAR*)pBuffer;
- newlen = len;
- /*
- * We have to do this in two passes. One to alloc new mem to
- * copy into, and the next to do the escape/ copy.
- * First, count unescaped quotes and alloc.
- */
- tmp = buf;
- while(i < len)
- {
- if(*tmp == '"')
- {
- newlen++;
- }
- if(*tmp == '\')
- {
- tmp++;
- i++;
- }
- tmp++;
- i++;
- }
- newbuf = new UCHAR[newlen];
- tmp = newbuf;
- /*
- * Now copy into the new buffer and unescape as you go along.
- */
- i = 0;
- while(i < len)
- {
- if(*buf == '"')
- {
- *tmp++ = '\';
- }
- if(*buf == '\')
- {
- *tmp++ = *buf++;
- i++;
- }
- *tmp++ = *buf++;
- i++;
- }
- /*
- * Set the buffer and return.
- */
- return (char*)newbuf;
- }
- void
- SDPMediaDescGenerator::RemoveASLine(char* pSDPData, UINT32 len)
- {
- /*
- * This method removes an extraneous b=AS line in place.
- */
- if (!pSDPData)
- {
- return;
- }
- char* pWriteCursor = (char*)strstr((const char*)pSDPData, "b=AS");
- if (!pWriteCursor)
- {
- return;
- }
- char* pReadCursor = pWriteCursor;
- UINT32 ulLength = (len - (pWriteCursor - pSDPData));
- //Find the end of the field
- while((ulLength != 0) &&
- (*pReadCursor != 0x0a) &&
- (*pReadCursor != 0x0d) &&
- (*pReadCursor != ' '))
- {
- pReadCursor++;
- ulLength--;
- }
- //Skip over the end of the field
- while((ulLength > 0) &&
- ((*pReadCursor == 0x0a) ||
- (*pReadCursor == 0x0d) ||
- (*pReadCursor == ' ')))
- {
- pReadCursor++;
- ulLength--;
- }
- if (!pReadCursor)
- {
- return;
- }
- if (ulLength == 0)
- {
- /*
- * There's no more data beyond the b=AS line.
- * Terminate the SDPData after previous line
- */
- *pWriteCursor = ' ';
- }
- else
- {
- memmove(pWriteCursor, pReadCursor, len - (pReadCursor - pSDPData));
- }
- }
- BOOL SDPMediaDescGenerator::GetUseSessionGUID() const
- {
- return m_bUseSessionGUID;
- }
- BOOL SDPMediaDescGenerator::GetUseAbsoluteURL() const
- {
- return m_bUseAbsoluteURL;
- }
- void SDPMediaDescGenerator::SetUseSessionGUID(BOOL bOption)
- {
- m_bUseSessionGUID = bOption;
- }
- void SDPMediaDescGenerator::SetUseAbsoluteURL(BOOL bOption)
- {
- m_bUseAbsoluteURL= bOption;
- }