"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_
|
||||
#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "module.h"
|
||||
#include "rtp_rtcp_defines.h"
|
||||
|
||||
@ -747,14 +749,15 @@ public:
|
||||
*
|
||||
* return -1 on failure else 0
|
||||
*/
|
||||
virtual WebRtc_Word32 RemoteRTCPStat( const WebRtc_UWord32 remoteSSRC,
|
||||
RTCPReportBlock* receiveBlock) = 0;
|
||||
virtual WebRtc_Word32 RemoteRTCPStat(
|
||||
std::vector<RTCPReportBlock>* receiveBlocks) const = 0;
|
||||
/*
|
||||
* Set received RTCP report block
|
||||
*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
|
@ -109,6 +109,9 @@ struct RTCPSenderInfo
|
||||
|
||||
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_UWord32 cumulativeLost; // 24 bits valid
|
||||
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));
|
||||
MOCK_METHOD1(RemoteRTCPStat,
|
||||
WebRtc_Word32(RTCPSenderInfo* senderInfo));
|
||||
MOCK_METHOD2(RemoteRTCPStat,
|
||||
WebRtc_Word32(const WebRtc_UWord32 remoteSSRC, RTCPReportBlock* receiveBlock));
|
||||
MOCK_CONST_METHOD1(RemoteRTCPStat,
|
||||
WebRtc_Word32(std::vector<RTCPReportBlock>* receiveBlocks));
|
||||
MOCK_METHOD2(AddRTCPReportBlock,
|
||||
WebRtc_Word32(const WebRtc_UWord32 SSRC, const RTCPReportBlock* receiveBlock));
|
||||
MOCK_METHOD1(RemoveRTCPReportBlock,
|
||||
|
@ -179,14 +179,13 @@ RTCPReceiver::SetSSRC( const WebRtc_UWord32 ssrc)
|
||||
_SSRC = ssrc;
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
RTCPReceiver::ResetRTT(const WebRtc_UWord32 remoteSSRC)
|
||||
{
|
||||
WebRtc_Word32 RTCPReceiver::ResetRTT(const WebRtc_UWord32 remoteSSRC) {
|
||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||
RTCPReportBlockInformation* reportBlock = GetReportBlockInformation(remoteSSRC);
|
||||
if(reportBlock == NULL)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "\tfailed to GetReportBlockInformation(%d)", remoteSSRC);
|
||||
RTCPReportBlockInformation* reportBlock =
|
||||
GetReportBlockInformation(remoteSSRC);
|
||||
if (reportBlock == NULL) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||
"\tfailed to GetReportBlockInformation(%u)", remoteSSRC);
|
||||
return -1;
|
||||
}
|
||||
reportBlock->RTT = 0;
|
||||
@ -197,35 +196,32 @@ RTCPReceiver::ResetRTT(const WebRtc_UWord32 remoteSSRC)
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
RTCPReceiver::RTT(const WebRtc_UWord32 remoteSSRC,
|
||||
WebRtc_Word32 RTCPReceiver::RTT(const WebRtc_UWord32 remoteSSRC,
|
||||
WebRtc_UWord16* RTT,
|
||||
WebRtc_UWord16* avgRTT,
|
||||
WebRtc_UWord16* minRTT,
|
||||
WebRtc_UWord16* maxRTT) const
|
||||
|
||||
{
|
||||
WebRtc_UWord16* maxRTT) const {
|
||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||
RTCPReportBlockInformation* reportBlock = GetReportBlockInformation(remoteSSRC);
|
||||
if(reportBlock == NULL)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "\tfailed to GetReportBlockInformation(%d)", remoteSSRC);
|
||||
|
||||
RTCPReportBlockInformation* reportBlock =
|
||||
GetReportBlockInformation(remoteSSRC);
|
||||
|
||||
if (reportBlock == NULL) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||
"\tfailed to GetReportBlockInformation(%u)",
|
||||
remoteSSRC);
|
||||
return -1;
|
||||
}
|
||||
if(RTT)
|
||||
{
|
||||
if (RTT) {
|
||||
*RTT = reportBlock->RTT;
|
||||
}
|
||||
if(avgRTT)
|
||||
{
|
||||
if (avgRTT) {
|
||||
*avgRTT = reportBlock->avgRTT;
|
||||
}
|
||||
if(minRTT)
|
||||
{
|
||||
if (minRTT) {
|
||||
*minRTT = reportBlock->minRTT;
|
||||
}
|
||||
if(maxRTT)
|
||||
{
|
||||
if (maxRTT) {
|
||||
*maxRTT = reportBlock->maxRTT;
|
||||
}
|
||||
return 0;
|
||||
@ -287,23 +283,24 @@ RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const
|
||||
|
||||
// statistics
|
||||
// we can get multiple receive reports when we receive the report from a CE
|
||||
WebRtc_Word32
|
||||
RTCPReceiver::StatisticsReceived(const WebRtc_UWord32 remoteSSRC,
|
||||
RTCPReportBlock* receiveBlock) const
|
||||
{
|
||||
if(receiveBlock == NULL)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
|
||||
WebRtc_Word32 RTCPReceiver::StatisticsReceived(
|
||||
std::vector<RTCPReportBlock>* receiveBlocks) const {
|
||||
if (receiveBlocks == NULL) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument",
|
||||
__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||
RTCPReportBlockInformation* reportBlockInfo = GetReportBlockInformation(remoteSSRC);
|
||||
if(reportBlockInfo == NULL)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "\tfailed to GetReportBlockInformation(%d)", remoteSSRC);
|
||||
return -1;
|
||||
|
||||
MapItem* ptrReportBlockInfoItem = _receivedReportBlockMap.First();
|
||||
while (ptrReportBlockInfoItem != NULL) {
|
||||
RTCPReportBlockInformation* item =
|
||||
static_cast<RTCPReportBlockInformation*> (
|
||||
ptrReportBlockInfoItem->GetItem());
|
||||
receiveBlocks->push_back(item->remoteReceiveBlock);
|
||||
ptrReportBlockInfoItem =
|
||||
_receivedReportBlockMap.Next(ptrReportBlockInfoItem);
|
||||
}
|
||||
memcpy(receiveBlock, &(reportBlockInfo->remoteReceiveBlock), sizeof(RTCPReportBlock));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -459,71 +456,55 @@ void
|
||||
RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
||||
RTCPPacketInformation& rtcpPacketInformation,
|
||||
const WebRtc_UWord32 remoteSSRC,
|
||||
const WebRtc_UWord8 numberOfReportBlocks)
|
||||
{
|
||||
// this will be called once per report block in the RTCP packet
|
||||
// we store all incoming reports
|
||||
// each packet has max 31 RR blocks
|
||||
const WebRtc_UWord8 numberOfReportBlocks) {
|
||||
// This will be called once per report block in the RTCP packet.
|
||||
// We filter out all report blocks that are not for us.
|
||||
// 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
|
||||
The SSRC identifier of the source to which the information in this
|
||||
reception report block pertains.
|
||||
*/
|
||||
// |rtcpPacket.ReportBlockItem.SSRC| is 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
|
||||
if( _SSRC &&
|
||||
numberOfReportBlocks > 1)
|
||||
{
|
||||
// we have more than one reportBlock in the RTCP packet
|
||||
if(rtcpPacket.ReportBlockItem.SSRC != _SSRC)
|
||||
{
|
||||
// this block is not for us ignore it
|
||||
// Filter out all report blocks that are not for us.
|
||||
if (rtcpPacket.ReportBlockItem.SSRC != _SSRC) {
|
||||
// This block is not for us ignore it.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// To avoid problem with acquiring _criticalSectionRTCPSender while holding
|
||||
// _criticalSectionRTCPReceiver.
|
||||
_criticalSectionRTCPReceiver->Leave();
|
||||
// to avoid problem with accuireing _criticalSectionRTCPSender while holding _criticalSectionRTCPReceiver
|
||||
|
||||
WebRtc_UWord32 sendTimeMS =
|
||||
_rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
|
||||
|
||||
_criticalSectionRTCPReceiver->Enter();
|
||||
|
||||
// ReportBlockItem.SSRC is who it's to
|
||||
// we store all incoming reports, used in conference relay
|
||||
|
||||
RTCPReportBlockInformation* reportBlock = CreateReportBlockInformation(remoteSSRC);
|
||||
if(reportBlock == NULL)
|
||||
{
|
||||
RTCPReportBlockInformation* reportBlock =
|
||||
CreateReportBlockInformation(remoteSSRC);
|
||||
if (reportBlock == NULL) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||
"\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
|
||||
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;
|
||||
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)
|
||||
{
|
||||
if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
|
||||
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
|
||||
WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
|
||||
WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
|
||||
@ -531,7 +512,8 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
||||
_clock.CurrentNTP(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
|
||||
|
||||
// time when we received this in MS
|
||||
WebRtc_UWord32 receiveTimeMS = ModuleRTPUtility::ConvertNTPTimeToMS(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
|
||||
WebRtc_UWord32 receiveTimeMS = ModuleRTPUtility::ConvertNTPTimeToMS(
|
||||
lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
|
||||
|
||||
// Estimate RTT
|
||||
WebRtc_UWord32 d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
|
||||
@ -540,24 +522,19 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
||||
|
||||
WebRtc_Word32 RTT = 0;
|
||||
|
||||
if(sendTimeMS > 0)
|
||||
{
|
||||
if (sendTimeMS > 0) {
|
||||
RTT = receiveTimeMS - d - sendTimeMS;
|
||||
if( RTT <= 0)
|
||||
{
|
||||
if (RTT <= 0) {
|
||||
RTT = 1;
|
||||
}
|
||||
if (RTT > reportBlock->maxRTT)
|
||||
{
|
||||
if (RTT > reportBlock->maxRTT) {
|
||||
// store max RTT
|
||||
reportBlock->maxRTT = (WebRtc_UWord16) RTT;
|
||||
}
|
||||
if(reportBlock->minRTT == 0)
|
||||
{
|
||||
if (reportBlock->minRTT == 0) {
|
||||
// first RTT
|
||||
reportBlock->minRTT = (WebRtc_UWord16) RTT;
|
||||
}else if (RTT < reportBlock->minRTT)
|
||||
{
|
||||
} else if (RTT < reportBlock->minRTT) {
|
||||
// Store min RTT
|
||||
reportBlock->minRTT = (WebRtc_UWord16) RTT;
|
||||
}
|
||||
@ -565,13 +542,12 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
||||
reportBlock->RTT = (WebRtc_UWord16) RTT;
|
||||
|
||||
// store average RTT
|
||||
if(reportBlock->numAverageCalcs != 0)
|
||||
{
|
||||
if (reportBlock->numAverageCalcs != 0) {
|
||||
float ac = static_cast<float> (reportBlock->numAverageCalcs);
|
||||
float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT) + ((1 / (ac + 1)) * RTT);
|
||||
float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
|
||||
+ ((1 / (ac + 1)) * RTT);
|
||||
reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
// first RTT
|
||||
reportBlock->avgRTT = (WebRtc_UWord16) RTT;
|
||||
}
|
||||
@ -579,16 +555,15 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
|
||||
}
|
||||
|
||||
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.AddReportInfo(reportBlock->remoteReceiveBlock.fractionLost,
|
||||
(WebRtc_UWord16)RTT,
|
||||
rtcpPacketInformation.AddReportInfo(
|
||||
reportBlock->remoteReceiveBlock.fractionLost, (WebRtc_UWord16) RTT,
|
||||
reportBlock->remoteReceiveBlock.extendedHighSeqNum,
|
||||
reportBlock->remoteReceiveBlock.jitter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RTCPReportBlockInformation*
|
||||
RTCPReceiver::CreateReportBlockInformation(WebRtc_UWord32 remoteSSRC)
|
||||
|
@ -11,6 +11,8 @@
|
||||
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_
|
||||
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "map_wrapper.h"
|
||||
#include "rtp_utility.h"
|
||||
@ -81,8 +83,9 @@ public:
|
||||
const WebRtc_UWord64 pitureID) const;
|
||||
|
||||
// get statistics
|
||||
WebRtc_Word32 StatisticsReceived(const WebRtc_UWord32 remoteSSRC,
|
||||
RTCPReportBlock* receiveBlock) const;
|
||||
WebRtc_Word32 StatisticsReceived(
|
||||
std::vector<RTCPReportBlock>* receiveBlocks) const;
|
||||
|
||||
// Get TMMBR
|
||||
WebRtc_Word32 TMMBRReceived(const WebRtc_UWord32 size,
|
||||
const WebRtc_UWord32 accNumCandidates,
|
||||
|
@ -1738,13 +1738,11 @@ WebRtc_Word32 ModuleRtpRtcpImpl::RemoteRTCPStat( RTCPSenderInfo* senderInfo)
|
||||
}
|
||||
|
||||
// received RTCP report
|
||||
WebRtc_Word32
|
||||
ModuleRtpRtcpImpl::RemoteRTCPStat(const WebRtc_UWord32 remoteSSRC,
|
||||
RTCPReportBlock* receiveBlock)
|
||||
{
|
||||
WebRtc_Word32 ModuleRtpRtcpImpl::RemoteRTCPStat(
|
||||
std::vector<RTCPReportBlock>* receiveBlocks) const {
|
||||
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteRTCPStat()");
|
||||
|
||||
return _rtcpReceiver.StatisticsReceived(remoteSSRC, receiveBlock);
|
||||
return _rtcpReceiver.StatisticsReceived(receiveBlocks);
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
|
@ -316,8 +316,8 @@ public:
|
||||
virtual WebRtc_Word32 RemoteRTCPStat( RTCPSenderInfo* senderInfo);
|
||||
|
||||
// Get received RTCP report, report block
|
||||
virtual WebRtc_Word32 RemoteRTCPStat( const WebRtc_UWord32 remoteSSRC,
|
||||
RTCPReportBlock* receiveBlock);
|
||||
virtual WebRtc_Word32 RemoteRTCPStat(
|
||||
std::vector<RTCPReportBlock>* receiveBlocks) const;
|
||||
|
||||
// Set received RTCP report block
|
||||
virtual WebRtc_Word32 AddRTCPReportBlock(const WebRtc_UWord32 SSRC,
|
||||
|
@ -113,24 +113,9 @@ class RtpRtcpRtcpTest : public ::testing::Test {
|
||||
delete receiver;
|
||||
}
|
||||
|
||||
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);
|
||||
EXPECT_EQ(0, module1->RegisterIncomingRTCPCallback(myRTCPFeedback1));
|
||||
EXPECT_EQ(0, module2->RegisterIncomingRTCPCallback(myRTCPFeedback2));
|
||||
void SetUpCallFromModule1(RtcpCallback* feedback1, RtcpCallback* feedback2 ) {
|
||||
EXPECT_EQ(0, module1->RegisterIncomingRTCPCallback(feedback1));
|
||||
EXPECT_EQ(0, module2->RegisterIncomingRTCPCallback(feedback2));
|
||||
|
||||
EXPECT_EQ(0, module1->SetRTCPStatus(kRtcpCompound));
|
||||
EXPECT_EQ(0, module2->SetRTCPStatus(kRtcpCompound));
|
||||
@ -161,6 +146,26 @@ TEST_F(RtpRtcpRtcpTest, RTCP) {
|
||||
const WebRtc_UWord8 test[9] = "testtest";
|
||||
EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
|
||||
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->SendRTCPSliceLossIndication(156));
|
||||
@ -237,10 +242,12 @@ TEST_F(RtpRtcpRtcpTest, RTCP) {
|
||||
EXPECT_EQ(0, strncmp(cName, "jane@192.168.0.2", RTCP_CNAME_SIZE));
|
||||
|
||||
// get all report blocks
|
||||
RTCPReportBlock reportBlockReceived;
|
||||
EXPECT_EQ(-1, module1->RemoteRTCPStat(test_ssrc, &reportBlockReceived));
|
||||
EXPECT_EQ(-1, module1->RemoteRTCPStat(test_ssrc + 1, NULL));
|
||||
EXPECT_EQ(0, module1->RemoteRTCPStat(test_ssrc + 1, &reportBlockReceived));
|
||||
std::vector<RTCPReportBlock> report_blocks;
|
||||
EXPECT_EQ(-1, module1->RemoteRTCPStat(NULL));
|
||||
EXPECT_EQ(0, module1->RemoteRTCPStat(&report_blocks));
|
||||
EXPECT_EQ(1u, report_blocks.size());
|
||||
const RTCPReportBlock& reportBlockReceived = report_blocks[0];
|
||||
|
||||
float secSinceLastReport =
|
||||
static_cast<float>(reportBlockReceived.delaySinceLastSR) / 65536.0f;
|
||||
EXPECT_GE(0.101f, secSinceLastReport);
|
||||
@ -295,3 +302,32 @@ TEST_F(RtpRtcpRtcpTest, RTCP) {
|
||||
delete myRTCPFeedback1;
|
||||
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 <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "modules/rtp_rtcp/interface/rtp_rtcp.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;
|
||||
// }
|
||||
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_),
|
||||
"%s: Could not get remote stats", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
fraction_lost = remote_stat.fractionLost;
|
||||
cumulative_lost = remote_stat.cumulativeLost;
|
||||
extended_max = remote_stat.extendedHighSeqNum;
|
||||
jitter_samples = remote_stat.jitter;
|
||||
std::vector<RTCPReportBlock>::const_iterator statistics =
|
||||
remote_stats.begin();
|
||||
for (; statistics != remote_stats.end(); ++statistics) {
|
||||
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 rtt = 0;
|
||||
|
@ -5330,40 +5330,46 @@ Channel::GetRemoteRTCPData(
|
||||
|
||||
if (NULL != jitter || NULL != fractionLost)
|
||||
{
|
||||
WebRtc_Word32 ret(-1);
|
||||
RTCPReportBlock reportBlock;
|
||||
WebRtc_Word32 remoteSSRC = _rtpRtcpModule.RemoteSSRC();
|
||||
if (remoteSSRC > 0)
|
||||
{
|
||||
// We must feed the module with remote SSRC to get the correct
|
||||
// report block.
|
||||
ret = _rtpRtcpModule.RemoteRTCPStat(remoteSSRC, &reportBlock);
|
||||
}
|
||||
if ((remoteSSRC < 0) || (ret != 0))
|
||||
{
|
||||
reportBlock.jitter = 0;
|
||||
reportBlock.fractionLost = 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 (_rtpRtcpModule.RemoteRTCPStat(&remote_stats) != 0 ||
|
||||
remote_stats.empty()) {
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceVoice,
|
||||
VoEId(_instanceId, _channelId),
|
||||
"GetRemoteRTCPData() failed to measure statistics due"
|
||||
" to lack of received RTP and/or RTCP packets");
|
||||
return -1;
|
||||
}
|
||||
if (NULL != jitter)
|
||||
{
|
||||
*jitter = reportBlock.jitter;
|
||||
|
||||
WebRtc_UWord32 remoteSSRC = _rtpRtcpModule.RemoteSSRC();
|
||||
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,
|
||||
VoEId(_instanceId, _channelId),
|
||||
"GetRemoteRTCPData() => jitter = %lu", *jitter);
|
||||
}
|
||||
if (NULL != fractionLost)
|
||||
{
|
||||
*fractionLost = reportBlock.fractionLost;
|
||||
|
||||
*fractionLost = it->fractionLost;
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
|
||||
VoEId(_instanceId, _channelId),
|
||||
"GetRemoteRTCPData() => fractionLost = %lu",
|
||||
*fractionLost);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user