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}
This commit is contained in:
hbos 2016-09-15 23:33:01 -07:00 committed by Commit bot
parent fe7d091f57
commit 74e1a4f96a
22 changed files with 457 additions and 385 deletions

10
.gn
View File

@ -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

View File

@ -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",

View File

@ -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
}

View File

@ -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_;
}

View File

@ -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<WebRtcSession> session_;
std::unique_ptr<StatsCollector> stats_;
rtc::scoped_refptr<RTCStatsCollector> stats_collector_;
};
} // namespace webrtc

View File

@ -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<DataChannelInterface> CreateDataChannel(
const std::string& label,

View File

@ -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<DataChannelInterface>,
CreateDataChannel, const std::string&, const DataChannelInit*)
PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, local_description)

View File

@ -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"

View File

@ -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>

View File

@ -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 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface {
} // namespace webrtc
#endif // WEBRTC_STATS_RTCSTATSCOLLECTOR_H_
#endif // WEBRTC_API_RTCSTATSCOLLECTOR_H_

View File

@ -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"

View File

@ -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"

281
webrtc/api/stats/rtcstats.h Normal file
View File

@ -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_

View File

@ -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 @@ class RTCPeerConnectionStats : public RTCStats {
} // namespace webrtc
#endif // WEBRTC_API_RTCSTATS_OBJECTS_H_
#endif // WEBRTC_API_STATS_RTCSTATS_OBJECTS_H_

View File

@ -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_

View File

@ -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",
]

View File

@ -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"

View File

@ -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 {

View File

@ -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>

View File

@ -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 {

View File

@ -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"

View File

@ -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',
],
},