📄 rtsptran.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 "hxtypes.h"
#include "hxassert.h"
#include "debug.h"
#include "hxcom.h"
#include "hxmarsh.h"
#include "hxstrutl.h"
#include "netbyte.h"
#include "hxengin.h"
#include "ihxpckts.h"
#include "hxcomm.h"
#include "hxmon.h"
#include "netbyte.h"
#include "hxstring.h"
#include "chxpckts.h"
#include "hxslist.h"
#include "hxmap.h"
#include "hxdeque.h"
#include "hxbitset.h"
#include "timebuff.h"
#include "timeval.h"
#include "tconverter.h"
#include "rtptypes.h"
#include "rtspmsg.h"
#include "hxcorgui.h"
#include "ntptime.h"
#include "rtspif.h"
#include "rtsptran.h"
//#include "rtpwrap.h" // Wrappers for PMC generated base classes
#include "basepkt.h"
#include "hxtbuf.h"
#include "transbuf.h"
#include "hxtick.h"
#include "random32.h" // random32()
#include "pkthndlr.h" // in rtpmisc for RTCP routine
#include "rtcputil.h" // takes care of RTCP in RTP mode
#include "hxprefs.h" // IHXPreferences
#include "hxmime.h"
#include "hxcore.h"
#include "hxheap.h"
#ifdef PAULM_IHXTCPSCAR
#include "objdbg.h"
#endif
#ifdef PAULM_TNGTCPTRANSTIMING
#include "classtimer.h"
ClassTimer g_TNGTCPTransTimer("TNGTCPTransport", 0, 3600);
#endif
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
#define STREAM_END_DELAY_BASE_TOLERANCE 3000
static const UINT32 TRANSPORT_BUF_GROWTH_RATE = 1000;
void
dump(const char* pFile, const char* pc)
{
FILE* fp = fopen(pFile, "a");
if(!fp)
{
return;
}
fprintf(fp, "%s", pc);
fclose(fp);
}
RTSPStreamData::RTSPStreamData(BOOL needReliable):
m_seqNo(0),
m_streamNumber(0),
m_reliableSeqNo(0),
m_lastTimestamp(0),
m_pTransportBuffer(0),
m_pResendBuffer(0),
m_pStreamStats(0),
m_bNeedReliable(needReliable),
m_packetSent(FALSE),
m_bReceivedAllPackets(FALSE),
m_bNeedToACK(FALSE),
m_bFirstPacket(TRUE),
m_bUsesRTPPackets(FALSE),
m_pTSConverter(NULL),
m_pTSOrderHack(NULL),
m_eMediaType(RTSPMEDIA_TYPE_UNKNOWN)
{
;
}
RTSPStreamData::~RTSPStreamData()
{
if (m_pTransportBuffer)
{
delete m_pTransportBuffer;
}
if (m_pResendBuffer)
{
delete m_pResendBuffer;
}
HX_DELETE(m_pTSConverter);
HX_DELETE(m_pTSOrderHack);
}
RTSPStreamHandler::RTSPStreamHandler(RTSPTransport* pOwner)
: m_pOwner(pOwner)
, m_lRefCount(0)
{
m_pStreamDataMap = new CHXMapLongToObj;
}
RTSPStreamHandler::~RTSPStreamHandler()
{
CHXMapLongToObj::Iterator i;
RTSPStreamData* pStreamData;
for(i=m_pStreamDataMap->Begin();i!=m_pStreamDataMap->End();++i)
{
pStreamData = (RTSPStreamData*)(*i);
delete pStreamData;
}
delete m_pStreamDataMap;
}
HX_RESULT
RTSPStreamHandler::initStreamData(
UINT16 streamNumber, BOOL needReliable, BOOL bIsSource, INT16 rtpPayloadType,
BOOL bRecordFlag, UINT32 wrapSequenceNumber, UINT32 ulBufferDepth,
BOOL bHasOutOfOrderTS, CHXTimestampConverter* pTSConverter,
RTSPMediaType eMediaType)
{
RTSPStreamData* pStreamData;
if(!m_pStreamDataMap->Lookup(streamNumber, (void*&)pStreamData))
{
pStreamData = new RTSPStreamData(needReliable);
pStreamData->m_streamNumber = streamNumber;
pStreamData->m_pTSConverter = pTSConverter;
pStreamData->m_eMediaType = eMediaType;
pStreamData->m_lastSeqNo = 0;
(*m_pStreamDataMap)[streamNumber] = pStreamData;
if (!bIsSource)
{
UINT32 ulSetMaximumBufferDepth;
UINT32 ulSetBufferDepth;
if (bRecordFlag && ulBufferDepth != TRANSPORT_BUF_DURATION_UNDEF)
{
ulSetMaximumBufferDepth = ulBufferDepth;
ulSetBufferDepth = ulBufferDepth;
}
else if (bRecordFlag)
{
ulSetMaximumBufferDepth = MAX_TRANSPORT_BUF_DURATION;
ulSetBufferDepth = MAX_TRANSPORT_BUF_DURATION;
}
else
{
ulSetMaximumBufferDepth = MAX_TRANSPORT_BUF_DURATION;
ulSetBufferDepth = TRANSPORT_BUF_DURATION;
}
RTSPTransportBuffer* pTransportBuffer =
new RTSPTransportBuffer(m_pOwner,
streamNumber,
ulSetBufferDepth,
ulSetMaximumBufferDepth,
TRANSPORT_BUF_GROWTH_RATE,
wrapSequenceNumber);
pStreamData->m_pTransportBuffer = pTransportBuffer;
pStreamData->m_pStreamStats = NULL;
pStreamData->m_bUsesRTPPackets = bHasOutOfOrderTS;
}
return HXR_OK;
}
return HXR_FAIL;
}
RTSPStreamData*
RTSPStreamHandler::getStreamData(UINT16 streamNumber)
{
RTSPStreamData* pStreamData = 0;
if(!m_pStreamDataMap->Lookup(streamNumber, (void*&)pStreamData))
{
return 0;
}
return pStreamData;
}
RTSPStreamData*
RTSPStreamHandler::firstStreamData()
{
streamIterator = m_pStreamDataMap->Begin();
if(streamIterator == m_pStreamDataMap->End())
{
return 0;
}
return (RTSPStreamData*)(*streamIterator);
}
RTSPStreamData*
RTSPStreamHandler::nextStreamData()
{
++streamIterator;
if(streamIterator == m_pStreamDataMap->End())
{
return 0;
}
return (RTSPStreamData*)(*streamIterator);
}
BOOL
RTSPStreamHandler::endStreamData()
{
return (streamIterator == m_pStreamDataMap->End());
}
HX_RESULT
RTSPStreamHandler::createResendBuffer(UINT16 streamNumber,
UINT32 wrapSequenceNumber)
{
RTSPStreamData* pStreamData;
if(!m_pStreamDataMap->Lookup(streamNumber, (void*&)pStreamData))
{
return HXR_FAILED;
}
RTSPResendBuffer* pResendBuffer;
pResendBuffer = new RTSPResendBuffer(RESEND_BUF_DURATION,
MAX_RESEND_BUF_DURATION,
RESEND_BUF_GROWTH_RATE,
wrapSequenceNumber);
pStreamData->m_pResendBuffer = pResendBuffer;
return HXR_OK;
}
RTSPResendBuffer*
RTSPStreamHandler::getResendBuffer(UINT16 streamNumber)
{
RTSPStreamData* pStreamData = 0;
if(!m_pStreamDataMap->Lookup(streamNumber, (void*&)pStreamData))
{
return 0;
}
return pStreamData->m_pResendBuffer;
}
/*
* RTSPTransport methods
*/
RTSPTransport::RTSPTransport(BOOL bIsSource):
m_pContext(NULL),
m_pCommonClassFactory(0),
m_pScheduler(0),
m_pResp(0),
m_pStreamHandler(0),
m_pRegistry(0),
m_pInternalReset(0),
m_pSrcBufferStats(0),
m_bIsSource(bIsSource),
m_bIsInitialized(FALSE),
m_bIsUpdated(FALSE),
m_ulPacketsSent(0),
m_lBytesSent(0),
m_bIsReceivedData(FALSE),
m_bSourceDone(FALSE),
m_bHackedRecordFlag(FALSE),
m_wrapSequenceNumber(0),
m_bMulticast(FALSE),
m_pPlayerState(NULL),
m_pPacketFilter(NULL),
m_pClientPacketList(NULL),
m_bPrefetch(FALSE),
m_bFastStart(FALSE),
m_ulPlayRangeFrom(RTSP_PLAY_RANGE_BLANK),
m_ulPlayRangeTo(RTSP_PLAY_RANGE_BLANK),
m_bPlayRequestSent(FALSE),
m_packets_since_last_drop(0),
m_ulTotalSuccessfulResends(0),
m_ulTotalFailedResends(0),
m_ulSendingTime(0),
m_drop_packets(FALSE),
m_bSkipTimeAdjustment(FALSE)
#ifdef RDT_MESSAGE_DEBUG
,m_bRDTMessageDebug(FALSE)
#endif
{
m_ulStartTime = HX_GET_TICKCOUNT();
}
RTSPTransport::~RTSPTransport()
{
HX_RELEASE(m_pCommonClassFactory);
HX_RELEASE(m_pScheduler);
HX_RELEASE(m_pResp);
HX_RELEASE(m_pRegistry);
if (m_pStreamHandler)
{
m_pStreamHandler->Release();
m_pStreamHandler = NULL;
}
HX_RELEASE(m_pInternalReset);
HX_RELEASE(m_pSrcBufferStats);
HX_RELEASE(m_pPlayerState);
HX_RELEASE(m_pPacketFilter);
HX_RELEASE(m_pContext);
HX_DELETE(m_pClientPacketList);
}
void
RTSPTransport::addStreamInfo(RTSPStreamInfo* pStreamInfo, UINT32 ulBufferDepth)
{
if(pStreamInfo)
{
if(!m_pStreamHandler)
{
m_pStreamHandler = new RTSPStreamHandler(this);
m_pStreamHandler->AddRef();
}
CHXTimestampConverter* pTSConverter = NULL;
if (pStreamInfo->m_HXFactor && pStreamInfo->m_RTPFactor)
{
pTSConverter = new CHXTimestampConverter(CHXTimestampConverter::FACTORS,
pStreamInfo->m_HXFactor,
pStreamInfo->m_RTPFactor);
}
else if (pStreamInfo->m_sampleRate)
{
pTSConverter = new CHXTimestampConverter(CHXTimestampConverter::SAMPLES,
pStreamInfo->m_sampleRate);
}
m_pStreamHandler->initStreamData(
pStreamInfo->m_streamNumber,
pStreamInfo->m_bNeedReliablePackets,
m_bIsSource,
pStreamInfo->m_rtpPayloadType,
m_bHackedRecordFlag,
m_wrapSequenceNumber,
ulBufferDepth,
pStreamInfo->m_bHasOutOfOrderTS,
pTSConverter,
pStreamInfo->m_eMediaType);
m_bSkipTimeAdjustment = pStreamInfo->m_bRealMedia;
RTSPStreamData* pStreamData = NULL;
pStreamData = m_pStreamHandler->getStreamData(pStreamInfo->m_streamNumber);
if (pStreamData && pStreamData->m_pTransportBuffer && m_bPrefetch)
{
pStreamData->m_pTransportBuffer->EnterPrefetch();
}
}
}
void
RTSPTransport::setFirstTimeStamp(UINT16 uStreamNumber, UINT32 ulTS,
BOOL bIsRaw)
{
RTSPStreamData* pStreamData =
m_pStreamHandler->getStreamData(uStreamNumber);
if (pStreamData)
{
if (pStreamData->m_pTSConverter)
{
pStreamData->m_pTSConverter->setHXAnchor(ulTS);
}
HX_DELETE(pStreamData->m_pTSOrderHack);
}
if (!m_bIsSource)
{
RTSPTransportBuffer* pTransportBuffer = pStreamData->m_pTransportBuffer;
if (pTransportBuffer && pStreamData)
{
if ((m_ulPlayRangeFrom != RTSP_PLAY_RANGE_BLANK) &&
(m_ulPlayRangeTo != RTSP_PLAY_RANGE_BLANK))
{
if ((pStreamData->m_eMediaType == RTSPMEDIA_TYPE_AUDIO) ||
(pStreamData->m_eMediaType == RTSPMEDIA_TYPE_VIDEO))
{
// For audio & video media, we'll inform transport of
// the media duration to help determining stream termination
pStreamData->m_pTransportBuffer->InformTimestampRange(
m_ulPlayRangeFrom,
m_ulPlayRangeTo,
STREAM_END_DELAY_BASE_TOLERANCE);
}
}
}
}
}
void
RTSPTransport::setPlayRange(UINT32 ulFrom, UINT32 ulTo)
{
// this is the Range values in PLAY request in RMA time (ms) called on PLAY
// request
m_ulPlayRangeFrom = ulFrom;
m_ulPlayRangeTo = ulTo;
}
void
RTSPTransport::setSessionID(const char* pSessionID)
{
m_sessionID = pSessionID;
}
UINT16
RTSPTransport::getSeqNum(UINT16 streamNumber)
{
RTSPStreamData* pStreamData;
pStreamData = m_pStreamHandler->getStreamData(streamNumber);
if(pStreamData)
{
return pStreamData->m_seqNo;
}
else
{
return 0; //XXXBAB - 0xffff?
}
}
UINT32
RTSPTransport::getTimestamp(UINT16 streamNumber)
{
RTSPStreamData* pStreamData;
pStreamData = m_pStreamHandler->getStreamData(streamNumber);
if(pStreamData)
{
// XXXGo - this is RTP time w/ offset (NOT RMA time) if RTPUDPTransprot...
return pStreamData->m_lastTimestamp;
}
else
{
return 0;
}
}
HX_RESULT
RTSPTransport::getPacket(UINT16 uStreamNumber, IHXPacket*& pPacket)
{
RTSPTransportBuffer* pTransportBuffer = getTransportBuffer(uStreamNumber);
RTSPStreamData* pStreamData = m_pStreamHandler->getStreamData(uStreamNumber);
if ((!pTransportBuffer) || (!pStreamData))
{
return HXR_FAIL;
}
ClientPacket* clientPacket;
HX_RESULT result = pTransportBuffer->GetPacket(clientPacket);
if (result != HXR_OK)
{
return result;
}
pPacket = clientPacket->GetPacket();
if (!pPacket)
{
/*
* This is a lost packet
*/
result = m_pCommonClassFactory->CreateInstance(CLSID_IHXPacket,
(void**)&pPacket);
if (result != HXR_OK)
{
return result;
}
UINT8 unASMFlags = 0;
UINT32 ulTime = 0;
if (clientPacket->IsDroppedPacket())
{
// Preserve dropped flag as an ASM flag.
// This allows other code along the packet
// path to differentiate this packet from a
// true lost packet.
unASMFlags |= HX_ASM_DROPPED_PKT;
// We have a valid timestamp for a dropped
// packet so lets put it in the IHXPacket
ulTime = clientPacket->GetTime();
}
pPacket->Set(0, ulTime, uStreamNumber, unASMFlags, 0);
pPacket->SetAsLost();
}
else if (pStreamData->m_bUsesRTPPackets)
{
if (!pStreamData->m_pTSOrderHack)
{
pStreamData->m_pTSOrderHack = new RTSPStreamData::TSOrderHackInfo();
if (pStreamData->m_pTSOrderHack)
{
pStreamData->m_pTSOrderHack->m_ulLastSentTS =
pPacket->GetTime();
pStreamData->m_pTSOrderHack->m_ulLastRecvTS =
pStreamData->m_pTSOrderHack->m_ulLastSentTS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -