Bug 1374465 - add framesDecoded to vid inbound stream stats;r?jib draft
authorNico Grunbaum
Mon, 03 Jul 2017 14:17:40 -0700
changeset 604360 30225790de9a03bc7436c27a08272ee1283dc1ab
parent 603312 a3b192dc8344679ce208af42b6246c3c0d42cab3
child 636165 5c08b4ddea8825af0fe4f04ef9b1662c1d7c3b65
push id67041
push userna-g@nostrum.com
push dateWed, 05 Jul 2017 19:53:08 +0000
reviewersjib
bugs1374465
milestone56.0a1
Bug 1374465 - add framesDecoded to vid inbound stream stats;r?jib MozReview-Commit-ID: GqbcQxOb69r
dom/media/tests/mochitest/test_peerConnection_stats.html
dom/media/webrtc/WebrtcGlobal.h
dom/webidl/RTCStatsReport.webidl
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
--- a/dom/media/tests/mochitest/test_peerConnection_stats.html
+++ b/dom/media/tests/mochitest/test_peerConnection_stats.html
@@ -11,18 +11,18 @@
     title: "webRtc Stats composition and sanity"
   });
 var statsExpectedByType = {
   "inbound-rtp": {
     expected: ["id", "timestamp", "type", "ssrc", "isRemote", "mediaType",
       "packetsReceived", "packetsLost", "bytesReceived", "jitter",],
     optional: ["roundTripTime", "remoteId", "nackCount",],
     localVideoOnly: ["discardedPackets", "framerateStdDev", "framerateMean",
-      "bitrateMean", "bitrateStdDev", "firCount", "pliCount",],
-    unimplemented: ["mediaTrackId", "transportId", "codecId", "framesDecoded",
+      "bitrateMean", "bitrateStdDev", "firCount", "pliCount", "framesDecoded",],
+    unimplemented: ["mediaTrackId", "transportId", "codecId",
       "packetsDiscarded", "associateStatsId",
       "sliCount", "qpSum", "packetsRepaired", "fractionLost",
       "burstPacketsLost", "burstLossCount", "burstDiscardCount",
       "gapDiscardRate", "gapLossRate",],
     deprecated: ["mozRtt"],
   },
   "outbound-rtp": {
     expected: ["id", "timestamp", "type", "ssrc", "isRemote", "mediaType",
@@ -253,17 +253,20 @@ var pedanticChecks = report => {
         expectations.localVideoOnly.forEach(field => {
           ok(stat.inner[field] !== undefined, stat.type + " has field " + field
             + " when mediaType is video");
         });
         // discardedPackets
         ok(stat.discardedPackets < 100, stat.type
           + ".discardedPackets is a sane number for a short test. value="
           + stat.discardedPackets);
-
+        // framesDecoded
+        ok(stat.framesDecoded > 0 && stat.framesDecoded < 1000000, stat.type
+          + ".framesDecoded is a sane number for a short test. value="
+          + stat.framesDecoded);
         // bitrateMean
         // special exception, TODO: Bug 1341533
         if (stat.bitrateMean !== undefined) {
           // TODO: uncomment when Bug 1341533 lands
           // ok(stat.bitrateMean >= 0 && stat.bitrateMean < 2 ** 25,
           //   stat.type + ".bitrateMean is sane. value="
           //   + stat.bitrateMean);
         }
--- a/dom/media/webrtc/WebrtcGlobal.h
+++ b/dom/media/webrtc/WebrtcGlobal.h
@@ -348,30 +348,32 @@ template<>
 struct ParamTraits<mozilla::dom::RTCInboundRTPStreamStats>
 {
   typedef mozilla::dom::RTCInboundRTPStreamStats paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mBytesReceived);
     WriteParam(aMsg, aParam.mDiscardedPackets);
+    WriteParam(aMsg, aParam.mFramesDecoded);
     WriteParam(aMsg, aParam.mJitter);
     WriteParam(aMsg, aParam.mMozAvSyncDelay);
     WriteParam(aMsg, aParam.mMozJitterBufferDelay);
     WriteParam(aMsg, aParam.mRoundTripTime);
     WriteParam(aMsg, aParam.mPacketsLost);
     WriteParam(aMsg, aParam.mPacketsReceived);
     WriteRTCRTPStreamStats(aMsg, aParam);
     WriteRTCStats(aMsg, aParam);
   }
 
   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) ||
         !ReadParam(aMsg, aIter, &(aResult->mDiscardedPackets)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mFramesDecoded)) ||
         !ReadParam(aMsg, aIter, &(aResult->mJitter)) ||
         !ReadParam(aMsg, aIter, &(aResult->mMozAvSyncDelay)) ||
         !ReadParam(aMsg, aIter, &(aResult->mMozJitterBufferDelay)) ||
         !ReadParam(aMsg, aIter, &(aResult->mRoundTripTime)) ||
         !ReadParam(aMsg, aIter, &(aResult->mPacketsLost)) ||
         !ReadParam(aMsg, aIter, &(aResult->mPacketsReceived)) ||
         !ReadRTCRTPStreamStats(aMsg, aIter, aResult) ||
         !ReadRTCStats(aMsg, aIter, aResult)) {
--- a/dom/webidl/RTCStatsReport.webidl
+++ b/dom/webidl/RTCStatsReport.webidl
@@ -54,16 +54,17 @@ dictionary RTCInboundRTPStreamStats : RT
   double jitter;
   unsigned long packetsLost;
   long mozAvSyncDelay;
   long mozJitterBufferDelay;
   long roundTripTime;
 
   // Video decoder measurement, not present in RTCP case
   unsigned long discardedPackets;
+  unsigned long framesDecoded;
 };
 
 dictionary RTCOutboundRTPStreamStats : RTCRTPStreamStats {
   unsigned long packetsSent;
   unsigned long long bytesSent;
   double targetBitrate;  // config encoder bitrate target of this SSRC in bits/s
 
   // Video encoder measurements, not present in RTCP case
--- a/media/webrtc/signaling/src/media-conduit/AudioConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.h
@@ -217,17 +217,18 @@ public:
                             uint32_t* framesEncoded) override
   {
     return false;
   }
   bool GetVideoDecoderStats(double* framerateMean,
                             double* framerateStdDev,
                             double* bitrateMean,
                             double* bitrateStdDev,
-                            uint32_t* discardedPackets) override
+                            uint32_t* discardedPackets,
+                            uint32_t* framesDecoded) override
   {
     return false;
   }
   bool GetAVStats(int32_t* jitterBufferDelayMs,
                   int32_t* playoutBufferDelayMs,
                   int32_t* avSyncOffsetMs) override;
   bool GetRTPStats(unsigned int* jitterMs, unsigned int* cumulativeLost) override;
   bool GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
--- a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
+++ b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
@@ -273,17 +273,18 @@ public:
                                     double* bitrateMean,
                                     double* bitrateStdDev,
                                     uint32_t* droppedFrames,
                                     uint32_t* framesEncoded) = 0;
   virtual bool GetVideoDecoderStats(double* framerateMean,
                                     double* framerateStdDev,
                                     double* bitrateMean,
                                     double* bitrateStdDev,
-                                    uint32_t* discardedPackets) = 0;
+                                    uint32_t* discardedPackets,
+                                    uint32_t* framesDecoded) = 0;
   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,
                                      uint32_t* jitterMs,
                                      uint32_t* packetsReceived,
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -146,24 +146,24 @@ WebrtcVideoConduit::StreamStatistics::Ge
   if (mFrameRate.NumDataValues() && mBitrate.NumDataValues()) {
     aOutFrMean = mFrameRate.Mean();
     aOutFrStdDev = mFrameRate.StandardDeviation();
     aOutBrMean = mBitrate.Mean();
     aOutBrStdDev = mBitrate.StandardDeviation();
     return true;
   }
   return false;
-};
+}
 
 void
 WebrtcVideoConduit::SendStreamStatistics::DroppedFrames(
   uint32_t& aOutDroppedFrames) const
 {
       aOutDroppedFrames = mDroppedFrames;
-};
+}
 
 void
 WebrtcVideoConduit::SendStreamStatistics::Update(
   const webrtc::VideoSendStream::Stats& aStats)
 {
   StreamStatistics::Update(aStats.encode_frame_rate, aStats.media_bitrate_bps);
   if (!aStats.substreams.empty()) {
     const webrtc::FrameCounts& fc =
@@ -173,33 +173,42 @@ WebrtcVideoConduit::SendStreamStatistics
                   "%s: framerate: %u, bitrate: %u, dropped frames delta: %u",
                   __FUNCTION__, aStats.encode_frame_rate,
                   aStats.media_bitrate_bps,
                   mFramesDeliveredToEncoder - mFramesEncoded - mDroppedFrames);
     mDroppedFrames = mFramesDeliveredToEncoder - mFramesEncoded;
   } else {
     CSFLogVerbose(logTag, "%s stats.substreams is empty", __FUNCTION__);
   }
-};
+}
 
 void
 WebrtcVideoConduit::ReceiveStreamStatistics::DiscardedPackets(
   uint32_t& aOutDiscPackets) const
 {
   aOutDiscPackets = mDiscardedPackets;
-};
+}
+
+void
+WebrtcVideoConduit::ReceiveStreamStatistics::FramesDecoded(
+  uint32_t& aFramesDecoded) const
+{
+  aFramesDecoded = mFramesDecoded;
+}
 
 void
 WebrtcVideoConduit::ReceiveStreamStatistics::Update(
   const webrtc::VideoReceiveStream::Stats& aStats)
 {
   CSFLogVerbose(logTag, "%s ", __FUNCTION__);
   StreamStatistics::Update(aStats.decode_frame_rate, aStats.total_bitrate_bps);
   mDiscardedPackets = aStats.discarded_packets;
-};
+  mFramesDecoded = aStats.frame_counts.key_frames
+                   + aStats.frame_counts.delta_frames;
+}
 
 /**
  * Factory Method for VideoConduit
  */
 RefPtr<VideoSessionConduit>
 VideoSessionConduit::Create(RefPtr<WebRtcCallWrapper> aCall)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
@@ -923,26 +932,28 @@ WebrtcVideoConduit::GetVideoEncoderStats
   }
 }
 
 bool
 WebrtcVideoConduit::GetVideoDecoderStats(double* framerateMean,
                                          double* framerateStdDev,
                                          double* bitrateMean,
                                          double* bitrateStdDev,
-                                         uint32_t* discardedPackets)
+                                         uint32_t* discardedPackets,
+                                         uint32_t* framesDecoded)
 {
   {
     MutexAutoLock lock(mCodecMutex);
     if (!mEngineReceiving || !mRecvStream) {
       return false;
     }
     mRecvStreamStats.GetVideoStreamStats(*framerateMean, *framerateStdDev,
       *bitrateMean, *bitrateStdDev);
     mRecvStreamStats.DiscardedPackets(*discardedPackets);
+    mRecvStreamStats.FramesDecoded(*framesDecoded);
     return true;
   }
 }
 
 bool
 WebrtcVideoConduit::GetAVStats(int32_t* jitterBufferDelayMs,
                                int32_t* playoutBufferDelayMs,
                                int32_t* avSyncOffsetMs)
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h
@@ -317,17 +317,18 @@ public:
                             double* bitrateMean,
                             double* bitrateStdDev,
                             uint32_t* droppedFrames,
                             uint32_t* framesEncoded) override;
   bool GetVideoDecoderStats(double* framerateMean,
                             double* framerateStdDev,
                             double* bitrateMean,
                             double* bitrateStdDev,
-                            uint32_t* discardedPackets) override;
+                            uint32_t* discardedPackets,
+                            uint32_t* framesDecoded) override;
   bool GetAVStats(int32_t* jitterBufferDelayMs,
                   int32_t* playoutBufferDelayMs,
                   int32_t* avSyncOffsetMs) override;
   bool GetRTPStats(unsigned int* jitterMs, unsigned int* cumulativeLost) override;
   bool GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
                              uint32_t* jitterMs,
                              uint32_t* packetsReceived,
                              uint64_t* bytesReceived,
@@ -393,19 +394,25 @@ private:
    */
   class ReceiveStreamStatistics : public StreamStatistics {
   public:
     /**
      * Returns the number of discarded packets
      * @param aOutDiscPackets: number of discarded packets
      */
     void DiscardedPackets(uint32_t& aOutDiscPackets) const;
+   /**
+    * Returns the number of frames decoded
+    * @param aOutDiscPackets: number of frames decoded
+    */
+    void FramesDecoded(uint32_t& aFramesDecoded) const;
     void Update(const webrtc::VideoReceiveStream::Stats& aStats);
   private:
     uint32_t mDiscardedPackets = 0;
+    uint32_t mFramesDecoded = 0;
   };
   /*
    * Stores encoder configuration information and produces
    * a VideoEncoderConfig from it.
    */
   class VideoStreamFactory;
   
   class VideoEncoderConfigBuilder {
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -3829,26 +3829,29 @@ PeerConnectionImpl::ExecuteStatsQuery_s(
         }
         // Lastly, fill in video decoder stats if this is video
         if (!isAudio) {
           double framerateMean;
           double framerateStdDev;
           double bitrateMean;
           double bitrateStdDev;
           uint32_t discardedPackets;
+          uint32_t framesDecoded;
           if (mp.Conduit()->GetVideoDecoderStats(&framerateMean,
                                                  &framerateStdDev,
                                                  &bitrateMean,
                                                  &bitrateStdDev,
-                                                 &discardedPackets)) {
+                                                 &discardedPackets,
+                                                 &framesDecoded)) {
             s.mFramerateMean.Construct(framerateMean);
             s.mFramerateStdDev.Construct(framerateStdDev);
             s.mBitrateMean.Construct(bitrateMean);
             s.mBitrateStdDev.Construct(bitrateStdDev);
             s.mDiscardedPackets.Construct(discardedPackets);
+            s.mFramesDecoded.Construct(framesDecoded);
           }
         }
         query->report->mInboundRTPStreamStats.Value().AppendElement(s,
                                                                     fallible);
         // Fill in Contributing Source statistics
         mp.GetContributingSourceStats(localId,
             query->report->mRtpContributingSourceStats.Value());
         break;