| Index: webrtc/api/rtcstatscollector.cc
|
| diff --git a/webrtc/api/rtcstatscollector.cc b/webrtc/api/rtcstatscollector.cc
|
| index 7f2f45e84a8a2f7787e37fc3a9c101df0ba288c3..216a5ac29916869530c9674659fbd135678fc0e4 100644
|
| --- a/webrtc/api/rtcstatscollector.cc
|
| +++ b/webrtc/api/rtcstatscollector.cc
|
| @@ -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;
|
| + // 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;
|
| + }
|
| + 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));
|
| + }
|
| }
|
| - 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);
|
| + // 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;
|
| }
|
| - 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& 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(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;
|
| + } 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));
|
| }
|
| - 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);
|
| + // 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(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) {
|
|
|