RTCMediaStream[Track]Stats added.

Not all members are collected by RTCStatsCollector and detached tracks
are not visible in the returned stats. This needs to be addressed before
closing crbug.com/660827 and crbug.com/659137

BUG=chromium:660827, chromium:659137, chromium:627816

Review-Url: https://codereview.webrtc.org/2467873005
Cr-Commit-Position: refs/heads/master@{#14978}
This commit is contained in:
hbos 2016-11-08 06:29:22 -08:00 committed by Commit bot
parent 8c375dedb2
commit 09bc128603
6 changed files with 601 additions and 2 deletions

View File

@ -15,6 +15,8 @@
#include <vector>
#include "webrtc/api/peerconnection.h"
#include "webrtc/api/peerconnectioninterface.h"
#include "webrtc/api/mediastreaminterface.h"
#include "webrtc/api/webrtcsession.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/timeutils.h"
@ -37,6 +39,11 @@ std::string RTCIceCandidatePairStatsIDFromConnectionInfo(
info.remote_candidate.id();
}
std::string RTCMediaStreamTrackStatsIDFromMediaStreamTrackInterface(
const MediaStreamTrackInterface& track) {
return "RTCMediaStreamTrack_" + track.id();
}
std::string RTCTransportStatsIDFromTransportChannel(
const std::string& transport_name, int channel_component) {
return "RTCTransport_" + transport_name + "_" +
@ -93,6 +100,13 @@ const char* DataStateToRTCDataChannelState(
}
}
void SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
const MediaStreamTrackInterface& track,
RTCMediaStreamTrackStats* track_stats) {
track_stats->track_identifier = track.id();
track_stats->ended = (track.state() == MediaStreamTrackInterface::kEnded);
}
void SetInboundRTPStreamStatsFromMediaReceiverInfo(
const cricket::MediaReceiverInfo& media_receiver_info,
RTCInboundRTPStreamStats* inbound_stats) {
@ -214,6 +228,93 @@ const std::string& ProduceIceCandidateStats(
return stats->id();
}
void ProduceMediaStreamAndTrackStats(
int64_t timestamp_us,
rtc::scoped_refptr<StreamCollectionInterface> streams,
bool is_local,
RTCStatsReport* report) {
// TODO(hbos): When "AddTrack" is implemented we should iterate tracks to
// find which streams exist, not iterate streams to find tracks.
// crbug.com/659137
// TODO(hbos): Return stats of detached tracks. We have to perform stats
// gathering at the time of detachment to get accurate stats and timestamps.
// crbug.com/659137
if (!streams)
return;
for (size_t i = 0; i < streams->count(); ++i) {
MediaStreamInterface* stream = streams->at(i);
std::unique_ptr<RTCMediaStreamStats> stream_stats(
new RTCMediaStreamStats("RTCMediaStream_" + stream->label(),
timestamp_us));
stream_stats->stream_identifier = stream->label();
stream_stats->track_ids = std::vector<std::string>();
// Audio Tracks
for (rtc::scoped_refptr<AudioTrackInterface> audio_track :
stream->GetAudioTracks()) {
std::string id = RTCMediaStreamTrackStatsIDFromMediaStreamTrackInterface(
*audio_track.get());
if (report->Get(id)) {
// Skip track, stats already exist for it.
continue;
}
std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats(
new RTCMediaStreamTrackStats(id, timestamp_us));
stream_stats->track_ids->push_back(audio_track_stats->id());
SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
*audio_track.get(),
audio_track_stats.get());
audio_track_stats->remote_source = !is_local;
audio_track_stats->detached = false;
int signal_level;
if (audio_track->GetSignalLevel(&signal_level)) {
// Convert signal level from [0,32767] int to [0,1] double.
RTC_DCHECK_GE(signal_level, 0);
RTC_DCHECK_LE(signal_level, 32767);
audio_track_stats->audio_level = signal_level / 32767.0;
}
if (audio_track->GetAudioProcessor()) {
AudioProcessorInterface::AudioProcessorStats audio_processor_stats;
audio_track->GetAudioProcessor()->GetStats(&audio_processor_stats);
audio_track_stats->echo_return_loss = static_cast<double>(
audio_processor_stats.echo_return_loss);
audio_track_stats->echo_return_loss_enhancement = static_cast<double>(
audio_processor_stats.echo_return_loss_enhancement);
}
report->AddStats(std::move(audio_track_stats));
}
// Video Tracks
for (rtc::scoped_refptr<VideoTrackInterface> video_track :
stream->GetVideoTracks()) {
std::string id = RTCMediaStreamTrackStatsIDFromMediaStreamTrackInterface(
*video_track.get());
if (report->Get(id)) {
// Skip track, stats already exist for it.
continue;
}
std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats(
new RTCMediaStreamTrackStats(id, timestamp_us));
stream_stats->track_ids->push_back(video_track_stats->id());
SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
*video_track.get(),
video_track_stats.get());
video_track_stats->remote_source = !is_local;
video_track_stats->detached = false;
if (video_track->GetSource()) {
VideoTrackSourceInterface::Stats video_track_source_stats;
if (video_track->GetSource()->GetStats(&video_track_source_stats)) {
video_track_stats->frame_width = static_cast<uint32_t>(
video_track_source_stats.input_width);
video_track_stats->frame_height = static_cast<uint32_t>(
video_track_source_stats.input_height);
}
}
report->AddStats(std::move(video_track_stats));
}
report->AddStats(std::move(stream_stats));
}
}
} // namespace
rtc::scoped_refptr<RTCStatsCollector> RTCStatsCollector::Create(
@ -301,6 +402,7 @@ void RTCStatsCollector::ProducePartialResultsOnSignalingThread(
timestamp_us, session_stats, transport_cert_stats, report.get());
}
ProduceDataChannelStats_s(timestamp_us, report.get());
ProduceMediaStreamAndTrackStats_s(timestamp_us, report.get());
ProducePeerConnectionStats_s(timestamp_us, report.get());
AddPartialResults(report);
@ -467,6 +569,15 @@ void RTCStatsCollector::ProduceIceCandidateAndPairStats_s(
}
}
void RTCStatsCollector::ProduceMediaStreamAndTrackStats_s(
int64_t timestamp_us, RTCStatsReport* report) const {
RTC_DCHECK(signaling_thread_->IsCurrent());
ProduceMediaStreamAndTrackStats(
timestamp_us, pc_->local_streams(), true, report);
ProduceMediaStreamAndTrackStats(
timestamp_us, pc_->remote_streams(), false, report);
}
void RTCStatsCollector::ProducePeerConnectionStats_s(
int64_t timestamp_us, RTCStatsReport* report) const {
RTC_DCHECK(signaling_thread_->IsCurrent());

View File

@ -98,6 +98,9 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface {
void ProduceIceCandidateAndPairStats_s(
int64_t timestamp_us, const SessionStats& session_stats,
RTCStatsReport* report) const;
// Produces |RTCMediaStreamStats| and |RTCMediaStreamTrackStats|.
void ProduceMediaStreamAndTrackStats_s(
int64_t timestamp_us, RTCStatsReport* report) const;
// Produces |RTCPeerConnectionStats|.
void ProducePeerConnectionStats_s(
int64_t timestamp_us, RTCStatsReport* report) const;

View File

@ -15,6 +15,8 @@
#include <string>
#include <vector>
#include "webrtc/api/mediastream.h"
#include "webrtc/api/mediastreamtrack.h"
#include "webrtc/api/jsepsessiondescription.h"
#include "webrtc/api/stats/rtcstats_objects.h"
#include "webrtc/api/stats/rtcstatsreport.h"
@ -70,6 +72,14 @@ void PrintTo(const RTCPeerConnectionStats& stats, ::std::ostream* os) {
*os << stats.ToString();
}
void PrintTo(const RTCMediaStreamStats& stats, ::std::ostream* os) {
*os << stats.ToString();
}
void PrintTo(const RTCMediaStreamTrackStats& stats, ::std::ostream* os) {
*os << stats.ToString();
}
void PrintTo(const RTCInboundRTPStreamStats& stats, ::std::ostream* os) {
*os << stats.ToString();
}
@ -150,6 +160,126 @@ std::unique_ptr<cricket::Candidate> CreateFakeCandidate(
return candidate;
}
class FakeAudioProcessorForStats
: public rtc::RefCountedObject<AudioProcessorInterface> {
public:
FakeAudioProcessorForStats(
AudioProcessorInterface::AudioProcessorStats stats)
: stats_(stats) {
}
void GetStats(AudioProcessorInterface::AudioProcessorStats* stats) override {
*stats = stats_;
}
private:
AudioProcessorInterface::AudioProcessorStats stats_;
};
class FakeAudioTrackForStats
: public MediaStreamTrack<AudioTrackInterface> {
public:
static rtc::scoped_refptr<FakeAudioTrackForStats> Create(
const std::string& id,
MediaStreamTrackInterface::TrackState state,
int signal_level,
rtc::scoped_refptr<FakeAudioProcessorForStats> processor) {
rtc::scoped_refptr<FakeAudioTrackForStats> audio_track_stats(
new rtc::RefCountedObject<FakeAudioTrackForStats>(
id, signal_level, processor));
audio_track_stats->set_state(state);
return audio_track_stats;
}
FakeAudioTrackForStats(
const std::string& id,
int signal_level,
rtc::scoped_refptr<FakeAudioProcessorForStats> processor)
: MediaStreamTrack<AudioTrackInterface>(id),
signal_level_(signal_level),
processor_(processor) {
}
std::string kind() const override {
return MediaStreamTrackInterface::kAudioKind;
}
webrtc::AudioSourceInterface* GetSource() const override { return nullptr; }
void AddSink(webrtc::AudioTrackSinkInterface* sink) override {}
void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {}
bool GetSignalLevel(int* level) override {
*level = signal_level_;
return true;
}
rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
return processor_;
}
private:
int signal_level_;
rtc::scoped_refptr<FakeAudioProcessorForStats> processor_;
};
class FakeVideoTrackSourceForStats
: public rtc::RefCountedObject<VideoTrackSourceInterface> {
public:
FakeVideoTrackSourceForStats(VideoTrackSourceInterface::Stats stats)
: stats_(stats) {
}
MediaSourceInterface::SourceState state() const override {
return MediaSourceInterface::kLive;
}
bool remote() const override { return false; }
void RegisterObserver(ObserverInterface* observer) override {}
void UnregisterObserver(ObserverInterface* observer) override {}
void AddOrUpdateSink(rtc::VideoSinkInterface<cricket::VideoFrame>* sink,
const rtc::VideoSinkWants& wants) override {}
void RemoveSink(rtc::VideoSinkInterface<cricket::VideoFrame>* sink) override {
}
bool is_screencast() const override { return false; }
rtc::Optional<bool> needs_denoising() const override {
return rtc::Optional<bool>();
}
bool GetStats(VideoTrackSourceInterface::Stats* stats) override {
*stats = stats_;
return true;
}
private:
VideoTrackSourceInterface::Stats stats_;
};
class FakeVideoTrackForStats
: public MediaStreamTrack<VideoTrackInterface> {
public:
static rtc::scoped_refptr<FakeVideoTrackForStats> Create(
const std::string& id,
MediaStreamTrackInterface::TrackState state,
rtc::scoped_refptr<VideoTrackSourceInterface> source) {
rtc::scoped_refptr<FakeVideoTrackForStats> video_track(
new rtc::RefCountedObject<FakeVideoTrackForStats>(id, source));
video_track->set_state(state);
return video_track;
}
FakeVideoTrackForStats(
const std::string& id,
rtc::scoped_refptr<VideoTrackSourceInterface> source)
: MediaStreamTrack<VideoTrackInterface>(id),
source_(source) {
}
std::string kind() const override {
return MediaStreamTrackInterface::kVideoKind;
}
VideoTrackSourceInterface* GetSource() const override {
return source_;
}
private:
rtc::scoped_refptr<VideoTrackSourceInterface> source_;
};
class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
public:
RTCStatsCollectorTestHelper()
@ -168,6 +298,8 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
session_(media_controller_.get()),
pc_() {
// Default return values for mocks.
EXPECT_CALL(pc_, local_streams()).WillRepeatedly(Return(nullptr));
EXPECT_CALL(pc_, remote_streams()).WillRepeatedly(Return(nullptr));
EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_));
EXPECT_CALL(pc_, sctp_data_channels()).WillRepeatedly(
ReturnRef(data_channels_));
@ -198,12 +330,12 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
private:
rtc::ScopedFakeClock fake_clock_;
webrtc::RtcEventLogNullImpl event_log_;
RtcEventLogNullImpl event_log_;
rtc::Thread* const worker_thread_;
rtc::Thread* const network_thread_;
cricket::FakeMediaEngine* media_engine_;
std::unique_ptr<cricket::ChannelManager> channel_manager_;
std::unique_ptr<webrtc::MediaControllerInterface> media_controller_;
std::unique_ptr<MediaControllerInterface> media_controller_;
MockWebRtcSession session_;
MockPeerConnection pc_;
@ -979,6 +1111,196 @@ TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
}
}
TEST_F(RTCStatsCollectorTest,
CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
rtc::scoped_refptr<StreamCollection> local_streams =
StreamCollection::Create();
rtc::scoped_refptr<StreamCollection> remote_streams =
StreamCollection::Create();
EXPECT_CALL(test_->pc(), local_streams())
.WillRepeatedly(Return(local_streams));
EXPECT_CALL(test_->pc(), remote_streams())
.WillRepeatedly(Return(remote_streams));
rtc::scoped_refptr<MediaStream> local_stream =
MediaStream::Create("LocalStreamLabel");
local_streams->AddStream(local_stream);
rtc::scoped_refptr<MediaStream> remote_stream =
MediaStream::Create("RemoteStreamLabel");
remote_streams->AddStream(remote_stream);
// Local audio track
AudioProcessorInterface::AudioProcessorStats local_audio_processor_stats;
local_audio_processor_stats.echo_return_loss = 42;
local_audio_processor_stats.echo_return_loss_enhancement = 52;
rtc::scoped_refptr<FakeAudioTrackForStats> local_audio_track =
FakeAudioTrackForStats::Create(
"LocalAudioTrackID",
MediaStreamTrackInterface::TrackState::kEnded,
32767,
new FakeAudioProcessorForStats(local_audio_processor_stats));
local_stream->AddTrack(local_audio_track);
// Remote audio track
AudioProcessorInterface::AudioProcessorStats remote_audio_processor_stats;
remote_audio_processor_stats.echo_return_loss = 13;
remote_audio_processor_stats.echo_return_loss_enhancement = 37;
rtc::scoped_refptr<FakeAudioTrackForStats> remote_audio_track =
FakeAudioTrackForStats::Create(
"RemoteAudioTrackID",
MediaStreamTrackInterface::TrackState::kLive,
0,
new FakeAudioProcessorForStats(remote_audio_processor_stats));
remote_stream->AddTrack(remote_audio_track);
rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
RTCMediaStreamStats expected_local_stream(
"RTCMediaStream_LocalStreamLabel", report->timestamp_us());
expected_local_stream.stream_identifier = local_stream->label();
expected_local_stream.track_ids = std::vector<std::string>();
expected_local_stream.track_ids->push_back(
"RTCMediaStreamTrack_LocalAudioTrackID");
EXPECT_TRUE(report->Get(expected_local_stream.id()));
EXPECT_EQ(expected_local_stream,
report->Get(expected_local_stream.id())->cast_to<
RTCMediaStreamStats>());
RTCMediaStreamStats expected_remote_stream(
"RTCMediaStream_RemoteStreamLabel", report->timestamp_us());
expected_remote_stream.stream_identifier = remote_stream->label();
expected_remote_stream.track_ids = std::vector<std::string>();
expected_remote_stream.track_ids->push_back(
"RTCMediaStreamTrack_RemoteAudioTrackID");
EXPECT_TRUE(report->Get(expected_remote_stream.id()));
EXPECT_EQ(expected_remote_stream,
report->Get(expected_remote_stream.id())->cast_to<
RTCMediaStreamStats>());
RTCMediaStreamTrackStats expected_local_audio_track(
"RTCMediaStreamTrack_LocalAudioTrackID", report->timestamp_us());
expected_local_audio_track.track_identifier = local_audio_track->id();
expected_local_audio_track.remote_source = false;
expected_local_audio_track.ended = true;
expected_local_audio_track.detached = false;
expected_local_audio_track.audio_level = 1.0;
expected_local_audio_track.echo_return_loss = 42.0;
expected_local_audio_track.echo_return_loss_enhancement = 52.0;
EXPECT_TRUE(report->Get(expected_local_audio_track.id()));
EXPECT_EQ(expected_local_audio_track,
report->Get(expected_local_audio_track.id())->cast_to<
RTCMediaStreamTrackStats>());
RTCMediaStreamTrackStats expected_remote_audio_track(
"RTCMediaStreamTrack_RemoteAudioTrackID", report->timestamp_us());
expected_remote_audio_track.track_identifier = remote_audio_track->id();
expected_remote_audio_track.remote_source = true;
expected_remote_audio_track.ended = false;
expected_remote_audio_track.detached = false;
expected_remote_audio_track.audio_level = 0.0;
expected_remote_audio_track.echo_return_loss = 13.0;
expected_remote_audio_track.echo_return_loss_enhancement = 37.0;
EXPECT_TRUE(report->Get(expected_remote_audio_track.id()));
EXPECT_EQ(expected_remote_audio_track,
report->Get(expected_remote_audio_track.id())->cast_to<
RTCMediaStreamTrackStats>());
}
TEST_F(RTCStatsCollectorTest,
CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
rtc::scoped_refptr<StreamCollection> local_streams =
StreamCollection::Create();
rtc::scoped_refptr<StreamCollection> remote_streams =
StreamCollection::Create();
EXPECT_CALL(test_->pc(), local_streams())
.WillRepeatedly(Return(local_streams));
EXPECT_CALL(test_->pc(), remote_streams())
.WillRepeatedly(Return(remote_streams));
rtc::scoped_refptr<MediaStream> local_stream =
MediaStream::Create("LocalStreamLabel");
local_streams->AddStream(local_stream);
rtc::scoped_refptr<MediaStream> remote_stream =
MediaStream::Create("RemoteStreamLabel");
remote_streams->AddStream(remote_stream);
// Local video track
VideoTrackSourceInterface::Stats local_video_track_source_stats;
local_video_track_source_stats.input_width = 1234;
local_video_track_source_stats.input_height = 4321;
rtc::scoped_refptr<FakeVideoTrackSourceForStats> local_video_track_source =
new FakeVideoTrackSourceForStats(local_video_track_source_stats);
rtc::scoped_refptr<FakeVideoTrackForStats> local_video_track =
FakeVideoTrackForStats::Create(
"LocalVideoTrackID",
MediaStreamTrackInterface::TrackState::kLive,
local_video_track_source);
local_stream->AddTrack(local_video_track);
// Remote video track
VideoTrackSourceInterface::Stats remote_video_track_source_stats;
remote_video_track_source_stats.input_width = 1234;
remote_video_track_source_stats.input_height = 4321;
rtc::scoped_refptr<FakeVideoTrackSourceForStats> remote_video_track_source =
new FakeVideoTrackSourceForStats(remote_video_track_source_stats);
rtc::scoped_refptr<FakeVideoTrackForStats> remote_video_track =
FakeVideoTrackForStats::Create(
"RemoteVideoTrackID",
MediaStreamTrackInterface::TrackState::kEnded,
remote_video_track_source);
remote_stream->AddTrack(remote_video_track);
rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
RTCMediaStreamStats expected_local_stream(
"RTCMediaStream_LocalStreamLabel", report->timestamp_us());
expected_local_stream.stream_identifier = local_stream->label();
expected_local_stream.track_ids = std::vector<std::string>();
expected_local_stream.track_ids->push_back(
"RTCMediaStreamTrack_LocalVideoTrackID");
EXPECT_TRUE(report->Get(expected_local_stream.id()));
EXPECT_EQ(expected_local_stream,
report->Get(expected_local_stream.id())->cast_to<
RTCMediaStreamStats>());
RTCMediaStreamStats expected_remote_stream(
"RTCMediaStream_RemoteStreamLabel", report->timestamp_us());
expected_remote_stream.stream_identifier = remote_stream->label();
expected_remote_stream.track_ids = std::vector<std::string>();
expected_remote_stream.track_ids->push_back(
"RTCMediaStreamTrack_RemoteVideoTrackID");
EXPECT_TRUE(report->Get(expected_remote_stream.id()));
EXPECT_EQ(expected_remote_stream,
report->Get(expected_remote_stream.id())->cast_to<
RTCMediaStreamStats>());
RTCMediaStreamTrackStats expected_local_video_track(
"RTCMediaStreamTrack_LocalVideoTrackID", report->timestamp_us());
expected_local_video_track.track_identifier = local_video_track->id();
expected_local_video_track.remote_source = false;
expected_local_video_track.ended = false;
expected_local_video_track.detached = false;
expected_local_video_track.frame_width = 1234;
expected_local_video_track.frame_height = 4321;
EXPECT_TRUE(report->Get(expected_local_video_track.id()));
EXPECT_EQ(expected_local_video_track,
report->Get(expected_local_video_track.id())->cast_to<
RTCMediaStreamTrackStats>());
RTCMediaStreamTrackStats expected_remote_video_track(
"RTCMediaStreamTrack_RemoteVideoTrackID", report->timestamp_us());
expected_remote_video_track.track_identifier = remote_video_track->id();
expected_remote_video_track.remote_source = true;
expected_remote_video_track.ended = true;
expected_remote_video_track.detached = false;
expected_remote_video_track.frame_width = 1234;
expected_remote_video_track.frame_height = 4321;
EXPECT_TRUE(report->Get(expected_remote_video_track.id()));
EXPECT_EQ(expected_remote_video_track,
report->Get(expected_remote_video_track.id())->cast_to<
RTCMediaStreamTrackStats>());
}
TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
cricket::VoiceChannel voice_channel(

View File

@ -183,6 +183,65 @@ class RTCRemoteIceCandidateStats final : public RTCIceCandidateStats {
const char* type() const override;
};
// https://w3c.github.io/webrtc-stats/#msstats-dict*
// TODO(hbos): Finish implementation. Tracking bug crbug.com/660827
class RTCMediaStreamStats final : public RTCStats {
public:
WEBRTC_RTCSTATS_DECL();
RTCMediaStreamStats(const std::string& id, int64_t timestamp_us);
RTCMediaStreamStats(std::string&& id, int64_t timestamp_us);
RTCMediaStreamStats(const RTCMediaStreamStats& other);
~RTCMediaStreamStats() override;
RTCStatsMember<std::string> stream_identifier;
RTCStatsMember<std::vector<std::string>> track_ids;
};
// https://w3c.github.io/webrtc-stats/#mststats-dict*
// TODO(hbos): Finish implementation. Tracking bug crbug.com/659137
class RTCMediaStreamTrackStats final : public RTCStats {
public:
WEBRTC_RTCSTATS_DECL();
RTCMediaStreamTrackStats(const std::string& id, int64_t timestamp_us);
RTCMediaStreamTrackStats(std::string&& id, int64_t timestamp_us);
RTCMediaStreamTrackStats(const RTCMediaStreamTrackStats& other);
~RTCMediaStreamTrackStats() override;
RTCStatsMember<std::string> track_identifier;
RTCStatsMember<bool> remote_source;
RTCStatsMember<bool> ended;
// TODO(hbos): |RTCStatsCollector| does not return stats for detached tracks.
// crbug.com/659137
RTCStatsMember<bool> detached;
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137
RTCStatsMember<std::vector<std::string>> ssrc_ids;
// Video-only members
RTCStatsMember<uint32_t> frame_width;
RTCStatsMember<uint32_t> frame_height;
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137
RTCStatsMember<double> frames_per_second;
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137
RTCStatsMember<uint32_t> frames_sent;
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137
RTCStatsMember<uint32_t> frames_received;
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137
RTCStatsMember<uint32_t> frames_decoded;
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137
RTCStatsMember<uint32_t> frames_dropped;
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137
RTCStatsMember<uint32_t> frames_corrupted;
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137
RTCStatsMember<uint32_t> partial_frames_lost;
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137
RTCStatsMember<uint32_t> full_frames_lost;
// Audio-only members
RTCStatsMember<double> audio_level;
RTCStatsMember<double> echo_return_loss;
RTCStatsMember<double> echo_return_loss_enhancement;
};
// https://w3c.github.io/webrtc-stats/#pcstats-dict*
// TODO(hbos): Finish implementation. Tracking bug crbug.com/636818
class RTCPeerConnectionStats final : public RTCStats {

View File

@ -28,6 +28,10 @@ class MockPeerConnection
MockPeerConnection()
: rtc::RefCountedObject<webrtc::PeerConnection>(
new FakePeerConnectionFactory()) {}
MOCK_METHOD0(local_streams,
rtc::scoped_refptr<StreamCollectionInterface>());
MOCK_METHOD0(remote_streams,
rtc::scoped_refptr<StreamCollectionInterface>());
MOCK_METHOD0(session, WebRtcSession*());
MOCK_CONST_METHOD0(sctp_data_channels,
const std::vector<rtc::scoped_refptr<DataChannel>>&());

View File

@ -267,6 +267,106 @@ const char* RTCRemoteIceCandidateStats::type() const {
return kType;
}
WEBRTC_RTCSTATS_IMPL(RTCMediaStreamStats, RTCStats, "stream",
&stream_identifier,
&track_ids);
RTCMediaStreamStats::RTCMediaStreamStats(
const std::string& id, int64_t timestamp_us)
: RTCMediaStreamStats(std::string(id), timestamp_us) {
}
RTCMediaStreamStats::RTCMediaStreamStats(
std::string&& id, int64_t timestamp_us)
: RTCStats(std::move(id), timestamp_us),
stream_identifier("streamIdentifier"),
track_ids("trackIds") {
}
RTCMediaStreamStats::RTCMediaStreamStats(
const RTCMediaStreamStats& other)
: RTCStats(other.id(), other.timestamp_us()),
stream_identifier(other.stream_identifier),
track_ids(other.track_ids) {
}
RTCMediaStreamStats::~RTCMediaStreamStats() {
}
WEBRTC_RTCSTATS_IMPL(RTCMediaStreamTrackStats, RTCStats, "track",
&track_identifier,
&remote_source,
&ended,
&detached,
&ssrc_ids,
&frame_width,
&frame_height,
&frames_per_second,
&frames_sent,
&frames_received,
&frames_decoded,
&frames_dropped,
&frames_corrupted,
&partial_frames_lost,
&full_frames_lost,
&audio_level,
&echo_return_loss,
&echo_return_loss_enhancement);
RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(
const std::string& id, int64_t timestamp_us)
: RTCMediaStreamTrackStats(std::string(id), timestamp_us) {
}
RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(
std::string&& id, int64_t timestamp_us)
: RTCStats(std::move(id), timestamp_us),
track_identifier("trackIdentifier"),
remote_source("remoteSource"),
ended("ended"),
detached("detached"),
ssrc_ids("ssrcIds"),
frame_width("frameWidth"),
frame_height("frameHeight"),
frames_per_second("framesPerSecond"),
frames_sent("framesSent"),
frames_received("framesReceived"),
frames_decoded("framesDecoded"),
frames_dropped("framesDropped"),
frames_corrupted("framesCorrupted"),
partial_frames_lost("partialFramesLost"),
full_frames_lost("fullFramesLost"),
audio_level("audioLevel"),
echo_return_loss("echoReturnLoss"),
echo_return_loss_enhancement("echoReturnLossEnhancement") {
}
RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(
const RTCMediaStreamTrackStats& other)
: RTCStats(other.id(), other.timestamp_us()),
track_identifier(other.track_identifier),
remote_source(other.remote_source),
ended(other.ended),
detached(other.detached),
ssrc_ids(other.ssrc_ids),
frame_width(other.frame_width),
frame_height(other.frame_height),
frames_per_second(other.frames_per_second),
frames_sent(other.frames_sent),
frames_received(other.frames_received),
frames_decoded(other.frames_decoded),
frames_dropped(other.frames_dropped),
frames_corrupted(other.frames_corrupted),
partial_frames_lost(other.partial_frames_lost),
full_frames_lost(other.full_frames_lost),
audio_level(other.audio_level),
echo_return_loss(other.echo_return_loss),
echo_return_loss_enhancement(other.echo_return_loss_enhancement) {
}
RTCMediaStreamTrackStats::~RTCMediaStreamTrackStats() {
}
WEBRTC_RTCSTATS_IMPL(RTCPeerConnectionStats, RTCStats, "peer-connection",
&data_channels_opened,
&data_channels_closed);