Bug 970686: Outbound getStats: Fixed RTCP timestamps and remote packets/bytes received. r=jesup

This commit is contained in:
Jan-Ivar Bruaroey 2014-03-14 14:34:02 -04:00
parent 6c8846b330
commit 3ffe31d869
27 changed files with 483 additions and 235 deletions

View File

@ -1594,8 +1594,8 @@ PeerConnectionWrapper.prototype = {
var res = stats[key];
// validate stats
ok(res.id == key, "Coherent stats id");
var nowish = Date.now() + 10000; // TODO: severe drift observed
var minimum = this.whenCreated - 10000; // on Windows XP (Bug 979649)
var nowish = Date.now() + 1000; // TODO: clock drift observed
var minimum = this.whenCreated - 1000; // on Windows XP (Bug 979649)
ok(res.timestamp >= minimum,
"Valid " + (res.isRemote? "rtcp" : "rtp") + " timestamp " +
res.timestamp + " >= " + minimum + " (" +
@ -1631,12 +1631,10 @@ PeerConnectionWrapper.prototype = {
if(res.type == "outboundrtp") {
ok(rem.type == "inboundrtp", "Rtcp is inbound");
ok(rem.packetsReceived !== undefined, "Rtcp packetsReceived");
// TODO: Re-enable once Bug 980497 is fixed
// ok(rem.packetsReceived <= res.packetsSent, "No more than sent");
ok(rem.packetsReceived <= res.packetsSent, "No more than sent");
ok(rem.packetsLost !== undefined, "Rtcp packetsLost");
ok(rem.bytesReceived >= rem.packetsReceived * 8, "Rtcp bytesReceived");
// TODO: Re-enable once Bug 980497 is fixed
// ok(rem.bytesReceived <= res.bytesSent, "No more than sent bytes");
ok(rem.bytesReceived <= res.bytesSent, "No more than sent bytes");
ok(rem.jitter !== undefined, "Rtcp jitter");
} else {
ok(rem.type == "outboundrtp", "Rtcp is outbound");

View File

@ -40,6 +40,7 @@ dictionary RTCInboundRTPStreamStats : RTCRTPStreamStats {
unsigned long packetsLost;
long mozAvSyncDelay;
long mozJitterBufferDelay;
long mozRtt;
};
dictionary RTCOutboundRTPStreamStats : RTCRTPStreamStats {
@ -58,7 +59,6 @@ dictionary RTCMediaStreamTrackStats : RTCStats {
unsigned long framesSent;
unsigned long framesReceived; // Only for remoteSource=true
unsigned long framesDecoded;
unsigned long first;
};
dictionary RTCMediaStreamStats : RTCStats {

View File

@ -153,26 +153,22 @@ NTPtoDOMHighResTimeStamp(uint32_t ntpHigh, uint32_t ntpLow) {
}
bool WebrtcAudioConduit::GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
unsigned int* jitterMs,
unsigned int* packetsReceived,
uint32_t* jitterMs,
uint32_t* packetsReceived,
uint64_t* bytesReceived,
unsigned int *cumulativeLost) {
unsigned int ntpHigh, ntpLow;
unsigned int rtpTimestamp, playoutTimestamp;
unsigned int packetsSent;
unsigned int bytesSent32;
unsigned short fractionLost;
bool result = !mPtrRTP->GetRemoteRTCPData(mChannel, ntpHigh, ntpLow,
rtpTimestamp, playoutTimestamp,
packetsSent, bytesSent32,
jitterMs,
&fractionLost, cumulativeLost);
uint32_t* cumulativeLost,
int32_t* rttMs) {
uint32_t ntpHigh, ntpLow;
uint16_t fractionLost;
bool result = !mPtrRTP->GetRemoteRTCPReceiverInfo(mChannel, ntpHigh, ntpLow,
*packetsReceived,
*bytesReceived,
*jitterMs,
fractionLost,
*cumulativeLost,
*rttMs);
if (result) {
*timestamp = NTPtoDOMHighResTimeStamp(ntpHigh, ntpLow);
*packetsReceived = (packetsSent >= *cumulativeLost) ?
(packetsSent - *cumulativeLost) : 0;
*bytesReceived = (packetsSent ?
(bytesSent32 / packetsSent) : 0) * (*packetsReceived);
}
return result;
}
@ -180,18 +176,13 @@ bool WebrtcAudioConduit::GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
bool WebrtcAudioConduit::GetRTCPSenderReport(DOMHighResTimeStamp* timestamp,
unsigned int* packetsSent,
uint64_t* bytesSent) {
unsigned int ntpHigh, ntpLow;
unsigned int rtpTimestamp, playoutTimestamp;
unsigned int bytesSent32;
unsigned int jitterMs;
unsigned short fractionLost;
bool result = !mPtrRTP->GetRemoteRTCPData(mChannel, ntpHigh, ntpLow,
rtpTimestamp, playoutTimestamp,
*packetsSent, bytesSent32,
&jitterMs, &fractionLost);
struct webrtc::SenderInfo senderInfo;
bool result = !mPtrRTP->GetRemoteRTCPSenderInfo(mChannel, &senderInfo);
if (result) {
*timestamp = NTPtoDOMHighResTimeStamp(ntpHigh, ntpLow);
*bytesSent = bytesSent32;
*timestamp = NTPtoDOMHighResTimeStamp(senderInfo.NTP_timestamp_high,
senderInfo.NTP_timestamp_low);
*packetsSent = senderInfo.sender_packet_count;
*bytesSent = senderInfo.sender_octet_count;
}
return result;
}

View File

@ -185,10 +185,11 @@ public:
int32_t* avSyncOffsetMs);
bool GetRTPStats(unsigned int* jitterMs, unsigned int* cumulativeLost);
bool GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
unsigned int* jitterMs,
unsigned int* packetsReceived,
uint32_t* jitterMs,
uint32_t* packetsReceived,
uint64_t* bytesReceived,
unsigned int *cumulativeLost);
uint32_t *cumulativeLost,
int32_t* rttMs);
bool GetRTCPSenderReport(DOMHighResTimeStamp* timestamp,
unsigned int* packetsSent,
uint64_t* bytesSent);

View File

@ -149,10 +149,11 @@ public:
virtual bool GetRTPStats(unsigned int* jitterMs,
unsigned int* cumulativeLost) = 0;
virtual bool GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
unsigned int* jitterMs,
unsigned int* packetsReceived,
uint32_t* jitterMs,
uint32_t* packetsReceived,
uint64_t* bytesReceived,
unsigned int* cumulativeLost) = 0;
uint32_t* cumulativeLost,
int32_t* rttMs) = 0;
virtual bool GetRTCPSenderReport(DOMHighResTimeStamp* timestamp,
unsigned int* packetsSent,
uint64_t* bytesSent) = 0;

View File

@ -157,29 +157,22 @@ bool WebrtcVideoConduit::GetRTPStats(unsigned int* jitterMs,
}
bool WebrtcVideoConduit::GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
unsigned int* jitterMs,
unsigned int* packetsReceived,
uint32_t* jitterMs,
uint32_t* packetsReceived,
uint64_t* bytesReceived,
unsigned int* cumulativeLost) {
unsigned int ntpHigh, ntpLow;
unsigned int packetsSent;
unsigned int bytesSent32;
unsigned short fractionLost;
unsigned extendedMax;
int rttMs;
bool result = !mPtrRTP->GetSentRTCPStatistics(mChannel, ntpHigh, ntpLow,
bytesSent32, packetsSent,
fractionLost,
*cumulativeLost,
extendedMax,
*jitterMs,
rttMs);
uint32_t* cumulativeLost,
int32_t* rttMs) {
uint32_t ntpHigh, ntpLow;
uint16_t fractionLost;
bool result = !mPtrRTP->GetRemoteRTCPReceiverInfo(mChannel, ntpHigh, ntpLow,
*packetsReceived,
*bytesReceived,
jitterMs,
&fractionLost,
cumulativeLost,
rttMs);
if (result) {
*timestamp = NTPtoDOMHighResTimeStamp(ntpHigh, ntpLow);
*packetsReceived = (packetsSent >= *cumulativeLost) ?
(packetsSent - *cumulativeLost) : 0;
*bytesReceived = (packetsSent ?
(bytesSent32 / packetsSent) : 0) * (*packetsReceived);
}
return result;
}
@ -187,22 +180,13 @@ bool WebrtcVideoConduit::GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
bool WebrtcVideoConduit::GetRTCPSenderReport(DOMHighResTimeStamp* timestamp,
unsigned int* packetsSent,
uint64_t* bytesSent) {
unsigned int ntpHigh, ntpLow;
unsigned int bytesSent32;
unsigned int jitterMs;
unsigned short fractionLost;
unsigned int cumulativeLost;
unsigned extendedMax;
int rttMs;
bool result = !mPtrRTP->GetReceivedRTCPStatistics(mChannel, ntpHigh, ntpLow,
bytesSent32, *packetsSent,
fractionLost,
cumulativeLost,
jitterMs, extendedMax,
rttMs);
struct webrtc::SenderInfo senderInfo;
bool result = !mPtrRTP->GetRemoteRTCPSenderInfo(mChannel, &senderInfo);
if (result) {
*timestamp = NTPtoDOMHighResTimeStamp(ntpHigh, ntpLow);
*bytesSent = bytesSent32;
*timestamp = NTPtoDOMHighResTimeStamp(senderInfo.NTP_timestamp_high,
senderInfo.NTP_timestamp_low);
*packetsSent = senderInfo.sender_packet_count;
*bytesSent = senderInfo.sender_octet_count;
}
return result;
}

View File

@ -210,10 +210,11 @@ public:
int32_t* avSyncOffsetMs);
bool GetRTPStats(unsigned int* jitterMs, unsigned int* cumulativeLost);
bool GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
unsigned int* jitterMs,
unsigned int* packetsReceived,
uint32_t* jitterMs,
uint32_t* packetsReceived,
uint64_t* bytesReceived,
unsigned int* cumulativeLost);
uint32_t* cumulativeLost,
int32_t* rttMs);
bool GetRTCPSenderReport(DOMHighResTimeStamp* timestamp,
unsigned int* packetsSent,
uint64_t* bytesSent);

View File

@ -2164,10 +2164,12 @@ PeerConnectionImpl::ExecuteStatsQuery_s(RTCStatsQuery *query) {
uint32_t packetsReceived;
uint64_t bytesReceived;
uint32_t packetsLost;
int32_t rtt;
if (mp.Conduit()->GetRTCPReceiverReport(&timestamp, &jitterMs,
&packetsReceived,
&bytesReceived,
&packetsLost)) {
&packetsLost,
&rtt)) {
remoteId = NS_LITERAL_STRING("outbound_rtcp_") + idstr;
RTCInboundRTPStreamStats s;
s.mTimestamp.Construct(timestamp);
@ -2182,6 +2184,7 @@ PeerConnectionImpl::ExecuteStatsQuery_s(RTCStatsQuery *query) {
s.mPacketsReceived.Construct(packetsReceived);
s.mBytesReceived.Construct(bytesReceived);
s.mPacketsLost.Construct(packetsLost);
s.mMozRtt.Construct(rtt);
query->report.mInboundRTPStreamStats.Value().AppendElement(s);
}
}

View File

@ -424,6 +424,17 @@ class RtpRtcp : public Module {
*/
virtual void SetRtt(uint32_t rtt) = 0;
/*
* Get time of last rr, as well as packets received remotely
* (derived from rr report + cached sender-side info).
*
* return -1 on failure else 0
*/
virtual int32_t GetReportBlockInfo(const uint32_t remote_ssrc,
uint32_t* ntp_high,
uint32_t* ntp_low,
uint32_t* packets_received,
uint64_t* octets_received) const = 0;
/*
* Force a send of a RTCP packet
* normal SR and RR are triggered via the process function

View File

@ -234,6 +234,27 @@ int RTCPReceiver::SetRTT(uint16_t rtt) {
return 0;
}
int32_t RTCPReceiver::GetReportBlockInfo(uint32_t remoteSSRC,
uint32_t* NTPHigh,
uint32_t* NTPLow,
uint32_t* PacketsReceived,
uint64_t* OctetsReceived) const
{
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
RTCPReportBlockInformation* reportBlock =
GetReportBlockInformation(remoteSSRC);
if (reportBlock == NULL) {
return -1;
}
*NTPHigh = reportBlock->lastReceivedRRNTPsecs;
*NTPLow = reportBlock->lastReceivedRRNTPfrac;
*PacketsReceived = reportBlock->remotePacketsReceived;
*OctetsReceived = reportBlock->remoteOctetsReceived;
return 0;
}
int32_t
RTCPReceiver::NTP(uint32_t *ReceivedNTPsecs,
uint32_t *ReceivedNTPfrac,
@ -477,8 +498,11 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
// To avoid problem with acquiring _criticalSectionRTCPSender while holding
// _criticalSectionRTCPReceiver.
_criticalSectionRTCPReceiver->Leave();
uint32_t sendTimeMS =
_rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
uint32_t sendTimeMS = 0;
uint32_t sentPackets = 0;
uint64_t sentOctets = 0;
_rtpRtcp.GetSendReportMetadata(rtcpPacket.ReportBlockItem.LastSR,
&sendTimeMS, &sentPackets, &sentOctets);
_criticalSectionRTCPReceiver->Enter();
RTCPReportBlockInformation* reportBlock =
@ -496,6 +520,12 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
reportBlock->remoteReceiveBlock.cumulativeLost =
rb.CumulativeNumOfPacketsLost;
if (sentPackets > rb.CumulativeNumOfPacketsLost) {
uint32_t packetsReceived = sentPackets - rb.CumulativeNumOfPacketsLost;
reportBlock->remotePacketsReceived = packetsReceived;
reportBlock->remoteOctetsReceived = (sentOctets / sentPackets) *
packetsReceived;
}
if (rb.ExtendedHighestSequenceNumber >
reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
// We have successfully delivered new RTP packets to the remote side after
@ -516,14 +546,15 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
rtcpPacket.ReportBlockItem.DelayLastSR;
// local NTP time when we received this
uint32_t lastReceivedRRNTPsecs = 0;
uint32_t lastReceivedRRNTPfrac = 0;
reportBlock->lastReceivedRRNTPsecs = 0;
reportBlock->lastReceivedRRNTPfrac = 0;
_clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
_clock->CurrentNtp(reportBlock->lastReceivedRRNTPsecs,
reportBlock->lastReceivedRRNTPfrac);
// time when we received this in MS
uint32_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
lastReceivedRRNTPfrac);
uint32_t receiveTimeMS = Clock::NtpToMs(reportBlock->lastReceivedRRNTPsecs,
reportBlock->lastReceivedRRNTPfrac);
// Estimate RTT
uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;

View File

@ -82,6 +82,12 @@ public:
int32_t ResetRTT(const uint32_t remoteSSRC);
int32_t GetReportBlockInfo(uint32_t remoteSSRC,
uint32_t* NTPHigh,
uint32_t* NTPLow,
uint32_t* PacketsReceived,
uint64_t* OctetsReceived) const;
int32_t SenderInfoReceived(RTCPSenderInfo* senderInfo) const;
// get statistics

View File

@ -101,6 +101,10 @@ RTCPPacketInformation::AddReportInfo(
RTCPReportBlockInformation::RTCPReportBlockInformation():
remoteReceiveBlock(),
remoteMaxJitter(0),
remotePacketsReceived(0),
remoteOctetsReceived(0),
lastReceivedRRNTPsecs(0),
lastReceivedRRNTPfrac(0),
RTT(0),
minRTT(0),
maxRTT(0),

View File

@ -32,6 +32,10 @@ public:
// Statistics
RTCPReportBlock remoteReceiveBlock;
uint32_t remoteMaxJitter;
uint32_t remotePacketsReceived;
uint64_t remoteOctetsReceived;
uint32_t lastReceivedRRNTPsecs;
uint32_t lastReceivedRRNTPfrac;
// RTT
uint16_t RTT;

View File

@ -127,6 +127,8 @@ RTCPSender::RTCPSender(const int32_t id,
_lastSendReport(),
_lastRTCPTime(),
_lastSRPacketCount(),
_lastSROctetCount(),
_CSRCs(0),
_CSRC(),
@ -157,6 +159,8 @@ RTCPSender::RTCPSender(const int32_t id,
memset(_CNAME, 0, sizeof(_CNAME));
memset(_lastSendReport, 0, sizeof(_lastSendReport));
memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
memset(_lastSRPacketCount, 0, sizeof(_lastSRPacketCount));
memset(_lastSROctetCount, 0, sizeof(_lastSROctetCount));
WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
}
@ -228,6 +232,8 @@ RTCPSender::Init()
memset(_CNAME, 0, sizeof(_CNAME));
memset(_lastSendReport, 0, sizeof(_lastSendReport));
memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
memset(_lastSRPacketCount, 0, sizeof(_lastSRPacketCount));
memset(_lastSROctetCount, 0, sizeof(_lastSROctetCount));
_nackCount = 0;
_pliCount = 0;
@ -569,26 +575,32 @@ RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
return _lastSendReport[0];
}
uint32_t
RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
bool
RTCPSender::GetSendReportMetadata(const uint32_t sendReport,
uint32_t *timeOfSend,
uint32_t *packetCount,
uint64_t *octetCount)
{
CriticalSectionScoped lock(_criticalSectionRTCPSender);
// This is only saved when we are the sender
if((_lastSendReport[0] == 0) || (sendReport == 0))
{
return 0; // will be ignored
return false;
} else
{
for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
{
if( _lastSendReport[i] == sendReport)
{
return _lastRTCPTime[i];
*timeOfSend = _lastRTCPTime[i];
*packetCount = _lastSRPacketCount[i];
*octetCount = _lastSROctetCount[i];
return true;
}
}
}
return 0;
return false;
}
int32_t RTCPSender::AddExternalReportBlock(
@ -664,10 +676,14 @@ int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
// shift old
_lastSendReport[i+1] = _lastSendReport[i];
_lastRTCPTime[i+1] =_lastRTCPTime[i];
_lastSRPacketCount[i+1] = _lastSRPacketCount[i];
_lastSROctetCount[i+1] = _lastSROctetCount[i];
}
_lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
_lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
_lastSRPacketCount[0] = feedback_state.packet_count_sent;
_lastSROctetCount[0] = feedback_state.byte_count_sent;
// The timestamp of this RTCP packet should be estimated as the timestamp of
// the frame being captured at this moment. We are calculating that

View File

@ -105,7 +105,10 @@ public:
int32_t RemoveMixedCNAME(const uint32_t SSRC);
uint32_t SendTimeOfSendReport(const uint32_t sendReport);
bool GetSendReportMetadata(const uint32_t sendReport,
uint32_t *timeOfSend,
uint32_t *packetCount,
uint64_t *octetCount);
bool TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP = false) const;
@ -288,6 +291,8 @@ private:
// Sent
uint32_t _lastSendReport[RTCP_NUMBER_OF_SR]; // allow packet loss and RTT above 1 sec
uint32_t _lastRTCPTime[RTCP_NUMBER_OF_SR];
uint32_t _lastSRPacketCount[RTCP_NUMBER_OF_SR];
uint64_t _lastSROctetCount[RTCP_NUMBER_OF_SR];
// send CSRCs
uint8_t _CSRCs;

View File

@ -910,6 +910,19 @@ void ModuleRtpRtcpImpl:: SetRtt(uint32_t rtt) {
rtcp_receiver_.SetRTT(static_cast<uint16_t>(rtt));
}
int32_t
ModuleRtpRtcpImpl::GetReportBlockInfo(const uint32_t remote_ssrc,
uint32_t* ntp_high,
uint32_t* ntp_low,
uint32_t* packets_received,
uint64_t* octets_received) const {
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "RemotePacketsReceived()");
return rtcp_receiver_.GetReportBlockInfo(remote_ssrc,
ntp_high, ntp_low,
packets_received, octets_received);
}
// Reset RTP data counters for the sending side.
int32_t ModuleRtpRtcpImpl::ResetSendDataCountersRTP() {
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_,
@ -1538,9 +1551,14 @@ int32_t ModuleRtpRtcpImpl::SendRTCPReferencePictureSelection(
feedback_state, kRtcpRpsi, 0, 0, false, picture_id);
}
uint32_t ModuleRtpRtcpImpl::SendTimeOfSendReport(
const uint32_t send_report) {
return rtcp_sender_.SendTimeOfSendReport(send_report);
bool ModuleRtpRtcpImpl::GetSendReportMetadata(const uint32_t send_report,
uint32_t *time_of_send,
uint32_t *packet_count,
uint64_t *octet_count) {
return rtcp_sender_.GetSendReportMetadata(send_report,
time_of_send,
packet_count,
octet_count);
}
void ModuleRtpRtcpImpl::OnReceivedNACK(

View File

@ -173,6 +173,12 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
virtual void SetRtt(uint32_t rtt) OVERRIDE;
virtual int32_t GetReportBlockInfo(const uint32_t remote_ssrc,
uint32_t* ntp_high,
uint32_t* ntp_low,
uint32_t* packets_received,
uint64_t* octets_received) const OVERRIDE;
// Force a send of an RTCP packet.
// Normal SR and RR are triggered via the process function.
virtual int32_t SendRTCP(uint32_t rtcp_packet_type = kRtcpReport) OVERRIDE;
@ -331,7 +337,10 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
uint32_t* fec_rate,
uint32_t* nackRate) const OVERRIDE;
virtual uint32_t SendTimeOfSendReport(const uint32_t send_report);
virtual bool GetSendReportMetadata(const uint32_t send_report,
uint32_t *time_of_send,
uint32_t *packet_count,
uint64_t *octet_count);
// Good state of RTP receiver inform sender.
virtual int32_t SendRTCPReferencePictureSelection(

View File

@ -91,6 +91,8 @@ class WEBRTC_DLLEXPORT ViERTCPObserver {
virtual ~ViERTCPObserver() {}
};
struct SenderInfo;
class WEBRTC_DLLEXPORT ViERTP_RTCP {
public:
enum { KDefaultDeltaTransmitTimeSeconds = 15 };
@ -171,6 +173,16 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP {
const int video_channel,
char rtcp_cname[KMaxRTCPCNameLength]) const = 0;
virtual int GetRemoteRTCPReceiverInfo(const int video_channel,
uint32_t& NTPHigh,
uint32_t& NTPLow,
uint32_t& receivedPacketCount,
uint64_t& receivedOctetCount,
uint32_t* jitter,
uint16_t* fractionLost,
uint32_t* cumulativeLost,
int32_t* rttMs) const = 0;
// This function sends an RTCP APP packet on a specific channel.
virtual int SendApplicationDefinedRTCPPacket(
const int video_channel,
@ -294,6 +306,10 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP {
unsigned int& bytes_received,
unsigned int& packets_received) const = 0;
// Gets the sender info part of the last received RTCP Sender Report (SR)
virtual int GetRemoteRTCPSenderInfo(const int video_channel,
SenderInfo* sender_info) const = 0;
// The function gets bandwidth usage statistics from the sent RTP streams in
// bits/s.
virtual int GetBandwidthUsage(const int video_channel,

View File

@ -30,6 +30,7 @@
#include "webrtc/video_engine/include/vie_image_process.h"
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
#include "webrtc/video_engine/vie_defines.h"
#include "webrtc/voice_engine/include/voe_rtp_rtcp.h" // for webrtc::SenderInfo
namespace webrtc {
@ -1177,6 +1178,81 @@ int32_t ViEChannel::SendApplicationDefinedRTCPPacket(
return 0;
}
int32_t ViEChannel::GetRemoteRTCPReceiverInfo(uint32_t& NTPHigh,
uint32_t& NTPLow,
uint32_t& receivedPacketCount,
uint64_t& receivedOctetCount,
uint32_t* jitterSamples,
uint16_t* fractionLost,
uint32_t* cumulativeLost,
int32_t* rttMs) {
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
__FUNCTION__);
// TODO: how do we do this for simulcast ? average for all
// except cumulative_lost that is the sum ?
// CriticalSectionScoped cs(rtp_rtcp_cs_.get());
// for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
// it != simulcast_rtp_rtcp_.end();
// it++) {
// RtpRtcp* rtp_rtcp = *it;
// }
uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc();
// 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;
}
std::vector<RTCPReportBlock>::const_iterator statistics =
remote_stats.begin();
for (; statistics != remote_stats.end(); ++statistics) {
if (statistics->remoteSSRC == remote_ssrc)
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();
remote_ssrc = statistics->remoteSSRC;
}
if (rtp_rtcp_->GetReportBlockInfo(remote_ssrc,
&NTPHigh,
&NTPLow,
&receivedPacketCount,
&receivedOctetCount) != 0) {
WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
"%s: failed to retrieve RTT", __FUNCTION__);
NTPHigh = 0;
NTPLow = 0;
receivedPacketCount = 0;
receivedOctetCount = 0;
}
*fractionLost = statistics->fractionLost;
*cumulativeLost = statistics->cumulativeLost;
*jitterSamples = statistics->jitter;
uint16_t dummy;
uint16_t rtt = 0;
if (rtp_rtcp_->RTT(remote_ssrc, &rtt, &dummy, &dummy, &dummy) != 0) {
WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
"%s: Could not get RTT", __FUNCTION__);
return -1;
}
*rttMs = rtt;
return 0;
}
int32_t ViEChannel::GetSendRtcpStatistics(uint32_t* ntp_high,
uint32_t* ntp_low,
uint32_t* bytes_sent,
@ -1345,6 +1421,26 @@ int32_t ViEChannel::GetRtpStatistics(uint32_t* bytes_sent,
return 0;
}
int32_t ViEChannel::GetRemoteRTCPSenderInfo(SenderInfo* sender_info) const {
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
__FUNCTION__);
// Get the sender info from the latest received RTCP Sender Report.
RTCPSenderInfo rtcp_sender_info;
if (rtp_rtcp_->RemoteRTCPStat(&rtcp_sender_info) != 0) {
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
"%s: failed to read RTCP SR sender info", __FUNCTION__);
return -1;
}
sender_info->NTP_timestamp_high = rtcp_sender_info.NTPseconds;
sender_info->NTP_timestamp_low = rtcp_sender_info.NTPfraction;
sender_info->RTP_timestamp = rtcp_sender_info.RTPtimeStamp;
sender_info->sender_packet_count = rtcp_sender_info.sendPacketCount;
sender_info->sender_octet_count = rtcp_sender_info.sendOctetCount;
return 0;
}
void ViEChannel::GetBandwidthUsage(uint32_t* total_bitrate_sent,
uint32_t* video_bitrate_sent,
uint32_t* fec_bitrate_sent,

View File

@ -48,6 +48,8 @@ class VideoDecoder;
class VideoRenderCallback;
class VoEVideoSync;
struct SenderInfo;
class ViEChannel
: public VCMFrameTypeCallback,
public VCMReceiveCallback,
@ -155,6 +157,7 @@ class ViEChannel
// Gets the CName of the incoming stream.
int32_t GetRemoteRTCPCName(char rtcp_cname[]);
int32_t RegisterRtpObserver(ViERTPObserver* observer);
int32_t RegisterRtcpObserver(ViERTCPObserver* observer);
int32_t SendApplicationDefinedRTCPPacket(
@ -163,6 +166,16 @@ class ViEChannel
const uint8_t* data,
uint16_t data_length_in_bytes);
// Gets info (including timestamp) from last rr + remote packetcount
// (derived from rr report + cached sender-side info).
int32_t GetRemoteRTCPReceiverInfo(uint32_t& NTPHigh, uint32_t& NTPLow,
uint32_t& receivedPacketCount,
uint64_t& receivedOctetCount,
uint32_t* jitterSamples,
uint16_t* fractionLost,
uint32_t* cumulativeLost,
int32_t* rttMs);
// Returns statistics reported by the remote client in an RTCP packet.
int32_t GetSendRtcpStatistics(uint32_t* ntp_high,
uint32_t* ntp_low,
@ -190,6 +203,9 @@ class ViEChannel
uint32_t* packets_sent,
uint32_t* bytes_received,
uint32_t* packets_received) const;
int32_t GetRemoteRTCPSenderInfo(SenderInfo* sender_info) const;
void GetBandwidthUsage(uint32_t* total_bitrate_sent,
uint32_t* video_bitrate_sent,
uint32_t* fec_bitrate_sent,

View File

@ -424,6 +424,41 @@ int ViERTP_RTCPImpl::GetRemoteRTCPCName(
return 0;
}
int ViERTP_RTCPImpl::GetRemoteRTCPReceiverInfo(const int video_channel,
uint32_t& NTPHigh,
uint32_t& NTPLow,
uint32_t& receivedPacketCount,
uint64_t& receivedOctetCount,
uint32_t* jitter,
uint16_t* fractionLost,
uint32_t* cumulativeLost,
int32_t* rttMs) const {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
ViEId(shared_data_->instance_id(), video_channel),
"%s(channel: %d)", __FUNCTION__, video_channel);
ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
ViEChannel* vie_channel = cs.Channel(video_channel);
if (!vie_channel) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), video_channel),
"%s: Channel %d doesn't exist", __FUNCTION__, video_channel);
shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
return -1;
}
if (vie_channel->GetRemoteRTCPReceiverInfo(NTPHigh,
NTPLow,
receivedPacketCount,
receivedOctetCount,
jitter,
fractionLost,
cumulativeLost,
rttMs) != 0) {
shared_data_->SetLastError(kViERtpRtcpUnknownError);
return -1;
}
return 0;
}
int ViERTP_RTCPImpl::SendApplicationDefinedRTCPPacket(
const int video_channel,
const unsigned char sub_type,
@ -921,6 +956,27 @@ int ViERTP_RTCPImpl::GetRTPStatistics(const int video_channel,
return 0;
}
int ViERTP_RTCPImpl::GetRemoteRTCPSenderInfo(const int video_channel,
SenderInfo* sender_info) const {
WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
ViEId(shared_data_->instance_id(), video_channel),
"%s(channel: %d)", __FUNCTION__, video_channel);
ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
ViEChannel* vie_channel = cs.Channel(video_channel);
if (!vie_channel) {
WEBRTC_TRACE(kTraceError, kTraceVideo,
ViEId(shared_data_->instance_id(), video_channel),
"%s: Channel %d doesn't exist", __FUNCTION__, video_channel);
shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
return -1;
}
if (vie_channel->GetRemoteRTCPSenderInfo(sender_info) != 0) {
shared_data_->SetLastError(kViERtpRtcpUnknownError);
return -1;
}
return 0;
}
int ViERTP_RTCPImpl::GetBandwidthUsage(const int video_channel,
unsigned int& total_bitrate_sent,
unsigned int& video_bitrate_sent,

View File

@ -55,6 +55,15 @@ class ViERTP_RTCPImpl
char rtcp_cname[KMaxRTCPCNameLength]) const;
virtual int GetRemoteRTCPCName(const int video_channel,
char rtcp_cname[KMaxRTCPCNameLength]) const;
virtual int GetRemoteRTCPReceiverInfo(const int video_channel,
uint32_t& NTPHigh,
uint32_t& NTPLow,
uint32_t& receivedPacketCount,
uint64_t& receivedOctetCount,
uint32_t* jitter,
uint16_t* fractionLost,
uint32_t* cumulativeLost,
int32_t* rttMs) const;
virtual int SendApplicationDefinedRTCPPacket(
const int video_channel,
const unsigned char sub_type,
@ -113,6 +122,8 @@ class ViERTP_RTCPImpl
unsigned int& packets_sent,
unsigned int& bytes_received,
unsigned int& packets_received) const;
virtual int GetRemoteRTCPSenderInfo(const int video_channel,
SenderInfo* sender_info) const;
virtual int GetBandwidthUsage(const int video_channel,
unsigned int& total_bitrate_sent,
unsigned int& video_bitrate_sent,

View File

@ -3797,107 +3797,81 @@ Channel::GetRemoteRTCP_CNAME(char cName[256])
}
int
Channel::GetRemoteRTCPData(
unsigned int& NTPHigh,
unsigned int& NTPLow,
unsigned int& timestamp,
unsigned int& playoutTimestamp,
unsigned int& sendPacketCount,
unsigned int& sendOctetCount,
unsigned int* jitter,
unsigned short* fractionLost,
unsigned int* cumulativeLost)
Channel::GetRemoteRTCPReceiverInfo(
uint32_t& NTPHigh,
uint32_t& NTPLow,
uint32_t& receivedPacketCount,
uint64_t& receivedOctetCount,
uint32_t& jitter,
uint16_t& fractionLost,
uint32_t& cumulativeLost,
int32_t& rttMs)
{
// --- Information from sender info in received Sender Reports
// 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),
"GetRemoteRTCPReceiverInfo() failed to measure statistics due"
" to lack of received RTP and/or RTCP packets");
return -1;
}
RTCPSenderInfo senderInfo;
if (_rtpRtcpModule->RemoteRTCPStat(&senderInfo) != 0)
{
_engineStatisticsPtr->SetLastError(
VE_RTP_RTCP_MODULE_ERROR, kTraceError,
"GetRemoteRTCPData() failed to retrieve sender info for remote "
"side");
return -1;
}
uint32_t remoteSSRC = rtp_receiver_->SSRC();
std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin();
for (; it != remote_stats.end(); ++it) {
if (it->remoteSSRC == remoteSSRC)
break;
}
NTPHigh = senderInfo.NTPseconds;
NTPLow = senderInfo.NTPfraction;
timestamp = senderInfo.RTPtimeStamp;
sendPacketCount = senderInfo.sendPacketCount;
sendOctetCount = senderInfo.sendOctetCount;
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;
}
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
if (_rtpRtcpModule->GetReportBlockInfo(remoteSSRC,
&NTPHigh,
&NTPLow,
&receivedPacketCount,
&receivedOctetCount) != 0) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice,
VoEId(_instanceId, _channelId),
"GetRemoteRTCPData() => NTPHigh=%lu, NTPLow=%lu, "
"timestamp=%lu",
NTPHigh, NTPLow, timestamp);
"GetRemoteRTCPReceiverInfo() failed to retrieve RTT from "
"the RTP/RTCP module");
NTPHigh = 0;
NTPLow = 0;
receivedPacketCount = 0;
receivedOctetCount = 0;
}
// --- Locally derived information
jitter = it->jitter;
fractionLost = it->fractionLost;
cumulativeLost = it->cumulativeLost;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
VoEId(_instanceId, _channelId),
"GetRemoteRTCPReceiverInfo() => jitter = %lu, "
"fractionLost = %lu, cumulativeLost = %lu",
jitter, fractionLost, cumulativeLost);
// This value is updated on each incoming RTCP packet (0 when no packet
// has been received)
playoutTimestamp = playout_timestamp_rtcp_;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
uint16_t dummy;
uint16_t rtt = 0;
if (_rtpRtcpModule->RTT(remoteSSRC, &rtt, &dummy, &dummy, &dummy)
!= 0)
{
WEBRTC_TRACE(kTraceWarning, kTraceVoice,
VoEId(_instanceId, _channelId),
"GetRemoteRTCPData() => playoutTimestamp=%lu",
playout_timestamp_rtcp_);
if (NULL != jitter || NULL != fractionLost || NULL != cumulativeLost)
{
// 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;
}
uint32_t remoteSSRC = rtp_receiver_->SSRC();
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;
}
if (jitter) {
*jitter = it->jitter;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
VoEId(_instanceId, _channelId),
"GetRemoteRTCPData() => jitter = %lu", *jitter);
}
if (fractionLost) {
*fractionLost = it->fractionLost;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
VoEId(_instanceId, _channelId),
"GetRemoteRTCPData() => fractionLost = %lu",
*fractionLost);
}
if (cumulativeLost) {
*cumulativeLost = it->cumulativeLost;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
VoEId(_instanceId, _channelId),
"GetRemoteRTCPData() => cumulativeLost = %lu",
*cumulativeLost);
}
}
return 0;
"GetRTPStatistics() failed to retrieve RTT from "
"the RTP/RTCP module");
}
rttMs = rtt;
return 0;
}
int

View File

@ -264,14 +264,13 @@ public:
int SetRTCP_CNAME(const char cName[256]);
int GetRTCP_CNAME(char cName[256]);
int GetRemoteRTCP_CNAME(char cName[256]);
int GetRemoteRTCPData(unsigned int& NTPHigh, unsigned int& NTPLow,
unsigned int& timestamp,
unsigned int& playoutTimestamp,
unsigned int& sendPacketCount,
unsigned int& sendOctetCount,
unsigned int* jitter,
unsigned short* fractionLost,
unsigned int* cumulativeLost);
int GetRemoteRTCPReceiverInfo(uint32_t& NTPHigh, uint32_t& NTPLow,
uint32_t& receivedPacketCount,
uint64_t& receivedOctetCount,
uint32_t& jitter,
uint16_t& fractionLost,
uint32_t& cumulativeLost,
int32_t& rttMs);
int SendApplicationDefinedRTCPPacket(unsigned char subType,
unsigned int name, const char* data,
unsigned short dataLengthInBytes);

View File

@ -182,12 +182,12 @@ public:
virtual int GetRemoteRTCP_CNAME(int channel, char cName[256]) = 0;
// Gets RTCP data from incoming RTCP Sender Reports.
virtual int GetRemoteRTCPData(
int channel, unsigned int& NTPHigh, unsigned int& NTPLow,
unsigned int& timestamp, unsigned int& playoutTimestamp,
unsigned int& sendPacketCount, unsigned int& sendOctetCount,
unsigned int* jitter = NULL, unsigned short* fractionLost = NULL,
unsigned int* cumulativeLost = NULL) = 0;
virtual int GetRemoteRTCPReceiverInfo(
int channel, uint32_t& NTPHigh, uint32_t& NTPLow,
uint32_t& receivedPacketCount, uint64_t& receivedOctetCount,
uint32_t& jitter, uint16_t& fractionLost,
uint32_t& cumulativeLost,
int32_t& rttMs) = 0;
// Gets RTP statistics for a specific |channel|.
virtual int GetRTPStatistics(

View File

@ -369,20 +369,19 @@ int VoERTP_RTCPImpl::GetRemoteRTCP_CNAME(int channel, char cName[256])
return channelPtr->GetRemoteRTCP_CNAME(cName);
}
int VoERTP_RTCPImpl::GetRemoteRTCPData(
int VoERTP_RTCPImpl::GetRemoteRTCPReceiverInfo(
int channel,
unsigned int& NTPHigh, // from sender info in SR
unsigned int& NTPLow, // from sender info in SR
unsigned int& timestamp, // from sender info in SR
unsigned int& playoutTimestamp, // derived locally
unsigned int& sendPacketCount, // from sender info in SR
unsigned int& sendOctetCount, // from sender info in SR
unsigned int* jitter, // from report block 1 in SR/RR
unsigned short* fractionLost, // from report block 1 in SR/RR
unsigned int* cumulativeLost) // from report block 1 in SR/RR
uint32_t& NTPHigh, // when last RR received
uint32_t& NTPLow, // when last RR received
uint32_t& receivedPacketCount, // derived from RR + cached info
uint64_t& receivedOctetCount, // derived from RR + cached info
uint32_t& jitter, // from report block 1 in RR
uint16_t& fractionLost, // from report block 1 in RR
uint32_t& cumulativeLost, // from report block 1 in RR
int32_t& rttMs)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"GetRemoteRTCPData(channel=%d,...)", channel);
"GetRemoteRTCPReceiverInfo(channel=%d,...)", channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
@ -393,18 +392,17 @@ int VoERTP_RTCPImpl::GetRemoteRTCPData(
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"GetRemoteRTCP_CNAME() failed to locate channel");
"GetRemoteRTCPReceiverInfo() failed to locate channel");
return -1;
}
return channelPtr->GetRemoteRTCPData(NTPHigh,
NTPLow,
timestamp,
playoutTimestamp,
sendPacketCount,
sendOctetCount,
jitter,
fractionLost,
cumulativeLost);
return channelPtr->GetRemoteRTCPReceiverInfo(NTPHigh,
NTPLow,
receivedPacketCount,
receivedOctetCount,
jitter,
fractionLost,
cumulativeLost,
rttMs);
}
int VoERTP_RTCPImpl::SendApplicationDefinedRTCPPacket(

View File

@ -40,16 +40,15 @@ public:
virtual int GetRemoteRTCP_CNAME(int channel, char cName[256]);
virtual int GetRemoteRTCPData(int channel,
unsigned int& NTPHigh,
unsigned int& NTPLow,
unsigned int& timestamp,
unsigned int& playoutTimestamp,
unsigned int& sendPacketCount,
unsigned int& sendOctetCount,
unsigned int* jitter = NULL,
unsigned short* fractionLost = NULL,
unsigned int* cumulativeLost = NULL);
virtual int GetRemoteRTCPReceiverInfo(int channel,
uint32_t& NTPHigh,
uint32_t& NTPLow,
uint32_t& receivedPacketCount,
uint64_t& receivedOctetCount,
uint32_t& jitter,
uint16_t& fractionLost,
uint32_t& cumulativeLost,
int32_t& rttMs);
virtual int SendApplicationDefinedRTCPPacket(
int channel,