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

📄 rtspprotocol.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
 *      Method:
 *          IHXASMSource::Subscribe
 *      Purpose:
 *          Subscribe to a stream
 */

STDMETHODIMP
RTSPProtocol::Subscribe
(
    UINT16 streamNumber,
    UINT16 ruleNumber
)
{
    RTSPSubscription sub;
    sub.m_streamNumber = streamNumber;
    sub.m_ruleNumber = ruleNumber;
    sub.m_bIsSubscribe = TRUE;
    CHXSimpleList subList;
    subList.AddTail(&sub);
    return m_pProtocolLib->Subscribe(&subList);
}

/************************************************************************
 *      Method:
 *          IHXASMSource::Unsubscribe
 *      Purpose:
 *          Unsubscribe from a stream
 */

STDMETHODIMP
RTSPProtocol::Unsubscribe
(
    UINT16 streamNumber,
    UINT16 ruleNumber
)
{
    RTSPSubscription sub;
    sub.m_streamNumber = streamNumber;
    sub.m_ruleNumber = ruleNumber;
    sub.m_bIsSubscribe = FALSE;
    CHXSimpleList subList;
    subList.AddTail(&sub);
    return m_pProtocolLib->Unsubscribe(&subList);
}

/*
 * IHXBackChannel methods
 */

/************************************************************************
 *      Method:
 *          IHXBackChannel::PacketReady
 *      Purpose:
 *          Send a packet from renderer back to file format
 */

STDMETHODIMP
RTSPProtocol::PacketReady
(
    IHXPacket* pPacket
)
{
    /*
     * XXXSMP - We'll use the transport when available eventually, but
     * Control messages will do for now.
     */
    if(m_pProtocolLib)
    {
        return m_pProtocolLib->BackChannelPacketReady(pPacket);
    }
    return HXR_FAIL;
}

/* HXProtocol methods */

HX_RESULT
RTSPProtocol::server_hello(void)
{
    HX_RESULT   theErr = HXR_OK;
    IUnknown*   pContext = NULL;
    IHXBuffer*  pBuffer = NULL;
    IHXValues*  pInfo = NULL;

    pContext = (IUnknown*)(IHXStreamSource*)mOwner;
    pContext->AddRef();

    if (m_bSDPInitiated)
    {
        pInfo = new CHXHeader();
        if (pInfo)
        {
            pInfo->AddRef();

            pBuffer = new CHXBuffer();
            if (pBuffer)
            {
                pBuffer->AddRef();
                pBuffer->Set((UCHAR*)mPath, strlen(mPath) + 1);
                pInfo->SetPropertyCString("helix-sdp", pBuffer);
                pBuffer->Release();
            }
        }
    }

    theErr = m_pProtocolLib->Init((IUnknown*)pContext,
                                  mHost,
                                  mPort,
                                  (IHXRTSPClientProtocolResponse*)this,
                                  mUseProxy?RTSP_INIT_HXPRIVATE_AUTHORIZATION:0,
                                  m_pIDInfo,
                                  pInfo,
                                  m_bHTTPOnly,
                                  mCloakPort,
                                  FALSE);

    if (pInfo)
    {
        UINT32  ulMulticastOnly = 0;

        // "MulticastOnly" is set by the RTSPClientProtocol when it's scalable
        // multicast via SDP file.
        //
        // If "MulticastOnly" is set and the current transport is not multicast then
        // we will returns error immediately and won't waste time in transport switching
        pInfo->GetPropertyULONG32("MulticastOnly", ulMulticastOnly);
        m_bMulticastOnly = (ulMulticastOnly > 0)?TRUE:FALSE;

        if (m_bMulticastOnly && mCurrentTransport != MulticastMode)
        {
            theErr = HXR_SE_MULTICAST_DELIVERY_ONLY;
        }
    }

    HX_RELEASE(pInfo);
    HX_RELEASE(pContext);

    return theErr;
}

HX_RESULT
RTSPProtocol::proxy_hello(void)
{
    m_pProtocolLib->SetProxy(mProxy, mProxyPort);

    return server_hello();
}
    
HX_RESULT
RTSPProtocol::process(void)
{
    HX_RESULT theErr = HXR_OK;

    if (m_LastError != HXR_OK)
    {
        return m_LastError;
    }

#ifdef _MACINTOSH
#if defined(HELIX_FEATURE_AUTHENTICATION)
    if (m_bHandleWWWAuthentication)
    {
        /* Need to wait for system time */
        if (HXMM_ATINTERRUPT())
        {
            return HXR_OK;
        }

        m_bHandleWWWAuthentication = FALSE;
        handlePendingWWWAuthentication(m_WWWResult, m_pWWWValues);
        HX_RELEASE(m_pWWWValues);
    }
#endif
#endif

    switch(m_idleState)
    {
        case INIT_SOCKETS_STATE:
        {
            IUnknown*           pContext = NULL;
            IHXInterruptState*  pInterruptState = NULL;

            mOwner->GetContext(pContext);
            if (pContext)
            {
                pContext->QueryInterface(IID_IHXInterruptState, (void**) &pInterruptState);
            }

            HX_RELEASE(pContext);

            /* We want to initialize sockets ONLY at system time */
            if (!pInterruptState ||
                !pInterruptState->AtInterruptTime())
            {
                // XXX HP: we should find better way to handle this
                //             when the UseUDPPort option is selected
                if (UDPMode == mCurrentTransport ||
                    MulticastMode == mCurrentTransport)
                {
                    theErr = m_pProtocolLib->InitSockets();
                }

                m_idleState = SEND_SETUP_REQUEST_STATE;
            }

            HX_RELEASE(pInterruptState);
        }
        break;

        case SEND_SETUP_REQUEST_STATE:
        {
            // Make sure we are finished with the file header
            if (!mOwner->m_bContinueWithHeaders)
            {
                theErr = send_setup_request();
                m_idleState = NULL_STATE;
            }
        }
        break;

        case ALERT_STATE:
        {
            // Set theErr to the correct ServerAlert HXR_ code.
            theErr = MAKE_SA(m_ulLastAlert);
            if (!IS_SERVER_ALERT(theErr))
            {
                theErr = HXR_SERVER_ALERT;
            }
            m_idleState = NULL_STATE;
        }
        break;

        default:
        break;
    }

    // check whether the connection has timed out
    if (!theErr && !m_bPaused)
    {
        ULONG32 ulNow = HX_GET_TICKCOUNT();

        if ((!mReceivedControl || (!m_bReceivedData && m_bPlaying))
            && mOwner->CheckTransportTimeout(ulNow))
        {
            /* Make sure that we have really not receioved any data.
             * If it is a sparse stream, transport may hold onto initial
             * data for around 2 seconds before releasing it to the next
             * layer.
             */
            if (!mReceivedControl)
            {
                theErr = HXR_NET_CONNECT;
            }
            else
            {
                if (m_pProtocolLib && m_pProtocolLib->IsDataReceived())
                {
                    /* We haver received the data.. Transport will
                    * eventually give it to use (hopefully!)
                    */
                    m_bReceivedData = TRUE;
                }
                else
                {
                    switch (mCurrentTransport)
                    {
                    case MulticastMode:
                        theErr = HXR_MULTICAST_UDP;
                        break;
                    case UDPMode:
                        theErr = HXR_NET_UDP;
                        break;
                    case TCPMode:
                        if (!m_bHTTPOnly)
                        {
                            theErr = HXR_NET_TCP;
                        }
                        else
                        {
                            theErr = HXR_DNR;
                        }
                        break;
                    default:
                        break;
                    }
                }
            }
        }

        // The following logic is to force reconnect when in certain cases, the UDP
        // channel would be closed after a long pause. This solves the 50% phenomenon.
        if (HXR_OK == theErr && m_bReceivedData && m_bAreResuming && mCurrentTransport == UDPMode)
        {
            if (mSourceEnd || (m_pProtocolLib && m_pProtocolLib->IsDataReceived()))
            {
                m_bAreResuming = FALSE;
            }
            else if (mOwner->CheckTransportTimeout(ulNow))
            {
                m_bAreResuming = FALSE;
                theErr = HXR_SERVER_TIMEOUT;
            }
        }

        // fallback to unicast if scalable multicast fails
        if (m_bSDPInitiated && HXR_MULTICAST_UDP == theErr && mLiveStream)
        {
            if (HXR_OK == SwitchToUnicast())
            {
                theErr = HXR_OK;
            }
            else
            {
                theErr = HXR_MULTICAST_JOIN;
            }
        }
    }

    // remember the last error so we won't proceed to the next
    // RTSP state in subsequent process() calls
    if (HXR_OK == m_LastError && HXR_OK != theErr)
    {
        m_LastError = theErr;
    }

    return theErr;
}

HX_RESULT
RTSPProtocol::abort(void)
{
    HX_RESULT theErr = HXR_OK;

//XXX...Currently unimplemented

    return theErr;
}

HX_RESULT
RTSPProtocol::GetEvent
(
    UINT16 uStreamNumber,
    CHXEvent*& pEvent
)
{
    HX_TRACE("RTSPProtocol::GetPacket");

    HX_RESULT result;
    IHXPacket* pPacket = NULL;

    pEvent = NULL;

    result = m_pProtocolLib->GetPacket(uStreamNumber, pPacket);

#ifdef _DEBUG
    if (result == HXR_AT_END)
    {
        STREAM_INFO* pStreamInfo;

        if (HXR_OK != mOwner->GetStreamInfo(uStreamNumber, pStreamInfo))
        {
            return HXR_FAIL;
        }

        HX_ASSERT(pStreamInfo->m_bSrcStreamDone);
    }
#endif

    if (pPacket)
    {
        // signal the raw data is received
        m_bReceivedData = TRUE;

        pEvent = new CHXEvent(pPacket);
        pPacket->Release();
    }

    return result;
}

HX_RESULT
RTSPProtocol::setup(const char* host, const char* path, UINT16 port,
                    BOOL LossCorrection, BOOL bHTTPCloak, 
                    BOOL bSDPInitiated, UINT16 cloakPort)
{
    HX_RESULT   theErr  = HXR_OK;
    IHXValues*  pRequestHeaders = NULL;
    IHXValues* pCloakValues = NULL;
    IHXBuffer*  pRegionData = NULL;

    m_bSDPInitiated = bSDPInitiated;

    mOwner->GetRequest(m_pRequest);

    // XXXkshoop store origional headers for use
    // in replaying Describe's.  This supports
    // authentication.
    HX_ASSERT(m_pRequest);
    if (m_pRequest)
    {
        m_spIHXValuesStoredHeaders.Release();
        theErr = m_pRequest->GetRequestHeaders(
            m_spIHXValuesStoredHeaders.ptr_reference());

        HX_VERIFY(SUCCEEDED(theErr) && m_spIHXValuesStoredHeaders.IsValid());
    }

    // setup base class members
    theErr = HXProtocol::setup(host, path, port, LossCorrection, bHTTPCloak,
                               m_bSDPInitiated, cloakPort);

    if (theErr)
    {
        return theErr;
    }

    if
    (
        m_pRequest
        &&
        SUCCEEDED(m_pRequest->GetRequestHeaders(pRequestHeaders))
        &&
        pRequestHeaders
    )
    {
        pRequestHeaders->GetPropertyCString("RegionData", pRegionData);
    }

    HX_RELEASE(pRequestHeaders);

    // construct the IHXValues
    m_pIDInfo = new CHXHeader();
    m_pIDInfo->AddRef();

    IHXBuffer*  pGUID = new CHXBuffer();
    IHXBuffer*  pClientID = new CHXBuffer();
    IHXBuffer*  pPragma = new CHXBuffer();

    pGUID->AddRef();
    pClientID->AddRef();
    pPragma->AddRef();

    pGUID->Set((const UCHAR*)m_pszGUID, strlen(m_pszGUID)+1);
    pClientID->Set((const UCHAR*)m_pszClientID, strlen(m_pszClientID)+1);
    pPragma->Set((const UCHAR*)PRAGMA, strlen(PRAGMA)+1);

    m_pIDInfo->SetPropertyCString("GUID", pGUID);
    m_pIDInfo->SetPropertyCString("ClientID", pClientID);

    // server doesn't like this in SDP initiated playback
    if (!m_bSDPInitiated)
    {
        m_pIDInfo->SetPropertyCString("Pragma", pPragma);
    }

#if 0
    IHXBuffer* pPasswordBuffer;
    if (m_pPreferences && m_pPreferences->ReadPref("LoadTestPassword",
       pPasswordBuffer) == HXR_OK)
    {
        char szLoadTestPasswordKey[HX_COMPANY_ID_KEY_SIZE] = {0}; /* Flawfinder: ignore */
        // create the encrypted key
        CalcCompanyIDKey((const char*)pPasswordBuffer->GetBuffer(),
                        (const char*)szStarttime,
                        (const char*)"LoadTestID",
                        (const char*)pRCMagic1,
                        (const char*)pMagic2,
                        (UCHAR*) &szLoadTestPasswordKey[0]);

        char szEncodedLTP[HX_COMPANY_ID_KEY_SIZE * 2]; // probably overkill /* Flawfinder: ignore */
        BinTo64((const BYTE*)szLoadTestPasswordKey, HX_COMPANY_ID_KEY_SIZE,
            szEncodedLTP);
        IHXBuffer* pEncodedLTPBuffer = new CHXBuffer();
        pEncodedLTPBuffer->AddRef();
        pEncodedLTPBuffer->Set((const UCHAR*)szEncodedLTP,
            strlen(szEncodedLTP)+1);
        m_pIDInfo->SetPropertyCString("LoadTestPassword", pEncodedLTPBuffer);
        pEncodedLTPBuffer->Release();
        HX_RELEASE(pPasswordBuffer);

        /*
         * XXXSMP Very poor way to set a requirement.  This won't work
         * as soon rmartsp needs to send other requirements.  Comment
      

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -