Bug 970686: Outbound getStats: Fixed RTCP timestamps and remote packets/bytes received. r=jesup
authorJan-Ivar Bruaroey <jib@mozilla.com>
Fri, 14 Mar 2014 14:34:02 -0400
changeset 190919 c8e80efab6fb0e88c4b607b548fc970498920426
parent 190918 5e86e89e463f3ba23c72a16ea99b57ab273fa6b9
child 190920 80fad01e53bbafade244f1f2124d11a628788456
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs970686
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 970686: Outbound getStats: Fixed RTCP timestamps and remote packets/bytes received. r=jesup
dom/media/tests/mochitest/pc.js
dom/webidl/RTCStatsReport.webidl
media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
media/webrtc/signaling/src/media-conduit/AudioConduit.h
media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
media/webrtc/signaling/src/media-conduit/VideoConduit.h
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/trunk/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_sender.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
media/webrtc/trunk/webrtc/video_engine/include/vie_rtp_rtcp.h
media/webrtc/trunk/webrtc/video_engine/vie_channel.cc
media/webrtc/trunk/webrtc/video_engine/vie_channel.h
media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.cc
media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.h
media/webrtc/trunk/webrtc/voice_engine/channel.cc
media/webrtc/trunk/webrtc/voice_engine/channel.h
media/webrtc/trunk/webrtc/voice_engine/include/voe_rtp_rtcp.h
media/webrtc/trunk/webrtc/voice_engine/voe_rtp_rtcp_impl.cc
media/webrtc/trunk/webrtc/voice_engine/voe_rtp_rtcp_impl.h
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -1589,18 +1589,18 @@ PeerConnectionWrapper.prototype = {
 
     // Use spec way of enumerating stats
     var counters = {};
     for (var key in stats) {
       if (stats.hasOwnProperty(key)) {
         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 + " (" +
                (res.timestamp - minimum) + " ms)");
         ok(res.timestamp <= nowish,
            "Valid " + (res.isRemote? "rtcp" : "rtp") + " timestamp " +
                res.timestamp + " <= " + nowish + " (" +
                (res.timestamp - nowish) + " ms)");
@@ -1626,22 +1626,20 @@ PeerConnectionWrapper.prototype = {
               }
               if (res.remoteId) {
                 var rem = stats[res.remoteId];
                 ok(rem.isRemote, "Remote is rtcp");
                 ok(rem.remoteId == res.id, "Remote backlink match");
                 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");
                   ok(rem.packetsSent !== undefined, "Rtcp packetsSent");
                   // We may have received more than outdated Rtcp packetsSent
                   ok(rem.bytesSent >= rem.packetsSent * 8, "Rtcp bytesSent");
                 }
                 ok(rem.ssrc == res.ssrc, "Remote ssrc match");
--- a/dom/webidl/RTCStatsReport.webidl
+++ b/dom/webidl/RTCStatsReport.webidl
@@ -35,16 +35,17 @@ dictionary RTCRTPStreamStats : RTCStats 
 
 dictionary RTCInboundRTPStreamStats : RTCRTPStreamStats {
   unsigned long packetsReceived;
   unsigned long long bytesReceived;
   double jitter;
   unsigned long packetsLost;
   long mozAvSyncDelay;
   long mozJitterBufferDelay;
+  long mozRtt;
 };
 
 dictionary RTCOutboundRTPStreamStats : RTCRTPStreamStats {
   unsigned long packetsSent;
   unsigned long long bytesSent;
 };
 
 dictionary RTCMediaStreamTrackStats : RTCStats {
@@ -53,17 +54,16 @@ dictionary RTCMediaStreamTrackStats : RT
   sequence<DOMString> ssrcIds;
   unsigned long audioLevel;       // Only for audio, the rest are only for video
   unsigned long frameWidth;
   unsigned long frameHeight;
   double framesPerSecond;         // The nominal FPS value
   unsigned long framesSent;
   unsigned long framesReceived;   // Only for remoteSource=true
   unsigned long framesDecoded;
-  unsigned long first;
 };
 
 dictionary RTCMediaStreamStats : RTCStats {
   DOMString streamIdentifier;     // stream.id property
   sequence<DOMString> trackIds;   // Note: stats object ids, not track.id
 };
 
 dictionary RTCTransportStats: RTCStats {
--- a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
@@ -148,55 +148,46 @@ bool WebrtcAudioConduit::GetRTPStats(uns
 
 DOMHighResTimeStamp
 NTPtoDOMHighResTimeStamp(uint32_t ntpHigh, uint32_t ntpLow) {
   return (uint32_t(ntpHigh - webrtc::kNtpJan1970) +
           double(ntpLow) / webrtc::kMagicNtpFractionalUnit) * 1000;
 }
 
 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;
 }
 
 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;
 }
 
 /*
  * WebRTCAudioConduit Implementation
  */
 MediaConduitErrorCode WebrtcAudioConduit::Init(WebrtcAudioConduit *other)
--- a/media/webrtc/signaling/src/media-conduit/AudioConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.h
@@ -180,20 +180,21 @@ public:
   webrtc::VoiceEngine* GetVoiceEngine() { return mVoiceEngine; }
   bool GetLocalSSRC(unsigned int* ssrc);
   bool GetRemoteSSRC(unsigned int* ssrc);
   bool GetAVStats(int32_t* jitterBufferDelayMs,
                   int32_t* playoutBufferDelayMs,
                   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);
 
 private:
   WebrtcAudioConduit(const WebrtcAudioConduit& other) MOZ_DELETE;
   void operator=(const WebrtcAudioConduit& other) MOZ_DELETE;
 
--- a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
+++ b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
@@ -144,20 +144,21 @@ public:
    * Functions returning stats needed by w3c stats model.
    */
   virtual bool GetAVStats(int32_t* jitterBufferDelayMs,
                           int32_t* playoutBufferDelayMs,
                           int32_t* avSyncOffsetMs) = 0;
   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;
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaSessionConduit)
 
 };
 
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -152,62 +152,46 @@ bool WebrtcVideoConduit::GetRTPStats(uns
                                              fractionLost,
                                              *cumulativeLost,
                                              extendedMax,
                                              *jitterMs,
                                              rttMs);
 }
 
 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;
 }
 
 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;
 }
 
 /**
  * Peforms intialization of the MANDATORY components of the Video Engine
  */
 MediaConduitErrorCode WebrtcVideoConduit::Init(WebrtcVideoConduit *other)
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h
@@ -205,20 +205,21 @@ public:
   webrtc::VideoEngine* GetVideoEngine() { return mVideoEngine; }
   bool GetLocalSSRC(unsigned int* ssrc);
   bool GetRemoteSSRC(unsigned int* ssrc);
   bool GetAVStats(int32_t* jitterBufferDelayMs,
                   int32_t* playoutBufferDelayMs,
                   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);
 
 private:
 
   WebrtcVideoConduit(const WebrtcVideoConduit& other) MOZ_DELETE;
   void operator=(const WebrtcVideoConduit& other) MOZ_DELETE;
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -2159,34 +2159,37 @@ PeerConnectionImpl::ExecuteStatsQuery_s(
           // First, fill in remote stat with rtcp receiver data, if present.
           // ReceiverReports have less information than SenderReports,
           // so fill in what we can.
           DOMHighResTimeStamp timestamp;
           uint32_t jitterMs;
           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);
             s.mId.Construct(remoteId);
             s.mType.Construct(RTCStatsType::Inboundrtp);
             if (ssrc.Length()) {
               s.mSsrc.Construct(ssrc);
             }
             s.mJitter.Construct(double(jitterMs)/1000);
             s.mRemoteId.Construct(localId);
             s.mIsRemote = true;
             s.mPacketsReceived.Construct(packetsReceived);
             s.mBytesReceived.Construct(bytesReceived);
             s.mPacketsLost.Construct(packetsLost);
+            s.mMozRtt.Construct(rtt);
             query->report.mInboundRTPStreamStats.Value().AppendElement(s);
           }
         }
         // Then, fill in local side (with cross-link to remote only if present)
         {
           RTCOutboundRTPStreamStats s;
           s.mTimestamp.Construct(query->now);
           s.mId.Construct(localId);
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h
@@ -420,16 +420,27 @@ class RtpRtcp : public Module {
 
     /*
      * Sets the estimated RTT, to be used for receive only modules without
      * possibility of calculating its own RTT.
      */
     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
     *
     *   return -1 on failure else 0
     */
     virtual int32_t SendRTCP(
         uint32_t rtcpPacketType = kRtcpReport) = 0;
 
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc
@@ -229,16 +229,37 @@ int RTCPReceiver::SetRTT(uint16_t rtt) {
   CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
   if (!_receivedReportBlockMap.empty()) {
     return -1;
   }
   _rtt = 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,
                   uint32_t *RTCPArrivalTimeSecs,
                   uint32_t *RTCPArrivalTimeFrac,
                   uint32_t *rtcp_timestamp) const
 {
     CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
@@ -472,18 +493,21 @@ RTCPReceiver::HandleReportBlock(const RT
       registered_ssrcs_.end()) {
     // This block is not for us ignore it.
     return;
   }
 
   // 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 =
       CreateReportBlockInformation(remoteSSRC);
   if (reportBlock == NULL) {
     WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
                  "\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
     return;
@@ -491,16 +515,22 @@ RTCPReceiver::HandleReportBlock(const RT
 
   _lastReceivedRrMs = _clock->TimeInMilliseconds();
   const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
   reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
   reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
   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
     // the last RR was sent from the remote side.
     _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
   }
   reportBlock->remoteReceiveBlock.extendedHighSeqNum =
       rb.ExtendedHighestSequenceNumber;
@@ -511,24 +541,25 @@ RTCPReceiver::HandleReportBlock(const RT
   if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
     reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
   }
 
   uint32_t delaySinceLastSendReport =
       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;
   d /= 65536;
   d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
 
   int32_t RTT = 0;
 
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h
@@ -77,16 +77,22 @@ public:
                 uint16_t* maxRTT) const;
 
     uint16_t RTT() const;
 
     int SetRTT(uint16_t rtt);
 
     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
     int32_t StatisticsReceived(
         std::vector<RTCPReportBlock>* receiveBlocks) const;
 
     // Returns true if we haven't received an RTCP RR for several RTCP
     // intervals, but only triggers true once.
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.cc
@@ -96,16 +96,20 @@ RTCPPacketInformation::AddReportInfo(
 {
   this->rtt = report_block_info.RTT;
   report_blocks.push_back(report_block_info.remoteReceiveBlock);
 }
 
 RTCPReportBlockInformation::RTCPReportBlockInformation():
     remoteReceiveBlock(),
     remoteMaxJitter(0),
+    remotePacketsReceived(0),
+    remoteOctetsReceived(0),
+    lastReceivedRRNTPsecs(0),
+    lastReceivedRRNTPfrac(0),
     RTT(0),
     minRTT(0),
     maxRTT(0),
     avgRTT(0),
     numAverageCalcs(0)
 {
     memset(&remoteReceiveBlock,0,sizeof(remoteReceiveBlock));
 }
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h
@@ -27,16 +27,20 @@ class RTCPReportBlockInformation
 {
 public:
     RTCPReportBlockInformation();
     ~RTCPReportBlockInformation();
 
     // Statistics
     RTCPReportBlock remoteReceiveBlock;
     uint32_t        remoteMaxJitter;
+    uint32_t        remotePacketsReceived;
+    uint64_t        remoteOctetsReceived;
+    uint32_t        lastReceivedRRNTPsecs;
+    uint32_t        lastReceivedRRNTPfrac;
 
     // RTT
     uint16_t    RTT;
     uint16_t    minRTT;
     uint16_t    maxRTT;
     uint16_t    avgRTT;
     uint32_t    numAverageCalcs;
 };
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
@@ -122,16 +122,18 @@ RTCPSender::RTCPSender(const int32_t id,
     internal_report_blocks_(),
     external_report_blocks_(),
     _csrcCNAMEs(),
 
     _cameraDelayMS(0),
 
     _lastSendReport(),
     _lastRTCPTime(),
+    _lastSRPacketCount(),
+    _lastSROctetCount(),
 
     _CSRCs(0),
     _CSRC(),
     _includeCSRCs(true),
 
     _sequenceNumberFIR(0),
 
     _lengthRembSSRC(0),
@@ -152,16 +154,18 @@ RTCPSender::RTCPSender(const int32_t id,
     _xrVoIPMetric(),
     _nackCount(0),
     _pliCount(0),
     _fullIntraRequestCount(0)
 {
     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__);
 }
 
 RTCPSender::~RTCPSender() {
   delete [] _rembSSRC;
   delete [] _appData;
 
@@ -223,16 +227,18 @@ RTCPSender::Init()
     _appLength = 0;
 
     _xrSendVoIPMetric = false;
 
     memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
     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;
     _fullIntraRequestCount = 0;
 
     return 0;
 }
 
@@ -564,36 +570,42 @@ uint32_t
 RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
 {
     CriticalSectionScoped lock(_criticalSectionRTCPSender);
 
     lastRTCPTime = _lastRTCPTime[0];
     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(
     uint32_t SSRC,
     const RTCPReportBlock* reportBlock) {
   CriticalSectionScoped lock(_criticalSectionRTCPSender);
   return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
 }
@@ -659,20 +671,24 @@ int32_t RTCPSender::BuildSR(const Feedba
     // Sender report
     rtcpbuffer[pos++]=(uint8_t)200;
 
     for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
     {
         // 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
     // timestamp as the last frame's timestamp + the time since the last frame
     // was captured.
     {
       // Needs protection since this method is called on the process thread.
       CriticalSectionScoped lock(_criticalSectionRTCPSender);
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_sender.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtcp_sender.h
@@ -100,17 +100,20 @@ public:
     int32_t CNAME(char cName[RTCP_CNAME_SIZE]);
     int32_t SetCNAME(const char cName[RTCP_CNAME_SIZE]);
 
     int32_t AddMixedCNAME(const uint32_t SSRC,
                           const char cName[RTCP_CNAME_SIZE]);
 
     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;
 
     uint32_t LastSendReport(uint32_t& lastRTCPTime);
 
     int32_t SendRTCP(
         const FeedbackState& feedback_state,
         uint32_t rtcpPacketTypeFlags,
@@ -283,16 +286,18 @@ private:
     std::map<uint32_t, RTCPReportBlock*> external_report_blocks_;
     std::map<uint32_t, RTCPUtility::RTCPCnameInformation*> _csrcCNAMEs;
 
     int32_t         _cameraDelayMS;
 
     // 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;
     uint32_t        _CSRC[kRtpCsrcSize];
     bool                _includeCSRCs;
 
     // Full intra request
     uint8_t         _sequenceNumberFIR;
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -905,16 +905,29 @@ int32_t ModuleRtpRtcpImpl::ResetRTT(cons
   return rtcp_receiver_.ResetRTT(remote_ssrc);
 }
 
 void ModuleRtpRtcpImpl:: SetRtt(uint32_t rtt) {
   WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "SetRtt(rtt: %u)", 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_,
                "ResetSendDataCountersRTP()");
 
   rtp_sender_.ResetDataCounters();
   return 0;  // TODO(pwestin): change to void.
 }
@@ -1533,19 +1546,24 @@ void ModuleRtpRtcpImpl::OnRequestSendRep
 
 int32_t ModuleRtpRtcpImpl::SendRTCPReferencePictureSelection(
     const uint64_t picture_id) {
   RTCPSender::FeedbackState feedback_state(this);
   return rtcp_sender_.SendRTCP(
       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(
     const std::list<uint16_t>& nack_sequence_numbers) {
   if (!rtp_sender_.StorePackets() ||
       nack_sequence_numbers.size() == 0) {
     return;
   }
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
@@ -168,16 +168,22 @@ class ModuleRtpRtcpImpl : public RtpRtcp
                       uint16_t* min_rtt,
                       uint16_t* max_rtt) const OVERRIDE;
 
   // Reset RoundTripTime statistics.
   virtual int32_t ResetRTT(const uint32_t remote_ssrc) OVERRIDE;
 
   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;
 
   virtual int32_t ResetSendDataCountersRTP() OVERRIDE;
 
   // Statistics of the amount of data sent and received.
   virtual int32_t DataCountersRTP(uint32_t* bytes_sent,
@@ -326,17 +332,20 @@ class ModuleRtpRtcpImpl : public RtpRtcp
 
   virtual int32_t BoundingSet(bool& tmmbr_owner, TMMBRSet*& bounding_set_rec);
 
   virtual void BitrateSent(uint32_t* total_rate,
                            uint32_t* video_rate,
                            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(
       const uint64_t picture_id) OVERRIDE;
 
   void OnReceivedTMMBR();
 
   // Bad state of RTP receiver request a keyframe.
--- a/media/webrtc/trunk/webrtc/video_engine/include/vie_rtp_rtcp.h
+++ b/media/webrtc/trunk/webrtc/video_engine/include/vie_rtp_rtcp.h
@@ -86,16 +86,18 @@ class WEBRTC_DLLEXPORT ViERTCPObserver {
       const unsigned char sub_type,
       const unsigned int name,
       const char* data,
       const unsigned short data_length_in_bytes) = 0;
  protected:
   virtual ~ViERTCPObserver() {}
 };
 
+struct SenderInfo;
+
 class WEBRTC_DLLEXPORT ViERTP_RTCP {
  public:
   enum { KDefaultDeltaTransmitTimeSeconds = 15 };
   enum { KMaxRTCPCNameLength = 256 };
 
   // Factory for the ViERTP_RTCP subā€API and increases an internal reference
   // counter if successful. Returns NULL if the API is not supported or if
   // construction fails.
@@ -166,16 +168,26 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP {
                            char rtcp_cname[KMaxRTCPCNameLength]) const = 0;
 
   // This function gets the RTCP canonical name (CNAME) for the RTCP reports
   // received on the specified channel.
   virtual int GetRemoteRTCPCName(
       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,
       const unsigned char sub_type,
       unsigned int name,
       const char* data,
       unsigned short data_length_in_bytes) = 0;
 
@@ -289,16 +301,20 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP {
 
   // The function gets statistics from the sent and received RTP streams.
   virtual int GetRTPStatistics(const int video_channel,
                                unsigned int& bytes_sent,
                                unsigned int& packets_sent,
                                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,
                                 unsigned int& total_bitrate_sent,
                                 unsigned int& video_bitrate_sent,
                                 unsigned int& fec_bitrate_sent,
                                 unsigned int& nackBitrateSent) const = 0;
 
--- a/media/webrtc/trunk/webrtc/video_engine/vie_channel.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_channel.cc
@@ -25,16 +25,17 @@
 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
 #include "webrtc/system_wrappers/interface/trace.h"
 #include "webrtc/video_engine/call_stats.h"
 #include "webrtc/video_engine/include/vie_codec.h"
 #include "webrtc/video_engine/include/vie_errors.h"
 #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 {
 
 const int kMaxDecodeWaitTimeMs = 50;
 const int kInvalidRtpExtensionId = 0;
 static const int kMaxTargetDelayMs = 10000;
 static const float kMaxIncompleteTimeMultiplier = 3.5f;
 
@@ -1172,16 +1173,91 @@ int32_t ViEChannel::SendApplicationDefin
                                                data_length_in_bytes) != 0) {
     WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
                  "%s: Could not send RTCP application data", __FUNCTION__);
     return -1;
   }
   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,
                                           uint32_t* packets_sent,
                                           uint16_t* fraction_lost,
                                           uint32_t* cumulative_lost,
                                           uint32_t* extended_max,
                                           uint32_t* jitter_samples,
@@ -1340,16 +1416,36 @@ int32_t ViEChannel::GetRtpStatistics(uin
     RtpRtcp* rtp_rtcp = *it;
     rtp_rtcp->DataCountersRTP(&bytes_sent_temp, &packets_sent_temp);
     bytes_sent += bytes_sent_temp;
     packets_sent += packets_sent_temp;
   }
   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,
                                    uint32_t* nackBitrateSent) const {
   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
                __FUNCTION__);
 
   rtp_rtcp_->BitrateSent(total_bitrate_sent, video_bitrate_sent,
--- a/media/webrtc/trunk/webrtc/video_engine/vie_channel.h
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_channel.h
@@ -43,16 +43,18 @@ class ViEDecoderObserver;
 class ViEEffectFilter;
 class ViERTCPObserver;
 class ViERTPObserver;
 class VideoCodingModule;
 class VideoDecoder;
 class VideoRenderCallback;
 class VoEVideoSync;
 
+struct SenderInfo;
+
 class ViEChannel
     : public VCMFrameTypeCallback,
       public VCMReceiveCallback,
       public VCMReceiveStatisticsCallback,
       public VCMPacketRequestCallback,
       public RtcpFeedback,
       public RtpFeedback,
       public ViEFrameProviderBase {
@@ -150,24 +152,35 @@ class ViEChannel
   // Sets the CName for the outgoing stream on the channel.
   int32_t SetRTCPCName(const char rtcp_cname[]);
 
   // Gets the CName for the outgoing stream on the channel.
   int32_t GetRTCPCName(char rtcp_cname[]);
 
   // 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(
       const uint8_t sub_type,
       uint32_t name,
       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,
                                 uint32_t* bytes_sent,
                                 uint32_t* packets_sent,
                                 uint16_t* fraction_lost,
                                 uint32_t* cumulative_lost,
                                 uint32_t* extended_max,
@@ -185,16 +198,19 @@ class ViEChannel
                                     uint32_t* jitter_samples,
                                     int32_t* rtt_ms);
 
   // Gets sent/received packets statistics.
   int32_t GetRtpStatistics(uint32_t* bytes_sent,
                            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,
                          uint32_t* nackBitrateSent) const;
   void GetEstimatedReceiveBandwidth(uint32_t* estimated_bandwidth) const;
 
   int32_t StartRTPDump(const char file_nameUTF8[1024],
                        RTPDirections direction);
--- a/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.cc
@@ -419,16 +419,51 @@ int ViERTP_RTCPImpl::GetRemoteRTCPCName(
   }
   if (vie_channel->GetRemoteRTCPCName(rtcp_cname) != 0) {
     shared_data_->SetLastError(kViERtpRtcpUnknownError);
     return -1;
   }
   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,
   unsigned int name,
   const char* data,
   uint16_t data_length_in_bytes) {
   WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
                ViEId(shared_data_->instance_id(), video_channel),
@@ -916,16 +951,37 @@ int ViERTP_RTCPImpl::GetRTPStatistics(co
                                     &bytes_received,
                                     &packets_received) != 0) {
     shared_data_->SetLastError(kViERtpRtcpUnknownError);
     return -1;
   }
   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,
                                        unsigned int& fec_bitrate_sent,
                                        unsigned int& nackBitrateSent) const {
   WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
                ViEId(shared_data_->instance_id(), video_channel),
                "%s(channel: %d)", __FUNCTION__, video_channel);
--- a/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.h
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.h
@@ -50,16 +50,25 @@ class ViERTP_RTCPImpl
   virtual int GetRTCPStatus(const int video_channel,
                             ViERTCPMode& rtcp_mode) const;
   virtual int SetRTCPCName(const int video_channel,
                            const char rtcp_cname[KMaxRTCPCNameLength]);
   virtual int GetRTCPCName(const int video_channel,
                            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,
       unsigned int name,
       const char* data,
       uint16_t data_length_in_bytes);
   virtual int SetNACKStatus(const int video_channel, const bool enable);
   virtual int SetFECStatus(const int video_channel, const bool enable,
@@ -108,16 +117,18 @@ class ViERTP_RTCPImpl
                                     unsigned int& cumulative_lost,
                                     unsigned int& extended_max,
                                     unsigned int& jitter, int& rtt_ms) const;
   virtual int GetRTPStatistics(const int video_channel,
                                unsigned int& bytes_sent,
                                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,
                                 unsigned int& fec_bitrate_sent,
                                 unsigned int& nackBitrateSent) const;
   virtual int GetEstimatedSendBandwidth(
       const int video_channel,
       unsigned int* estimated_bandwidth) const;
--- a/media/webrtc/trunk/webrtc/voice_engine/channel.cc
+++ b/media/webrtc/trunk/webrtc/voice_engine/channel.cc
@@ -3792,117 +3792,91 @@ Channel::GetRemoteRTCP_CNAME(char cName[
     strcpy(cName, cname);
     WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
                  VoEId(_instanceId, _channelId),
                  "GetRemoteRTCP_CNAME() => cName=%s", cName);
     return 0;
 }
 
 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
-
-    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;
-    }
-
-    NTPHigh = senderInfo.NTPseconds;
-    NTPLow = senderInfo.NTPfraction;
-    timestamp = senderInfo.RTPtimeStamp;
-    sendPacketCount = senderInfo.sendPacketCount;
-    sendOctetCount = senderInfo.sendOctetCount;
-
-    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
-                 VoEId(_instanceId, _channelId),
-                 "GetRemoteRTCPData() => NTPHigh=%lu, NTPLow=%lu, "
-                 "timestamp=%lu",
-                 NTPHigh, NTPLow, timestamp);
-
-    // --- Locally derived information
-
-    // This value is updated on each incoming RTCP packet (0 when no packet
-    // has been received)
-    playoutTimestamp = playout_timestamp_rtcp_;
-
-    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
+  // 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;
+  }
+
+  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 (_rtpRtcpModule->GetReportBlockInfo(remoteSSRC,
+                                         &NTPHigh,
+                                         &NTPLow,
+                                         &receivedPacketCount,
+                                         &receivedOctetCount) != 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;
+                 "GetRemoteRTCPReceiverInfo() failed to retrieve RTT from "
+                 "the RTP/RTCP module");
+    NTPHigh = 0;
+    NTPLow = 0;
+    receivedPacketCount = 0;
+    receivedOctetCount = 0;
+  }
+
+  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);
+
+  uint16_t dummy;
+  uint16_t rtt = 0;
+  if (_rtpRtcpModule->RTT(remoteSSRC, &rtt, &dummy, &dummy, &dummy)
+      != 0)
+  {
+    WEBRTC_TRACE(kTraceWarning, kTraceVoice,
+                 VoEId(_instanceId, _channelId),
+                 "GetRTPStatistics() failed to retrieve RTT from "
+                 "the RTP/RTCP module");
+  }
+  rttMs = rtt;
+  return 0;
 }
 
 int
 Channel::SendApplicationDefinedRTCPPacket(unsigned char subType,
                                              unsigned int name,
                                              const char* data,
                                              unsigned short dataLengthInBytes)
 {
--- a/media/webrtc/trunk/webrtc/voice_engine/channel.h
+++ b/media/webrtc/trunk/webrtc/voice_engine/channel.h
@@ -259,24 +259,23 @@ public:
     int GetRemoteCSRCs(unsigned int arrCSRC[15]);
     int SetRTPAudioLevelIndicationStatus(bool enable, unsigned char ID);
     int GetRTPAudioLevelIndicationStatus(bool& enable, unsigned char& ID);
     int SetRTCPStatus(bool enable);
     int GetRTCPStatus(bool& enabled);
     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);
     int GetRTPStatistics(unsigned int& averageJitterMs,
                          unsigned int& maxJitterMs,
                          unsigned int& discardedPackets,
                          unsigned int& cumulativeLost);
     int GetRemoteRTCPSenderInfo(SenderInfo* sender_info);
--- a/media/webrtc/trunk/webrtc/voice_engine/include/voe_rtp_rtcp.h
+++ b/media/webrtc/trunk/webrtc/voice_engine/include/voe_rtp_rtcp.h
@@ -177,22 +177,22 @@ public:
     // specific |channel|.
     virtual int GetRTCP_CNAME(int channel, char cName[256]) = 0;
 
     // Gets the canonical name (CNAME) parameter for incoming RTCP reports
     // on a specific channel.
     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(
         int channel, unsigned int& averageJitterMs, unsigned int& maxJitterMs,
         unsigned int& discardedPackets, unsigned int& cumulativeLost) = 0;
 
     // Gets RTCP statistics for a specific |channel|.
     virtual int GetRTCPStatistics(int channel, CallStatistics& stats) = 0;
--- a/media/webrtc/trunk/webrtc/voice_engine/voe_rtp_rtcp_impl.cc
+++ b/media/webrtc/trunk/webrtc/voice_engine/voe_rtp_rtcp_impl.cc
@@ -364,52 +364,50 @@ int VoERTP_RTCPImpl::GetRemoteRTCP_CNAME
     {
         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
             "GetRemoteRTCP_CNAME() failed to locate channel");
         return -1;
     }
     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);
         return -1;
     }
     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
     voe::Channel* channelPtr = ch.channel();
     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(
     int channel,
     unsigned char subType,
     unsigned int name,
     const char* data,
     unsigned short dataLengthInBytes)
--- a/media/webrtc/trunk/webrtc/voice_engine/voe_rtp_rtcp_impl.h
+++ b/media/webrtc/trunk/webrtc/voice_engine/voe_rtp_rtcp_impl.h
@@ -35,26 +35,25 @@ public:
     virtual int GetRTCPStatus(int channel, bool& enabled);
 
     virtual int SetRTCP_CNAME(int channel, const char cName[256]);
 
     virtual int GetRTCP_CNAME(int channel, char cName[256]);
 
     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,
         unsigned char subType,
         unsigned int name,
         const char* data,
         unsigned short dataLengthInBytes);