From 74e1a4f96a4915c9ad3b0ddeff87cc9797606453 Mon Sep 17 00:00:00 2001 From: hbos Date: Thu, 15 Sep 2016 23:33:01 -0700 Subject: [PATCH] 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} --- .gn | 10 +- webrtc/api/BUILD.gn | 22 +- webrtc/api/api.gyp | 20 +- webrtc/api/peerconnection.cc | 6 + webrtc/api/peerconnection.h | 3 + webrtc/api/peerconnectioninterface.h | 7 + webrtc/api/peerconnectionproxy.h | 1 + webrtc/api/rtcstats.h | 272 +---------------- webrtc/{stats => api}/rtcstatscollector.cc | 2 +- webrtc/{stats => api}/rtcstatscollector.h | 10 +- .../rtcstatscollector_unittest.cc | 6 +- webrtc/api/rtcstatsreport.h | 81 +---- webrtc/api/stats/rtcstats.h | 281 ++++++++++++++++++ webrtc/api/{ => stats}/rtcstats_objects.h | 8 +- webrtc/api/stats/rtcstatsreport.h | 90 ++++++ webrtc/stats/BUILD.gn | 6 +- webrtc/stats/rtcstats.cc | 2 +- webrtc/stats/rtcstats_objects.cc | 2 +- webrtc/stats/rtcstats_unittest.cc | 2 +- webrtc/stats/rtcstatsreport.cc | 2 +- webrtc/stats/rtcstatsreport_unittest.cc | 4 +- webrtc/stats/stats.gyp | 5 +- 22 files changed, 457 insertions(+), 385 deletions(-) rename webrtc/{stats => api}/rtcstatscollector.cc (99%) rename webrtc/{stats => api}/rtcstatscollector.h (94%) rename webrtc/{stats => api}/rtcstatscollector_unittest.cc (99%) create mode 100644 webrtc/api/stats/rtcstats.h rename webrtc/api/{ => stats}/rtcstats_objects.h (83%) create mode 100644 webrtc/api/stats/rtcstatsreport.h diff --git a/.gn b/.gn index 65bc7dd3ec..db61a47138 100644 --- a/.gn +++ b/.gn @@ -20,18 +20,20 @@ secondary_source = "//build/secondary/" # "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 4f15bc4b05..b7cd679f28 100644 --- a/webrtc/api/BUILD.gn +++ b/webrtc/api/BUILD.gn @@ -84,9 +84,8 @@ rtc_source_set("libjingle_peerconnection") { "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 @@ rtc_source_set("libjingle_peerconnection") { deps = [ ":call_api", + ":rtc_stats_api", "../call", "../media", "../pc", + "../stats", ] if (rtc_use_quic) { @@ -298,6 +299,20 @@ if (is_android && !build_with_chromium) { } } +# 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 @@ if (rtc_include_tests) { "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 5b14fdfc2d..d017cda2d6 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 bdd33d7d37..144b1c64b5 100644 --- a/webrtc/api/peerconnection.cc +++ b/webrtc/api/peerconnection.cc @@ -632,6 +632,7 @@ bool PeerConnection::Initialize( 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 @@ bool PeerConnection::GetStats(StatsObserver* observer, 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 042e7f1bd4..3087160e43 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 @@ class PeerConnection : public PeerConnectionInterface, bool GetStats(StatsObserver* observer, webrtc::MediaStreamTrackInterface* track, StatsOutputLevel level) override; + void GetStats(RTCStatsCollectorCallback* callback) override; SignalingState signaling_state() override; @@ -427,6 +429,7 @@ class PeerConnection : public PeerConnectionInterface, std::unique_ptr session_; std::unique_ptr stats_; + rtc::scoped_refptr stats_collector_; }; } // namespace webrtc diff --git a/webrtc/api/peerconnectioninterface.h b/webrtc/api/peerconnectioninterface.h index f5d8c63b67..a04e53e2ac 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 @@ class PeerConnectionInterface : public rtc::RefCountInterface { 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 CreateDataChannel( const std::string& label, diff --git a/webrtc/api/peerconnectionproxy.h b/webrtc/api/peerconnectionproxy.h index 37f2e89f9b..8c15b3d79f 100644 --- a/webrtc/api/peerconnectionproxy.h +++ b/webrtc/api/peerconnectionproxy.h @@ -42,6 +42,7 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection) PROXY_METHOD3(bool, GetStats, StatsObserver*, MediaStreamTrackInterface*, StatsOutputLevel) + PROXY_METHOD1(void, GetStats, RTCStatsCollectorCallback*) PROXY_METHOD2(rtc::scoped_refptr, 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 e2cbf29c74..55aeb1d8a0 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 -#include -#include -#include -#include - -#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, as public -// fields, allowing the following: -// -// RTCFooStats foo("fooId", GetCurrentTime()); -// foo.bar = 42; -// foo.baz = std::vector(); -// 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 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 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 - const T& cast_to() const { - RTC_DCHECK_EQ(type(), T::kType); - return static_cast(*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 - 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 foo; -// RTCStatsMember 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 copy() const override { \ - return std::unique_ptr(new this_class(*this)); \ - } \ - const char* type() const override { return this_class::kType; } \ - protected: \ - std::vector \ - 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 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|. 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 - kSequenceUint32, // std::vector - kSequenceInt64, // std::vector - kSequenceUint64, // std::vector - kSequenceDouble, // std::vector - kSequenceString, // std::vector - }; - - 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 - const T& cast_to() const { - RTC_DCHECK_EQ(type(), T::kType); - return static_cast(*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 -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& other) - : RTCStatsMemberInterface(other.name_, other.is_defined_), - value_(other.value_) {} - explicit RTCStatsMember(RTCStatsMember&& 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& 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 99% rename from webrtc/stats/rtcstatscollector.cc rename to webrtc/api/rtcstatscollector.cc index 3ff41558b3..d2938a4c29 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 #include diff --git a/webrtc/stats/rtcstatscollector.h b/webrtc/api/rtcstatscollector.h similarity index 94% rename from webrtc/stats/rtcstatscollector.h rename to webrtc/api/rtcstatscollector.h index ee59a10022..61edc52d0d 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 #include -#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 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface { } // 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 99% rename from webrtc/stats/rtcstatscollector_unittest.cc rename to webrtc/api/rtcstatscollector_unittest.cc index a90c334ae4..446990c574 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 #include #include #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 fbd78b93f4..b16a53b588 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 -#include -#include -#include - -#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> 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& report, - StatsMap::const_iterator it); - - // Reference report to make sure it is kept alive. - rtc::scoped_refptr report_; - StatsMap::const_iterator it_; - }; - - static rtc::scoped_refptr Create(); - - RTCStatsReport(); - RTCStatsReport(const RTCStatsReport& other) = delete; - - bool AddStats(std::unique_ptr 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 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 - std::vector GetStatsOfType() const { - std::vector stats_of_type; - for (const RTCStats& stats : *this) { - if (stats.type() == T::kType) - stats_of_type.push_back(&stats.cast_to()); - } - return stats_of_type; - } - - friend class rtc::RefCountedObject; - - 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 0000000000..01dd1c3e21 --- /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 +#include +#include +#include +#include + +#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, as public +// fields, allowing the following: +// +// RTCFooStats foo("fooId", GetCurrentTime()); +// foo.bar = 42; +// foo.baz = std::vector(); +// 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 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 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 + const T& cast_to() const { + RTC_DCHECK_EQ(type(), T::kType); + return static_cast(*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 + 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 foo; +// RTCStatsMember 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 copy() const override { \ + return std::unique_ptr(new this_class(*this)); \ + } \ + const char* type() const override { return this_class::kType; } \ + protected: \ + std::vector \ + 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 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|. 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 + kSequenceUint32, // std::vector + kSequenceInt64, // std::vector + kSequenceUint64, // std::vector + kSequenceDouble, // std::vector + kSequenceString, // std::vector + }; + + 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 + const T& cast_to() const { + RTC_DCHECK_EQ(type(), T::kType); + return static_cast(*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 +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& other) + : RTCStatsMemberInterface(other.name_, other.is_defined_), + value_(other.value_) {} + explicit RTCStatsMember(RTCStatsMember&& 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& 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 4bc889d5d0..ac480a937b 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 -#include "webrtc/api/rtcstats.h" +#include "webrtc/api/stats/rtcstats.h" namespace webrtc { @@ -32,4 +32,4 @@ class RTCPeerConnectionStats : public RTCStats { } // 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 0000000000..beb8650353 --- /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 +#include +#include +#include + +#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> 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& report, + StatsMap::const_iterator it); + + // Reference report to make sure it is kept alive. + rtc::scoped_refptr report_; + StatsMap::const_iterator it_; + }; + + static rtc::scoped_refptr Create(); + + RTCStatsReport(); + RTCStatsReport(const RTCStatsReport& other) = delete; + + bool AddStats(std::unique_ptr 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 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 + std::vector GetStatsOfType() const { + std::vector stats_of_type; + for (const RTCStats& stats : *this) { + if (stats.type() == T::kType) + stats_of_type.push_back(&stats.cast_to()); + } + return stats_of_type; + } + + friend class rtc::RefCountedObject; + + 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 1b5da8df67..0f13c101e1 100644 --- a/webrtc/stats/BUILD.gn +++ b/webrtc/stats/BUILD.gn @@ -20,8 +20,6 @@ rtc_source_set("rtc_stats") { sources = [ "rtcstats.cc", "rtcstats_objects.cc", - "rtcstatscollector.cc", - "rtcstatscollector.h", "rtcstatsreport.cc", ] @@ -31,7 +29,8 @@ rtc_source_set("rtc_stats") { } deps = [ - "../api:libjingle_peerconnection", + "../api:rtc_stats_api", + "../base:rtc_base_approved", ] } @@ -41,7 +40,6 @@ if (rtc_include_tests) { 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 8fc0ebbc7f..6b6c437c22 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 46962f20b6..c435908dc4 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 f6de8e607c..685093a493 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 diff --git a/webrtc/stats/rtcstatsreport.cc b/webrtc/stats/rtcstatsreport.cc index 00a55f41fc..4be554daae 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 2dcb58428a..9a0bb1a125 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 49932e871e..bbeb0213d0 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', ], },