Bug 1380555 - P2 - Refactor isRemote from telemetry;r?mjf draft
authorNico Grunbaum
Wed, 09 Aug 2017 10:34:50 -0700
changeset 649186 80839eb6f5856f7c8213c4df4a04cd15acd66455
parent 643445 d451d1c9c5cd6d9d057d92e7c2272778c8354d4a
child 727028 af15994bfb56da3a72be8e07aca16bde9f056cf3
push id74979
push userna-g@nostrum.com
push dateFri, 18 Aug 2017 19:25:19 +0000
reviewersmjf
bugs1380555
milestone56.0a1
Bug 1380555 - P2 - Refactor isRemote from telemetry;r?mjf MozReview-Commit-ID: ESqSZyijKYL
media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp
@@ -183,18 +183,19 @@ void PeerConnectionCtx::Destroy() {
 typedef Vector<nsAutoPtr<RTCStatsQuery>> RTCStatsQueries;
 
 // Telemetry reporting every second after start of first call.
 // The threading model around the media pipelines is weird:
 // - The pipelines are containers,
 // - containers that are only safe on main thread, with members only safe on STS,
 // - hence the there and back again approach.
 
+template <class T>
 static auto
-FindId(const Sequence<RTCInboundRTPStreamStats>& aArray,
+FindId(const Sequence<T>& aArray,
        const nsString &aId) -> decltype(aArray.Length()) {
   for (decltype(aArray.Length()) i = 0; i < aArray.Length(); i++) {
     if (aArray[i].mId.Value() == aId) {
       return i;
     }
   }
   return aArray.NoIndex;
 }
@@ -224,70 +225,109 @@ EverySecondTelemetryCallback_s(nsAutoPtr
   }
   PeerConnectionCtx *ctx = PeerConnectionCtx::GetInstance();
 
   for (auto & q : *aQueryList) {
     PeerConnectionImpl::ExecuteStatsQuery_s(q);
     auto& r = *q->report;
     if (r.mInboundRTPStreamStats.WasPassed()) {
       // First, get reports from a second ago, if any, for calculations below
-      const Sequence<RTCInboundRTPStreamStats> *lastInboundStats = nullptr;
+      const Sequence<RTCInboundRTPStreamStats>* lastInboundStats = nullptr;
+      const Sequence<RTCRemoteInboundRTPStreamStats>* lastRemoteInboundStats =
+          nullptr;
       {
         auto i = FindId(ctx->mLastReports, r.mPcid);
         if (i != ctx->mLastReports.NoIndex) {
-          lastInboundStats = &ctx->mLastReports[i]->mInboundRTPStreamStats.Value();
+          lastInboundStats =
+              &ctx->mLastReports[i]->mInboundRTPStreamStats.Value();
+          lastRemoteInboundStats =
+              &ctx->mLastReports[i]->mRemoteInboundRTPStreamStats.Value();
         }
       }
 
+      auto mediaIsAudio = [](const RTCRTPStreamStats& stat) {
+        return stat.mMediaType.Value().EqualsLiteral("audio");
+      };
+
+      auto recordAudioBandwidth = [](const RTCReceivedRTPStreamStats& s,
+                                     const RTCReceivedRTPStreamStats& lasts,
+                                     bool isAudio,
+                                     HistogramID audioId,
+                                     HistogramID videoId) {
+        if (lasts.mBytesReceived.WasPassed()) {
+          auto delta_ms = int32_t(s.mTimestamp.Value() -
+                                 lasts.mTimestamp.Value());
+          // In theory we're called every second, so delta *should* be in that range.
+          // Small deltas could cause errors due to division
+          if (delta_ms > 500 && delta_ms < 60000) {
+           auto id = isAudio ? audioId : videoId;
+           Accumulate(id, ((s.mBytesReceived.Value() -
+                            lasts.mBytesReceived.Value()) * 8) / delta_ms);
+          }
+          // We could accumulate values until enough time has passed
+          // and then Accumulate() but this isn't that important.
+        }
+      };
+
+      HistogramID id;
       // Then, look for the things we want telemetry on
-      auto& array = r.mInboundRTPStreamStats.Value();
-      for (decltype(array.Length()) i = 0; i < array.Length(); i++) {
-        auto& s = array[i];
-        bool isAudio = (s.mId.Value().Find("audio") != -1);
+      //Record Remote Inbound Stats
+      for (const auto& s : r.mRemoteInboundRTPStreamStats.Value()) {
+        bool isAudio = mediaIsAudio(s);
         if (s.mPacketsLost.WasPassed() && s.mPacketsReceived.WasPassed() &&
             (s.mPacketsLost.Value() + s.mPacketsReceived.Value()) != 0) {
-          HistogramID id;
-          // TODO @@NG TELEMETRY
+              id = isAudio ? WEBRTC_AUDIO_QUALITY_OUTBOUND_PACKETLOSS_RATE :
+                             WEBRTC_VIDEO_QUALITY_OUTBOUND_PACKETLOSS_RATE;
+              // *1000 so we can read in 10's of a percent (permille)
+              Accumulate(id,
+                        (s.mPacketsLost.Value() * 1000) /
+                        (s.mPacketsLost.Value() + s.mPacketsReceived.Value()));
+
+        }
+        if( s.mRoundTripTime.WasPassed()) {
+          id = isAudio ? WEBRTC_AUDIO_QUALITY_OUTBOUND_RTT :
+                         WEBRTC_VIDEO_QUALITY_OUTBOUND_RTT;
+           Accumulate(id, s.mRoundTripTime.Value());
+        }
+        if (lastRemoteInboundStats && s.mBytesReceived.WasPassed()) {
+          auto& laststats = *lastRemoteInboundStats;
+          auto i = FindId(laststats, s.mId.Value());
+          if (i != laststats.NoIndex) {
+            auto& lasts = laststats[i];
+            recordAudioBandwidth(s, lasts, isAudio,
+                                 WEBRTC_AUDIO_QUALITY_OUTBOUND_BANDWIDTH_KBITS,
+                                 WEBRTC_VIDEO_QUALITY_OUTBOUND_BANDWIDTH_KBITS);
+          }
+        }
+      }
+      // Record Local Inbound Stats
+      for (const auto& s : r.mInboundRTPStreamStats.Value()) {
+        bool isAudio = mediaIsAudio(s);
+        if (s.mPacketsLost.WasPassed() && s.mPacketsReceived.WasPassed() &&
+            (s.mPacketsLost.Value() + s.mPacketsReceived.Value()) != 0) {
           id = isAudio ? WEBRTC_AUDIO_QUALITY_INBOUND_PACKETLOSS_RATE :
                          WEBRTC_VIDEO_QUALITY_INBOUND_PACKETLOSS_RATE;
           // *1000 so we can read in 10's of a percent (permille)
           Accumulate(id,
                      (s.mPacketsLost.Value() * 1000) /
                      (s.mPacketsLost.Value() + s.mPacketsReceived.Value()));
         }
         if (s.mJitter.WasPassed()) {
-          HistogramID id;
-          // TODO @@NG TELEMETRY
-            id = isAudio ? WEBRTC_AUDIO_QUALITY_INBOUND_JITTER :
-                           WEBRTC_VIDEO_QUALITY_INBOUND_JITTER;
-          //}
+          id = isAudio ? WEBRTC_AUDIO_QUALITY_INBOUND_JITTER :
+                         WEBRTC_VIDEO_QUALITY_INBOUND_JITTER;
           Accumulate(id, s.mJitter.Value());
         }
-        // TODO @@NG TELEMETRY
         if (lastInboundStats && s.mBytesReceived.WasPassed()) {
           auto& laststats = *lastInboundStats;
           auto i = FindId(laststats, s.mId.Value());
           if (i != laststats.NoIndex) {
             auto& lasts = laststats[i];
-            if (lasts.mBytesReceived.WasPassed()) {
-              auto delta_ms = int32_t(s.mTimestamp.Value() -
-                                      lasts.mTimestamp.Value());
-              // In theory we're called every second, so delta *should* be in that range.
-              // Small deltas could cause errors due to division
-              if (delta_ms > 500 && delta_ms < 60000) {
-                HistogramID id;
-                // TODO @NG TELEMETRY
-                id = isAudio ? WEBRTC_AUDIO_QUALITY_INBOUND_BANDWIDTH_KBITS :
-                               WEBRTC_VIDEO_QUALITY_INBOUND_BANDWIDTH_KBITS;
-                Accumulate(id, ((s.mBytesReceived.Value() -
-                                 lasts.mBytesReceived.Value()) * 8) / delta_ms);
-              }
-              // We could accumulate values until enough time has passed
-              // and then Accumulate() but this isn't that important.
-            }
+            recordAudioBandwidth(s, lasts, isAudio,
+                                 WEBRTC_AUDIO_QUALITY_INBOUND_BANDWIDTH_KBITS,
+                                 WEBRTC_VIDEO_QUALITY_INBOUND_BANDWIDTH_KBITS);
           }
         }
       }
     }
   }
   // Steal and hang on to reports for the next second
   ctx->mLastReports.Clear();
   for (auto & q : *aQueryList) {