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

📄 rtptran.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        *ppvObj = this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXCallback))
    {
        AddRef();
        *ppvObj = (IHXCallback*)this;
        return HXR_OK;
    }
    *ppvObj = NULL;
    return HXR_NOINTERFACE;
}

STDMETHODIMP_(UINT32)
RTPUDPTransport::KeepAliveCB::AddRef()
{
    return InterlockedIncrement(&m_lRefCount);
}

STDMETHODIMP_(UINT32)
RTPUDPTransport::KeepAliveCB::Release()
{
    if(InterlockedDecrement(&m_lRefCount) > 0)
    {
	return m_lRefCount;
    }
    delete this;
    return 0;
}

STDMETHODIMP
RTPUDPTransport::KeepAliveCB::Func()
{
    if (m_pTransport)
    {
	m_pTransport->onNATKeepAlive();
    }
    return HXR_OK;
}


/*
 * RTP TCP
 */

RTPTCPTransport::RTPTCPTransport(BOOL bIsSource)
    : RTPBaseTransport(bIsSource)
    , m_pTCPSocket(0)
    , m_tcpInterleave(0)
{ 
    m_wrapSequenceNumber = DEFAULT_WRAP_SEQ_NO;
}

RTPTCPTransport::~RTPTCPTransport()
{
    HX_RELEASE(m_pTCPSocket);
}

void
RTPTCPTransport::Done()
{
    RTPBaseTransport::Done();
}


RTSPTransportTypeEnum
RTPTCPTransport::tag()
{
    return RTSP_TR_RTP_TCP;
}

HX_RESULT
RTPTCPTransport::init(IUnknown* pContext, 
		      IHXTCPSocket* pSocket,
		      IHXRTSPTransportResponse* pResp)
{
    m_pTCPSocket = pSocket;
    m_pTCPSocket->AddRef();
    m_pResp = pResp;
    m_pResp->AddRef();

    /* Set DiffServ Code Point */
    IHXSetSocketOption* pOpt = NULL;
    if (SUCCEEDED(m_pTCPSocket->QueryInterface(IID_IHXSetSocketOption, (void**)&pOpt)))
    {
	IHXQoSDiffServConfigurator* pCfg = NULL;
	if (SUCCEEDED(pContext->QueryInterface(IID_IHXQoSDiffServConfigurator, (void**)&pCfg)))
	{
	    pCfg->ConfigureSocket(pOpt, HX_QOS_DIFFSERV_CLASS_MEDIA);
	    pCfg->Release();
	    pCfg = NULL;
	}
	
	pOpt->Release();
	pOpt = NULL;
    }

    HX_RESULT hresult = Init(pContext);
    if (HXR_OK != hresult)
    {
	return hresult;
    }

    RTPBaseTransport::init();

    return HXR_OK;
}

HX_RESULT
RTPTCPTransport::sendPacket(BasePacket* pPacket)
{
    HX_ASSERT(m_bActive);

    HX_RESULT theErr;
    if (m_ulPayloadWirePacket!=0)
    {
	IHXBuffer* pSendBuf = NULL;
	theErr = reflectPacket(pPacket, pSendBuf);
	
	if (HXR_OK == theErr)
	{
	    theErr = writePacket(pSendBuf);

	    pSendBuf->Release();
	}
	else if (HXR_IGNORE == theErr)
	{
	    return HXR_OK;
	}

	return theErr;
    }

    IHXBuffer* pPacketBuf = NULL;
    
    theErr = makePacket(pPacket, pPacketBuf);

    if (HXR_OK == theErr)
    {
	theErr = writePacket(pPacketBuf);

	/* send SR if necessary */
    	if (HXR_OK == theErr && m_pRTCPTran->m_bSendReport && 
	    m_pRTCPTran->m_bSendRTCP)
    	{
	    m_pRTCPTran->sendSenderReport();
	    m_pRTCPTran->m_bSendReport = FALSE;
	    m_pRTCPTran->scheduleNextReport();
    	}	
    }

    HX_RELEASE(pPacketBuf);
    return theErr;
}

HX_RESULT
RTPTCPTransport::writePacket(IHXBuffer* pBuf)
{
    if (!m_pTCPSocket)
        return HXR_FAIL;

    // need to put $\000[datalen] in front of packet data

    UINT32 dataLen = pBuf->GetSize();

    if(dataLen > 0xffff)
    {
	return HXR_FAIL;
    }

    //XXXTDM: always true, m_tcpInteleave is signed (why?)
    //HX_ASSERT(0xFF != m_tcpInterleave);

    IHXBuffer* pHeader = NULL;
    m_pCommonClassFactory->CreateInstance(IID_IHXBuffer, 
                                          (void**)&pHeader);
    BYTE* pHeaderData;

    if(!pHeader)
    {
        return HXR_OUTOFMEMORY;
    }
    pHeader->SetSize(4);
    pHeaderData = pHeader->GetBuffer();

    pHeaderData[0] = '$';
    pHeaderData[1] = m_tcpInterleave;
    putshort(&pHeaderData[2], (UINT16)dataLen);

    HX_RESULT rc;
    rc = m_pTCPSocket->Write(pHeader);
    if (SUCCEEDED(rc))
    {
        rc = m_pTCPSocket->Write(pBuf);
    }
    if(rc)
    {
        m_pResp->OnProtocolError(HXR_NET_SOCKET_INVALID);
    }
    pHeader->Release();

    return rc;
}


/******************************************************************************
*   RTCP RTCP RTCP RTCP RTCP
******************************************************************************/

RTCPBaseTransport::RTCPBaseTransport(BOOL bIsSource):
    RTSPTransport(bIsSource),
    m_lRefCount(0),
    m_bCallbackPending(FALSE),
    m_pReportCallback(0),
    m_reportTimeoutID(0),
    m_bSchedulerStarted(FALSE),
    m_bSendRTCP(TRUE),
    m_bSendBye(FALSE),
    m_bSendReport(FALSE),
    m_pcCNAME(NULL),
    m_pReportHandler(NULL),
    m_pDataTransport(NULL),
    m_pTSConverter(NULL),
    m_streamNumber(0xffff),
    m_pSignalBus(NULL),
    m_pQoSSignal_RR(NULL),
    m_pQoSSignal_APP(NULL),
    m_pSessionId(NULL),
    m_bSSRCDetermined(FALSE),
    m_ulSSRCDetermined(0)
{
}

RTCPBaseTransport::~RTCPBaseTransport()
{
    HX_DELETE(m_pTSConverter);
}

STDMETHODIMP
RTCPBaseTransport::QueryInterface(REFIID riid, void** ppvObj)
{
    if (IsEqualIID(riid, IID_IUnknown))
    {
        AddRef();
        *ppvObj = this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXQoSSignalSourceResponse))
    {
        AddRef();
        *ppvObj = (IHXQoSSignalSourceResponse*)this;
        return HXR_OK;
    }

    *ppvObj = NULL;
    return HXR_NOINTERFACE;
}

STDMETHODIMP_(UINT32)
RTCPBaseTransport::AddRef()
{
    return InterlockedIncrement(&m_lRefCount);
}

STDMETHODIMP_(UINT32)
RTCPBaseTransport::Release()
{
    if(InterlockedDecrement(&m_lRefCount) > 0)
    {
	return m_lRefCount;
    }
    delete this;
    return 0;
}

void
RTCPBaseTransport::Done()
{
    stopScheduler();
    HX_RELEASE(m_pPacketFilter);
    HX_VECTOR_DELETE(m_pcCNAME);
    HX_DELETE(m_pReportHandler);

    HX_RELEASE(m_pQoSSignal_RR);
    HX_RELEASE(m_pQoSSignal_APP);
    HX_RELEASE(m_pSignalBus);
    HX_RELEASE(m_pSessionId);
}

HX_RESULT
RTCPBaseTransport::init()
{
    HX_ASSERT(!m_pReportCallback);
    HX_ASSERT(!m_pcCNAME);
    
    m_pReportCallback = new ReportCallback(this);
    if(!m_pReportCallback)
    {
        return HXR_OUTOFMEMORY;
    }
    m_pReportCallback->AddRef();

    char cname[16] = {0}; /* Flawfinder: ignore */
    itoa(random32(HX_GET_TICKCOUNT()), cname, 10);    
    m_pcCNAME = (BYTE*)new_string(cname);
    HX_ASSERT(m_pcCNAME);
    return HXR_OK;
}

void 
RTCPBaseTransport::addStreamInfo (RTSPStreamInfo* pStreamInfo,
				  UINT32 ulBufferDepth)
{
    UINT32 ulInvalidRate = (UINT32)-1;

    UINT32 ulAvgBitRate = pStreamInfo->m_ulAvgBitRate;
    UINT32 ulRRBitRate = pStreamInfo->m_ulRtpRRBitRate;
    UINT32 ulRSBitRate = pStreamInfo->m_ulRtpRSBitRate;
    BOOL   bUseRFC1889MinTime = FALSE;

    if (!ulAvgBitRate)
    {
	// We don't know the average bitrate.
	// Make something up
	ulAvgBitRate = 20000;
    }
    else
    {
	UINT32 ulRTCPBw = ulAvgBitRate / 20; // 5% of AvgBitRate

	if ((ulRRBitRate == ulInvalidRate) &&
	    (ulRSBitRate != ulInvalidRate) &&
	    (ulRTCPBw > ulRSBitRate))
	{
	    ulRRBitRate = ulRTCPBw - ulRSBitRate;
	}
	else if ((ulRRBitRate != ulInvalidRate) &&
		 (ulRSBitRate == ulInvalidRate) &&
		 (ulRTCPBw > ulRRBitRate))
	{
	    ulRSBitRate = ulRTCPBw - ulRRBitRate;
	}
    }

    if ((ulRRBitRate == ulInvalidRate) ||
	(ulRSBitRate == ulInvalidRate))
    {
	// If one of the bitrates is still
	// invalid at this point we just
	// default to the RFC 1889 behavior.
	// RS = 1.25% of the average bitrate
	// RR = 3.75% of the average bitrate
	
	bUseRFC1889MinTime = TRUE;
	m_bSendRTCP = TRUE;

	ulRSBitRate = ulAvgBitRate / 80; // 1.25%
	ulRRBitRate = ((ulAvgBitRate / 80) * 3 +
		       ((ulAvgBitRate % 80) * 3) / 80); // 3.75%
    }
    else if (ulRRBitRate == 0)
    {
	// We have been told not
	// to send RTCP reports
	m_bSendRTCP = FALSE;
    }

    if (m_pReportHandler)
    {
	// Get the minimum RTCP report interval
	UINT32 ulMinIntervalMs = (bUseRFC1889MinTime) ? 5000 : 1;

	// Pass the report interval parameters to 
	// the report handler
	m_pReportHandler->SetRTCPIntervalParams(ulRSBitRate, ulRRBitRate,
						ulMinIntervalMs);
    }
}

void
RTCPBaseTransport::setSSRC(UINT32 ulSSRC)
{
    m_bSSRCDetermined = TRUE;
    m_ulSSRCDetermined = ulSSRC;
}

void
RTCPBaseTransport::setSessionID(const char* pSessionID)
{
    /* cache the session id for use in retrieving signal bus*/
    if(pSessionID && (SUCCEEDED(m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
								      (void**)&m_pSessionId))))
    {
	m_pSessionId->Set((UCHAR*)pSessionID, 
			  strlen(pSessionID)+1);


	IHXQoSSignalSource* pSignalSrc = NULL;

	if (m_pSessionId && SUCCEEDED(m_pContext->QueryInterface(IID_IHXQoSSignalSource,
								 (void**) &pSignalSrc)))
	{
	    pSignalSrc->GetSignalBus(m_pSessionId, (IHXQoSSignalSourceResponse*)this);
	    HX_RELEASE(pSignalSrc);
	}
	else
	{
	    m_pSignalBus = NULL;
	}
    }
}

STDMETHODIMP
RTCPBaseTransport::SignalBusReady (HX_RESULT hResult, IHXQoSSignalBus* pBus, 
				   IHXBuffer* pSessionId)
{
    if (FAILED(hResult))
    {
	HX_ASSERT(0);
	return HXR_OK;
    }

    m_pSignalBus = pBus;
    m_pSignalBus->AddRef();

    if (m_pDataTransport)
    {
        if (FAILED(m_pSignalBus->QueryInterface(IID_IHXQoSTransportAdaptationInfo,
                                                (void**)&m_pDataTransport->m_pQoSInfo)))
        {
            m_pDataTransport->m_pQoSInfo = NULL;
        }
    }
    else
    {
        HX_ASSERT(0);
    }

    if (SUCCEEDED(m_pCommonClassFactory->CreateInstance(CLSID_IHXQoSSignal,
							(void**)&m_pQoSSignal_RR)))
    {
	m_pQoSSignal_RR->SetId(MAKE_HX_QOS_SIGNAL_ID(HX_QOS_SIGNAL_LAYER_FRAMING_TRANSPORT,
						  HX_QOS_SIGNAL_RELEVANCE_METRIC,
						  HX_QOS_SIGNAL_RTCP_RR));
    }
    else
    {
	HX_ASSERT(0);
	m_pQoSSignal_RR = NULL;
    }

    if (SUCCEEDED(m_pCommonClassFactory->CreateInstance(CLSID_IHXQoSSignal,
							(void**)&m_pQoSSignal_APP)))
    {
        m_pQoSSignal_APP->SetId(MAKE_HX_QOS_SIGNAL_ID(HX_QOS_SIGNAL_LAYER_FRAMING_TRANSPORT,
 							 HX_QOS_SIGNAL_RELEVANCE_METRIC,
 							 HX_QOS_SIGNAL_COMMON_BUFSTATE));
    }
    else
    {
	HX_ASSERT(0);
	m_pQoSSignal_APP = NULL;
    }

    return HXR_OK;
}

HX_RESULT 
RTCPBaseTransport::SetTSConverter(CHXTimestampConverter::ConversionFactors conversionFactors)
{
    HX_DELETE(m_pTSConverter);

    m_pTSConverter = new CHXTimestampConverter(conversionFactors);

    return m_pTSConverter ? HXR_OK : HXR_OUTOFMEMORY;
}

HX_RESULT
RTCPBaseTransport::startScheduler()
{
    if(!m_bSchedulerStarted && m_bSendRTCP)
    {
	HX_ASSERT(!m_bCallbackPending);
	m_bSchedulerStarted = TRUE;
	if (!m_bMulticast)
	{
	    // we wanna send the report right away!
	    m_bSendReport = TRUE;
	}
	else
	{    
	    if (!m_bCallbackPending)
	    {
		scheduleNextReport();
	    }
	}
    }

    return HXR_OK;
}

HX_RESULT
RTCPBaseTransport::stopScheduler()
{
    if(m_bCallbackPending)
    {
	HX_ASSERT(m_pScheduler);
	m_pScheduler->Remove(m_reportTimeoutID);
	m_bCallbackPending = FALSE;
    }
    HX_RELEASE(m_pReportCallback);

    return HXR_OK;
}

void
RTCPBaseTransport::scheduleNextReport()
{
    if (m_bSendRTCP)
    {
	HX_ASSERT(!m_bSendReport);
	HX_ASSERT(!m_bCallbackPending);
	HX_ASSERT(m_pReportCallback);
	
	HXTimeval rmatv = m_pScheduler->GetCurrentSchedulerTime();
	Timeval tvNow((INT32)rmatv.tv_sec, (INT32)rmatv.tv_usec);
	
	tvNow += Timeval(m_pReportHandler->GetRTCPInterval());
	
	rmatv.tv_sec = tvNow.tv_sec;
	rmatv.tv_usec = tvNow.tv_usec;
	m_reportTimeout

⌨️ 快捷键说明

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