📄 rtpclsnc.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 ***** */
/****************************************************************************
* Defines
*/
/****************************************************************************
* Includes
*/
#include "hxcom.h"
#include "rtpclsnc.h"
#include "ihxpckts.h"
#include "rtspif.h"
#include "ntptime.h"
/****************************************************************************
* CRTPClientStreamSync
*/
/****************************************************************************
* Constructor/Destructor
*/
CRTPClientStreamSync::CRTPClientStreamSync(void)
: m_pTSConverter(NULL)
, m_bIsImportedTSConverter(FALSE)
, m_bIsSyncMaster(FALSE)
, m_bStartSyncSet(FALSE)
, m_bIsStronglySynced(FALSE)
, m_bNTPtoHXOffsetSet(FALSE)
, m_lNTPtoHXOffset(0)
, m_lTimeOffsetRTP(0)
, m_lTimeOffsetHX(0)
, m_lSyncOffsetRTP(0)
, m_lSyncOffsetHX(0)
, m_lOffsetToMasterRTP(0)
, m_lOffsetToMasterHX(0)
, m_bStartTimeSet(FALSE)
, m_ulStartTime(0)
, m_pSyncServer(NULL)
, m_ulAcceptableSyncNoise(RTPCL_ACCEPTABLE_SYNC_NOISE)
{
;
}
CRTPClientStreamSync::~CRTPClientStreamSync(void)
{
Close();
}
/****************************************************************************
* Main Interface
*/
/****************************************************************************
* CRTPClientStreamSync::Init
*/
HX_RESULT CRTPClientStreamSync::Init(ULONG32 ulHXAFactor,
ULONG32 ulRTPFactor,
IHXTransportSyncServer* pSyncServer,
BOOL bIsSyncMaster,
ULONG32 ulAcceptableSyncNoise)
{
HX_RESULT retVal = HXR_OK;
ReleaseTSConverter();
HX_RELEASE(m_pSyncServer);
Reset();
m_ulAcceptableSyncNoise = ulAcceptableSyncNoise;
m_bIsSyncMaster = bIsSyncMaster;
m_pSyncServer = pSyncServer;
if (m_pSyncServer)
{
m_pSyncServer->AddRef();
}
retVal = HXR_OUTOFMEMORY;
m_pTSConverter = new CHXTimestampConverter(CHXTimestampConverter::FACTORS,
ulHXAFactor,
ulRTPFactor);
if (m_pTSConverter)
{
retVal = HXR_OK;
}
return retVal;
}
HX_RESULT CRTPClientStreamSync::Init(CHXTimestampConverter* pTSConverter,
IHXTransportSyncServer* pSyncServer,
BOOL bIsSyncMaster,
ULONG32 ulAcceptableSyncNoise)
{
HX_RESULT retVal = HXR_OK;
ReleaseTSConverter();
HX_RELEASE(m_pSyncServer);
Reset();
m_ulAcceptableSyncNoise = ulAcceptableSyncNoise;
m_bIsSyncMaster = bIsSyncMaster;
m_pSyncServer = pSyncServer;
if (m_pSyncServer)
{
m_pSyncServer->AddRef();
}
m_pTSConverter = pTSConverter;
if (m_pTSConverter)
{
m_bIsImportedTSConverter = TRUE;
}
return retVal;
}
/****************************************************************************
* CRTPClientStreamSync::Close
*/
void CRTPClientStreamSync::Close(void)
{
ReleaseTSConverter();
HX_RELEASE(m_pSyncServer);
}
/****************************************************************************
* CRTPClientStreamSync::Reset
*/
void CRTPClientStreamSync::Reset(void)
{
m_bStartSyncSet = FALSE;
m_bIsStronglySynced = FALSE;
m_bNTPtoHXOffsetSet = FALSE;
m_lNTPtoHXOffset = 0;
m_lTimeOffsetRTP = 0;
m_lTimeOffsetHX = 0;
m_lSyncOffsetHX = 0;
m_lSyncOffsetRTP = 0;
m_lOffsetToMasterHX = 0;
m_lOffsetToMasterRTP = 0;
m_bStartTimeSet = FALSE;
m_ulStartTime = 0;
if (m_pTSConverter)
{
m_pTSConverter->ReInit(m_pTSConverter->GetConversionFactors());
}
}
/****************************************************************************
* CRTPClientStreamSync::SetStartTime
*
* Establishes the reference starting time (in ms) of the session to be used
* for computation of individual initial stream syncronization offsets in
* case the stream RTP-NPT time is not explictly provided (e.g. via rtp-info
* in PLAY response).
* This function can be called multiple times by various streams in the
* the session. However, only the first setting will take effect and will
* be reflected to all other streams.
* ulRefHXStartTime - reference starting time (in ms) of a session
* (normally this is the reference arrival time
* of the first packet of the stream)
* bAsSecondaryRecepient - TRUE = called as reaction of some other stream
* establishing the sessions reference
* start time and thus reflection to other
* streams in the session should not be
* attempted
* FALSE = stream initiated establishing of the
* sessions reference start time and thus
* the reflection of the start time to
* all streams in the session is to be
* attempted
*/
HX_RESULT CRTPClientStreamSync::SetStartTime(ULONG32 ulRefHXStartTime,
BOOL bAsSecondaryRecipient)
{
HX_RESULT retVal = HXR_UNEXPECTED;
if (!m_bStartSyncSet)
{
retVal = HXR_IGNORE;
if (!m_bStartTimeSet)
{
retVal = HXR_OK;
if (bAsSecondaryRecipient)
{
m_bStartTimeSet = TRUE;
m_ulStartTime = ulRefHXStartTime;
}
else
{
if (m_pSyncServer)
{
retVal = m_pSyncServer->DistributeStartTime(
ulRefHXStartTime);
}
}
}
}
return retVal;
}
/****************************************************************************
* CRTPClientStreamSync::SetStartSync
*
* Establishes intial synchronization of the stream relative to other
* streams. This method must be called to enable the syncronization
* functionality of this class.
* ulRTPTime - stream RTP time in vicinity of the first RTP time
* stamp received for the stream, corresponding to
* the passed in RMA time (in RTP units)
* ulHXTime - stream NPT time corresponding to the passed in
* RTP time (in ms)
* bIsNominalHXTime - FALSE = binding between RTP and NPT is exact
* (This normally means that RTP-NPT mapping
* was explictly provided through out of
* band means such as rtp-info in PLAY
* response)
* TRUE = binding between RTP and NPT is loose
* (This normally means that RTP-NPT mapping
* was NOT explictly provided through out of
* band means such as rtp-info in PLAY
* response. In such case offset between
* streams will be established using the
* difference in arrival time of the first
* stream packets - if supplied to this
* class.)
* ulRefHXStartTime - reference time value in ms representing the arrival
* time of the packet corresponding to the passed in
* RTP time. This value must be properly set if
* bIsNominalHXTime == TRUE and SetStartTime() method
* was invoked on any of the streams in the session.
* This value is used to compute the initial
* synchronization offset of the stream based on the
* packet arrival time when RTP-NPT mapping is not
* explicitly communicated
* (bIsNominalHXTime == TRUE).
*/
HX_RESULT CRTPClientStreamSync::SetStartSync(ULONG32 ulRTPTime,
ULONG32 ulHXTime,
BOOL bIsNominalHXTime,
ULONG32 ulRefHXStartTime)
{
HX_RESULT retVal = HXR_UNEXPECTED;
if (!m_bIsStronglySynced)
{
LONG32 lHXTimeAdjustment = 0;
retVal = HXR_OK;
m_bStartSyncSet = TRUE;
m_bIsStronglySynced = (!bIsNominalHXTime);
if (bIsNominalHXTime && m_bStartTimeSet)
{
lHXTimeAdjustment = ((LONG32)
(ulRefHXStartTime - m_ulStartTime));
}
if (m_pTSConverter)
{
m_lTimeOffsetRTP = ulRTPTime -
m_pTSConverter->hxa2rtp_raw(ulHXTime + lHXTimeAdjustment);
m_pTSConverter->setAnchor(ulHXTime + lHXTimeAdjustment,
ulRTPTime);
m_lTimeOffsetHX = 0;
}
else
{
m_lTimeOffsetHX = m_lTimeOffsetRTP =
(ulRTPTime - ulHXTime - lHXTimeAdjustment);
}
}
return retVal;
}
/****************************************************************************
* CRTPClientStreamSync::HandleMasterSync
*
* Incorporates the synchronization adjustment as requested by the master
* syncronization stream. Master synchronization stream (usally audio stream)
* does not adjust its time-line but rather reflects its adjustment to all
* other streams. This is normally done to avoid gaps or clipping in audio.
* ulHXTime - NPT (Normal Play time) of the master sync. stream when
* the synchronization adjustemnt of slave streams was
* requested (in ms)
* lHXOffsetToMaster - time offset from master stream to apply (in ms)
*/
HX_RESULT CRTPClientStreamSync::HandleMasterSync(ULONG32 ulHXTime,
LONG32 lHXOffsetToMaster)
{
HX_RESULT retVal = HXR_IGNORE;
if (!m_bIsSyncMaster)
{
retVal = HXR_OK;
m_lOffsetToMasterHX = lHXOffsetToMaster;
if (lHXOffsetToMaster >= 0)
{
m_lOffsetToMasterRTP = (LONG32)
(m_pTSConverter->hxa2rtp_raw((ULONG32) lHXOffsetToMaster));
}
else
{
m_lOffsetToMasterRTP = (LONG32)
(-m_pTSConverter->hxa2rtp_raw((ULONG32) (-lHXOffsetToMaster)));
}
}
return retVal;
}
/****************************************************************************
* CRTPClientStreamSync::AnchorSync
*
* Establishes the mapping between NPT (Normal play time) and NTP time.
* This relationship is needed before RTCP reported (NTP,RTP) time stamp
* pairs can be applied to synchronization. This mapping is common for
* all streams in the session and is normally established by reception
* of the first RTCP packet after the starting stream synchronization is
* known (or is estimated).
* ulHXTime - NPT time corresponding to passed in NTP time
* ulNTPHXTime - NTP time in ms corresponding to passed in NPT time
*/
HX_RESULT CRTPClientStreamSync::AnchorSync(ULONG32 ulHXTime,
ULONG32 ulNTPHXTime)
{
HX_RESULT retVal = HXR_OK;
m_lNTPtoHXOffset = ulHXTime - ulNTPHXTime;
m_bNTPtoHXOffsetSet = TRUE;
return retVal;
}
/****************************************************************************
* CRTPClientStreamSync::HandleRTCPSync
*
* Incorporates the NTP and RTP time stamp relationships reported by RTCP
* into synchronization equation.
* ntpTime - RTCP reported NTP time
* ulRTPTime - RTCP reported RTP time
*/
HX_RESULT CRTPClientStreamSync::HandleRTCPSync(NTPTime ntpTime,
ULONG32 ulRTPTime)
{
HX_RESULT retVal = HXR_IGNORE;
ULONG32 ulNtpHX = ntpTime.toMSec();
// We ignore the RTCP sync until we can compute npt (m_bStartSyncSet) or
// if the RTCP packet contains no synchronization information
// (ulNtpHX == 0)
if ((ulNtpHX != 0) && m_bStartSyncSet)
{
// Npt time can be computed (ulHXTime)
ULONG32 ulHXTime = m_pTSConverter->rtp2hxa(ulRTPTime);
retVal = HXR_OK;
if (m_bNTPtoHXOffsetSet)
{
// We can sync - NTP to NPT offset is known
ULONG32 ulExpectedHXTime = ulNtpHX + m_lNTPtoHXOffset;
LONG32 lSyncOffsetHX = ulExpectedHXTime - ulHXTime;
LONG32 lSyncOffsetChange = lSyncOffsetHX - m_lSyncOffsetHX;
if (((ULONG32)lSyncOffsetChange > m_ulAcceptableSyncNoise) ||
(lSyncOffsetChange < (LONG32)(-m_ulAcceptableSyncNoise)))
{
if (m_bIsSyncMaster && m_pSyncServer)
{
m_pSyncServer->DistributeSync(ulHXTime, -lSyncOffsetHX);
}
else
{
m_lSyncOffsetHX = lSyncOffsetHX;
if (lSyncOffsetHX >= 0)
{
m_lSyncOffsetRTP = (LONG32)
(m_pTSConverter->hxa2rtp_raw((ULONG32) lSyncOffsetHX));
}
else
{
m_lSyncOffsetRTP = (LONG32)
(-m_pTSConverter->hxa2rtp_raw((ULONG32) (-lSyncOffsetHX)));
}
}
}
m_bIsStronglySynced = TRUE;
}
else
{
// This the first RTCP sync accross all streams, anchor sync
if (m_pSyncServer)
{
m_pSyncServer->DistributeSyncAnchor(ulHXTime, ulNtpHX);
}
}
}
return retVal;
}
/****************************************************************************
* Private Methods
*/
/****************************************************************************
* CRTPClientStreamSync::ReleaseTSConverter
*/
void CRTPClientStreamSync::ReleaseTSConverter(void)
{
if (m_bIsImportedTSConverter)
{
m_pTSConverter = NULL;
}
else
{
HX_DELETE(m_pTSConverter);
}
m_bIsImportedTSConverter = FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -