⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdpmdparse.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* ***** 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 + -