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:
parent
8c375dedb2
commit
09bc128603
@ -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());
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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>>&());
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user