PeerConnection[Interface]::GetStats(RTCStatsCollectorCallback*) added.

New file structure and targets:

rtc_stats_api
  webrtc/api/stats/rtcstats.h
  webrtc/api/stats/rtcstats_objects.h
  webrtc/api/stats/rtcstatsreport.h

rtc_stats (dep on rtc_stats_api)
  webrtc/stats/rtcstats.cc
  webrtc/stats/rtcstats_objects.cc
  webrtc/stats/rtcstatsreport.cc

libjingle_peerconnection (dep on rtc_stats)
  webrtc/api/rtcstatscollector.cc
  webrtc/api/rtcstatscollector.h

Placing rtc_stats_api headers in this separate target instead of
libjingle_peerconnection avoids a circular dependency
libjingle_peerconnection -> rtc_stats -> libjingle_peerconnection

Code changes:

PeerConnectionInterface::GetStats(RTCStatsCollectorCallback*) added for
the new stats collection API. Implemented by PeerConnection.

BUG=chromium:627816

Review-Url: https://codereview.webrtc.org/2331373004
Cr-Commit-Position: refs/heads/master@{#14246}
diff --git a/.gn b/.gn
index 65bc7dd..db61a47 100644
--- a/.gn
+++ b/.gn
@@ -20,18 +20,20 @@
 # "gn check" or "gn gen --check".
 # TODO(kjellander): Keep adding paths to this list as work in webrtc:5589 is done.
 check_targets = [
+  "//webrtc/api:rtc_stats_api",
   "//webrtc/modules/audio_coding:g711_test",
   "//webrtc/modules/audio_coding:g722_test",
+  "//webrtc/modules/audio_coding:ilbc_test",
+  "//webrtc/modules/audio_coding:isac",
+  "//webrtc/modules/audio_coding:isac_api_test",
   "//webrtc/modules/audio_coding:isac_fix_test",
+  "//webrtc/modules/audio_coding:isac_switch_samprate_test",
   "//webrtc/modules/audio_coding:isac_test",
   "//webrtc/modules/audio_coding:webrtc_opus_fec_test",
   "//webrtc/modules/audio_device/*",
   "//webrtc/modules/audio_mixer/*",
+  "//webrtc/stats:rtc_stats",
   "//webrtc/voice_engine:level_indicator",
-  "//webrtc/modules/audio_coding:ilbc_test",
-  "//webrtc/modules/audio_coding:isac",
-  "//webrtc/modules/audio_coding:isac_api_test",
-  "//webrtc/modules/audio_coding:isac_switch_samprate_test",
 ]
 
 # These are the list of GN files that run exec_script. This whitelist exists
diff --git a/webrtc/api/BUILD.gn b/webrtc/api/BUILD.gn
index 4f15bc4..b7cd679 100644
--- a/webrtc/api/BUILD.gn
+++ b/webrtc/api/BUILD.gn
@@ -84,9 +84,8 @@
     "proxy.h",
     "remoteaudiosource.cc",
     "remoteaudiosource.h",
-    "rtcstats.h",
-    "rtcstats_objects.h",
-    "rtcstatsreport.h",
+    "rtcstatscollector.cc",
+    "rtcstatscollector.h",
     "rtpparameters.h",
     "rtpreceiver.cc",
     "rtpreceiver.h",
@@ -125,9 +124,11 @@
 
   deps = [
     ":call_api",
+    ":rtc_stats_api",
     "../call",
     "../media",
     "../pc",
+    "../stats",
   ]
 
   if (rtc_use_quic) {
@@ -298,6 +299,20 @@
   }
 }
 
+# GYP version: webrtc/api/api.gyp:rtc_stats_api
+rtc_source_set("rtc_stats_api") {
+  cflags = []
+  sources = [
+    "stats/rtcstats.h",
+    "stats/rtcstats_objects.h",
+    "stats/rtcstatsreport.h",
+  ]
+
+  deps = [
+    "../base:rtc_base_approved",
+  ]
+}
+
 if (rtc_include_tests) {
   config("peerconnection_unittests_config") {
     # The warnings below are enabled by default. Since GN orders compiler flags
@@ -336,6 +351,7 @@
       "peerconnectionfactory_unittest.cc",
       "peerconnectioninterface_unittest.cc",
       "proxy_unittest.cc",
+      "rtcstatscollector_unittest.cc",
       "rtpsenderreceiver_unittest.cc",
       "statscollector_unittest.cc",
       "test/fakeaudiocapturemodule.cc",
diff --git a/webrtc/api/api.gyp b/webrtc/api/api.gyp
index 5b14fdf..d017cda 100644
--- a/webrtc/api/api.gyp
+++ b/webrtc/api/api.gyp
@@ -115,8 +115,10 @@
       'type': 'static_library',
       'dependencies': [
         ':call_api',
+        ':rtc_stats_api',
         '<(webrtc_root)/media/media.gyp:rtc_media',
         '<(webrtc_root)/pc/pc.gyp:rtc_pc',
+        '<(webrtc_root)/stats/stats.gyp:rtc_stats',
       ],
       'sources': [
         'audiotrack.cc',
@@ -157,9 +159,8 @@
         'proxy.h',
         'remoteaudiosource.cc',
         'remoteaudiosource.h',
-        'rtcstats.h',
-        'rtcstats_objects.h',
-        'rtcstatsreport.h',
+        'rtcstatscollector.cc',
+        'rtcstatscollector.h',
         'rtpparameters.h',
         'rtpreceiver.cc',
         'rtpreceiver.h',
@@ -217,5 +218,18 @@
         }],
       ],
     },  # target libjingle_peerconnection
+    {
+      # GN version: webrtc/api:rtc_stats_api
+      'target_name': 'rtc_stats_api',
+      'type': 'static_library',
+      'dependencies': [
+        '<(webrtc_root)/base/base.gyp:rtc_base_approved',
+      ],
+      'sources': [
+        'stats/rtcstats.h',
+        'stats/rtcstats_objects.h',
+        'stats/rtcstatsreport.h',
+      ],
+    },  # target rtc_stats_api
   ],  # targets
 }
diff --git a/webrtc/api/peerconnection.cc b/webrtc/api/peerconnection.cc
index bdd33d7..144b1c6 100644
--- a/webrtc/api/peerconnection.cc
+++ b/webrtc/api/peerconnection.cc
@@ -632,6 +632,7 @@
               configuration.redetermine_role_on_ice_restart))));
 
   stats_.reset(new StatsCollector(this));
+  stats_collector_ = RTCStatsCollector::Create(this);
 
   enable_ice_renomination_ = configuration.enable_ice_renomination;
 
@@ -888,6 +889,11 @@
   return true;
 }
 
+void PeerConnection::GetStats(RTCStatsCollectorCallback* callback) {
+  RTC_DCHECK(stats_collector_);
+  stats_collector_->GetStatsReport(callback);
+}
+
 PeerConnectionInterface::SignalingState PeerConnection::signaling_state() {
   return signaling_state_;
 }
diff --git a/webrtc/api/peerconnection.h b/webrtc/api/peerconnection.h
index 042e7f1..3087160 100644
--- a/webrtc/api/peerconnection.h
+++ b/webrtc/api/peerconnection.h
@@ -18,6 +18,7 @@
 
 #include "webrtc/api/peerconnectionfactory.h"
 #include "webrtc/api/peerconnectioninterface.h"
+#include "webrtc/api/rtcstatscollector.h"
 #include "webrtc/api/rtpreceiver.h"
 #include "webrtc/api/rtpsender.h"
 #include "webrtc/api/statscollector.h"
@@ -102,6 +103,7 @@
   bool GetStats(StatsObserver* observer,
                 webrtc::MediaStreamTrackInterface* track,
                 StatsOutputLevel level) override;
+  void GetStats(RTCStatsCollectorCallback* callback) override;
 
   SignalingState signaling_state() override;
 
@@ -427,6 +429,7 @@
 
   std::unique_ptr<WebRtcSession> session_;
   std::unique_ptr<StatsCollector> stats_;
+  rtc::scoped_refptr<RTCStatsCollector> stats_collector_;
 };
 
 }  // namespace webrtc
diff --git a/webrtc/api/peerconnectioninterface.h b/webrtc/api/peerconnectioninterface.h
index f5d8c63..a04e53e 100644
--- a/webrtc/api/peerconnectioninterface.h
+++ b/webrtc/api/peerconnectioninterface.h
@@ -60,6 +60,7 @@
 #include "webrtc/api/dtmfsenderinterface.h"
 #include "webrtc/api/jsep.h"
 #include "webrtc/api/mediastreaminterface.h"
+#include "webrtc/api/rtcstatscollector.h"
 #include "webrtc/api/rtpreceiverinterface.h"
 #include "webrtc/api/rtpsenderinterface.h"
 #include "webrtc/api/statstypes.h"
@@ -440,6 +441,12 @@
   virtual bool GetStats(StatsObserver* observer,
                         MediaStreamTrackInterface* track,
                         StatsOutputLevel level) = 0;
+  // Gets stats using the new stats collection API, see webrtc/api/stats/. These
+  // will replace old stats collection API when the new API has matured enough.
+  // TODO(hbos): Default implementation that does nothing only exists as to not
+  // break third party projects. As soon as they have been updated this should
+  // be changed to "= 0;".
+  virtual void GetStats(RTCStatsCollectorCallback* callback) {}
 
   virtual rtc::scoped_refptr<DataChannelInterface> CreateDataChannel(
       const std::string& label,
diff --git a/webrtc/api/peerconnectionproxy.h b/webrtc/api/peerconnectionproxy.h
index 37f2e89..8c15b3d 100644
--- a/webrtc/api/peerconnectionproxy.h
+++ b/webrtc/api/peerconnectionproxy.h
@@ -42,6 +42,7 @@
   PROXY_METHOD3(bool, GetStats, StatsObserver*,
                 MediaStreamTrackInterface*,
                 StatsOutputLevel)
+  PROXY_METHOD1(void, GetStats, RTCStatsCollectorCallback*)
   PROXY_METHOD2(rtc::scoped_refptr<DataChannelInterface>,
                 CreateDataChannel, const std::string&, const DataChannelInit*)
   PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, local_description)
diff --git a/webrtc/api/rtcstats.h b/webrtc/api/rtcstats.h
index e2cbf29..55aeb1d 100644
--- a/webrtc/api/rtcstats.h
+++ b/webrtc/api/rtcstats.h
@@ -8,274 +8,6 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef WEBRTC_API_RTCSTATS_H_
-#define WEBRTC_API_RTCSTATS_H_
+// TODO(hbos): Remove this file once Chromium uses the correct include path.
 
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "webrtc/base/checks.h"
-
-namespace webrtc {
-
-class RTCStatsMemberInterface;
-
-// Abstract base class for RTCStats-derived dictionaries, see
-// https://w3c.github.io/webrtc-stats/.
-//
-// All derived classes must have the following static variable defined:
-//   static const char kType[];
-// It is used as a unique class identifier and a string representation of the
-// class type, see https://w3c.github.io/webrtc-stats/#rtcstatstype-str*.
-// Use the |WEBRTC_RTCSTATS_IMPL| macro when implementing subclasses, see macro
-// for details.
-//
-// Derived classes list their dictionary members, RTCStatsMember<T>, as public
-// fields, allowing the following:
-//
-// RTCFooStats foo("fooId", GetCurrentTime());
-// foo.bar = 42;
-// foo.baz = std::vector<std::string>();
-// foo.baz->push_back("hello world");
-// uint32_t x = *foo.bar;
-//
-// Pointers to all the members are available with |Members|, allowing iteration:
-//
-// for (const RTCStatsMemberInterface* member : foo.Members()) {
-//   printf("%s = %s\n", member->name(), member->ValueToString().c_str());
-// }
-class RTCStats {
- public:
-  RTCStats(const std::string& id, int64_t timestamp_us)
-      : id_(id), timestamp_us_(timestamp_us) {}
-  RTCStats(std::string&& id, int64_t timestamp_us)
-      : id_(std::move(id)), timestamp_us_(timestamp_us) {}
-  virtual ~RTCStats() {}
-
-  virtual std::unique_ptr<RTCStats> copy() const = 0;
-
-  const std::string& id() const { return id_; }
-  // Time relative to the UNIX epoch (Jan 1, 1970, UTC), in microseconds.
-  int64_t timestamp_us() const { return timestamp_us_; }
-  // Returns the static member variable |kType| of the implementing class.
-  virtual const char* type() const = 0;
-  // Returns a vector of pointers to all the RTCStatsMemberInterface members of
-  // this class. This allows for iteration of members.
-  std::vector<const RTCStatsMemberInterface*> Members() const;
-
-  // Creates a human readable string representation of the report, listing all
-  // of its members (names and values).
-  std::string ToString() const;
-
-  // Downcasts the stats object to an |RTCStats| subclass |T|. DCHECKs that the
-  // object is of type |T|.
-  template<typename T>
-  const T& cast_to() const {
-    RTC_DCHECK_EQ(type(), T::kType);
-    return static_cast<const T&>(*this);
-  }
-
- protected:
-  // Gets a vector of all members of this |RTCStats| object, including members
-  // derived from parent classes. |additional_capacity| is how many more members
-  // shall be reserved in the vector (so that subclasses can allocate a vector
-  // with room for both parent and child members without it having to resize).
-  virtual std::vector<const RTCStatsMemberInterface*>
-  MembersOfThisObjectAndAncestors(
-      size_t additional_capacity) const;
-
-  std::string const id_;
-  int64_t timestamp_us_;
-};
-
-// All |RTCStats| classes should use this macro in a public section of the class
-// definition.
-//
-// This macro declares the static |kType| and overrides methods as required by
-// subclasses of |RTCStats|: |copy|, |type|, and
-// |MembersOfThisObjectAndAncestors|. The |...| argument is a list of addresses
-// to each member defined in the implementing class (list cannot be empty, must
-// have at least one new member).
-//
-// (Since class names need to be known to implement these methods this cannot be
-// part of the base |RTCStats|. While these methods could be implemented using
-// templates, that would only work for immediate subclasses. Subclasses of
-// subclasses also have to override these methods, resulting in boilerplate
-// code. Using a macro avoids this and works for any |RTCStats| class, including
-// grandchildren.)
-//
-// Sample usage:
-//
-// rtcfoostats.h:
-//   class RTCFooStats : public RTCStats {
-//    public:
-//     RTCFooStats(const std::string& id, int64_t timestamp_us)
-//         : RTCStats(id, timestamp_us),
-//           foo("foo"),
-//           bar("bar") {
-//     }
-//
-//     WEBRTC_RTCSTATS_IMPL(RTCStats, RTCFooStats,
-//         &foo,
-//         &bar);
-//
-//     RTCStatsMember<int32_t> foo;
-//     RTCStatsMember<int32_t> bar;
-//   };
-//
-// rtcfoostats.cc:
-//   const char RTCFooStats::kType[] = "foo-stats";
-//
-#define WEBRTC_RTCSTATS_IMPL(parent_class, this_class, ...)                    \
- public:                                                                       \
-  static const char kType[];                                                   \
-  std::unique_ptr<webrtc::RTCStats> copy() const override {                    \
-    return std::unique_ptr<webrtc::RTCStats>(new this_class(*this));           \
-  }                                                                            \
-  const char* type() const override { return this_class::kType; }              \
- protected:                                                                    \
-  std::vector<const webrtc::RTCStatsMemberInterface*>                          \
-  MembersOfThisObjectAndAncestors(                                             \
-      size_t local_var_additional_capacity) const override {                   \
-    const webrtc::RTCStatsMemberInterface* local_var_members[] = {             \
-      __VA_ARGS__                                                              \
-    };                                                                         \
-    size_t local_var_members_count =                                           \
-        sizeof(local_var_members) / sizeof(local_var_members[0]);              \
-    std::vector<const webrtc::RTCStatsMemberInterface*> local_var_members_vec =\
-        parent_class::MembersOfThisObjectAndAncestors(                         \
-            local_var_members_count + local_var_additional_capacity);          \
-    RTC_DCHECK_GE(                                                             \
-        local_var_members_vec.capacity() - local_var_members_vec.size(),       \
-        local_var_members_count + local_var_additional_capacity);              \
-    local_var_members_vec.insert(local_var_members_vec.end(),                  \
-                                 &local_var_members[0],                        \
-                                 &local_var_members[local_var_members_count]); \
-    return local_var_members_vec;                                              \
-  }                                                                            \
- public:
-
-// Interface for |RTCStats| members, which have a name and a value of a type
-// defined in a subclass. Only the types listed in |Type| are supported, these
-// are implemented by |RTCStatsMember<T>|. The value of a member may be
-// undefined, the value can only be read if |is_defined|.
-class RTCStatsMemberInterface {
- public:
-  // Member value types.
-  enum Type {
-    kInt32,                 // int32_t
-    kUint32,                // uint32_t
-    kInt64,                 // int64_t
-    kUint64,                // uint64_t
-    kDouble,                // double
-    kString,                // std::string
-
-    kSequenceInt32,         // std::vector<int32_t>
-    kSequenceUint32,        // std::vector<uint32_t>
-    kSequenceInt64,         // std::vector<int64_t>
-    kSequenceUint64,        // std::vector<uint64_t>
-    kSequenceDouble,        // std::vector<double>
-    kSequenceString,        // std::vector<std::string>
-  };
-
-  virtual ~RTCStatsMemberInterface() {}
-
-  const char* name() const { return name_; }
-  virtual Type type() const = 0;
-  virtual bool is_sequence() const = 0;
-  virtual bool is_string() const = 0;
-  bool is_defined() const { return is_defined_; }
-  virtual std::string ValueToString() const = 0;
-
-  template<typename T>
-  const T& cast_to() const {
-    RTC_DCHECK_EQ(type(), T::kType);
-    return static_cast<const T&>(*this);
-  }
-
- protected:
-  RTCStatsMemberInterface(const char* name, bool is_defined)
-      : name_(name), is_defined_(is_defined) {}
-
-  const char* const name_;
-  bool is_defined_;
-};
-
-// Template implementation of |RTCStatsMemberInterface|. Every possible |T| is
-// specialized in rtcstats.cc, using a different |T| results in a linker error
-// (undefined reference to |kType|). The supported types are the ones described
-// by |RTCStatsMemberInterface::Type|.
-template<typename T>
-class RTCStatsMember : public RTCStatsMemberInterface {
- public:
-  static const Type kType;
-
-  explicit RTCStatsMember(const char* name)
-      : RTCStatsMemberInterface(name, false),
-        value_() {}
-  RTCStatsMember(const char* name, const T& value)
-      : RTCStatsMemberInterface(name, true),
-        value_(value) {}
-  RTCStatsMember(const char* name, T&& value)
-      : RTCStatsMemberInterface(name, true),
-        value_(std::move(value)) {}
-  explicit RTCStatsMember(const RTCStatsMember<T>& other)
-      : RTCStatsMemberInterface(other.name_, other.is_defined_),
-        value_(other.value_) {}
-  explicit RTCStatsMember(RTCStatsMember<T>&& other)
-      : RTCStatsMemberInterface(other.name_, other.is_defined_),
-        value_(std::move(other.value_)) {}
-
-  Type type() const override { return kType; }
-  bool is_sequence() const override;
-  bool is_string() const override;
-  std::string ValueToString() const override;
-
-  // Assignment operators.
-  T& operator=(const T& value) {
-    value_ = value;
-    is_defined_ = true;
-    return value_;
-  }
-  T& operator=(const T&& value) {
-    value_ = std::move(value);
-    is_defined_ = true;
-    return value_;
-  }
-  T& operator=(const RTCStatsMember<T>& other) {
-    RTC_DCHECK(other.is_defined_);
-    value_ = other.is_defined_;
-    is_defined_ = true;
-    return value_;
-  }
-
-  // Value getters.
-  T& operator*() {
-    RTC_DCHECK(is_defined_);
-    return value_;
-  }
-  const T& operator*() const {
-    RTC_DCHECK(is_defined_);
-    return value_;
-  }
-
-  // Value getters, arrow operator.
-  T* operator->() {
-    RTC_DCHECK(is_defined_);
-    return &value_;
-  }
-  const T* operator->() const {
-    RTC_DCHECK(is_defined_);
-    return &value_;
-  }
-
- private:
-  T value_;
-};
-
-}  // namespace webrtc
-
-#endif  // WEBRTC_API_RTCSTATS_H_
+#include "webrtc/api/stats/rtcstats.h"
diff --git a/webrtc/stats/rtcstatscollector.cc b/webrtc/api/rtcstatscollector.cc
similarity index 98%
rename from webrtc/stats/rtcstatscollector.cc
rename to webrtc/api/rtcstatscollector.cc
index 3ff4155..d2938a4 100644
--- a/webrtc/stats/rtcstatscollector.cc
+++ b/webrtc/api/rtcstatscollector.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "webrtc/stats/rtcstatscollector.h"
+#include "webrtc/api/rtcstatscollector.h"
 
 #include <memory>
 #include <utility>
diff --git a/webrtc/stats/rtcstatscollector.h b/webrtc/api/rtcstatscollector.h
similarity index 93%
rename from webrtc/stats/rtcstatscollector.h
rename to webrtc/api/rtcstatscollector.h
index ee59a10..61edc52 100644
--- a/webrtc/stats/rtcstatscollector.h
+++ b/webrtc/api/rtcstatscollector.h
@@ -8,14 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef WEBRTC_STATS_RTCSTATSCOLLECTOR_H_
-#define WEBRTC_STATS_RTCSTATSCOLLECTOR_H_
+#ifndef WEBRTC_API_RTCSTATSCOLLECTOR_H_
+#define WEBRTC_API_RTCSTATSCOLLECTOR_H_
 
 #include <memory>
 #include <vector>
 
-#include "webrtc/api/rtcstats_objects.h"
-#include "webrtc/api/rtcstatsreport.h"
+#include "webrtc/api/stats/rtcstats_objects.h"
+#include "webrtc/api/stats/rtcstatsreport.h"
 #include "webrtc/base/asyncinvoker.h"
 #include "webrtc/base/refcount.h"
 #include "webrtc/base/scoped_ref_ptr.h"
@@ -94,4 +94,4 @@
 
 }  // namespace webrtc
 
-#endif  // WEBRTC_STATS_RTCSTATSCOLLECTOR_H_
+#endif  // WEBRTC_API_RTCSTATSCOLLECTOR_H_
diff --git a/webrtc/stats/rtcstatscollector_unittest.cc b/webrtc/api/rtcstatscollector_unittest.cc
similarity index 98%
rename from webrtc/stats/rtcstatscollector_unittest.cc
rename to webrtc/api/rtcstatscollector_unittest.cc
index a90c334..446990c 100644
--- a/webrtc/stats/rtcstatscollector_unittest.cc
+++ b/webrtc/api/rtcstatscollector_unittest.cc
@@ -8,15 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "webrtc/stats/rtcstatscollector.h"
+#include "webrtc/api/rtcstatscollector.h"
 
 #include <memory>
 #include <string>
 #include <vector>
 
 #include "webrtc/api/jsepsessiondescription.h"
-#include "webrtc/api/rtcstats_objects.h"
-#include "webrtc/api/rtcstatsreport.h"
+#include "webrtc/api/stats/rtcstats_objects.h"
+#include "webrtc/api/stats/rtcstatsreport.h"
 #include "webrtc/api/test/mock_datachannel.h"
 #include "webrtc/api/test/mock_peerconnection.h"
 #include "webrtc/api/test/mock_webrtcsession.h"
diff --git a/webrtc/api/rtcstatsreport.h b/webrtc/api/rtcstatsreport.h
index fbd78b9..b16a53b 100644
--- a/webrtc/api/rtcstatsreport.h
+++ b/webrtc/api/rtcstatsreport.h
@@ -8,83 +8,6 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef WEBRTC_API_RTCSTATSREPORT_H_
-#define WEBRTC_API_RTCSTATSREPORT_H_
+// TODO(hbos): Remove this file once Chromium uses the correct include path.
 
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "webrtc/api/rtcstats.h"
-#include "webrtc/base/refcount.h"
-#include "webrtc/base/scoped_ref_ptr.h"
-
-namespace webrtc {
-
-// A collection of stats.
-// This is accessible as a map from |RTCStats::id| to |RTCStats|.
-class RTCStatsReport : public rtc::RefCountInterface {
- public:
-  typedef std::map<std::string, std::unique_ptr<const RTCStats>> StatsMap;
-
-  class ConstIterator {
-   public:
-    ConstIterator(const ConstIterator&& other);
-    ~ConstIterator();
-
-    ConstIterator& operator++();
-    ConstIterator& operator++(int);
-    const RTCStats& operator*() const;
-    bool operator==(const ConstIterator& other) const;
-    bool operator!=(const ConstIterator& other) const;
-
-   private:
-    friend class RTCStatsReport;
-    ConstIterator(const rtc::scoped_refptr<const RTCStatsReport>& report,
-                  StatsMap::const_iterator it);
-
-    // Reference report to make sure it is kept alive.
-    rtc::scoped_refptr<const RTCStatsReport> report_;
-    StatsMap::const_iterator it_;
-  };
-
-  static rtc::scoped_refptr<RTCStatsReport> Create();
-
-  RTCStatsReport();
-  RTCStatsReport(const RTCStatsReport& other) = delete;
-
-  bool AddStats(std::unique_ptr<const RTCStats> stats);
-  const RTCStats* Get(const std::string& id) const;
-  size_t size() const { return stats_.size(); }
-
-  // Takes ownership of all the stats in |victim|, leaving it empty.
-  void TakeMembersFrom(rtc::scoped_refptr<RTCStatsReport> victim);
-
-  // Stats iterators. Stats are ordered lexicographically on |RTCStats::id|.
-  ConstIterator begin() const;
-  ConstIterator end() const;
-
-  // Gets the subset of stats that are of type |T|, where |T| is any class
-  // descending from |RTCStats|.
-  template<typename T>
-  std::vector<const T*> GetStatsOfType() const {
-    std::vector<const T*> stats_of_type;
-    for (const RTCStats& stats : *this) {
-      if (stats.type() == T::kType)
-        stats_of_type.push_back(&stats.cast_to<const T>());
-    }
-    return stats_of_type;
-  }
-
-  friend class rtc::RefCountedObject<RTCStatsReport>;
-
- private:
-  ~RTCStatsReport() override;
-
-  StatsMap stats_;
-};
-
-}  // namespace webrtc
-
-#endif  // WEBRTC_API_RTCSTATSREPORT_H_
+#include "webrtc/api/stats/rtcstatsreport.h"
diff --git a/webrtc/api/stats/rtcstats.h b/webrtc/api/stats/rtcstats.h
new file mode 100644
index 0000000..01dd1c3
--- /dev/null
+++ b/webrtc/api/stats/rtcstats.h
@@ -0,0 +1,281 @@
+/*
+ *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_API_STATS_RTCSTATS_H_
+#define WEBRTC_API_STATS_RTCSTATS_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "webrtc/base/checks.h"
+
+namespace webrtc {
+
+class RTCStatsMemberInterface;
+
+// Abstract base class for RTCStats-derived dictionaries, see
+// https://w3c.github.io/webrtc-stats/.
+//
+// All derived classes must have the following static variable defined:
+//   static const char kType[];
+// It is used as a unique class identifier and a string representation of the
+// class type, see https://w3c.github.io/webrtc-stats/#rtcstatstype-str*.
+// Use the |WEBRTC_RTCSTATS_IMPL| macro when implementing subclasses, see macro
+// for details.
+//
+// Derived classes list their dictionary members, RTCStatsMember<T>, as public
+// fields, allowing the following:
+//
+// RTCFooStats foo("fooId", GetCurrentTime());
+// foo.bar = 42;
+// foo.baz = std::vector<std::string>();
+// foo.baz->push_back("hello world");
+// uint32_t x = *foo.bar;
+//
+// Pointers to all the members are available with |Members|, allowing iteration:
+//
+// for (const RTCStatsMemberInterface* member : foo.Members()) {
+//   printf("%s = %s\n", member->name(), member->ValueToString().c_str());
+// }
+class RTCStats {
+ public:
+  RTCStats(const std::string& id, int64_t timestamp_us)
+      : id_(id), timestamp_us_(timestamp_us) {}
+  RTCStats(std::string&& id, int64_t timestamp_us)
+      : id_(std::move(id)), timestamp_us_(timestamp_us) {}
+  virtual ~RTCStats() {}
+
+  virtual std::unique_ptr<RTCStats> copy() const = 0;
+
+  const std::string& id() const { return id_; }
+  // Time relative to the UNIX epoch (Jan 1, 1970, UTC), in microseconds.
+  int64_t timestamp_us() const { return timestamp_us_; }
+  // Returns the static member variable |kType| of the implementing class.
+  virtual const char* type() const = 0;
+  // Returns a vector of pointers to all the RTCStatsMemberInterface members of
+  // this class. This allows for iteration of members.
+  std::vector<const RTCStatsMemberInterface*> Members() const;
+
+  // Creates a human readable string representation of the report, listing all
+  // of its members (names and values).
+  std::string ToString() const;
+
+  // Downcasts the stats object to an |RTCStats| subclass |T|. DCHECKs that the
+  // object is of type |T|.
+  template<typename T>
+  const T& cast_to() const {
+    RTC_DCHECK_EQ(type(), T::kType);
+    return static_cast<const T&>(*this);
+  }
+
+ protected:
+  // Gets a vector of all members of this |RTCStats| object, including members
+  // derived from parent classes. |additional_capacity| is how many more members
+  // shall be reserved in the vector (so that subclasses can allocate a vector
+  // with room for both parent and child members without it having to resize).
+  virtual std::vector<const RTCStatsMemberInterface*>
+  MembersOfThisObjectAndAncestors(
+      size_t additional_capacity) const;
+
+  std::string const id_;
+  int64_t timestamp_us_;
+};
+
+// All |RTCStats| classes should use this macro in a public section of the class
+// definition.
+//
+// This macro declares the static |kType| and overrides methods as required by
+// subclasses of |RTCStats|: |copy|, |type|, and
+// |MembersOfThisObjectAndAncestors|. The |...| argument is a list of addresses
+// to each member defined in the implementing class (list cannot be empty, must
+// have at least one new member).
+//
+// (Since class names need to be known to implement these methods this cannot be
+// part of the base |RTCStats|. While these methods could be implemented using
+// templates, that would only work for immediate subclasses. Subclasses of
+// subclasses also have to override these methods, resulting in boilerplate
+// code. Using a macro avoids this and works for any |RTCStats| class, including
+// grandchildren.)
+//
+// Sample usage:
+//
+// rtcfoostats.h:
+//   class RTCFooStats : public RTCStats {
+//    public:
+//     RTCFooStats(const std::string& id, int64_t timestamp_us)
+//         : RTCStats(id, timestamp_us),
+//           foo("foo"),
+//           bar("bar") {
+//     }
+//
+//     WEBRTC_RTCSTATS_IMPL(RTCStats, RTCFooStats,
+//         &foo,
+//         &bar);
+//
+//     RTCStatsMember<int32_t> foo;
+//     RTCStatsMember<int32_t> bar;
+//   };
+//
+// rtcfoostats.cc:
+//   const char RTCFooStats::kType[] = "foo-stats";
+//
+#define WEBRTC_RTCSTATS_IMPL(parent_class, this_class, ...)                    \
+ public:                                                                       \
+  static const char kType[];                                                   \
+  std::unique_ptr<webrtc::RTCStats> copy() const override {                    \
+    return std::unique_ptr<webrtc::RTCStats>(new this_class(*this));           \
+  }                                                                            \
+  const char* type() const override { return this_class::kType; }              \
+ protected:                                                                    \
+  std::vector<const webrtc::RTCStatsMemberInterface*>                          \
+  MembersOfThisObjectAndAncestors(                                             \
+      size_t local_var_additional_capacity) const override {                   \
+    const webrtc::RTCStatsMemberInterface* local_var_members[] = {             \
+      __VA_ARGS__                                                              \
+    };                                                                         \
+    size_t local_var_members_count =                                           \
+        sizeof(local_var_members) / sizeof(local_var_members[0]);              \
+    std::vector<const webrtc::RTCStatsMemberInterface*> local_var_members_vec =\
+        parent_class::MembersOfThisObjectAndAncestors(                         \
+            local_var_members_count + local_var_additional_capacity);          \
+    RTC_DCHECK_GE(                                                             \
+        local_var_members_vec.capacity() - local_var_members_vec.size(),       \
+        local_var_members_count + local_var_additional_capacity);              \
+    local_var_members_vec.insert(local_var_members_vec.end(),                  \
+                                 &local_var_members[0],                        \
+                                 &local_var_members[local_var_members_count]); \
+    return local_var_members_vec;                                              \
+  }                                                                            \
+ public:
+
+// Interface for |RTCStats| members, which have a name and a value of a type
+// defined in a subclass. Only the types listed in |Type| are supported, these
+// are implemented by |RTCStatsMember<T>|. The value of a member may be
+// undefined, the value can only be read if |is_defined|.
+class RTCStatsMemberInterface {
+ public:
+  // Member value types.
+  enum Type {
+    kInt32,                 // int32_t
+    kUint32,                // uint32_t
+    kInt64,                 // int64_t
+    kUint64,                // uint64_t
+    kDouble,                // double
+    kString,                // std::string
+
+    kSequenceInt32,         // std::vector<int32_t>
+    kSequenceUint32,        // std::vector<uint32_t>
+    kSequenceInt64,         // std::vector<int64_t>
+    kSequenceUint64,        // std::vector<uint64_t>
+    kSequenceDouble,        // std::vector<double>
+    kSequenceString,        // std::vector<std::string>
+  };
+
+  virtual ~RTCStatsMemberInterface() {}
+
+  const char* name() const { return name_; }
+  virtual Type type() const = 0;
+  virtual bool is_sequence() const = 0;
+  virtual bool is_string() const = 0;
+  bool is_defined() const { return is_defined_; }
+  virtual std::string ValueToString() const = 0;
+
+  template<typename T>
+  const T& cast_to() const {
+    RTC_DCHECK_EQ(type(), T::kType);
+    return static_cast<const T&>(*this);
+  }
+
+ protected:
+  RTCStatsMemberInterface(const char* name, bool is_defined)
+      : name_(name), is_defined_(is_defined) {}
+
+  const char* const name_;
+  bool is_defined_;
+};
+
+// Template implementation of |RTCStatsMemberInterface|. Every possible |T| is
+// specialized in rtcstats.cc, using a different |T| results in a linker error
+// (undefined reference to |kType|). The supported types are the ones described
+// by |RTCStatsMemberInterface::Type|.
+template<typename T>
+class RTCStatsMember : public RTCStatsMemberInterface {
+ public:
+  static const Type kType;
+
+  explicit RTCStatsMember(const char* name)
+      : RTCStatsMemberInterface(name, false),
+        value_() {}
+  RTCStatsMember(const char* name, const T& value)
+      : RTCStatsMemberInterface(name, true),
+        value_(value) {}
+  RTCStatsMember(const char* name, T&& value)
+      : RTCStatsMemberInterface(name, true),
+        value_(std::move(value)) {}
+  explicit RTCStatsMember(const RTCStatsMember<T>& other)
+      : RTCStatsMemberInterface(other.name_, other.is_defined_),
+        value_(other.value_) {}
+  explicit RTCStatsMember(RTCStatsMember<T>&& other)
+      : RTCStatsMemberInterface(other.name_, other.is_defined_),
+        value_(std::move(other.value_)) {}
+
+  Type type() const override { return kType; }
+  bool is_sequence() const override;
+  bool is_string() const override;
+  std::string ValueToString() const override;
+
+  // Assignment operators.
+  T& operator=(const T& value) {
+    value_ = value;
+    is_defined_ = true;
+    return value_;
+  }
+  T& operator=(const T&& value) {
+    value_ = std::move(value);
+    is_defined_ = true;
+    return value_;
+  }
+  T& operator=(const RTCStatsMember<T>& other) {
+    RTC_DCHECK(other.is_defined_);
+    value_ = other.is_defined_;
+    is_defined_ = true;
+    return value_;
+  }
+
+  // Value getters.
+  T& operator*() {
+    RTC_DCHECK(is_defined_);
+    return value_;
+  }
+  const T& operator*() const {
+    RTC_DCHECK(is_defined_);
+    return value_;
+  }
+
+  // Value getters, arrow operator.
+  T* operator->() {
+    RTC_DCHECK(is_defined_);
+    return &value_;
+  }
+  const T* operator->() const {
+    RTC_DCHECK(is_defined_);
+    return &value_;
+  }
+
+ private:
+  T value_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_API_STATS_RTCSTATS_H_
diff --git a/webrtc/api/rtcstats_objects.h b/webrtc/api/stats/rtcstats_objects.h
similarity index 83%
rename from webrtc/api/rtcstats_objects.h
rename to webrtc/api/stats/rtcstats_objects.h
index 4bc889d..ac480a9 100644
--- a/webrtc/api/rtcstats_objects.h
+++ b/webrtc/api/stats/rtcstats_objects.h
@@ -8,12 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef WEBRTC_API_RTCSTATS_OBJECTS_H_
-#define WEBRTC_API_RTCSTATS_OBJECTS_H_
+#ifndef WEBRTC_API_STATS_RTCSTATS_OBJECTS_H_
+#define WEBRTC_API_STATS_RTCSTATS_OBJECTS_H_
 
 #include <string>
 
-#include "webrtc/api/rtcstats.h"
+#include "webrtc/api/stats/rtcstats.h"
 
 namespace webrtc {
 
@@ -32,4 +32,4 @@
 
 }  // namespace webrtc
 
-#endif  // WEBRTC_API_RTCSTATS_OBJECTS_H_
+#endif  // WEBRTC_API_STATS_RTCSTATS_OBJECTS_H_
diff --git a/webrtc/api/stats/rtcstatsreport.h b/webrtc/api/stats/rtcstatsreport.h
new file mode 100644
index 0000000..beb8650
--- /dev/null
+++ b/webrtc/api/stats/rtcstatsreport.h
@@ -0,0 +1,90 @@
+/*
+ *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_API_STATS_RTCSTATSREPORT_H_
+#define WEBRTC_API_STATS_RTCSTATSREPORT_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "webrtc/api/stats/rtcstats.h"
+#include "webrtc/base/refcount.h"
+#include "webrtc/base/scoped_ref_ptr.h"
+
+namespace webrtc {
+
+// A collection of stats.
+// This is accessible as a map from |RTCStats::id| to |RTCStats|.
+class RTCStatsReport : public rtc::RefCountInterface {
+ public:
+  typedef std::map<std::string, std::unique_ptr<const RTCStats>> StatsMap;
+
+  class ConstIterator {
+   public:
+    ConstIterator(const ConstIterator&& other);
+    ~ConstIterator();
+
+    ConstIterator& operator++();
+    ConstIterator& operator++(int);
+    const RTCStats& operator*() const;
+    bool operator==(const ConstIterator& other) const;
+    bool operator!=(const ConstIterator& other) const;
+
+   private:
+    friend class RTCStatsReport;
+    ConstIterator(const rtc::scoped_refptr<const RTCStatsReport>& report,
+                  StatsMap::const_iterator it);
+
+    // Reference report to make sure it is kept alive.
+    rtc::scoped_refptr<const RTCStatsReport> report_;
+    StatsMap::const_iterator it_;
+  };
+
+  static rtc::scoped_refptr<RTCStatsReport> Create();
+
+  RTCStatsReport();
+  RTCStatsReport(const RTCStatsReport& other) = delete;
+
+  bool AddStats(std::unique_ptr<const RTCStats> stats);
+  const RTCStats* Get(const std::string& id) const;
+  size_t size() const { return stats_.size(); }
+
+  // Takes ownership of all the stats in |victim|, leaving it empty.
+  void TakeMembersFrom(rtc::scoped_refptr<RTCStatsReport> victim);
+
+  // Stats iterators. Stats are ordered lexicographically on |RTCStats::id|.
+  ConstIterator begin() const;
+  ConstIterator end() const;
+
+  // Gets the subset of stats that are of type |T|, where |T| is any class
+  // descending from |RTCStats|.
+  template<typename T>
+  std::vector<const T*> GetStatsOfType() const {
+    std::vector<const T*> stats_of_type;
+    for (const RTCStats& stats : *this) {
+      if (stats.type() == T::kType)
+        stats_of_type.push_back(&stats.cast_to<const T>());
+    }
+    return stats_of_type;
+  }
+
+  friend class rtc::RefCountedObject<RTCStatsReport>;
+
+ private:
+  ~RTCStatsReport() override;
+
+  StatsMap stats_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_API_STATS_RTCSTATSREPORT_H_
diff --git a/webrtc/stats/BUILD.gn b/webrtc/stats/BUILD.gn
index 1b5da8d..0f13c10 100644
--- a/webrtc/stats/BUILD.gn
+++ b/webrtc/stats/BUILD.gn
@@ -20,8 +20,6 @@
   sources = [
     "rtcstats.cc",
     "rtcstats_objects.cc",
-    "rtcstatscollector.cc",
-    "rtcstatscollector.h",
     "rtcstatsreport.cc",
   ]
 
@@ -31,7 +29,8 @@
   }
 
   deps = [
-    "../api:libjingle_peerconnection",
+    "../api:rtc_stats_api",
+    "../base:rtc_base_approved",
   ]
 }
 
@@ -41,7 +40,6 @@
     testonly = true
     sources = [
       "rtcstats_unittest.cc",
-      "rtcstatscollector_unittest.cc",
       "rtcstatsreport_unittest.cc",
     ]
 
diff --git a/webrtc/stats/rtcstats.cc b/webrtc/stats/rtcstats.cc
index 8fc0ebb..6b6c437 100644
--- a/webrtc/stats/rtcstats.cc
+++ b/webrtc/stats/rtcstats.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "webrtc/api/rtcstats.h"
+#include "webrtc/api/stats/rtcstats.h"
 
 #include "webrtc/base/stringencode.h"
 
diff --git a/webrtc/stats/rtcstats_objects.cc b/webrtc/stats/rtcstats_objects.cc
index 46962f2..c435908 100644
--- a/webrtc/stats/rtcstats_objects.cc
+++ b/webrtc/stats/rtcstats_objects.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "webrtc/api/rtcstats_objects.h"
+#include "webrtc/api/stats/rtcstats_objects.h"
 
 namespace webrtc {
 
diff --git a/webrtc/stats/rtcstats_unittest.cc b/webrtc/stats/rtcstats_unittest.cc
index f6de8e6..685093a 100644
--- a/webrtc/stats/rtcstats_unittest.cc
+++ b/webrtc/stats/rtcstats_unittest.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "webrtc/api/rtcstats.h"
+#include "webrtc/api/stats/rtcstats.h"
 
 #include <cstring>
 
diff --git a/webrtc/stats/rtcstatsreport.cc b/webrtc/stats/rtcstatsreport.cc
index 00a55f4..4be554d 100644
--- a/webrtc/stats/rtcstatsreport.cc
+++ b/webrtc/stats/rtcstatsreport.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "webrtc/api/rtcstatsreport.h"
+#include "webrtc/api/stats/rtcstatsreport.h"
 
 namespace webrtc {
 
diff --git a/webrtc/stats/rtcstatsreport_unittest.cc b/webrtc/stats/rtcstatsreport_unittest.cc
index 2dcb584..9a0bb1a 100644
--- a/webrtc/stats/rtcstatsreport_unittest.cc
+++ b/webrtc/stats/rtcstatsreport_unittest.cc
@@ -8,9 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "webrtc/api/rtcstatsreport.h"
+#include "webrtc/api/stats/rtcstatsreport.h"
 
-#include "webrtc/api/rtcstats.h"
+#include "webrtc/api/stats/rtcstats.h"
 #include "webrtc/base/checks.h"
 #include "webrtc/base/gunit.h"
 
diff --git a/webrtc/stats/stats.gyp b/webrtc/stats/stats.gyp
index 49932e8..bbeb021 100644
--- a/webrtc/stats/stats.gyp
+++ b/webrtc/stats/stats.gyp
@@ -14,13 +14,12 @@
       'target_name': 'rtc_stats',
       'type': 'static_library',
       'dependencies': [
-        '<(webrtc_root)/api/api.gyp:libjingle_peerconnection',
+        '<(webrtc_root)/api/api.gyp:rtc_stats_api',
+        '<(webrtc_root)/base/base.gyp:rtc_base_approved',
       ],
       'sources': [
         'rtcstats.cc',
         'rtcstats_objects.cc',
-        'rtcstatscollector.cc',
-        'rtcstatscollector.h',
         'rtcstatsreport.cc',
       ],
     },