RTCMediaStreamTrackStats.framesDropped collected by RTCStatsCollector.

Spec: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-framesdropped
Implemented as frames_received - frames_rendered.

Part of this CL is adding frames_rendered to VideoReceiveStream::Stats
and updating it at ReceiveStatisticsProxy::OnRenderedFrame.

BUG=webrtc:6757, chromium:659137, chromium:627816
NOTRY=True

Review-Url: https://codereview.webrtc.org/2607933002
Cr-Commit-Position: refs/heads/master@{#16213}
diff --git a/webrtc/api/stats/rtcstats_objects.h b/webrtc/api/stats/rtcstats_objects.h
index 3bbe228..760ec9e 100644
--- a/webrtc/api/stats/rtcstats_objects.h
+++ b/webrtc/api/stats/rtcstats_objects.h
@@ -268,7 +268,6 @@
   RTCStatsMember<uint32_t> frames_sent;
   RTCStatsMember<uint32_t> frames_received;
   RTCStatsMember<uint32_t> frames_decoded;
-  // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137
   RTCStatsMember<uint32_t> frames_dropped;
   // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137
   RTCStatsMember<uint32_t> frames_corrupted;
diff --git a/webrtc/media/base/mediachannel.h b/webrtc/media/base/mediachannel.h
index ecff95a..4333fa4 100644
--- a/webrtc/media/base/mediachannel.h
+++ b/webrtc/media/base/mediachannel.h
@@ -751,6 +751,7 @@
         framerate_render_output(0),
         frames_received(0),
         frames_decoded(0),
+        frames_rendered(0),
         decode_ms(0),
         max_decode_ms(0),
         jitter_buffer_ms(0),
@@ -779,6 +780,7 @@
   int framerate_render_output;
   uint32_t frames_received;
   uint32_t frames_decoded;
+  uint32_t frames_rendered;
 
   // All stats below are gathered per-VideoReceiver, but some will be correlated
   // across MediaStreamTracks.  NOTE(hta): when sinking stats into per-SSRC
diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc
index 2031ca5..9e7f5c4 100644
--- a/webrtc/media/engine/webrtcvideoengine2.cc
+++ b/webrtc/media/engine/webrtcvideoengine2.cc
@@ -2389,6 +2389,7 @@
   info.frames_received = stats.frame_counts.key_frames +
                          stats.frame_counts.delta_frames;
   info.frames_decoded = stats.frames_decoded;
+  info.frames_rendered = stats.frames_rendered;
 
   info.codec_name = GetCodecNameFromPayloadType(stats.current_payload_type);
 
diff --git a/webrtc/media/engine/webrtcvideoengine2_unittest.cc b/webrtc/media/engine/webrtcvideoengine2_unittest.cc
index dd332f6..f72d7ae 100644
--- a/webrtc/media/engine/webrtcvideoengine2_unittest.cc
+++ b/webrtc/media/engine/webrtcvideoengine2_unittest.cc
@@ -3323,7 +3323,8 @@
   stats.height = 10;
   stats.frame_counts.key_frames = 11;
   stats.frame_counts.delta_frames = 12;
-  stats.frames_decoded = 13;
+  stats.frames_rendered = 13;
+  stats.frames_decoded = 14;
   stream->SetStats(stats);
 
   cricket::VideoMediaInfo info;
@@ -3341,6 +3342,7 @@
   EXPECT_EQ(stats.height, info.receivers[0].frame_height);
   EXPECT_EQ(stats.frame_counts.key_frames + stats.frame_counts.delta_frames,
             info.receivers[0].frames_received);
+  EXPECT_EQ(stats.frames_rendered, info.receivers[0].frames_rendered);
   EXPECT_EQ(stats.frames_decoded, info.receivers[0].frames_decoded);
 }
 
diff --git a/webrtc/pc/rtcstats_integrationtest.cc b/webrtc/pc/rtcstats_integrationtest.cc
index 6bba2cb..0765276 100644
--- a/webrtc/pc/rtcstats_integrationtest.cc
+++ b/webrtc/pc/rtcstats_integrationtest.cc
@@ -444,13 +444,15 @@
             media_stream_track.frames_received);
         verifier.TestMemberIsNonNegative<uint32_t>(
             media_stream_track.frames_decoded);
+        verifier.TestMemberIsNonNegative<uint32_t>(
+            media_stream_track.frames_dropped);
       } else {
         verifier.TestMemberIsNonNegative<uint32_t>(
             media_stream_track.frames_sent);
         verifier.TestMemberIsUndefined(media_stream_track.frames_received);
         verifier.TestMemberIsUndefined(media_stream_track.frames_decoded);
+        verifier.TestMemberIsUndefined(media_stream_track.frames_dropped);
       }
-      verifier.TestMemberIsUndefined(media_stream_track.frames_dropped);
       verifier.TestMemberIsUndefined(media_stream_track.frames_corrupted);
       verifier.TestMemberIsUndefined(media_stream_track.partial_frames_lost);
       verifier.TestMemberIsUndefined(media_stream_track.full_frames_lost);
diff --git a/webrtc/pc/rtcstatscollector.cc b/webrtc/pc/rtcstatscollector.cc
index 1a25f32..774d1d7 100644
--- a/webrtc/pc/rtcstatscollector.cc
+++ b/webrtc/pc/rtcstatscollector.cc
@@ -445,6 +445,10 @@
   // received from. Since we don't support that, this is correct and is the same
   // value as "RTCInboundRTPStreamStats.framesDecoded". crbug.com/659137
   video_track_stats->frames_decoded = video_receiver_info.frames_decoded;
+  RTC_DCHECK_GE(video_receiver_info.frames_received,
+                video_receiver_info.frames_rendered);
+  video_track_stats->frames_dropped = video_receiver_info.frames_received -
+                                      video_receiver_info.frames_rendered;
   return video_track_stats;
 }
 
diff --git a/webrtc/pc/rtcstatscollector_unittest.cc b/webrtc/pc/rtcstatscollector_unittest.cc
index fd6e1ba..d6dbffb 100644
--- a/webrtc/pc/rtcstatscollector_unittest.cc
+++ b/webrtc/pc/rtcstatscollector_unittest.cc
@@ -1542,8 +1542,9 @@
   video_receiver_info_ssrc3.local_stats[0].ssrc = 3;
   video_receiver_info_ssrc3.frame_width = 6789;
   video_receiver_info_ssrc3.frame_height = 9876;
-  video_receiver_info_ssrc3.frames_received = 2468;
-  video_receiver_info_ssrc3.frames_decoded = 1234;
+  video_receiver_info_ssrc3.frames_received = 1000;
+  video_receiver_info_ssrc3.frames_decoded = 995;
+  video_receiver_info_ssrc3.frames_rendered = 990;
 
   // Remote video track with undefined (default) values
   rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc4 =
@@ -1559,6 +1560,7 @@
   video_receiver_info_ssrc4.frame_height = 0;
   video_receiver_info_ssrc4.frames_received = 0;
   video_receiver_info_ssrc4.frames_decoded = 0;
+  video_receiver_info_ssrc4.frames_rendered = 0;
 
   test_->CreateMockRtpSendersReceiversAndChannels(
       {}, {},
@@ -1633,8 +1635,9 @@
   expected_remote_video_track_ssrc3.detached = false;
   expected_remote_video_track_ssrc3.frame_width = 6789;
   expected_remote_video_track_ssrc3.frame_height = 9876;
-  expected_remote_video_track_ssrc3.frames_received = 2468;
-  expected_remote_video_track_ssrc3.frames_decoded = 1234;
+  expected_remote_video_track_ssrc3.frames_received = 1000;
+  expected_remote_video_track_ssrc3.frames_decoded = 995;
+  expected_remote_video_track_ssrc3.frames_dropped = 1000 - 990;
   ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc3.id()));
   EXPECT_EQ(expected_remote_video_track_ssrc3,
             report->Get(expected_remote_video_track_ssrc3.id())->cast_to<
@@ -1650,6 +1653,7 @@
   expected_remote_video_track_ssrc4.detached = false;
   expected_remote_video_track_ssrc4.frames_received = 0;
   expected_remote_video_track_ssrc4.frames_decoded = 0;
+  expected_remote_video_track_ssrc4.frames_dropped = 0;
   // Should be undefined: |expected_remote_video_track_ssrc4.frame_width| and
   // |expected_remote_video_track_ssrc4.frame_height|.
   ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc4.id()));
diff --git a/webrtc/video/receive_statistics_proxy.cc b/webrtc/video/receive_statistics_proxy.cc
index 673fabb..68050ba 100644
--- a/webrtc/video/receive_statistics_proxy.cc
+++ b/webrtc/video/receive_statistics_proxy.cc
@@ -414,6 +414,7 @@
   rtc::CritScope lock(&crit_);
   renders_fps_estimator_.Update(1, now);
   stats_.render_frame_rate = renders_fps_estimator_.Rate(now).value_or(0);
+  ++stats_.frames_rendered;
   stats_.width = width;
   stats_.height = height;
   render_width_counter_.Add(width);
diff --git a/webrtc/video/receive_statistics_proxy_unittest.cc b/webrtc/video/receive_statistics_proxy_unittest.cc
index a485eda..d431bc4 100644
--- a/webrtc/video/receive_statistics_proxy_unittest.cc
+++ b/webrtc/video/receive_statistics_proxy_unittest.cc
@@ -12,6 +12,8 @@
 
 #include <memory>
 
+#include "webrtc/api/video/video_frame.h"
+#include "webrtc/api/video/video_rotation.h"
 #include "webrtc/modules/video_coding/include/video_codec_interface.h"
 #include "webrtc/system_wrappers/include/metrics.h"
 #include "webrtc/system_wrappers/include/metrics_default.h"
@@ -57,6 +59,16 @@
   }
 }
 
+TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
+  EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
+  webrtc::VideoFrame frame(
+      webrtc::I420Buffer::Create(1, 1), 0, 0, webrtc::kVideoRotation_0);
+  for (uint32_t i = 1; i <= 3; ++i) {
+    statistics_proxy_->OnRenderedFrame(frame);
+    EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
+  }
+}
+
 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
   EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
 }
diff --git a/webrtc/video_receive_stream.h b/webrtc/video_receive_stream.h
index 3a0c358..7d97a29 100644
--- a/webrtc/video_receive_stream.h
+++ b/webrtc/video_receive_stream.h
@@ -57,6 +57,7 @@
     int network_frame_rate = 0;
     int decode_frame_rate = 0;
     int render_frame_rate = 0;
+    uint32_t frames_rendered = 0;
 
     // Decoder stats.
     std::string decoder_implementation_name = "unknown";