xref: /aosp_15_r20/external/webrtc/api/stats/rtc_stats.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef API_STATS_RTC_STATS_H_
12 #define API_STATS_RTC_STATS_H_
13 
14 #include <stddef.h>
15 #include <stdint.h>
16 
17 #include <map>
18 #include <memory>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "absl/types/optional.h"
24 #include "rtc_base/checks.h"
25 #include "rtc_base/system/rtc_export.h"
26 #include "rtc_base/system/rtc_export_template.h"
27 
28 namespace webrtc {
29 
30 class RTCStatsMemberInterface;
31 
32 // Abstract base class for RTCStats-derived dictionaries, see
33 // https://w3c.github.io/webrtc-stats/.
34 //
35 // All derived classes must have the following static variable defined:
36 //   static const char kType[];
37 // It is used as a unique class identifier and a string representation of the
38 // class type, see https://w3c.github.io/webrtc-stats/#rtcstatstype-str*.
39 // Use the `WEBRTC_RTCSTATS_IMPL` macro when implementing subclasses, see macro
40 // for details.
41 //
42 // Derived classes list their dictionary members, RTCStatsMember<T>, as public
43 // fields, allowing the following:
44 //
45 // RTCFooStats foo("fooId", GetCurrentTime());
46 // foo.bar = 42;
47 // foo.baz = std::vector<std::string>();
48 // foo.baz->push_back("hello world");
49 // uint32_t x = *foo.bar;
50 //
51 // Pointers to all the members are available with `Members`, allowing iteration:
52 //
53 // for (const RTCStatsMemberInterface* member : foo.Members()) {
54 //   printf("%s = %s\n", member->name(), member->ValueToString().c_str());
55 // }
56 class RTC_EXPORT RTCStats {
57  public:
RTCStats(const std::string & id,int64_t timestamp_us)58   RTCStats(const std::string& id, int64_t timestamp_us)
59       : id_(id), timestamp_us_(timestamp_us) {}
RTCStats(std::string && id,int64_t timestamp_us)60   RTCStats(std::string&& id, int64_t timestamp_us)
61       : id_(std::move(id)), timestamp_us_(timestamp_us) {}
~RTCStats()62   virtual ~RTCStats() {}
63 
64   virtual std::unique_ptr<RTCStats> copy() const = 0;
65 
id()66   const std::string& id() const { return id_; }
67   // Time relative to the UNIX epoch (Jan 1, 1970, UTC), in microseconds.
timestamp_us()68   int64_t timestamp_us() const { return timestamp_us_; }
69   // Returns the static member variable `kType` of the implementing class.
70   virtual const char* type() const = 0;
71   // Returns a vector of pointers to all the `RTCStatsMemberInterface` members
72   // of this class. This allows for iteration of members. For a given class,
73   // `Members` always returns the same members in the same order.
74   std::vector<const RTCStatsMemberInterface*> Members() const;
75   // Checks if the two stats objects are of the same type and have the same
76   // member values. Timestamps are not compared. These operators are exposed for
77   // testing.
78   bool operator==(const RTCStats& other) const;
79   bool operator!=(const RTCStats& other) const;
80 
81   // Creates a JSON readable string representation of the stats
82   // object, listing all of its members (names and values).
83   std::string ToJson() const;
84 
85   // Downcasts the stats object to an `RTCStats` subclass `T`. DCHECKs that the
86   // object is of type `T`.
87   template <typename T>
cast_to()88   const T& cast_to() const {
89     RTC_DCHECK_EQ(type(), T::kType);
90     return static_cast<const T&>(*this);
91   }
92 
93  protected:
94   // Gets a vector of all members of this `RTCStats` object, including members
95   // derived from parent classes. `additional_capacity` is how many more members
96   // shall be reserved in the vector (so that subclasses can allocate a vector
97   // with room for both parent and child members without it having to resize).
98   virtual std::vector<const RTCStatsMemberInterface*>
99   MembersOfThisObjectAndAncestors(size_t additional_capacity) const;
100 
101   std::string const id_;
102   int64_t timestamp_us_;
103 };
104 
105 // All `RTCStats` classes should use these macros.
106 // `WEBRTC_RTCSTATS_DECL` is placed in a public section of the class definition.
107 // `WEBRTC_RTCSTATS_IMPL` is placed outside the class definition (in a .cc).
108 //
109 // These macros declare (in _DECL) and define (in _IMPL) the static `kType` and
110 // overrides methods as required by subclasses of `RTCStats`: `copy`, `type` and
111 // `MembersOfThisObjectAndAncestors`. The |...| argument is a list of addresses
112 // to each member defined in the implementing class. The list must have at least
113 // one member.
114 //
115 // (Since class names need to be known to implement these methods this cannot be
116 // part of the base `RTCStats`. While these methods could be implemented using
117 // templates, that would only work for immediate subclasses. Subclasses of
118 // subclasses also have to override these methods, resulting in boilerplate
119 // code. Using a macro avoids this and works for any `RTCStats` class, including
120 // grandchildren.)
121 //
122 // Sample usage:
123 //
124 // rtcfoostats.h:
125 //   class RTCFooStats : public RTCStats {
126 //    public:
127 //     WEBRTC_RTCSTATS_DECL();
128 //
129 //     RTCFooStats(const std::string& id, int64_t timestamp_us);
130 //
131 //     RTCStatsMember<int32_t> foo;
132 //     RTCStatsMember<int32_t> bar;
133 //   };
134 //
135 // rtcfoostats.cc:
136 //   WEBRTC_RTCSTATS_IMPL(RTCFooStats, RTCStats, "foo-stats"
137 //       &foo,
138 //       &bar);
139 //
140 //   RTCFooStats::RTCFooStats(const std::string& id, int64_t timestamp_us)
141 //       : RTCStats(id, timestamp_us),
142 //         foo("foo"),
143 //         bar("bar") {
144 //   }
145 //
146 #define WEBRTC_RTCSTATS_DECL()                                          \
147  protected:                                                             \
148   std::vector<const webrtc::RTCStatsMemberInterface*>                   \
149   MembersOfThisObjectAndAncestors(size_t local_var_additional_capacity) \
150       const override;                                                   \
151                                                                         \
152  public:                                                                \
153   static const char kType[];                                            \
154                                                                         \
155   std::unique_ptr<webrtc::RTCStats> copy() const override;              \
156   const char* type() const override
157 
158 #define WEBRTC_RTCSTATS_IMPL(this_class, parent_class, type_str, ...)          \
159   const char this_class::kType[] = type_str;                                   \
160                                                                                \
161   std::unique_ptr<webrtc::RTCStats> this_class::copy() const {                 \
162     return std::make_unique<this_class>(*this);                                \
163   }                                                                            \
164                                                                                \
165   const char* this_class::type() const { return this_class::kType; }           \
166                                                                                \
167   std::vector<const webrtc::RTCStatsMemberInterface*>                          \
168   this_class::MembersOfThisObjectAndAncestors(                                 \
169       size_t local_var_additional_capacity) const {                            \
170     const webrtc::RTCStatsMemberInterface* local_var_members[] = {             \
171         __VA_ARGS__};                                                          \
172     size_t local_var_members_count =                                           \
173         sizeof(local_var_members) / sizeof(local_var_members[0]);              \
174     std::vector<const webrtc::RTCStatsMemberInterface*>                        \
175         local_var_members_vec = parent_class::MembersOfThisObjectAndAncestors( \
176             local_var_members_count + local_var_additional_capacity);          \
177     RTC_DCHECK_GE(                                                             \
178         local_var_members_vec.capacity() - local_var_members_vec.size(),       \
179         local_var_members_count + local_var_additional_capacity);              \
180     local_var_members_vec.insert(local_var_members_vec.end(),                  \
181                                  &local_var_members[0],                        \
182                                  &local_var_members[local_var_members_count]); \
183     return local_var_members_vec;                                              \
184   }
185 
186 // A version of WEBRTC_RTCSTATS_IMPL() where "..." is omitted, used to avoid a
187 // compile error on windows. This is used if the stats dictionary does not
188 // declare any members of its own (but perhaps its parent dictionary does).
189 #define WEBRTC_RTCSTATS_IMPL_NO_MEMBERS(this_class, parent_class, type_str) \
190   const char this_class::kType[] = type_str;                                \
191                                                                             \
192   std::unique_ptr<webrtc::RTCStats> this_class::copy() const {              \
193     return std::make_unique<this_class>(*this);                             \
194   }                                                                         \
195                                                                             \
196   const char* this_class::type() const { return this_class::kType; }        \
197                                                                             \
198   std::vector<const webrtc::RTCStatsMemberInterface*>                       \
199   this_class::MembersOfThisObjectAndAncestors(                              \
200       size_t local_var_additional_capacity) const {                         \
201     return parent_class::MembersOfThisObjectAndAncestors(0);                \
202   }
203 
204 // Non-standard stats members can be exposed to the JavaScript API in Chrome
205 // e.g. through origin trials. The group ID can be used by the blink layer to
206 // determine if a stats member should be exposed or not. Multiple non-standard
207 // stats members can share the same group ID so that they are exposed together.
208 enum class NonStandardGroupId {
209   // Group ID used for testing purposes only.
210   kGroupIdForTesting,
211   // I2E:
212   // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/hE2B1iItPDk
213   kRtcAudioJitterBufferMaxPackets,
214   // I2E:
215   // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/YbhMyqLXXXo
216   kRtcStatsRelativePacketArrivalDelay,
217 };
218 
219 // Certain stat members should only be exposed to the JavaScript API in
220 // certain circumstances as to avoid passive fingerprinting.
221 enum class StatExposureCriteria : uint8_t {
222   // The stat should always be exposed. This is the default.
223   kAlways,
224   // The stat exposes hardware capabilities and thus should has limited exposure
225   // to JavaScript. The requirements for exposure are written in the spec at
226   // https://w3c.github.io/webrtc-stats/#limiting-exposure-of-hardware-capabilities.
227   kHardwareCapability,
228 };
229 
230 // Interface for `RTCStats` members, which have a name and a value of a type
231 // defined in a subclass. Only the types listed in `Type` are supported, these
232 // are implemented by `RTCStatsMember<T>`. The value of a member may be
233 // undefined, the value can only be read if `is_defined`.
234 class RTCStatsMemberInterface {
235  public:
236   // Member value types.
237   enum Type {
238     kBool,    // bool
239     kInt32,   // int32_t
240     kUint32,  // uint32_t
241     kInt64,   // int64_t
242     kUint64,  // uint64_t
243     kDouble,  // double
244     kString,  // std::string
245 
246     kSequenceBool,    // std::vector<bool>
247     kSequenceInt32,   // std::vector<int32_t>
248     kSequenceUint32,  // std::vector<uint32_t>
249     kSequenceInt64,   // std::vector<int64_t>
250     kSequenceUint64,  // std::vector<uint64_t>
251     kSequenceDouble,  // std::vector<double>
252     kSequenceString,  // std::vector<std::string>
253 
254     kMapStringUint64,  // std::map<std::string, uint64_t>
255     kMapStringDouble,  // std::map<std::string, double>
256   };
257 
~RTCStatsMemberInterface()258   virtual ~RTCStatsMemberInterface() {}
259 
name()260   const char* name() const { return name_; }
261   virtual Type type() const = 0;
262   virtual bool is_sequence() const = 0;
263   virtual bool is_string() const = 0;
264   virtual bool is_defined() const = 0;
265   // Is this part of the stats spec? Used so that chromium can easily filter
266   // out anything unstandardized.
267   virtual bool is_standardized() const = 0;
268   // Non-standard stats members can have group IDs in order to be exposed in
269   // JavaScript through experiments. Standardized stats have no group IDs.
group_ids()270   virtual std::vector<NonStandardGroupId> group_ids() const { return {}; }
271   // The conditions for exposing the statistic to JavaScript. Stats with
272   // criteria that is not kAlways has some restriction and should be filtered
273   // in accordance to the spec.
exposure_criteria()274   virtual StatExposureCriteria exposure_criteria() const {
275     return StatExposureCriteria::kAlways;
276   }
277   // Type and value comparator. The names are not compared. These operators are
278   // exposed for testing.
279   bool operator==(const RTCStatsMemberInterface& other) const {
280     return IsEqual(other);
281   }
282   bool operator!=(const RTCStatsMemberInterface& other) const {
283     return !(*this == other);
284   }
285   virtual std::string ValueToString() const = 0;
286   // This is the same as ValueToString except for kInt64 and kUint64 types,
287   // where the value is represented as a double instead of as an integer.
288   // Since JSON stores numbers as floating point numbers, very large integers
289   // cannot be accurately represented, so we prefer to display them as doubles
290   // instead.
291   virtual std::string ValueToJson() const = 0;
292 
293   template <typename T>
cast_to()294   const T& cast_to() const {
295     RTC_DCHECK_EQ(type(), T::StaticType());
296     return static_cast<const T&>(*this);
297   }
298 
299  protected:
RTCStatsMemberInterface(const char * name)300   explicit RTCStatsMemberInterface(const char* name) : name_(name) {}
301 
302   virtual bool IsEqual(const RTCStatsMemberInterface& other) const = 0;
303 
304   const char* const name_;
305 };
306 
307 // Template implementation of `RTCStatsMemberInterface`.
308 // The supported types are the ones described by
309 // `RTCStatsMemberInterface::Type`.
310 template <typename T>
311 class RTCStatsMember : public RTCStatsMemberInterface {
312  public:
RTCStatsMember(const char * name)313   explicit RTCStatsMember(const char* name)
314       : RTCStatsMemberInterface(name), value_() {}
RTCStatsMember(const char * name,const T & value)315   RTCStatsMember(const char* name, const T& value)
316       : RTCStatsMemberInterface(name), value_(value) {}
RTCStatsMember(const char * name,T && value)317   RTCStatsMember(const char* name, T&& value)
318       : RTCStatsMemberInterface(name), value_(std::move(value)) {}
RTCStatsMember(const RTCStatsMember<T> & other)319   explicit RTCStatsMember(const RTCStatsMember<T>& other)
320       : RTCStatsMemberInterface(other.name_), value_(other.value_) {}
RTCStatsMember(RTCStatsMember<T> && other)321   explicit RTCStatsMember(RTCStatsMember<T>&& other)
322       : RTCStatsMemberInterface(other.name_), value_(std::move(other.value_)) {}
323 
324   static Type StaticType();
type()325   Type type() const override { return StaticType(); }
326   bool is_sequence() const override;
327   bool is_string() const override;
is_defined()328   bool is_defined() const override { return value_.has_value(); }
is_standardized()329   bool is_standardized() const override { return true; }
330   std::string ValueToString() const override;
331   std::string ValueToJson() const override;
332 
333   template <typename U>
ValueOrDefault(U default_value)334   inline T ValueOrDefault(U default_value) const {
335     return value_.value_or(default_value);
336   }
337 
338   // Assignment operators.
339   T& operator=(const T& value) {
340     value_ = value;
341     return value_.value();
342   }
343   T& operator=(const T&& value) {
344     value_ = std::move(value);
345     return value_.value();
346   }
347 
348   // Value getters.
349   T& operator*() {
350     RTC_DCHECK(value_);
351     return *value_;
352   }
353   const T& operator*() const {
354     RTC_DCHECK(value_);
355     return *value_;
356   }
357 
358   // Value getters, arrow operator.
359   T* operator->() {
360     RTC_DCHECK(value_);
361     return &(*value_);
362   }
363   const T* operator->() const {
364     RTC_DCHECK(value_);
365     return &(*value_);
366   }
367 
368  protected:
IsEqual(const RTCStatsMemberInterface & other)369   bool IsEqual(const RTCStatsMemberInterface& other) const override {
370     if (type() != other.type() ||
371         is_standardized() != other.is_standardized() ||
372         exposure_criteria() != other.exposure_criteria())
373       return false;
374     const RTCStatsMember<T>& other_t =
375         static_cast<const RTCStatsMember<T>&>(other);
376     return value_ == other_t.value_;
377   }
378 
379  private:
380   absl::optional<T> value_;
381 };
382 
383 namespace rtc_stats_internal {
384 
385 typedef std::map<std::string, uint64_t> MapStringUint64;
386 typedef std::map<std::string, double> MapStringDouble;
387 
388 }  // namespace rtc_stats_internal
389 
390 #define WEBRTC_DECLARE_RTCSTATSMEMBER(T)                                    \
391   template <>                                                               \
392   RTC_EXPORT RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType(); \
393   template <>                                                               \
394   RTC_EXPORT bool RTCStatsMember<T>::is_sequence() const;                   \
395   template <>                                                               \
396   RTC_EXPORT bool RTCStatsMember<T>::is_string() const;                     \
397   template <>                                                               \
398   RTC_EXPORT std::string RTCStatsMember<T>::ValueToString() const;          \
399   template <>                                                               \
400   RTC_EXPORT std::string RTCStatsMember<T>::ValueToJson() const;            \
401   extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)             \
402       RTCStatsMember<T>
403 
404 WEBRTC_DECLARE_RTCSTATSMEMBER(bool);
405 WEBRTC_DECLARE_RTCSTATSMEMBER(int32_t);
406 WEBRTC_DECLARE_RTCSTATSMEMBER(uint32_t);
407 WEBRTC_DECLARE_RTCSTATSMEMBER(int64_t);
408 WEBRTC_DECLARE_RTCSTATSMEMBER(uint64_t);
409 WEBRTC_DECLARE_RTCSTATSMEMBER(double);
410 WEBRTC_DECLARE_RTCSTATSMEMBER(std::string);
411 WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<bool>);
412 WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int32_t>);
413 WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint32_t>);
414 WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int64_t>);
415 WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint64_t>);
416 WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<double>);
417 WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<std::string>);
418 WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64);
419 WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble);
420 
421 // For stats with restricted exposure.
422 template <typename T, StatExposureCriteria E>
423 class RTCRestrictedStatsMember : public RTCStatsMember<T> {
424  public:
RTCRestrictedStatsMember(const char * name)425   explicit RTCRestrictedStatsMember(const char* name)
426       : RTCStatsMember<T>(name) {}
RTCRestrictedStatsMember(const char * name,const T & value)427   RTCRestrictedStatsMember(const char* name, const T& value)
428       : RTCStatsMember<T>(name, value) {}
RTCRestrictedStatsMember(const char * name,T && value)429   RTCRestrictedStatsMember(const char* name, T&& value)
430       : RTCStatsMember<T>(name, std::move(value)) {}
RTCRestrictedStatsMember(const RTCRestrictedStatsMember<T,E> & other)431   RTCRestrictedStatsMember(const RTCRestrictedStatsMember<T, E>& other)
432       : RTCStatsMember<T>(other) {}
RTCRestrictedStatsMember(RTCRestrictedStatsMember<T,E> && other)433   RTCRestrictedStatsMember(RTCRestrictedStatsMember<T, E>&& other)
434       : RTCStatsMember<T>(std::move(other)) {}
435 
exposure_criteria()436   StatExposureCriteria exposure_criteria() const override { return E; }
437 
438   T& operator=(const T& value) { return RTCStatsMember<T>::operator=(value); }
439   T& operator=(const T&& value) {
440     return RTCStatsMember<T>::operator=(std::move(value));
441   }
442 
443  private:
444   static_assert(E != StatExposureCriteria::kAlways,
445                 "kAlways is the default exposure criteria. Use "
446                 "RTCStatMember<T> instead.");
447 };
448 
449 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
450     RTCRestrictedStatsMember<bool, StatExposureCriteria::kHardwareCapability>;
451 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
452     RTCRestrictedStatsMember<int32_t,
453                              StatExposureCriteria::kHardwareCapability>;
454 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
455     RTCRestrictedStatsMember<uint32_t,
456                              StatExposureCriteria::kHardwareCapability>;
457 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
458     RTCRestrictedStatsMember<int64_t,
459                              StatExposureCriteria::kHardwareCapability>;
460 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
461     RTCRestrictedStatsMember<uint64_t,
462                              StatExposureCriteria::kHardwareCapability>;
463 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
464     RTCRestrictedStatsMember<double, StatExposureCriteria::kHardwareCapability>;
465 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
466     RTCRestrictedStatsMember<std::string,
467                              StatExposureCriteria::kHardwareCapability>;
468 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
469     RTCRestrictedStatsMember<std::vector<bool>,
470                              StatExposureCriteria::kHardwareCapability>;
471 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
472     RTCRestrictedStatsMember<std::vector<int32_t>,
473                              StatExposureCriteria::kHardwareCapability>;
474 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
475     RTCRestrictedStatsMember<std::vector<uint32_t>,
476                              StatExposureCriteria::kHardwareCapability>;
477 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
478     RTCRestrictedStatsMember<std::vector<int64_t>,
479                              StatExposureCriteria::kHardwareCapability>;
480 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
481     RTCRestrictedStatsMember<std::vector<uint64_t>,
482                              StatExposureCriteria::kHardwareCapability>;
483 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
484     RTCRestrictedStatsMember<std::vector<double>,
485                              StatExposureCriteria::kHardwareCapability>;
486 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
487     RTCRestrictedStatsMember<std::vector<std::string>,
488                              StatExposureCriteria::kHardwareCapability>;
489 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
490     RTCRestrictedStatsMember<std::map<std::string, uint64_t>,
491                              StatExposureCriteria::kHardwareCapability>;
492 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
493     RTCRestrictedStatsMember<std::map<std::string, double>,
494                              StatExposureCriteria::kHardwareCapability>;
495 
496 // Using inheritance just so that it's obvious from the member's declaration
497 // whether it's standardized or not.
498 template <typename T>
499 class RTCNonStandardStatsMember : public RTCStatsMember<T> {
500  public:
RTCNonStandardStatsMember(const char * name)501   explicit RTCNonStandardStatsMember(const char* name)
502       : RTCStatsMember<T>(name) {}
RTCNonStandardStatsMember(const char * name,std::initializer_list<NonStandardGroupId> group_ids)503   RTCNonStandardStatsMember(const char* name,
504                             std::initializer_list<NonStandardGroupId> group_ids)
505       : RTCStatsMember<T>(name), group_ids_(group_ids) {}
RTCNonStandardStatsMember(const char * name,const T & value)506   RTCNonStandardStatsMember(const char* name, const T& value)
507       : RTCStatsMember<T>(name, value) {}
RTCNonStandardStatsMember(const char * name,T && value)508   RTCNonStandardStatsMember(const char* name, T&& value)
509       : RTCStatsMember<T>(name, std::move(value)) {}
RTCNonStandardStatsMember(const RTCNonStandardStatsMember<T> & other)510   explicit RTCNonStandardStatsMember(const RTCNonStandardStatsMember<T>& other)
511       : RTCStatsMember<T>(other), group_ids_(other.group_ids_) {}
RTCNonStandardStatsMember(RTCNonStandardStatsMember<T> && other)512   explicit RTCNonStandardStatsMember(RTCNonStandardStatsMember<T>&& other)
513       : RTCStatsMember<T>(std::move(other)),
514         group_ids_(std::move(other.group_ids_)) {}
515 
is_standardized()516   bool is_standardized() const override { return false; }
517 
group_ids()518   std::vector<NonStandardGroupId> group_ids() const override {
519     return group_ids_;
520   }
521 
522   T& operator=(const T& value) { return RTCStatsMember<T>::operator=(value); }
523   T& operator=(const T&& value) {
524     return RTCStatsMember<T>::operator=(std::move(value));
525   }
526 
527  private:
528   std::vector<NonStandardGroupId> group_ids_;
529 };
530 
531 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
532     RTCNonStandardStatsMember<bool>;
533 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
534     RTCNonStandardStatsMember<int32_t>;
535 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
536     RTCNonStandardStatsMember<uint32_t>;
537 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
538     RTCNonStandardStatsMember<int64_t>;
539 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
540     RTCNonStandardStatsMember<uint64_t>;
541 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
542     RTCNonStandardStatsMember<double>;
543 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
544     RTCNonStandardStatsMember<std::string>;
545 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
546     RTCNonStandardStatsMember<std::vector<bool>>;
547 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
548     RTCNonStandardStatsMember<std::vector<int32_t>>;
549 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
550     RTCNonStandardStatsMember<std::vector<uint32_t>>;
551 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
552     RTCNonStandardStatsMember<std::vector<int64_t>>;
553 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
554     RTCNonStandardStatsMember<std::vector<uint64_t>>;
555 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
556     RTCNonStandardStatsMember<std::vector<double>>;
557 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
558     RTCNonStandardStatsMember<std::vector<std::string>>;
559 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
560     RTCNonStandardStatsMember<std::map<std::string, uint64_t>>;
561 extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
562     RTCNonStandardStatsMember<std::map<std::string, double>>;
563 
564 }  // namespace webrtc
565 
566 #endif  // API_STATS_RTC_STATS_H_
567