"ViE GetSentRTCPStatistics fails on a sending channel if it don't receive rtp video packets. BUG=222 TEST= tested in loopback. No new test added yet. Review URL: http://webrtc-codereview.appspot.com/343003 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1387 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
01530a2ac2
commit
ce5990cb0b
@ -11,6 +11,8 @@
|
|||||||
#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_H_
|
#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_H_
|
||||||
#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_H_
|
#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
#include "rtp_rtcp_defines.h"
|
#include "rtp_rtcp_defines.h"
|
||||||
|
|
||||||
@ -740,21 +742,22 @@ public:
|
|||||||
*
|
*
|
||||||
* return -1 on failure else 0
|
* return -1 on failure else 0
|
||||||
*/
|
*/
|
||||||
virtual WebRtc_Word32 RemoteRTCPStat( RTCPSenderInfo* senderInfo) = 0;
|
virtual WebRtc_Word32 RemoteRTCPStat(RTCPSenderInfo* senderInfo) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get received RTCP report block
|
* Get received RTCP report block
|
||||||
*
|
*
|
||||||
* return -1 on failure else 0
|
* return -1 on failure else 0
|
||||||
*/
|
*/
|
||||||
virtual WebRtc_Word32 RemoteRTCPStat( const WebRtc_UWord32 remoteSSRC,
|
virtual WebRtc_Word32 RemoteRTCPStat(
|
||||||
RTCPReportBlock* receiveBlock) = 0;
|
std::vector<RTCPReportBlock>* receiveBlocks) const = 0;
|
||||||
/*
|
/*
|
||||||
* Set received RTCP report block
|
* Set received RTCP report block
|
||||||
*
|
*
|
||||||
* return -1 on failure else 0
|
* return -1 on failure else 0
|
||||||
*/
|
*/
|
||||||
virtual WebRtc_Word32 AddRTCPReportBlock(const WebRtc_UWord32 SSRC,
|
virtual WebRtc_Word32 AddRTCPReportBlock(
|
||||||
|
const WebRtc_UWord32 SSRC,
|
||||||
const RTCPReportBlock* receiveBlock) = 0;
|
const RTCPReportBlock* receiveBlock) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -109,6 +109,9 @@ struct RTCPSenderInfo
|
|||||||
|
|
||||||
struct RTCPReportBlock
|
struct RTCPReportBlock
|
||||||
{
|
{
|
||||||
|
// Fields as described by RFC 3550 6.4.2.
|
||||||
|
WebRtc_UWord32 remoteSSRC; // SSRC of sender of this report.
|
||||||
|
WebRtc_UWord32 sourceSSRC; // SSRC of the RTP packet sender.
|
||||||
WebRtc_UWord8 fractionLost;
|
WebRtc_UWord8 fractionLost;
|
||||||
WebRtc_UWord32 cumulativeLost; // 24 bits valid
|
WebRtc_UWord32 cumulativeLost; // 24 bits valid
|
||||||
WebRtc_UWord32 extendedHighSeqNum;
|
WebRtc_UWord32 extendedHighSeqNum;
|
||||||
|
@ -170,8 +170,8 @@ class MockRtpRtcp : public RtpRtcp {
|
|||||||
WebRtc_Word32(WebRtc_UWord32 *bytesSent, WebRtc_UWord32 *packetsSent, WebRtc_UWord32 *bytesReceived, WebRtc_UWord32 *packetsReceived));
|
WebRtc_Word32(WebRtc_UWord32 *bytesSent, WebRtc_UWord32 *packetsSent, WebRtc_UWord32 *bytesReceived, WebRtc_UWord32 *packetsReceived));
|
||||||
MOCK_METHOD1(RemoteRTCPStat,
|
MOCK_METHOD1(RemoteRTCPStat,
|
||||||
WebRtc_Word32(RTCPSenderInfo* senderInfo));
|
WebRtc_Word32(RTCPSenderInfo* senderInfo));
|
||||||
MOCK_METHOD2(RemoteRTCPStat,
|
MOCK_CONST_METHOD1(RemoteRTCPStat,
|
||||||
WebRtc_Word32(const WebRtc_UWord32 remoteSSRC, RTCPReportBlock* receiveBlock));
|
WebRtc_Word32(std::vector<RTCPReportBlock>* receiveBlocks));
|
||||||
MOCK_METHOD2(AddRTCPReportBlock,
|
MOCK_METHOD2(AddRTCPReportBlock,
|
||||||
WebRtc_Word32(const WebRtc_UWord32 SSRC, const RTCPReportBlock* receiveBlock));
|
WebRtc_Word32(const WebRtc_UWord32 SSRC, const RTCPReportBlock* receiveBlock));
|
||||||
MOCK_METHOD1(RemoveRTCPReportBlock,
|
MOCK_METHOD1(RemoveRTCPReportBlock,
|
||||||
|
@ -179,14 +179,13 @@ RTCPReceiver::SetSSRC( const WebRtc_UWord32 ssrc)
|
|||||||
_SSRC = ssrc;
|
_SSRC = ssrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32 RTCPReceiver::ResetRTT(const WebRtc_UWord32 remoteSSRC) {
|
||||||
RTCPReceiver::ResetRTT(const WebRtc_UWord32 remoteSSRC)
|
|
||||||
{
|
|
||||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||||
RTCPReportBlockInformation* reportBlock = GetReportBlockInformation(remoteSSRC);
|
RTCPReportBlockInformation* reportBlock =
|
||||||
if(reportBlock == NULL)
|
GetReportBlockInformation(remoteSSRC);
|
||||||
{
|
if (reportBlock == NULL) {
|
||||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "\tfailed to GetReportBlockInformation(%d)", remoteSSRC);
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||||
|
"\tfailed to GetReportBlockInformation(%u)", remoteSSRC);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
reportBlock->RTT = 0;
|
reportBlock->RTT = 0;
|
||||||
@ -197,35 +196,32 @@ RTCPReceiver::ResetRTT(const WebRtc_UWord32 remoteSSRC)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32 RTCPReceiver::RTT(const WebRtc_UWord32 remoteSSRC,
|
||||||
RTCPReceiver::RTT(const WebRtc_UWord32 remoteSSRC,
|
|
||||||
WebRtc_UWord16* RTT,
|
WebRtc_UWord16* RTT,
|
||||||
WebRtc_UWord16* avgRTT,
|
WebRtc_UWord16* avgRTT,
|
||||||
WebRtc_UWord16* minRTT,
|
WebRtc_UWord16* minRTT,
|
||||||
WebRtc_UWord16* maxRTT) const
|
WebRtc_UWord16* maxRTT) const {
|
||||||
|
|
||||||
{
|
|
||||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||||
RTCPReportBlockInformation* reportBlock = GetReportBlockInformation(remoteSSRC);
|
|
||||||
if(reportBlock == NULL)
|
RTCPReportBlockInformation* reportBlock =
|
||||||
{
|
GetReportBlockInformation(remoteSSRC);
|
||||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "\tfailed to GetReportBlockInformation(%d)", remoteSSRC);
|
|
||||||
|
if (reportBlock == NULL) {
|
||||||
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||||
|
"\tfailed to GetReportBlockInformation(%u)",
|
||||||
|
remoteSSRC);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(RTT)
|
if (RTT) {
|
||||||
{
|
|
||||||
*RTT = reportBlock->RTT;
|
*RTT = reportBlock->RTT;
|
||||||
}
|
}
|
||||||
if(avgRTT)
|
if (avgRTT) {
|
||||||
{
|
|
||||||
*avgRTT = reportBlock->avgRTT;
|
*avgRTT = reportBlock->avgRTT;
|
||||||
}
|
}
|
||||||
if(minRTT)
|
if (minRTT) {
|
||||||
{
|
|
||||||
*minRTT = reportBlock->minRTT;
|
*minRTT = reportBlock->minRTT;
|
||||||
}
|
}
|
||||||
if(maxRTT)
|
if (maxRTT) {
|
||||||
{
|
|
||||||
*maxRTT = reportBlock->maxRTT;
|
*maxRTT = reportBlock->maxRTT;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -287,23 +283,24 @@ RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const
|
|||||||
|
|
||||||
// statistics
|
// statistics
|
||||||
// we can get multiple receive reports when we receive the report from a CE
|
// we can get multiple receive reports when we receive the report from a CE
|
||||||
WebRtc_Word32
|
WebRtc_Word32 RTCPReceiver::StatisticsReceived(
|
||||||
RTCPReceiver::StatisticsReceived(const WebRtc_UWord32 remoteSSRC,
|
std::vector<RTCPReportBlock>* receiveBlocks) const {
|
||||||
RTCPReportBlock* receiveBlock) const
|
if (receiveBlocks == NULL) {
|
||||||
{
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument",
|
||||||
if(receiveBlock == NULL)
|
__FUNCTION__);
|
||||||
{
|
|
||||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||||
RTCPReportBlockInformation* reportBlockInfo = GetReportBlockInformation(remoteSSRC);
|
|
||||||
if(reportBlockInfo == NULL)
|
MapItem* ptrReportBlockInfoItem = _receivedReportBlockMap.First();
|
||||||
{
|
while (ptrReportBlockInfoItem != NULL) {
|
||||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "\tfailed to GetReportBlockInformation(%d)", remoteSSRC);
|
RTCPReportBlockInformation* item =
|
||||||
return -1;
|
static_cast<RTCPReportBlockInformation*> (
|
||||||
|
ptrReportBlockInfoItem->GetItem());
|
||||||
|
receiveBlocks->push_back(item->remoteReceiveBlock);
|
||||||
|
ptrReportBlockInfoItem =
|
||||||
|
_receivedReportBlockMap.Next(ptrReportBlockInfoItem);
|
||||||
}
|
}
|
||||||
memcpy(receiveBlock, &(reportBlockInfo->remoteReceiveBlock), sizeof(RTCPReportBlock));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,71 +456,55 @@ void
|
|||||||
RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
||||||
RTCPPacketInformation& rtcpPacketInformation,
|
RTCPPacketInformation& rtcpPacketInformation,
|
||||||
const WebRtc_UWord32 remoteSSRC,
|
const WebRtc_UWord32 remoteSSRC,
|
||||||
const WebRtc_UWord8 numberOfReportBlocks)
|
const WebRtc_UWord8 numberOfReportBlocks) {
|
||||||
{
|
// This will be called once per report block in the RTCP packet.
|
||||||
// this will be called once per report block in the RTCP packet
|
// We filter out all report blocks that are not for us.
|
||||||
// we store all incoming reports
|
// Each packet has max 31 RR blocks.
|
||||||
// each packet has max 31 RR blocks
|
|
||||||
//
|
//
|
||||||
// we can calc RTT if we send a send report and get a report block back
|
// We can calc RTT if we send a send report and get a report block back.
|
||||||
|
|
||||||
/*
|
// |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
|
||||||
rtcpPacket.ReportBlockItem.SSRC
|
// which the information in this reception report block pertains.
|
||||||
The SSRC identifier of the source to which the information in this
|
|
||||||
reception report block pertains.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// if we receive a RTCP packet with multiple reportBlocks only store the ones to us
|
// Filter out all report blocks that are not for us.
|
||||||
if( _SSRC &&
|
if (rtcpPacket.ReportBlockItem.SSRC != _SSRC) {
|
||||||
numberOfReportBlocks > 1)
|
// This block is not for us ignore it.
|
||||||
{
|
|
||||||
// we have more than one reportBlock in the RTCP packet
|
|
||||||
if(rtcpPacket.ReportBlockItem.SSRC != _SSRC)
|
|
||||||
{
|
|
||||||
// this block is not for us ignore it
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// To avoid problem with acquiring _criticalSectionRTCPSender while holding
|
||||||
|
// _criticalSectionRTCPReceiver.
|
||||||
_criticalSectionRTCPReceiver->Leave();
|
_criticalSectionRTCPReceiver->Leave();
|
||||||
// to avoid problem with accuireing _criticalSectionRTCPSender while holding _criticalSectionRTCPReceiver
|
|
||||||
|
|
||||||
WebRtc_UWord32 sendTimeMS =
|
WebRtc_UWord32 sendTimeMS =
|
||||||
_rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
|
_rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
|
||||||
|
|
||||||
_criticalSectionRTCPReceiver->Enter();
|
_criticalSectionRTCPReceiver->Enter();
|
||||||
|
|
||||||
// ReportBlockItem.SSRC is who it's to
|
RTCPReportBlockInformation* reportBlock =
|
||||||
// we store all incoming reports, used in conference relay
|
CreateReportBlockInformation(remoteSSRC);
|
||||||
|
if (reportBlock == NULL) {
|
||||||
RTCPReportBlockInformation* reportBlock = CreateReportBlockInformation(remoteSSRC);
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||||
if(reportBlock == NULL)
|
"\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
|
||||||
|
reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
|
||||||
|
reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
|
||||||
|
reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
|
||||||
|
reportBlock->remoteReceiveBlock.cumulativeLost =
|
||||||
|
rb.CumulativeNumOfPacketsLost;
|
||||||
|
reportBlock->remoteReceiveBlock.extendedHighSeqNum =
|
||||||
|
rb.ExtendedHighestSequenceNumber;
|
||||||
|
reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
|
||||||
|
reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
|
||||||
|
reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
|
||||||
|
|
||||||
reportBlock->remoteReceiveBlock.fractionLost = rtcpPacket.ReportBlockItem.FractionLost;
|
if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
|
||||||
reportBlock->remoteReceiveBlock.cumulativeLost = rtcpPacket.ReportBlockItem.CumulativeNumOfPacketsLost;
|
|
||||||
reportBlock->remoteReceiveBlock.extendedHighSeqNum= rtcpPacket.ReportBlockItem.ExtendedHighestSequenceNumber;
|
|
||||||
reportBlock->remoteReceiveBlock.jitter = rtcpPacket.ReportBlockItem.Jitter;
|
|
||||||
reportBlock->remoteReceiveBlock.delaySinceLastSR = rtcpPacket.ReportBlockItem.DelayLastSR;
|
|
||||||
reportBlock->remoteReceiveBlock.lastSR = rtcpPacket.ReportBlockItem.LastSR;
|
|
||||||
|
|
||||||
if(rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter)
|
|
||||||
{
|
|
||||||
reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
|
reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_UWord32 delaySinceLastSendReport = rtcpPacket.ReportBlockItem.DelayLastSR;
|
WebRtc_UWord32 delaySinceLastSendReport =
|
||||||
|
rtcpPacket.ReportBlockItem.DelayLastSR;
|
||||||
|
|
||||||
// do we have a local SSRC
|
|
||||||
// keep track of our relayed SSRC too
|
|
||||||
if(_SSRC)
|
|
||||||
{
|
|
||||||
// we filter rtcpPacket.ReportBlockItem.SSRC to our SSRC
|
|
||||||
// hence only reports to us
|
|
||||||
if( rtcpPacket.ReportBlockItem.SSRC == _SSRC)
|
|
||||||
{
|
|
||||||
// local NTP time when we received this
|
// local NTP time when we received this
|
||||||
WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
|
WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
|
||||||
WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
|
WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
|
||||||
@ -531,63 +512,57 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
|||||||
_clock.CurrentNTP(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
|
_clock.CurrentNTP(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
|
||||||
|
|
||||||
// time when we received this in MS
|
// time when we received this in MS
|
||||||
WebRtc_UWord32 receiveTimeMS = ModuleRTPUtility::ConvertNTPTimeToMS(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
|
WebRtc_UWord32 receiveTimeMS = ModuleRTPUtility::ConvertNTPTimeToMS(
|
||||||
|
lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
|
||||||
|
|
||||||
// Estimate RTT
|
// Estimate RTT
|
||||||
WebRtc_UWord32 d =(delaySinceLastSendReport&0x0000ffff)*1000;
|
WebRtc_UWord32 d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
|
||||||
d /= 65536;
|
d /= 65536;
|
||||||
d+=((delaySinceLastSendReport&0xffff0000)>>16)*1000;
|
d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
|
||||||
|
|
||||||
WebRtc_Word32 RTT = 0;
|
WebRtc_Word32 RTT = 0;
|
||||||
|
|
||||||
if(sendTimeMS > 0)
|
if (sendTimeMS > 0) {
|
||||||
{
|
|
||||||
RTT = receiveTimeMS - d - sendTimeMS;
|
RTT = receiveTimeMS - d - sendTimeMS;
|
||||||
if( RTT <= 0)
|
if (RTT <= 0) {
|
||||||
{
|
|
||||||
RTT = 1;
|
RTT = 1;
|
||||||
}
|
}
|
||||||
if (RTT > reportBlock->maxRTT)
|
if (RTT > reportBlock->maxRTT) {
|
||||||
{
|
|
||||||
// store max RTT
|
// store max RTT
|
||||||
reportBlock->maxRTT = (WebRtc_UWord16)RTT;
|
reportBlock->maxRTT = (WebRtc_UWord16) RTT;
|
||||||
}
|
}
|
||||||
if(reportBlock->minRTT == 0)
|
if (reportBlock->minRTT == 0) {
|
||||||
{
|
|
||||||
// first RTT
|
// first RTT
|
||||||
reportBlock->minRTT = (WebRtc_UWord16)RTT;
|
reportBlock->minRTT = (WebRtc_UWord16) RTT;
|
||||||
}else if (RTT < reportBlock->minRTT)
|
} else if (RTT < reportBlock->minRTT) {
|
||||||
{
|
|
||||||
// Store min RTT
|
// Store min RTT
|
||||||
reportBlock->minRTT = (WebRtc_UWord16)RTT;
|
reportBlock->minRTT = (WebRtc_UWord16) RTT;
|
||||||
}
|
}
|
||||||
// store last RTT
|
// store last RTT
|
||||||
reportBlock->RTT = (WebRtc_UWord16)RTT;
|
reportBlock->RTT = (WebRtc_UWord16) RTT;
|
||||||
|
|
||||||
// store average RTT
|
// store average RTT
|
||||||
if(reportBlock->numAverageCalcs != 0)
|
if (reportBlock->numAverageCalcs != 0) {
|
||||||
{
|
float ac = static_cast<float> (reportBlock->numAverageCalcs);
|
||||||
float ac = static_cast<float>(reportBlock->numAverageCalcs);
|
float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
|
||||||
float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT) + ((1 / (ac + 1)) * RTT);
|
+ ((1 / (ac + 1)) * RTT);
|
||||||
reportBlock->avgRTT = static_cast<int>(newAverage + 0.5f);
|
reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
|
||||||
}else
|
} else {
|
||||||
{
|
|
||||||
// first RTT
|
// first RTT
|
||||||
reportBlock->avgRTT = (WebRtc_UWord16)RTT;
|
reportBlock->avgRTT = (WebRtc_UWord16) RTT;
|
||||||
}
|
}
|
||||||
reportBlock->numAverageCalcs++;
|
reportBlock->numAverageCalcs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
|
WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
|
||||||
" -> Received report block(%d), from SSRC:0x%x, RTT:%d, loss:%d", _id, remoteSSRC, RTT, rtcpPacket.ReportBlockItem.FractionLost);
|
" -> Received report block(%d), from SSRC:0x%x, RTT:%d, loss:%d",
|
||||||
|
_id, remoteSSRC, RTT, rtcpPacket.ReportBlockItem.FractionLost);
|
||||||
|
|
||||||
// rtcpPacketInformation
|
// rtcpPacketInformation
|
||||||
rtcpPacketInformation.AddReportInfo(reportBlock->remoteReceiveBlock.fractionLost,
|
rtcpPacketInformation.AddReportInfo(
|
||||||
(WebRtc_UWord16)RTT,
|
reportBlock->remoteReceiveBlock.fractionLost, (WebRtc_UWord16) RTT,
|
||||||
reportBlock->remoteReceiveBlock.extendedHighSeqNum,
|
reportBlock->remoteReceiveBlock.extendedHighSeqNum,
|
||||||
reportBlock->remoteReceiveBlock.jitter);
|
reportBlock->remoteReceiveBlock.jitter);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RTCPReportBlockInformation*
|
RTCPReportBlockInformation*
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_
|
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_
|
||||||
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_
|
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "typedefs.h"
|
#include "typedefs.h"
|
||||||
#include "map_wrapper.h"
|
#include "map_wrapper.h"
|
||||||
#include "rtp_utility.h"
|
#include "rtp_utility.h"
|
||||||
@ -81,8 +83,9 @@ public:
|
|||||||
const WebRtc_UWord64 pitureID) const;
|
const WebRtc_UWord64 pitureID) const;
|
||||||
|
|
||||||
// get statistics
|
// get statistics
|
||||||
WebRtc_Word32 StatisticsReceived(const WebRtc_UWord32 remoteSSRC,
|
WebRtc_Word32 StatisticsReceived(
|
||||||
RTCPReportBlock* receiveBlock) const;
|
std::vector<RTCPReportBlock>* receiveBlocks) const;
|
||||||
|
|
||||||
// Get TMMBR
|
// Get TMMBR
|
||||||
WebRtc_Word32 TMMBRReceived(const WebRtc_UWord32 size,
|
WebRtc_Word32 TMMBRReceived(const WebRtc_UWord32 size,
|
||||||
const WebRtc_UWord32 accNumCandidates,
|
const WebRtc_UWord32 accNumCandidates,
|
||||||
|
@ -1738,13 +1738,11 @@ WebRtc_Word32 ModuleRtpRtcpImpl::RemoteRTCPStat( RTCPSenderInfo* senderInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// received RTCP report
|
// received RTCP report
|
||||||
WebRtc_Word32
|
WebRtc_Word32 ModuleRtpRtcpImpl::RemoteRTCPStat(
|
||||||
ModuleRtpRtcpImpl::RemoteRTCPStat(const WebRtc_UWord32 remoteSSRC,
|
std::vector<RTCPReportBlock>* receiveBlocks) const {
|
||||||
RTCPReportBlock* receiveBlock)
|
|
||||||
{
|
|
||||||
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteRTCPStat()");
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteRTCPStat()");
|
||||||
|
|
||||||
return _rtcpReceiver.StatisticsReceived(remoteSSRC, receiveBlock);
|
return _rtcpReceiver.StatisticsReceived(receiveBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32
|
||||||
|
@ -316,8 +316,8 @@ public:
|
|||||||
virtual WebRtc_Word32 RemoteRTCPStat( RTCPSenderInfo* senderInfo);
|
virtual WebRtc_Word32 RemoteRTCPStat( RTCPSenderInfo* senderInfo);
|
||||||
|
|
||||||
// Get received RTCP report, report block
|
// Get received RTCP report, report block
|
||||||
virtual WebRtc_Word32 RemoteRTCPStat( const WebRtc_UWord32 remoteSSRC,
|
virtual WebRtc_Word32 RemoteRTCPStat(
|
||||||
RTCPReportBlock* receiveBlock);
|
std::vector<RTCPReportBlock>* receiveBlocks) const;
|
||||||
|
|
||||||
// Set received RTCP report block
|
// Set received RTCP report block
|
||||||
virtual WebRtc_Word32 AddRTCPReportBlock(const WebRtc_UWord32 SSRC,
|
virtual WebRtc_Word32 AddRTCPReportBlock(const WebRtc_UWord32 SSRC,
|
||||||
|
@ -113,24 +113,9 @@ class RtpRtcpRtcpTest : public ::testing::Test {
|
|||||||
delete receiver;
|
delete receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_id;
|
void SetUpCallFromModule1(RtcpCallback* feedback1, RtcpCallback* feedback2 ) {
|
||||||
RtpRtcp* module1;
|
EXPECT_EQ(0, module1->RegisterIncomingRTCPCallback(feedback1));
|
||||||
RtpRtcp* module2;
|
EXPECT_EQ(0, module2->RegisterIncomingRTCPCallback(feedback2));
|
||||||
RtpReceiver* receiver;
|
|
||||||
LoopBackTransport* transport1;
|
|
||||||
LoopBackTransport* transport2;
|
|
||||||
WebRtc_UWord32 test_ssrc;
|
|
||||||
WebRtc_UWord32 test_timestamp;
|
|
||||||
WebRtc_UWord16 test_sequence_number;
|
|
||||||
WebRtc_UWord32 test_CSRC[webrtc::kRtpCsrcSize];
|
|
||||||
FakeRtpRtcpClock fake_clock;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(RtpRtcpRtcpTest, RTCP) {
|
|
||||||
RtcpCallback* myRTCPFeedback1 = new RtcpCallback(module1);
|
|
||||||
RtcpCallback* myRTCPFeedback2 = new RtcpCallback(module2);
|
|
||||||
EXPECT_EQ(0, module1->RegisterIncomingRTCPCallback(myRTCPFeedback1));
|
|
||||||
EXPECT_EQ(0, module2->RegisterIncomingRTCPCallback(myRTCPFeedback2));
|
|
||||||
|
|
||||||
EXPECT_EQ(0, module1->SetRTCPStatus(kRtcpCompound));
|
EXPECT_EQ(0, module1->SetRTCPStatus(kRtcpCompound));
|
||||||
EXPECT_EQ(0, module2->SetRTCPStatus(kRtcpCompound));
|
EXPECT_EQ(0, module2->SetRTCPStatus(kRtcpCompound));
|
||||||
@ -161,6 +146,26 @@ TEST_F(RtpRtcpRtcpTest, RTCP) {
|
|||||||
const WebRtc_UWord8 test[9] = "testtest";
|
const WebRtc_UWord8 test[9] = "testtest";
|
||||||
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
|
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
|
||||||
0, test, 8));
|
0, test, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_id;
|
||||||
|
RtpRtcp* module1;
|
||||||
|
RtpRtcp* module2;
|
||||||
|
RtpReceiver* receiver;
|
||||||
|
LoopBackTransport* transport1;
|
||||||
|
LoopBackTransport* transport2;
|
||||||
|
WebRtc_UWord32 test_ssrc;
|
||||||
|
WebRtc_UWord32 test_timestamp;
|
||||||
|
WebRtc_UWord16 test_sequence_number;
|
||||||
|
WebRtc_UWord32 test_CSRC[webrtc::kRtpCsrcSize];
|
||||||
|
FakeRtpRtcpClock fake_clock;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(RtpRtcpRtcpTest, RTCP) {
|
||||||
|
RtcpCallback* myRTCPFeedback1 = new RtcpCallback(module1);
|
||||||
|
RtcpCallback* myRTCPFeedback2 = new RtcpCallback(module2);
|
||||||
|
|
||||||
|
SetUpCallFromModule1(myRTCPFeedback1, myRTCPFeedback2);
|
||||||
|
|
||||||
EXPECT_EQ(0, module1->SendRTCPReferencePictureSelection(kTestPictureId));
|
EXPECT_EQ(0, module1->SendRTCPReferencePictureSelection(kTestPictureId));
|
||||||
EXPECT_EQ(0, module1->SendRTCPSliceLossIndication(156));
|
EXPECT_EQ(0, module1->SendRTCPSliceLossIndication(156));
|
||||||
@ -237,10 +242,12 @@ TEST_F(RtpRtcpRtcpTest, RTCP) {
|
|||||||
EXPECT_EQ(0, strncmp(cName, "jane@192.168.0.2", RTCP_CNAME_SIZE));
|
EXPECT_EQ(0, strncmp(cName, "jane@192.168.0.2", RTCP_CNAME_SIZE));
|
||||||
|
|
||||||
// get all report blocks
|
// get all report blocks
|
||||||
RTCPReportBlock reportBlockReceived;
|
std::vector<RTCPReportBlock> report_blocks;
|
||||||
EXPECT_EQ(-1, module1->RemoteRTCPStat(test_ssrc, &reportBlockReceived));
|
EXPECT_EQ(-1, module1->RemoteRTCPStat(NULL));
|
||||||
EXPECT_EQ(-1, module1->RemoteRTCPStat(test_ssrc + 1, NULL));
|
EXPECT_EQ(0, module1->RemoteRTCPStat(&report_blocks));
|
||||||
EXPECT_EQ(0, module1->RemoteRTCPStat(test_ssrc + 1, &reportBlockReceived));
|
EXPECT_EQ(1u, report_blocks.size());
|
||||||
|
const RTCPReportBlock& reportBlockReceived = report_blocks[0];
|
||||||
|
|
||||||
float secSinceLastReport =
|
float secSinceLastReport =
|
||||||
static_cast<float>(reportBlockReceived.delaySinceLastSR) / 65536.0f;
|
static_cast<float>(reportBlockReceived.delaySinceLastSR) / 65536.0f;
|
||||||
EXPECT_GE(0.101f, secSinceLastReport);
|
EXPECT_GE(0.101f, secSinceLastReport);
|
||||||
@ -295,3 +302,32 @@ TEST_F(RtpRtcpRtcpTest, RTCP) {
|
|||||||
delete myRTCPFeedback1;
|
delete myRTCPFeedback1;
|
||||||
delete myRTCPFeedback2;
|
delete myRTCPFeedback2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RtpRtcpRtcpTest, RemoteRTCPStatRemote) {
|
||||||
|
std::vector<RTCPReportBlock> report_blocks;
|
||||||
|
|
||||||
|
RtcpCallback feedback1(module1);
|
||||||
|
RtcpCallback feedback2(module2);
|
||||||
|
|
||||||
|
SetUpCallFromModule1(&feedback1, &feedback2);
|
||||||
|
EXPECT_EQ(0, module1->RemoteRTCPStat(&report_blocks));
|
||||||
|
EXPECT_EQ(0u, report_blocks.size());
|
||||||
|
|
||||||
|
// send RTCP packet, triggered by timer
|
||||||
|
fake_clock.IncrementTime(7500);
|
||||||
|
module1->Process();
|
||||||
|
fake_clock.IncrementTime(100);
|
||||||
|
module2->Process();
|
||||||
|
|
||||||
|
EXPECT_EQ(0, module1->RemoteRTCPStat(&report_blocks));
|
||||||
|
ASSERT_EQ(1u, report_blocks.size());
|
||||||
|
|
||||||
|
// |test_ssrc+1| is the SSRC of module2 that send the report.
|
||||||
|
EXPECT_EQ(test_ssrc+1, report_blocks[0].remoteSSRC);
|
||||||
|
EXPECT_EQ(test_ssrc, report_blocks[0].sourceSSRC);
|
||||||
|
|
||||||
|
EXPECT_EQ(0u, report_blocks[0].cumulativeLost);
|
||||||
|
EXPECT_LT(0u, report_blocks[0].delaySinceLastSR);
|
||||||
|
EXPECT_EQ(test_sequence_number, report_blocks[0].extendedHighSeqNum);
|
||||||
|
EXPECT_EQ(0u, report_blocks[0].fractionLost);
|
||||||
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "video_engine/vie_channel.h"
|
#include "video_engine/vie_channel.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "modules/rtp_rtcp/interface/rtp_rtcp.h"
|
#include "modules/rtp_rtcp/interface/rtp_rtcp.h"
|
||||||
#include "modules/udp_transport/interface/udp_transport.h"
|
#include "modules/udp_transport/interface/udp_transport.h"
|
||||||
@ -941,16 +942,36 @@ WebRtc_Word32 ViEChannel::GetSendRtcpStatistics(WebRtc_UWord16& fraction_lost,
|
|||||||
// RtpRtcp* rtp_rtcp = *it;
|
// RtpRtcp* rtp_rtcp = *it;
|
||||||
// }
|
// }
|
||||||
WebRtc_UWord32 remoteSSRC = rtp_rtcp_.RemoteSSRC();
|
WebRtc_UWord32 remoteSSRC = rtp_rtcp_.RemoteSSRC();
|
||||||
RTCPReportBlock remote_stat;
|
|
||||||
if (rtp_rtcp_.RemoteRTCPStat(remoteSSRC, &remote_stat) != 0) {
|
// Get all RTCP receiver report blocks that have been received on this
|
||||||
|
// channel. If we receive RTP packets from a remote source we know the
|
||||||
|
// remote SSRC and use the report block from him.
|
||||||
|
// Otherwise use the first report block.
|
||||||
|
std::vector<RTCPReportBlock> remote_stats;
|
||||||
|
if (rtp_rtcp_.RemoteRTCPStat(&remote_stats) != 0 || remote_stats.empty()) {
|
||||||
WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
|
WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
|
||||||
"%s: Could not get remote stats", __FUNCTION__);
|
"%s: Could not get remote stats", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fraction_lost = remote_stat.fractionLost;
|
std::vector<RTCPReportBlock>::const_iterator statistics =
|
||||||
cumulative_lost = remote_stat.cumulativeLost;
|
remote_stats.begin();
|
||||||
extended_max = remote_stat.extendedHighSeqNum;
|
for (; statistics != remote_stats.end(); ++statistics) {
|
||||||
jitter_samples = remote_stat.jitter;
|
if (statistics->remoteSSRC == remoteSSRC)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statistics == remote_stats.end()) {
|
||||||
|
// If we have not received any RTCP packets from this SSRC it probably means
|
||||||
|
// we have not received any RTP packets.
|
||||||
|
// Use the first received report block instead.
|
||||||
|
statistics = remote_stats.begin();
|
||||||
|
remoteSSRC = statistics->remoteSSRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
fraction_lost = statistics->fractionLost;
|
||||||
|
cumulative_lost = statistics->cumulativeLost;
|
||||||
|
extended_max = statistics->extendedHighSeqNum;
|
||||||
|
jitter_samples = statistics->jitter;
|
||||||
|
|
||||||
WebRtc_UWord16 dummy;
|
WebRtc_UWord16 dummy;
|
||||||
WebRtc_UWord16 rtt = 0;
|
WebRtc_UWord16 rtt = 0;
|
||||||
|
@ -5330,40 +5330,46 @@ Channel::GetRemoteRTCPData(
|
|||||||
|
|
||||||
if (NULL != jitter || NULL != fractionLost)
|
if (NULL != jitter || NULL != fractionLost)
|
||||||
{
|
{
|
||||||
WebRtc_Word32 ret(-1);
|
// Get all RTCP receiver report blocks that have been received on this
|
||||||
RTCPReportBlock reportBlock;
|
// channel. If we receive RTP packets from a remote source we know the
|
||||||
WebRtc_Word32 remoteSSRC = _rtpRtcpModule.RemoteSSRC();
|
// remote SSRC and use the report block from him.
|
||||||
if (remoteSSRC > 0)
|
// Otherwise use the first report block.
|
||||||
{
|
std::vector<RTCPReportBlock> remote_stats;
|
||||||
// We must feed the module with remote SSRC to get the correct
|
if (_rtpRtcpModule.RemoteRTCPStat(&remote_stats) != 0 ||
|
||||||
// report block.
|
remote_stats.empty()) {
|
||||||
ret = _rtpRtcpModule.RemoteRTCPStat(remoteSSRC, &reportBlock);
|
|
||||||
}
|
|
||||||
if ((remoteSSRC < 0) || (ret != 0))
|
|
||||||
{
|
|
||||||
reportBlock.jitter = 0;
|
|
||||||
reportBlock.fractionLost = 0;
|
|
||||||
WEBRTC_TRACE(kTraceWarning, kTraceVoice,
|
WEBRTC_TRACE(kTraceWarning, kTraceVoice,
|
||||||
VoEId(_instanceId, _channelId),
|
VoEId(_instanceId, _channelId),
|
||||||
"GetRemoteRTCPData() failed to measure statistics due"
|
"GetRemoteRTCPData() failed to measure statistics due"
|
||||||
" to lack of received RTP and/or RTCP packets");
|
" to lack of received RTP and/or RTCP packets");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if (NULL != jitter)
|
|
||||||
{
|
WebRtc_UWord32 remoteSSRC = _rtpRtcpModule.RemoteSSRC();
|
||||||
*jitter = reportBlock.jitter;
|
std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin();
|
||||||
|
for (; it != remote_stats.end(); ++it) {
|
||||||
|
if (it->remoteSSRC == remoteSSRC)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it == remote_stats.end()) {
|
||||||
|
// If we have not received any RTCP packets from this SSRC it probably
|
||||||
|
// means that we have not received any RTP packets.
|
||||||
|
// Use the first received report block instead.
|
||||||
|
it = remote_stats.begin();
|
||||||
|
remoteSSRC = it->remoteSSRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
*jitter = it->jitter;
|
||||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
|
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
|
||||||
VoEId(_instanceId, _channelId),
|
VoEId(_instanceId, _channelId),
|
||||||
"GetRemoteRTCPData() => jitter = %lu", *jitter);
|
"GetRemoteRTCPData() => jitter = %lu", *jitter);
|
||||||
}
|
|
||||||
if (NULL != fractionLost)
|
*fractionLost = it->fractionLost;
|
||||||
{
|
|
||||||
*fractionLost = reportBlock.fractionLost;
|
|
||||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
|
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
|
||||||
VoEId(_instanceId, _channelId),
|
VoEId(_instanceId, _channelId),
|
||||||
"GetRemoteRTCPData() => fractionLost = %lu",
|
"GetRemoteRTCPData() => fractionLost = %lu",
|
||||||
*fractionLost);
|
*fractionLost);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user