Initial WebRtcVideoEngine2::GetStats().

Also forward-declaring and moving WebRtcVideoRenderer out of header.

BUG=1788
R=pthatcher@webrtc.org, wu@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/13869004

git-svn-id: http://webrtc.googlecode.com/svn/trunk/talk@6729 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/media/webrtc/webrtcvideoengine2.cc b/media/webrtc/webrtcvideoengine2.cc
index 03c5e14..1ce1b99 100644
--- a/media/webrtc/webrtcvideoengine2.cc
+++ b/media/webrtc/webrtcvideoengine2.cc
@@ -638,8 +638,6 @@
   const webrtc::I420VideoFrame* const frame_;
 };
 
-// WebRtcVideoChannel2
-
 WebRtcVideoChannel2::WebRtcVideoChannel2(
     WebRtcVideoEngine2* engine,
     VoiceMediaChannel* voice_channel,
@@ -1048,10 +1046,36 @@
 
 bool WebRtcVideoChannel2::GetStats(const StatsOptions& options,
                                    VideoMediaInfo* info) {
-  // TODO(pbos): Implement.
+  info->Clear();
+  FillSenderStats(info);
+  FillReceiverStats(info);
+  FillBandwidthEstimationStats(info);
   return true;
 }
 
+void WebRtcVideoChannel2::FillSenderStats(VideoMediaInfo* video_media_info) {
+  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
+           send_streams_.begin();
+       it != send_streams_.end();
+       ++it) {
+    video_media_info->senders.push_back(it->second->GetVideoSenderInfo());
+  }
+}
+
+void WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) {
+  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
+           receive_streams_.begin();
+       it != receive_streams_.end();
+       ++it) {
+    video_media_info->receivers.push_back(it->second->GetVideoReceiverInfo());
+  }
+}
+
+void WebRtcVideoChannel2::FillBandwidthEstimationStats(
+    VideoMediaInfo* video_media_info) {
+  // TODO(pbos): Implement.
+}
+
 bool WebRtcVideoChannel2::SetCapturer(uint32 ssrc, VideoCapturer* capturer) {
   LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> "
                << (capturer != NULL ? "(capturer)" : "NULL");
@@ -1549,6 +1573,60 @@
   sending_ = false;
 }
 
+VideoSenderInfo
+WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
+  VideoSenderInfo info;
+  talk_base::CritScope cs(&lock_);
+  for (size_t i = 0; i < parameters_.config.rtp.ssrcs.size(); ++i) {
+    info.add_ssrc(parameters_.config.rtp.ssrcs[i]);
+  }
+
+  webrtc::VideoSendStream::Stats stats = stream_->GetStats();
+  info.framerate_input = stats.input_frame_rate;
+  info.framerate_sent = stats.encode_frame_rate;
+
+  for (std::map<uint32_t, webrtc::StreamStats>::iterator it =
+           stats.substreams.begin();
+       it != stats.substreams.end();
+       ++it) {
+    // TODO(pbos): Wire up additional stats, such as padding bytes.
+    webrtc::StreamStats stream_stats = it->second;
+    info.bytes_sent += stream_stats.rtp_stats.bytes +
+                       stream_stats.rtp_stats.header_bytes +
+                       stream_stats.rtp_stats.padding_bytes;
+    info.packets_sent += stream_stats.rtp_stats.packets;
+    info.packets_lost += stream_stats.rtcp_stats.cumulative_lost;
+  }
+
+  if (!stats.substreams.empty()) {
+    // TODO(pbos): Report fraction lost per SSRC.
+    webrtc::StreamStats first_stream_stats = stats.substreams.begin()->second;
+    info.fraction_lost =
+        static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) /
+        (1 << 8);
+  }
+
+  if (capturer_ != NULL && !capturer_->IsMuted()) {
+    VideoFormat last_captured_frame_format;
+    capturer_->GetStats(&info.adapt_frame_drops,
+                        &info.effects_frame_drops,
+                        &info.capturer_frame_time,
+                        &last_captured_frame_format);
+    info.input_frame_width = last_captured_frame_format.width;
+    info.input_frame_height = last_captured_frame_format.height;
+    info.send_frame_width =
+        static_cast<int>(parameters_.video_streams.front().width);
+    info.send_frame_height =
+        static_cast<int>(parameters_.video_streams.front().height);
+  }
+
+  // TODO(pbos): Support or remove the following stats.
+  info.packets_cached = -1;
+  info.rtt_ms = -1;
+
+  return info;
+}
+
 void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
   if (stream_ != NULL) {
     call_->DestroyVideoSendStream(stream_);
@@ -1671,6 +1749,29 @@
   last_height_ = height;
 }
 
+VideoReceiverInfo
+WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() {
+  VideoReceiverInfo info;
+  info.add_ssrc(config_.rtp.remote_ssrc);
+  webrtc::VideoReceiveStream::Stats stats = stream_->GetStats();
+  info.bytes_rcvd = stats.rtp_stats.bytes + stats.rtp_stats.header_bytes +
+                    stats.rtp_stats.padding_bytes;
+  info.packets_rcvd = stats.rtp_stats.packets;
+
+  info.framerate_rcvd = stats.network_frame_rate;
+  info.framerate_decoded = stats.decode_frame_rate;
+  info.framerate_output = stats.render_frame_rate;
+
+  talk_base::CritScope frame_cs(&renderer_lock_);
+  info.frame_width = last_width_;
+  info.frame_height = last_height_;
+
+  // TODO(pbos): Support or remove the following stats.
+  info.packets_concealed = -1;
+
+  return info;
+}
+
 WebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings()
     : rtx_payload_type(-1) {}
 
diff --git a/media/webrtc/webrtcvideoengine2.h b/media/webrtc/webrtcvideoengine2.h
index fe798b5..e93f571 100644
--- a/media/webrtc/webrtcvideoengine2.h
+++ b/media/webrtc/webrtcvideoengine2.h
@@ -80,6 +80,7 @@
 
 class WebRtcVideoEngine2;
 class WebRtcVideoChannel2;
+class WebRtcVideoRenderer;
 
 class WebRtcVideoEncoderFactory2 {
  public:
@@ -277,6 +278,8 @@
     void Start();
     void Stop();
 
+    VideoSenderInfo GetVideoSenderInfo();
+
    private:
     // Parameters needed to reconstruct the underlying stream.
     // webrtc::VideoSendStream doesn't support setting a lot of options on the
@@ -337,6 +340,8 @@
     void SetRenderer(cricket::VideoRenderer* renderer);
     cricket::VideoRenderer* GetRenderer();
 
+    VideoReceiverInfo GetVideoReceiverInfo();
+
    private:
     void SetSize(int width, int height);
     void RecreateWebRtcStream();
@@ -348,8 +353,8 @@
 
     talk_base::CriticalSection renderer_lock_;
     cricket::VideoRenderer* renderer_ GUARDED_BY(renderer_lock_);
-    int last_width_;
-    int last_height_;
+    int last_width_ GUARDED_BY(renderer_lock_);
+    int last_height_ GUARDED_BY(renderer_lock_);
   };
 
   void Construct(webrtc::Call* call, WebRtcVideoEngine2* engine);
@@ -365,6 +370,10 @@
   std::vector<VideoCodecSettings> FilterSupportedCodecs(
       const std::vector<VideoCodecSettings>& mapped_codecs);
 
+  void FillSenderStats(VideoMediaInfo* info);
+  void FillReceiverStats(VideoMediaInfo* info);
+  void FillBandwidthEstimationStats(VideoMediaInfo* info);
+
   uint32_t rtcp_receiver_report_ssrc_;
   bool sending_;
   talk_base::scoped_ptr<webrtc::Call> call_;
diff --git a/media/webrtc/webrtcvideoengine2_unittest.cc b/media/webrtc/webrtcvideoengine2_unittest.cc
index d272929..0954bcb 100644
--- a/media/webrtc/webrtcvideoengine2_unittest.cc
+++ b/media/webrtc/webrtcvideoengine2_unittest.cc
@@ -451,15 +451,13 @@
   Base::SetSendSetsTransportBufferSizes();
 }
 
-// TODO(juberti): Fix this test to tolerate missing stats.
-TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_GetStats) { Base::GetStats(); }
+TEST_F(WebRtcVideoChannel2BaseTest, GetStats) { Base::GetStats(); }
 
-// TODO(juberti): Fix this test to tolerate missing stats.
-TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_GetStatsMultipleRecvStreams) {
+TEST_F(WebRtcVideoChannel2BaseTest, GetStatsMultipleRecvStreams) {
   Base::GetStatsMultipleRecvStreams();
 }
 
-TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_GetStatsMultipleSendStreams) {
+TEST_F(WebRtcVideoChannel2BaseTest, GetStatsMultipleSendStreams) {
   Base::GetStatsMultipleSendStreams();
 }