Get VideoCapturer stats via VideoTrackSourceInterface in StatsCollector,
without involving the VideoMediaChannel.

BUG=webrtc:5426

Review URL: https://codereview.webrtc.org/1827023002

Cr-Commit-Position: refs/heads/master@{#12193}
diff --git a/webrtc/api/mediastreaminterface.h b/webrtc/api/mediastreaminterface.h
index 349fcc0..f1730c5 100644
--- a/webrtc/api/mediastreaminterface.h
+++ b/webrtc/api/mediastreaminterface.h
@@ -88,6 +88,10 @@
   static const char kAudioKind[];
   static const char kVideoKind[];
 
+  // The kind() method must return kAudioKind only if the object is a
+  // subclass of AudioTrackInterface, and kVideoKind only if the
+  // object is a subclass of VideoTrackInterface. It is typically used
+  // to protect a static_cast<> to the corresponding subclass.
   virtual std::string kind() const = 0;
   virtual std::string id() const = 0;
   virtual bool enabled() const = 0;
@@ -106,6 +110,11 @@
     : public MediaSourceInterface,
       public rtc::VideoSourceInterface<cricket::VideoFrame> {
  public:
+  struct Stats {
+    // Original size of captured frame, before video adaptation.
+    int input_width;
+    int input_height;
+  };
   // Get access to the source implementation of cricket::VideoCapturer.
   // This can be used for receiving frames and state notifications.
   // But it should not be used for starting or stopping capturing.
@@ -132,6 +141,11 @@
   // the encoder.
   virtual rtc::Optional<bool> needs_denoising() const = 0;
 
+  // Returns false if no stats are available, e.g, for a remote
+  // source, or a source which has not seen its first frame yet.
+  // Should avoid blocking.
+  virtual bool GetStats(Stats* stats) = 0;
+
  protected:
   virtual ~VideoTrackSourceInterface() {}
 };
diff --git a/webrtc/api/rtpsender.h b/webrtc/api/rtpsender.h
index 879a332..3919e07 100644
--- a/webrtc/api/rtpsender.h
+++ b/webrtc/api/rtpsender.h
@@ -101,6 +101,8 @@
   bool SetParameters(const RtpParameters& parameters);
 
  private:
+  // TODO(nisse): Since SSRC == 0 is technically valid, figure out
+  // some other way to test if we have a valid SSRC.
   bool can_send_track() const { return track_ && ssrc_; }
   // Helper function to construct options for
   // AudioProviderInterface::SetAudioSend.
diff --git a/webrtc/api/statscollector.cc b/webrtc/api/statscollector.cc
index d77953b..0182a37 100644
--- a/webrtc/api/statscollector.cc
+++ b/webrtc/api/statscollector.cc
@@ -236,11 +236,9 @@
     { StatsReport::kStatsValueNameEncodeUsagePercent,
       info.encode_usage_percent },
     { StatsReport::kStatsValueNameFirsReceived, info.firs_rcvd },
-    { StatsReport::kStatsValueNameFrameHeightInput, info.input_frame_height },
     { StatsReport::kStatsValueNameFrameHeightSent, info.send_frame_height },
     { StatsReport::kStatsValueNameFrameRateInput, info.framerate_input },
     { StatsReport::kStatsValueNameFrameRateSent, info.framerate_sent },
-    { StatsReport::kStatsValueNameFrameWidthInput, info.input_frame_width },
     { StatsReport::kStatsValueNameFrameWidthSent, info.send_frame_width },
     { StatsReport::kStatsValueNameNacksReceived, info.nacks_rcvd },
     { StatsReport::kStatsValueNamePacketsLost, info.packets_lost },
@@ -474,6 +472,7 @@
     ExtractSessionInfo();
     ExtractVoiceInfo();
     ExtractVideoInfo(level);
+    ExtractSenderInfo();
     ExtractDataInfo();
     UpdateTrackReports();
   }
@@ -828,6 +827,39 @@
   }
 }
 
+void StatsCollector::ExtractSenderInfo() {
+  RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
+
+  for (const auto& sender : pc_->GetSenders()) {
+    // TODO(nisse): SSRC == 0 currently means none. Delete check when
+    // that is fixed.
+    if (!sender->ssrc()) {
+      continue;
+    }
+    const rtc::scoped_refptr<MediaStreamTrackInterface> track(sender->track());
+    if (!track || track->kind() != MediaStreamTrackInterface::kVideoKind) {
+      continue;
+    }
+    // Safe, because kind() == kVideoKind implies a subclass of
+    // VideoTrackInterface; see mediastreaminterface.h.
+    VideoTrackSourceInterface* source =
+        static_cast<VideoTrackInterface*>(track.get())->GetSource();
+
+    VideoTrackSourceInterface::Stats stats;
+    if (!source->GetStats(&stats)) {
+      continue;
+    }
+    const StatsReport::Id stats_id = StatsReport::NewIdWithDirection(
+        StatsReport::kStatsReportTypeSsrc,
+        rtc::ToString<uint32_t>(sender->ssrc()), StatsReport::kSend);
+    StatsReport* report = reports_.FindOrAddNew(stats_id);
+    report->AddInt(StatsReport::kStatsValueNameFrameWidthInput,
+                   stats.input_width);
+    report->AddInt(StatsReport::kStatsValueNameFrameHeightInput,
+                   stats.input_height);
+  }
+}
+
 void StatsCollector::ExtractDataInfo() {
   RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
 
diff --git a/webrtc/api/statscollector.h b/webrtc/api/statscollector.h
index 3757279..8c359e4 100644
--- a/webrtc/api/statscollector.h
+++ b/webrtc/api/statscollector.h
@@ -113,6 +113,7 @@
   void ExtractSessionInfo();
   void ExtractVoiceInfo();
   void ExtractVideoInfo(PeerConnectionInterface::StatsOutputLevel level);
+  void ExtractSenderInfo();
   void BuildSsrcToTransportId();
   webrtc::StatsReport* GetReport(const StatsReport::StatsType& type,
                                  const std::string& id,
diff --git a/webrtc/api/videocapturertracksource.cc b/webrtc/api/videocapturertracksource.cc
index 0543dff..cb53961 100644
--- a/webrtc/api/videocapturertracksource.cc
+++ b/webrtc/api/videocapturertracksource.cc
@@ -360,6 +360,11 @@
   // Initialize hasn't succeeded until a successful state change has occurred.
 }
 
+bool VideoCapturerTrackSource::GetStats(Stats* stats) {
+  return video_capturer_->GetInputSize(&stats->input_width,
+                                       &stats->input_height);
+}
+
 void VideoCapturerTrackSource::Stop() {
   if (!started_) {
     return;
diff --git a/webrtc/api/videocapturertracksource.h b/webrtc/api/videocapturertracksource.h
index 3673bf7..0d1142d 100644
--- a/webrtc/api/videocapturertracksource.h
+++ b/webrtc/api/videocapturertracksource.h
@@ -58,6 +58,8 @@
     return needs_denoising_;
   }
 
+  bool GetStats(Stats* stats) override;
+
   void Stop() override;
   void Restart() override;
 
diff --git a/webrtc/api/videosourceproxy.h b/webrtc/api/videosourceproxy.h
index fa6c428..f43c0db 100644
--- a/webrtc/api/videosourceproxy.h
+++ b/webrtc/api/videosourceproxy.h
@@ -28,6 +28,7 @@
 PROXY_METHOD0(void, Restart)
 PROXY_CONSTMETHOD0(bool, is_screencast)
 PROXY_CONSTMETHOD0(rtc::Optional<bool>, needs_denoising)
+PROXY_METHOD1(bool, GetStats, Stats*)
 PROXY_METHOD2(void,
               AddOrUpdateSink,
               rtc::VideoSinkInterface<cricket::VideoFrame>*,
diff --git a/webrtc/api/videotracksource.h b/webrtc/api/videotracksource.h
index 6d23d2e..108209d 100644
--- a/webrtc/api/videotracksource.h
+++ b/webrtc/api/videotracksource.h
@@ -40,6 +40,8 @@
   virtual rtc::Optional<bool> needs_denoising() const {
     return rtc::Optional<bool>(); }
 
+  bool GetStats(Stats* stats) override { return false; }
+
   void AddOrUpdateSink(rtc::VideoSinkInterface<cricket::VideoFrame>* sink,
                        const rtc::VideoSinkWants& wants) override;
   void RemoveSink(rtc::VideoSinkInterface<cricket::VideoFrame>* sink) override;