RTCMediaStreamTrackStats collected on a per-attachment basis.

According to recent spec change:
https://github.com/w3c/webrtc-stats/pull/138/files

This establishes the relationship between tracks and
[Voice/Video][Sender/Receiver]Info(s). Follow-up CLs will easily be able
to collect more stats from them.

BUG=webrtc:6757, chromium:659137, chromium:627816

Review-Url: https://codereview.webrtc.org/2641763003
Cr-Commit-Position: refs/heads/master@{#16181}
This commit is contained in:
hbos 2017-01-20 02:47:10 -08:00 committed by Commit bot
parent fd6c94d311
commit 9e30274c03
3 changed files with 585 additions and 358 deletions

View File

@ -433,17 +433,10 @@ class RTCStatsReportVerifier {
// Video or audio media stream track?
if (*media_stream_track.kind == RTCMediaStreamTrackKind::kVideo) {
// Video-only members
if (!*media_stream_track.remote_source) {
verifier.TestMemberIsNonNegative<uint32_t>(
media_stream_track.frame_width);
verifier.TestMemberIsNonNegative<uint32_t>(
media_stream_track.frame_height);
} else {
// TODO(hbos): Frame width/height should be defined for the remote case.
// Is this a real problem or an artifact of testing? crbug.com/659137
verifier.TestMemberIsUndefined(media_stream_track.frame_width);
verifier.TestMemberIsUndefined(media_stream_track.frame_height);
}
verifier.TestMemberIsNonNegative<uint32_t>(
media_stream_track.frame_width);
verifier.TestMemberIsNonNegative<uint32_t>(
media_stream_track.frame_height);
verifier.TestMemberIsUndefined(media_stream_track.frames_per_second);
verifier.TestMemberIsUndefined(media_stream_track.frames_sent);
verifier.TestMemberIsUndefined(media_stream_track.frames_received);
@ -470,14 +463,14 @@ class RTCStatsReportVerifier {
verifier.TestMemberIsUndefined(media_stream_track.partial_frames_lost);
verifier.TestMemberIsUndefined(media_stream_track.full_frames_lost);
// Audio-only members
// TODO(hbos): Why are the audio track missing |audio_level|,
// |echo_return_loss| and |echo_return_loss_enhancement|? Is this a real
// problem or does it have to do with testing and not using real devices?
verifier.TestMemberIsNonNegative<double>(media_stream_track.audio_level);
// TODO(hbos): Find out why |echo_return_loss| and
// |echo_return_loss_enhancement| are undefined in the integration test.
// Is this a real problem or a test problem? Update test so that they are.
// crbug.com/627816
verifier.MarkMemberTested(media_stream_track.audio_level, true);
verifier.MarkMemberTested(media_stream_track.echo_return_loss, true);
verifier.MarkMemberTested(
media_stream_track.echo_return_loss_enhancement, true);
verifier.TestMemberIsUndefined(media_stream_track.echo_return_loss);
verifier.TestMemberIsUndefined(
media_stream_track.echo_return_loss_enhancement);
}
return verifier.ExpectAllMembersSuccessfullyTested();
}

View File

@ -11,6 +11,7 @@
#include "webrtc/api/rtcstatscollector.h"
#include <memory>
#include <sstream>
#include <utility>
#include <vector>
@ -53,10 +54,17 @@ std::string RTCIceCandidatePairStatsIDFromConnectionInfo(
info.remote_candidate.id();
}
std::string RTCMediaStreamTrackStatsIDFromTrackID(
const std::string& id, bool is_local) {
return (is_local ? "RTCMediaStreamTrack_local_" + id
: "RTCMediaStreamTrack_remote_" + id);
std::string RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
bool is_local, const char* kind, const std::string& id, uint32_t ssrc) {
RTC_DCHECK(kind == MediaStreamTrackInterface::kAudioKind ||
kind == MediaStreamTrackInterface::kVideoKind);
std::ostringstream oss;
oss << (is_local ? "RTCMediaStreamTrack_local_"
: "RTCMediaStreamTrack_remote_");
oss << kind << "_";
oss << id << "_";
oss << ssrc;
return oss.str();
}
std::string RTCTransportStatsIDFromTransportChannel(
@ -151,6 +159,12 @@ const char* DtlsTransportStateToRTCDtlsTransportState(
}
}
double DoubleAudioLevelFromIntAudioLevel(int audio_level) {
RTC_DCHECK_GE(audio_level, 0);
RTC_DCHECK_LE(audio_level, 32767);
return audio_level / 32767.0;
}
std::unique_ptr<RTCCodecStats> CodecStatsFromRtpCodecParameters(
uint64_t timestamp_us, bool inbound, bool audio,
const RtpCodecParameters& codec_params) {
@ -322,8 +336,112 @@ const std::string& ProduceIceCandidateStats(
return stats->id();
}
std::unique_ptr<RTCMediaStreamTrackStats>
ProduceMediaStreamTrackStatsFromVoiceSenderInfo(
int64_t timestamp_us,
const AudioTrackInterface& audio_track,
const cricket::VoiceSenderInfo& voice_sender_info) {
std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats(
new RTCMediaStreamTrackStats(
RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
true, MediaStreamTrackInterface::kAudioKind, audio_track.id(),
voice_sender_info.ssrc()),
timestamp_us,
RTCMediaStreamTrackKind::kAudio));
SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
audio_track, audio_track_stats.get());
audio_track_stats->remote_source = false;
audio_track_stats->detached = false;
if (voice_sender_info.audio_level >= 0) {
audio_track_stats->audio_level = DoubleAudioLevelFromIntAudioLevel(
voice_sender_info.audio_level);
}
if (voice_sender_info.echo_return_loss != -100) {
audio_track_stats->echo_return_loss = static_cast<double>(
voice_sender_info.echo_return_loss);
}
if (voice_sender_info.echo_return_loss_enhancement != -100) {
audio_track_stats->echo_return_loss_enhancement = static_cast<double>(
voice_sender_info.echo_return_loss_enhancement);
}
return audio_track_stats;
}
std::unique_ptr<RTCMediaStreamTrackStats>
ProduceMediaStreamTrackStatsFromVoiceReceiverInfo(
int64_t timestamp_us,
const AudioTrackInterface& audio_track,
const cricket::VoiceReceiverInfo& voice_receiver_info) {
std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats(
new RTCMediaStreamTrackStats(
RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
false, MediaStreamTrackInterface::kAudioKind, audio_track.id(),
voice_receiver_info.ssrc()),
timestamp_us,
RTCMediaStreamTrackKind::kAudio));
SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
audio_track, audio_track_stats.get());
audio_track_stats->remote_source = true;
audio_track_stats->detached = false;
if (voice_receiver_info.audio_level >= 0) {
audio_track_stats->audio_level = DoubleAudioLevelFromIntAudioLevel(
voice_receiver_info.audio_level);
}
return audio_track_stats;
}
std::unique_ptr<RTCMediaStreamTrackStats>
ProduceMediaStreamTrackStatsFromVideoSenderInfo(
int64_t timestamp_us,
const VideoTrackInterface& video_track,
const cricket::VideoSenderInfo& video_sender_info) {
std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats(
new RTCMediaStreamTrackStats(
RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
true, MediaStreamTrackInterface::kVideoKind, video_track.id(),
video_sender_info.ssrc()),
timestamp_us,
RTCMediaStreamTrackKind::kVideo));
SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
video_track, video_track_stats.get());
video_track_stats->remote_source = false;
video_track_stats->detached = false;
video_track_stats->frame_width = static_cast<uint32_t>(
video_sender_info.send_frame_width);
video_track_stats->frame_height = static_cast<uint32_t>(
video_sender_info.send_frame_height);
return video_track_stats;
}
std::unique_ptr<RTCMediaStreamTrackStats>
ProduceMediaStreamTrackStatsFromVideoReceiverInfo(
int64_t timestamp_us,
const VideoTrackInterface& video_track,
const cricket::VideoReceiverInfo& video_receiver_info) {
std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats(
new RTCMediaStreamTrackStats(
RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
false, MediaStreamTrackInterface::kVideoKind, video_track.id(),
video_receiver_info.ssrc()),
timestamp_us,
RTCMediaStreamTrackKind::kVideo));
SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
video_track, video_track_stats.get());
video_track_stats->remote_source = true;
video_track_stats->detached = false;
if (video_receiver_info.frame_width > 0 &&
video_receiver_info.frame_height > 0) {
video_track_stats->frame_width = static_cast<uint32_t>(
video_receiver_info.frame_width);
video_track_stats->frame_height = static_cast<uint32_t>(
video_receiver_info.frame_height);
}
return video_track_stats;
}
void ProduceMediaStreamAndTrackStats(
int64_t timestamp_us,
const TrackMediaInfoMap& track_media_info_map,
rtc::scoped_refptr<StreamCollectionInterface> streams,
bool is_local,
RTCStatsReport* report) {
@ -344,73 +462,71 @@ void ProduceMediaStreamAndTrackStats(
stream->label(), timestamp_us));
stream_stats->stream_identifier = stream->label();
stream_stats->track_ids = std::vector<std::string>();
// Audio Tracks
for (const rtc::scoped_refptr<AudioTrackInterface>& audio_track :
stream->GetAudioTracks()) {
std::string id = RTCMediaStreamTrackStatsIDFromTrackID(
audio_track->id(), is_local);
if (report->Get(id)) {
// Skip track, stats already exist for it.
continue;
}
std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats(
new RTCMediaStreamTrackStats(id, timestamp_us,
RTCMediaStreamTrackKind::kAudio));
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);
if (audio_processor_stats.echo_return_loss != -100) {
audio_track_stats->echo_return_loss = static_cast<double>(
audio_processor_stats.echo_return_loss);
// The track stats are per-attachment to the connection. There can be one
// for receiving (remote) tracks and multiple attachments for sending
// (local) tracks.
if (is_local) {
// Local Audio Tracks
for (const rtc::scoped_refptr<AudioTrackInterface>& audio_track :
stream->GetAudioTracks()) {
const std::vector<cricket::VoiceSenderInfo*>* voice_sender_infos =
track_media_info_map.GetVoiceSenderInfos(*audio_track);
if (!voice_sender_infos) {
continue;
}
if (audio_processor_stats.echo_return_loss_enhancement != -100) {
audio_track_stats->echo_return_loss_enhancement = static_cast<double>(
audio_processor_stats.echo_return_loss_enhancement);
for (const auto& voice_sender_info : *voice_sender_infos) {
std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats =
ProduceMediaStreamTrackStatsFromVoiceSenderInfo(
timestamp_us, *audio_track, *voice_sender_info);
stream_stats->track_ids->push_back(audio_track_stats->id());
report->AddStats(std::move(audio_track_stats));
}
}
report->AddStats(std::move(audio_track_stats));
}
// Video Tracks
for (const rtc::scoped_refptr<VideoTrackInterface>& video_track :
stream->GetVideoTracks()) {
std::string id = RTCMediaStreamTrackStatsIDFromTrackID(
video_track->id(), is_local);
if (report->Get(id)) {
// Skip track, stats already exist for it.
continue;
}
std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats(
new RTCMediaStreamTrackStats(id, timestamp_us,
RTCMediaStreamTrackKind::kVideo));
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);
// Local Video Tracks
for (const rtc::scoped_refptr<VideoTrackInterface>& video_track :
stream->GetVideoTracks()) {
const std::vector<cricket::VideoSenderInfo*>* video_sender_infos =
track_media_info_map.GetVideoSenderInfos(*video_track);
if (!video_sender_infos) {
continue;
}
for (const auto& video_sender_info : *video_sender_infos) {
std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats =
ProduceMediaStreamTrackStatsFromVideoSenderInfo(
timestamp_us, *video_track, *video_sender_info);
stream_stats->track_ids->push_back(video_track_stats->id());
report->AddStats(std::move(video_track_stats));
}
}
report->AddStats(std::move(video_track_stats));
} else {
// Remote Audio Tracks
for (const rtc::scoped_refptr<AudioTrackInterface>& audio_track :
stream->GetAudioTracks()) {
const cricket::VoiceReceiverInfo* voice_receiver_info =
track_media_info_map.GetVoiceReceiverInfo(*audio_track);
if (!voice_receiver_info) {
continue;
}
std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats =
ProduceMediaStreamTrackStatsFromVoiceReceiverInfo(
timestamp_us, *audio_track, *voice_receiver_info);
stream_stats->track_ids->push_back(audio_track_stats->id());
report->AddStats(std::move(audio_track_stats));
}
// Remote Video Tracks
for (const rtc::scoped_refptr<VideoTrackInterface>& video_track :
stream->GetVideoTracks()) {
const cricket::VideoReceiverInfo* video_receiver_info =
track_media_info_map.GetVideoReceiverInfo(*video_track);
if (!video_receiver_info) {
continue;
}
std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats =
ProduceMediaStreamTrackStatsFromVideoReceiverInfo(
timestamp_us, *video_track, *video_receiver_info);
stream_stats->track_ids->push_back(video_track_stats->id());
report->AddStats(std::move(video_track_stats));
}
}
report->AddStats(std::move(stream_stats));
}
@ -749,10 +865,17 @@ void RTCStatsCollector::ProduceIceCandidateAndPairStats_n(
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);
RTC_DCHECK(track_media_info_map_);
ProduceMediaStreamAndTrackStats(timestamp_us,
*track_media_info_map_,
pc_->local_streams(),
true,
report);
ProduceMediaStreamAndTrackStats(timestamp_us,
*track_media_info_map_,
pc_->remote_streams(),
false,
report);
}
void RTCStatsCollector::ProducePeerConnectionStats_s(
@ -795,8 +918,11 @@ void RTCStatsCollector::ProduceRTPStreamStats_n(
if (audio_track) {
RTC_DCHECK(track_to_id_.find(audio_track.get()) != track_to_id_.end());
inbound_audio->media_track_id =
RTCMediaStreamTrackStatsIDFromTrackID(
track_to_id_.find(audio_track.get())->second, false);
RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
false,
MediaStreamTrackInterface::kAudioKind,
track_to_id_.find(audio_track.get())->second,
voice_receiver_info.ssrc());
}
inbound_audio->transport_id = transport_id;
if (voice_receiver_info.codec_payload_type) {
@ -825,8 +951,11 @@ void RTCStatsCollector::ProduceRTPStreamStats_n(
if (audio_track) {
RTC_DCHECK(track_to_id_.find(audio_track.get()) != track_to_id_.end());
outbound_audio->media_track_id =
RTCMediaStreamTrackStatsIDFromTrackID(
track_to_id_.find(audio_track.get())->second, true);
RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
true,
MediaStreamTrackInterface::kAudioKind,
track_to_id_.find(audio_track.get())->second,
voice_sender_info.ssrc());
}
outbound_audio->transport_id = transport_id;
if (voice_sender_info.codec_payload_type) {
@ -861,8 +990,11 @@ void RTCStatsCollector::ProduceRTPStreamStats_n(
if (video_track) {
RTC_DCHECK(track_to_id_.find(video_track.get()) != track_to_id_.end());
inbound_video->media_track_id =
RTCMediaStreamTrackStatsIDFromTrackID(
track_to_id_.find(video_track.get())->second, false);
RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
false,
MediaStreamTrackInterface::kVideoKind,
track_to_id_.find(video_track.get())->second,
video_receiver_info.ssrc());
}
inbound_video->transport_id = transport_id;
if (video_receiver_info.codec_payload_type) {
@ -891,8 +1023,11 @@ void RTCStatsCollector::ProduceRTPStreamStats_n(
if (video_track) {
RTC_DCHECK(track_to_id_.find(video_track.get()) != track_to_id_.end());
outbound_video->media_track_id =
RTCMediaStreamTrackStatsIDFromTrackID(
track_to_id_.find(video_track.get())->second, true);
RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
true,
MediaStreamTrackInterface::kVideoKind,
track_to_id_.find(video_track.get())->second,
video_sender_info.ssrc());
}
outbound_video->transport_id = transport_id;
if (video_sender_info.codec_payload_type) {

View File

@ -10,6 +10,7 @@
#include "webrtc/api/rtcstatscollector.h"
#include <initializer_list>
#include <memory>
#include <ostream>
#include <string>
@ -170,44 +171,20 @@ 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) {
MediaStreamTrackInterface::TrackState state) {
rtc::scoped_refptr<FakeAudioTrackForStats> audio_track_stats(
new rtc::RefCountedObject<FakeAudioTrackForStats>(
id, signal_level, processor));
new rtc::RefCountedObject<FakeAudioTrackForStats>(id));
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) {
FakeAudioTrackForStats(const std::string& id)
: MediaStreamTrack<AudioTrackInterface>(id) {
}
std::string kind() const override {
@ -216,47 +193,10 @@ class FakeAudioTrackForStats
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;
}
bool GetSignalLevel(int* level) override { return false; }
rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
return processor_;
return nullptr;
}
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<webrtc::VideoFrame>* sink,
const rtc::VideoSinkWants& wants) override {}
void RemoveSink(rtc::VideoSinkInterface<webrtc::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
@ -264,52 +204,72 @@ class FakeVideoTrackForStats
public:
static rtc::scoped_refptr<FakeVideoTrackForStats> Create(
const std::string& id,
MediaStreamTrackInterface::TrackState state,
rtc::scoped_refptr<VideoTrackSourceInterface> source) {
MediaStreamTrackInterface::TrackState state) {
rtc::scoped_refptr<FakeVideoTrackForStats> video_track(
new rtc::RefCountedObject<FakeVideoTrackForStats>(id, source));
new rtc::RefCountedObject<FakeVideoTrackForStats>(id));
video_track->set_state(state);
return video_track;
}
FakeVideoTrackForStats(
const std::string& id,
rtc::scoped_refptr<VideoTrackSourceInterface> source)
: MediaStreamTrack<VideoTrackInterface>(id),
source_(source) {
FakeVideoTrackForStats(const std::string& id)
: MediaStreamTrack<VideoTrackInterface>(id) {
}
std::string kind() const override {
return MediaStreamTrackInterface::kVideoKind;
}
VideoTrackSourceInterface* GetSource() const override {
return source_;
}
private:
rtc::scoped_refptr<VideoTrackSourceInterface> source_;
VideoTrackSourceInterface* GetSource() const override { return nullptr; }
};
rtc::scoped_refptr<MediaStreamTrackInterface> CreateFakeTrack(
cricket::MediaType media_type,
const std::string& track_id) {
const std::string& track_id,
MediaStreamTrackInterface::TrackState track_state) {
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
return FakeAudioTrackForStats::Create(
track_id,
MediaStreamTrackInterface::TrackState::kLive,
32767,
new FakeAudioProcessorForStats(
AudioProcessorInterface::AudioProcessorStats()));
return FakeAudioTrackForStats::Create(track_id, track_state);
} else {
RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
return FakeVideoTrackForStats::Create(
track_id,
MediaStreamTrackInterface::TrackState::kLive,
new FakeVideoTrackSourceForStats(
VideoTrackSourceInterface::Stats()));
return FakeVideoTrackForStats::Create(track_id, track_state);
}
}
rtc::scoped_refptr<MockRtpSender> CreateMockSender(
rtc::scoped_refptr<MediaStreamTrackInterface> track, uint32_t ssrc) {
rtc::scoped_refptr<MockRtpSender> sender(
new rtc::RefCountedObject<MockRtpSender>());
EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track));
EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc));
EXPECT_CALL(*sender, media_type()).WillRepeatedly(Return(
track->kind() == MediaStreamTrackInterface::kAudioKind
? cricket::MEDIA_TYPE_AUDIO : cricket::MEDIA_TYPE_VIDEO));
EXPECT_CALL(*sender, GetParameters()).WillRepeatedly(Invoke(
[ssrc]() {
RtpParameters params;
params.encodings.push_back(RtpEncodingParameters());
params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
return params;
}));
return sender;
}
rtc::scoped_refptr<MockRtpReceiver> CreateMockReceiver(
rtc::scoped_refptr<MediaStreamTrackInterface> track, uint32_t ssrc) {
rtc::scoped_refptr<MockRtpReceiver> receiver(
new rtc::RefCountedObject<MockRtpReceiver>());
EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track));
EXPECT_CALL(*receiver, media_type()).WillRepeatedly(Return(
track->kind() == MediaStreamTrackInterface::kAudioKind
? cricket::MEDIA_TYPE_AUDIO : cricket::MEDIA_TYPE_VIDEO));
EXPECT_CALL(*receiver, GetParameters()).WillRepeatedly(Invoke(
[ssrc]() {
RtpParameters params;
params.encodings.push_back(RtpEncodingParameters());
params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
return params;
}));
return receiver;
}
class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
public:
RTCStatsCollectorTestHelper()
@ -377,25 +337,16 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
rtc::scoped_refptr<MediaStreamTrackInterface> track;
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
track = CreateFakeTrack(media_type, track_id);
track = CreateFakeTrack(media_type, track_id,
MediaStreamTrackInterface::kLive);
local_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get()));
} else {
track = CreateFakeTrack(media_type, track_id);
track = CreateFakeTrack(media_type, track_id,
MediaStreamTrackInterface::kLive);
local_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get()));
}
rtc::scoped_refptr<MockRtpSender> sender(
new rtc::RefCountedObject<MockRtpSender>());
EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track));
EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc));
EXPECT_CALL(*sender, media_type()).WillRepeatedly(Return(media_type));
EXPECT_CALL(*sender, GetParameters()).WillRepeatedly(Invoke(
[ssrc]() {
RtpParameters params;
params.encodings.push_back(RtpEncodingParameters());
params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
return params;
}));
rtc::scoped_refptr<MockRtpSender> sender = CreateMockSender(track, ssrc);
EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return(
std::vector<rtc::scoped_refptr<RtpSenderInterface>>({
rtc::scoped_refptr<RtpSenderInterface>(sender.get()) })));
@ -415,29 +366,123 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
rtc::scoped_refptr<MediaStreamTrackInterface> track;
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
track = CreateFakeTrack(media_type, track_id);
track = CreateFakeTrack(media_type, track_id,
MediaStreamTrackInterface::kLive);
remote_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get()));
} else {
track = CreateFakeTrack(media_type, track_id);
track = CreateFakeTrack(media_type, track_id,
MediaStreamTrackInterface::kLive);
remote_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get()));
}
rtc::scoped_refptr<MockRtpReceiver> receiver(
new rtc::RefCountedObject<MockRtpReceiver>());
EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track));
EXPECT_CALL(*receiver, media_type()).WillRepeatedly(Return(media_type));
EXPECT_CALL(*receiver, GetParameters()).WillRepeatedly(Invoke(
[ssrc]() {
RtpParameters params;
params.encodings.push_back(RtpEncodingParameters());
params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
return params;
}));
rtc::scoped_refptr<MockRtpReceiver> receiver =
CreateMockReceiver(track, ssrc);
EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return(
std::vector<rtc::scoped_refptr<RtpReceiverInterface>>({
rtc::scoped_refptr<RtpReceiverInterface>(receiver.get()) })));
}
// Attaches tracks to peer connections by configuring RTP senders and RTP
// receivers according to the tracks' pairings with
// |[Voice/Video][Sender/Receiver]Info| and their SSRCs. Local tracks can be
// associated with multiple |[Voice/Video]SenderInfo|s, remote tracks can only
// be associated with one |[Voice/Video]ReceiverInfo|.
void CreateMockRtpSendersReceiversAndChannels(
std::initializer_list<std::pair<MediaStreamTrackInterface*,
cricket::VoiceSenderInfo>> local_audio_track_info_pairs,
std::initializer_list<std::pair<MediaStreamTrackInterface*,
cricket::VoiceReceiverInfo>> remote_audio_track_info_pairs,
std::initializer_list<std::pair<MediaStreamTrackInterface*,
cricket::VideoSenderInfo>> local_video_track_info_pairs,
std::initializer_list<std::pair<MediaStreamTrackInterface*,
cricket::VideoReceiverInfo>> remote_video_track_info_pairs) {
voice_media_info_.reset(new cricket::VoiceMediaInfo());
video_media_info_.reset(new cricket::VideoMediaInfo());
rtp_senders_.clear();
rtp_receivers_.clear();
// Local audio tracks and voice sender infos
for (auto& pair : local_audio_track_info_pairs) {
MediaStreamTrackInterface* local_audio_track = pair.first;
const cricket::VoiceSenderInfo& voice_sender_info = pair.second;
RTC_DCHECK_EQ(local_audio_track->kind(),
MediaStreamTrackInterface::kAudioKind);
voice_media_info_->senders.push_back(voice_sender_info);
rtc::scoped_refptr<MockRtpSender> rtp_sender =
CreateMockSender(rtc::scoped_refptr<MediaStreamTrackInterface>(
local_audio_track),
voice_sender_info.local_stats[0].ssrc);
rtp_senders_.push_back(rtc::scoped_refptr<RtpSenderInterface>(
rtp_sender.get()));
}
// Remote audio tracks and voice receiver infos
for (auto& pair : remote_audio_track_info_pairs) {
MediaStreamTrackInterface* remote_audio_track = pair.first;
const cricket::VoiceReceiverInfo& voice_receiver_info = pair.second;
RTC_DCHECK_EQ(remote_audio_track->kind(),
MediaStreamTrackInterface::kAudioKind);
voice_media_info_->receivers.push_back(voice_receiver_info);
rtc::scoped_refptr<MockRtpReceiver> rtp_receiver =
CreateMockReceiver(rtc::scoped_refptr<MediaStreamTrackInterface>(
remote_audio_track),
voice_receiver_info.local_stats[0].ssrc);
rtp_receivers_.push_back(rtc::scoped_refptr<RtpReceiverInterface>(
rtp_receiver.get()));
}
// Local video tracks and video sender infos
for (auto& pair : local_video_track_info_pairs) {
MediaStreamTrackInterface* local_video_track = pair.first;
const cricket::VideoSenderInfo& video_sender_info = pair.second;
RTC_DCHECK_EQ(local_video_track->kind(),
MediaStreamTrackInterface::kVideoKind);
video_media_info_->senders.push_back(video_sender_info);
rtc::scoped_refptr<MockRtpSender> rtp_sender =
CreateMockSender(rtc::scoped_refptr<MediaStreamTrackInterface>(
local_video_track),
video_sender_info.local_stats[0].ssrc);
rtp_senders_.push_back(rtc::scoped_refptr<RtpSenderInterface>(
rtp_sender.get()));
}
// Remote video tracks and video receiver infos
for (auto& pair : remote_video_track_info_pairs) {
MediaStreamTrackInterface* remote_video_track = pair.first;
const cricket::VideoReceiverInfo& video_receiver_info = pair.second;
RTC_DCHECK_EQ(remote_video_track->kind(),
MediaStreamTrackInterface::kVideoKind);
video_media_info_->receivers.push_back(video_receiver_info);
rtc::scoped_refptr<MockRtpReceiver> rtp_receiver =
CreateMockReceiver(rtc::scoped_refptr<MediaStreamTrackInterface>(
remote_video_track),
video_receiver_info.local_stats[0].ssrc);
rtp_receivers_.push_back(rtc::scoped_refptr<RtpReceiverInterface>(
rtp_receiver.get()));
}
EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return(rtp_senders_));
EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return(rtp_receivers_));
MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
voice_channel_.reset(new cricket::VoiceChannel(
worker_thread_, network_thread_, nullptr, media_engine_,
voice_media_channel, "VoiceContentName", kDefaultRtcpMuxRequired,
kDefaultSrtpRequired));
EXPECT_CALL(session_, voice_channel())
.WillRepeatedly(Return(voice_channel_.get()));
EXPECT_CALL(*voice_media_channel, GetStats(_))
.WillOnce(DoAll(SetArgPointee<0>(*voice_media_info_), Return(true)));
MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel();
video_channel_.reset(new cricket::VideoChannel(
worker_thread_, network_thread_, nullptr, video_media_channel,
"VideoContentName", kDefaultRtcpMuxRequired, kDefaultSrtpRequired));
EXPECT_CALL(session_, video_channel())
.WillRepeatedly(Return(video_channel_.get()));
EXPECT_CALL(*video_media_channel, GetStats(_))
.WillOnce(DoAll(SetArgPointee<0>(*video_media_info_), Return(true)));
}
private:
rtc::ScopedFakeClock fake_clock_;
RtcEventLogNullImpl event_log_;
@ -451,6 +496,12 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
MockPeerConnection pc_;
std::vector<rtc::scoped_refptr<DataChannel>> data_channels_;
std::unique_ptr<cricket::VoiceChannel> voice_channel_;
std::unique_ptr<cricket::VideoChannel> video_channel_;
std::unique_ptr<cricket::VoiceMediaInfo> voice_media_info_;
std::unique_ptr<cricket::VideoMediaInfo> video_media_info_;
std::vector<rtc::scoped_refptr<RtpSenderInterface>> rtp_senders_;
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> rtp_receivers_;
};
class RTCTestStats : public RTCStats {
@ -1333,37 +1384,54 @@ TEST_F(RTCStatsCollectorTest,
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);
rtc::scoped_refptr<MediaStreamTrackInterface> local_audio_track =
CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID",
MediaStreamTrackInterface::kEnded);
local_stream->AddTrack(static_cast<AudioTrackInterface*>(
local_audio_track.get()));
cricket::VoiceSenderInfo voice_sender_info_ssrc1;
voice_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
voice_sender_info_ssrc1.local_stats[0].ssrc = 1;
voice_sender_info_ssrc1.audio_level = 32767;
voice_sender_info_ssrc1.echo_return_loss = 42;
voice_sender_info_ssrc1.echo_return_loss_enhancement = 52;
// Uses default values, the corresponding stats object should contain
// undefined members.
cricket::VoiceSenderInfo voice_sender_info_ssrc2;
voice_sender_info_ssrc2.local_stats.push_back(cricket::SsrcSenderInfo());
voice_sender_info_ssrc2.local_stats[0].ssrc = 2;
voice_sender_info_ssrc2.audio_level = 0;
voice_sender_info_ssrc2.echo_return_loss = -100;
voice_sender_info_ssrc2.echo_return_loss_enhancement = -100;
// 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<MediaStreamTrackInterface> remote_audio_track =
CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID",
MediaStreamTrackInterface::kLive);
remote_stream->AddTrack(static_cast<AudioTrackInterface*>(
remote_audio_track.get()));
cricket::VoiceReceiverInfo voice_receiver_info;
voice_receiver_info.local_stats.push_back(cricket::SsrcReceiverInfo());
voice_receiver_info.local_stats[0].ssrc = 3;
voice_receiver_info.audio_level = 16383;
test_->CreateMockRtpSendersReceiversAndChannels(
{ std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1),
std::make_pair(local_audio_track.get(), voice_sender_info_ssrc2) },
{ std::make_pair(remote_audio_track.get(), voice_receiver_info) },
{}, {});
rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
RTCMediaStreamStats expected_local_stream(
"RTCMediaStream_local_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_local_LocalAudioTrackID");
expected_local_stream.track_ids = std::vector<std::string>(
{ "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1",
"RTCMediaStreamTrack_local_audio_LocalAudioTrackID_2" });
ASSERT_TRUE(report->Get(expected_local_stream.id()));
EXPECT_EQ(expected_local_stream,
report->Get(expected_local_stream.id())->cast_to<
@ -1372,86 +1440,57 @@ TEST_F(RTCStatsCollectorTest,
RTCMediaStreamStats expected_remote_stream(
"RTCMediaStream_remote_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_remote_RemoteAudioTrackID");
expected_remote_stream.track_ids = std::vector<std::string>({
"RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_3" });
ASSERT_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_local_LocalAudioTrackID", report->timestamp_us(),
RTCMediaStreamTrackKind::kAudio);
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;
ASSERT_TRUE(report->Get(expected_local_audio_track.id()));
EXPECT_EQ(expected_local_audio_track,
report->Get(expected_local_audio_track.id())->cast_to<
RTCMediaStreamTrackStats expected_local_audio_track_ssrc1(
"RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1",
report->timestamp_us(), RTCMediaStreamTrackKind::kAudio);
expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id();
expected_local_audio_track_ssrc1.remote_source = false;
expected_local_audio_track_ssrc1.ended = true;
expected_local_audio_track_ssrc1.detached = false;
expected_local_audio_track_ssrc1.audio_level = 1.0;
expected_local_audio_track_ssrc1.echo_return_loss = 42.0;
expected_local_audio_track_ssrc1.echo_return_loss_enhancement = 52.0;
ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc1.id()));
EXPECT_EQ(expected_local_audio_track_ssrc1,
report->Get(expected_local_audio_track_ssrc1.id())->cast_to<
RTCMediaStreamTrackStats>());
RTCMediaStreamTrackStats expected_local_audio_track_ssrc2(
"RTCMediaStreamTrack_local_audio_LocalAudioTrackID_2",
report->timestamp_us(), RTCMediaStreamTrackKind::kAudio);
expected_local_audio_track_ssrc2.track_identifier = local_audio_track->id();
expected_local_audio_track_ssrc2.remote_source = false;
expected_local_audio_track_ssrc2.ended = true;
expected_local_audio_track_ssrc2.detached = false;
expected_local_audio_track_ssrc2.audio_level = 0.0;
// Should be undefined: |expected_local_audio_track_ssrc2.echo_return_loss|
// and |expected_local_audio_track_ssrc2.echo_return_loss_enhancement|.
ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc2.id()));
EXPECT_EQ(expected_local_audio_track_ssrc2,
report->Get(expected_local_audio_track_ssrc2.id())->cast_to<
RTCMediaStreamTrackStats>());
RTCMediaStreamTrackStats expected_remote_audio_track(
"RTCMediaStreamTrack_remote_RemoteAudioTrackID", report->timestamp_us(),
RTCMediaStreamTrackKind::kAudio);
"RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_3",
report->timestamp_us(), RTCMediaStreamTrackKind::kAudio);
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;
expected_remote_audio_track.audio_level = 16383.0 / 32767.0;
ASSERT_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_Audio_Defaults) {
rtc::scoped_refptr<StreamCollection> local_streams =
StreamCollection::Create();
EXPECT_CALL(test_->pc(), local_streams())
.WillRepeatedly(Return(local_streams));
rtc::scoped_refptr<MediaStream> local_stream =
MediaStream::Create("LocalStreamLabel");
local_streams->AddStream(local_stream);
// Local audio track
AudioProcessorInterface::AudioProcessorStats local_audio_processor_stats;
local_audio_processor_stats.echo_return_loss = -100;
local_audio_processor_stats.echo_return_loss_enhancement = -100;
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);
rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
RTCMediaStreamTrackStats expected_local_audio_track(
"RTCMediaStreamTrack_local_LocalAudioTrackID", report->timestamp_us(),
RTCMediaStreamTrackKind::kAudio);
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;
// Should be undefined: |expected_local_audio_track.echo_return_loss| and
// |expected_local_audio_track.echo_return_loss_enhancement|.
ASSERT_TRUE(report->Get(expected_local_audio_track.id()));
EXPECT_EQ(expected_local_audio_track,
report->Get(expected_local_audio_track.id())->cast_to<
RTCMediaStreamTrackStats>());
}
TEST_F(RTCStatsCollectorTest,
CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
rtc::scoped_refptr<StreamCollection> local_streams =
@ -1471,39 +1510,67 @@ TEST_F(RTCStatsCollectorTest,
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);
rtc::scoped_refptr<MediaStreamTrackInterface> local_video_track =
CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID",
MediaStreamTrackInterface::kLive);
local_stream->AddTrack(static_cast<VideoTrackInterface*>(
local_video_track.get()));
// 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);
cricket::VideoSenderInfo video_sender_info_ssrc1;
video_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
video_sender_info_ssrc1.local_stats[0].ssrc = 1;
video_sender_info_ssrc1.send_frame_width = 1234;
video_sender_info_ssrc1.send_frame_height = 4321;
cricket::VideoSenderInfo video_sender_info_ssrc2;
video_sender_info_ssrc2.local_stats.push_back(cricket::SsrcSenderInfo());
video_sender_info_ssrc2.local_stats[0].ssrc = 2;
video_sender_info_ssrc2.send_frame_width = 4321;
video_sender_info_ssrc2.send_frame_height = 1234;
// Remote video track with values
rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc3 =
CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID3",
MediaStreamTrackInterface::kEnded);
remote_stream->AddTrack(static_cast<VideoTrackInterface*>(
remote_video_track_ssrc3.get()));
cricket::VideoReceiverInfo video_receiver_info_ssrc3;
video_receiver_info_ssrc3.local_stats.push_back(cricket::SsrcReceiverInfo());
video_receiver_info_ssrc3.local_stats[0].ssrc = 3;
video_receiver_info_ssrc3.frame_width = 6789;
video_receiver_info_ssrc3.frame_height = 9876;
// Remote video track with undefined (default) values
rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc4 =
CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID4",
MediaStreamTrackInterface::kLive);
remote_stream->AddTrack(static_cast<VideoTrackInterface*>(
remote_video_track_ssrc4.get()));
cricket::VideoReceiverInfo video_receiver_info_ssrc4;
video_receiver_info_ssrc4.local_stats.push_back(cricket::SsrcReceiverInfo());
video_receiver_info_ssrc4.local_stats[0].ssrc = 4;
video_receiver_info_ssrc4.frame_width = 0;
video_receiver_info_ssrc4.frame_height = 0;
test_->CreateMockRtpSendersReceiversAndChannels(
{}, {},
{ std::make_pair(local_video_track.get(), video_sender_info_ssrc1),
std::make_pair(local_video_track.get(), video_sender_info_ssrc2) },
{ std::make_pair(remote_video_track_ssrc3.get(),
video_receiver_info_ssrc3),
std::make_pair(remote_video_track_ssrc4.get(),
video_receiver_info_ssrc4) });
rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
RTCMediaStreamStats expected_local_stream(
"RTCMediaStream_local_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_local_LocalVideoTrackID");
expected_local_stream.track_ids = std::vector<std::string>({
"RTCMediaStreamTrack_local_video_LocalVideoTrackID_1",
"RTCMediaStreamTrack_local_video_LocalVideoTrackID_2" });
ASSERT_TRUE(report->Get(expected_local_stream.id()));
EXPECT_EQ(expected_local_stream,
report->Get(expected_local_stream.id())->cast_to<
@ -1512,40 +1579,70 @@ TEST_F(RTCStatsCollectorTest,
RTCMediaStreamStats expected_remote_stream(
"RTCMediaStream_remote_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_remote_RemoteVideoTrackID");
expected_remote_stream.track_ids = std::vector<std::string>({
"RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_3",
"RTCMediaStreamTrack_remote_video_RemoteVideoTrackID4_4" });
ASSERT_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_local_LocalVideoTrackID", report->timestamp_us(),
RTCMediaStreamTrackKind::kVideo);
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;
ASSERT_TRUE(report->Get(expected_local_video_track.id()));
EXPECT_EQ(expected_local_video_track,
report->Get(expected_local_video_track.id())->cast_to<
RTCMediaStreamTrackStats expected_local_video_track_ssrc1(
"RTCMediaStreamTrack_local_video_LocalVideoTrackID_1",
report->timestamp_us(), RTCMediaStreamTrackKind::kVideo);
expected_local_video_track_ssrc1.track_identifier = local_video_track->id();
expected_local_video_track_ssrc1.remote_source = false;
expected_local_video_track_ssrc1.ended = false;
expected_local_video_track_ssrc1.detached = false;
expected_local_video_track_ssrc1.frame_width = 1234;
expected_local_video_track_ssrc1.frame_height = 4321;
ASSERT_TRUE(report->Get(expected_local_video_track_ssrc1.id()));
EXPECT_EQ(expected_local_video_track_ssrc1,
report->Get(expected_local_video_track_ssrc1.id())->cast_to<
RTCMediaStreamTrackStats>());
RTCMediaStreamTrackStats expected_remote_video_track(
"RTCMediaStreamTrack_remote_RemoteVideoTrackID", report->timestamp_us(),
RTCMediaStreamTrackKind::kVideo);
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;
ASSERT_TRUE(report->Get(expected_remote_video_track.id()));
EXPECT_EQ(expected_remote_video_track,
report->Get(expected_remote_video_track.id())->cast_to<
RTCMediaStreamTrackStats expected_local_video_track_ssrc2(
"RTCMediaStreamTrack_local_video_LocalVideoTrackID_2",
report->timestamp_us(), RTCMediaStreamTrackKind::kVideo);
expected_local_video_track_ssrc2.track_identifier = local_video_track->id();
expected_local_video_track_ssrc2.remote_source = false;
expected_local_video_track_ssrc2.ended = false;
expected_local_video_track_ssrc2.detached = false;
expected_local_video_track_ssrc2.frame_width = 4321;
expected_local_video_track_ssrc2.frame_height = 1234;
ASSERT_TRUE(report->Get(expected_local_video_track_ssrc2.id()));
EXPECT_EQ(expected_local_video_track_ssrc2,
report->Get(expected_local_video_track_ssrc2.id())->cast_to<
RTCMediaStreamTrackStats>());
RTCMediaStreamTrackStats expected_remote_video_track_ssrc3(
"RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_3",
report->timestamp_us(), RTCMediaStreamTrackKind::kVideo);
expected_remote_video_track_ssrc3.track_identifier =
remote_video_track_ssrc3->id();
expected_remote_video_track_ssrc3.remote_source = true;
expected_remote_video_track_ssrc3.ended = true;
expected_remote_video_track_ssrc3.detached = false;
expected_remote_video_track_ssrc3.frame_width = 6789;
expected_remote_video_track_ssrc3.frame_height = 9876;
ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc3.id()));
EXPECT_EQ(expected_remote_video_track_ssrc3,
report->Get(expected_remote_video_track_ssrc3.id())->cast_to<
RTCMediaStreamTrackStats>());
RTCMediaStreamTrackStats expected_remote_video_track_ssrc4(
"RTCMediaStreamTrack_remote_video_RemoteVideoTrackID4_4",
report->timestamp_us(), RTCMediaStreamTrackKind::kVideo);
expected_remote_video_track_ssrc4.track_identifier =
remote_video_track_ssrc4->id();
expected_remote_video_track_ssrc4.remote_source = true;
expected_remote_video_track_ssrc4.ended = false;
expected_remote_video_track_ssrc4.detached = false;
// Should be undefined: |expected_remote_video_track_ssrc4.frame_width| and
// |expected_remote_video_track_ssrc4.frame_height|.
ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc4.id()));
EXPECT_EQ(expected_remote_video_track_ssrc4,
report->Get(expected_remote_video_track_ssrc4.id())->cast_to<
RTCMediaStreamTrackStats>());
}
@ -1608,7 +1705,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
expected_audio.is_remote = false;
expected_audio.media_type = "audio";
expected_audio.media_track_id =
"RTCMediaStreamTrack_remote_RemoteAudioTrackID";
"RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_1";
expected_audio.transport_id = "RTCTransport_TransportName_" +
rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
expected_audio.codec_id = "RTCCodec_InboundAudio_42";
@ -1690,7 +1787,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
expected_video.is_remote = false;
expected_video.media_type = "video";
expected_video.media_track_id =
"RTCMediaStreamTrack_remote_RemoteVideoTrackID";
"RTCMediaStreamTrack_remote_video_RemoteVideoTrackID_1";
expected_video.transport_id = "RTCTransport_TransportName_" +
rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
expected_video.codec_id = "RTCCodec_InboundVideo_42";
@ -1768,7 +1865,8 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
expected_audio.ssrc = "1";
expected_audio.is_remote = false;
expected_audio.media_type = "audio";
expected_audio.media_track_id = "RTCMediaStreamTrack_local_LocalAudioTrackID";
expected_audio.media_track_id =
"RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1";
expected_audio.transport_id = "RTCTransport_TransportName_" +
rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
expected_audio.codec_id = "RTCCodec_OutboundAudio_42";
@ -1846,7 +1944,8 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
expected_video.ssrc = "1";
expected_video.is_remote = false;
expected_video.media_type = "video";
expected_video.media_track_id = "RTCMediaStreamTrack_local_LocalVideoTrackID";
expected_video.media_track_id =
"RTCMediaStreamTrack_local_video_LocalVideoTrackID_1";
expected_video.transport_id = "RTCTransport_TransportName_" +
rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
expected_video.codec_id = "RTCCodec_OutboundVideo_42";