RTCCodecStats[1] added.
RTCStatsCollector supports "payloadType", "codec" and "clockRate". "channels", "parameters" and "implementation" need to be supported before closing crbug.com/659117. [1] https://w3c.github.io/webrtc-stats/#codec-dict* BUG=chromium:659117, chromium:627816, chromium:657854 NOTRY=True Review-Url: https://codereview.webrtc.org/2509803004 Cr-Commit-Position: refs/heads/master@{#15207}
This commit is contained in:
parent
71caaca254
commit
0adb8285b1
@ -33,6 +33,20 @@ std::string RTCCertificateIDFromFingerprint(const std::string& fingerprint) {
|
||||
return "RTCCertificate_" + fingerprint;
|
||||
}
|
||||
|
||||
std::string RTCCodecStatsIDFromDirectionMediaAndPayload(
|
||||
bool inbound, bool audio, uint32_t payload_type) {
|
||||
// TODO(hbos): When we are able to handle multiple m= lines of the same media
|
||||
// type (and multiple BaseChannels for the same type is possible?) this needs
|
||||
// to be updated to differentiate the transport being used, and stats need to
|
||||
// be collected for all of them. crbug.com/659117
|
||||
if (inbound) {
|
||||
return audio ? "RTCCodec_InboundAudio_" + rtc::ToString<>(payload_type)
|
||||
: "RTCCodec_InboundVideo_" + rtc::ToString<>(payload_type);
|
||||
}
|
||||
return audio ? "RTCCodec_OutboundAudio_" + rtc::ToString<>(payload_type)
|
||||
: "RTCCodec_OutboundVideo_" + rtc::ToString<>(payload_type);
|
||||
}
|
||||
|
||||
std::string RTCIceCandidatePairStatsIDFromConnectionInfo(
|
||||
const cricket::ConnectionInfo& info) {
|
||||
return "RTCIceCandidatePair_" + info.local_candidate.id() + "_" +
|
||||
@ -100,6 +114,21 @@ const char* DataStateToRTCDataChannelState(
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<RTCCodecStats> CodecStatsFromRtpCodecParameters(
|
||||
uint64_t timestamp_us, bool inbound, bool audio,
|
||||
const RtpCodecParameters& codec_params) {
|
||||
RTC_DCHECK_GE(codec_params.payload_type, 0);
|
||||
RTC_DCHECK_LE(codec_params.payload_type, 127);
|
||||
uint32_t payload_type = static_cast<uint32_t>(codec_params.payload_type);
|
||||
std::unique_ptr<RTCCodecStats> codec_stats(new RTCCodecStats(
|
||||
RTCCodecStatsIDFromDirectionMediaAndPayload(inbound, audio, payload_type),
|
||||
timestamp_us));
|
||||
codec_stats->payload_type = payload_type;
|
||||
codec_stats->codec = (audio ? "audio/" : "video/") + codec_params.mime_type;
|
||||
codec_stats->clock_rate = static_cast<uint32_t>(codec_params.clock_rate);
|
||||
return codec_stats;
|
||||
}
|
||||
|
||||
void SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
|
||||
const MediaStreamTrackInterface& track,
|
||||
RTCMediaStreamTrackStats* track_stats) {
|
||||
@ -402,14 +431,17 @@ void RTCStatsCollector::ProducePartialResultsOnSignalingThread(
|
||||
SessionStats session_stats;
|
||||
if (pc_->session()->GetTransportStats(&session_stats)) {
|
||||
std::map<std::string, CertificateStatsPair> transport_cert_stats =
|
||||
PrepareTransportCertificateStats_s(session_stats);
|
||||
PrepareTransportCertificateStats(session_stats);
|
||||
MediaInfo media_info = PrepareMediaInfo(session_stats);
|
||||
|
||||
ProduceCertificateStats_s(
|
||||
timestamp_us, transport_cert_stats, report.get());
|
||||
ProduceCodecStats_s(
|
||||
timestamp_us, media_info, report.get());
|
||||
ProduceIceCandidateAndPairStats_s(
|
||||
timestamp_us, session_stats, report.get());
|
||||
ProduceRTPStreamStats_s(
|
||||
timestamp_us, session_stats, report.get());
|
||||
timestamp_us, session_stats, media_info, report.get());
|
||||
ProduceTransportStats_s(
|
||||
timestamp_us, session_stats, transport_cert_stats, report.get());
|
||||
}
|
||||
@ -511,6 +543,38 @@ void RTCStatsCollector::ProduceCertificateStats_s(
|
||||
}
|
||||
}
|
||||
|
||||
void RTCStatsCollector::ProduceCodecStats_s(
|
||||
int64_t timestamp_us, const MediaInfo& media_info,
|
||||
RTCStatsReport* report) const {
|
||||
RTC_DCHECK(signaling_thread_->IsCurrent());
|
||||
// Audio
|
||||
if (media_info.voice) {
|
||||
// Inbound
|
||||
for (const auto& pair : media_info.voice->receive_codecs) {
|
||||
report->AddStats(CodecStatsFromRtpCodecParameters(
|
||||
timestamp_us, true, true, pair.second));
|
||||
}
|
||||
// Outbound
|
||||
for (const auto& pair : media_info.voice->send_codecs) {
|
||||
report->AddStats(CodecStatsFromRtpCodecParameters(
|
||||
timestamp_us, false, true, pair.second));
|
||||
}
|
||||
}
|
||||
// Video
|
||||
if (media_info.video) {
|
||||
// Inbound
|
||||
for (const auto& pair : media_info.video->receive_codecs) {
|
||||
report->AddStats(CodecStatsFromRtpCodecParameters(
|
||||
timestamp_us, true, false, pair.second));
|
||||
}
|
||||
// Outbound
|
||||
for (const auto& pair : media_info.video->send_codecs) {
|
||||
report->AddStats(CodecStatsFromRtpCodecParameters(
|
||||
timestamp_us, false, false, pair.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RTCStatsCollector::ProduceDataChannelStats_s(
|
||||
int64_t timestamp_us, RTCStatsReport* report) const {
|
||||
RTC_DCHECK(signaling_thread_->IsCurrent());
|
||||
@ -602,93 +666,107 @@ void RTCStatsCollector::ProducePeerConnectionStats_s(
|
||||
|
||||
void RTCStatsCollector::ProduceRTPStreamStats_s(
|
||||
int64_t timestamp_us, const SessionStats& session_stats,
|
||||
RTCStatsReport* report) const {
|
||||
const MediaInfo& media_info, RTCStatsReport* report) const {
|
||||
RTC_DCHECK(signaling_thread_->IsCurrent());
|
||||
|
||||
// Audio
|
||||
if (pc_->session()->voice_channel()) {
|
||||
cricket::VoiceMediaInfo voice_media_info;
|
||||
if (pc_->session()->voice_channel()->GetStats(&voice_media_info)) {
|
||||
std::string transport_id = RTCTransportStatsIDFromBaseChannel(
|
||||
session_stats.proxy_to_transport, *pc_->session()->voice_channel());
|
||||
RTC_DCHECK(!transport_id.empty());
|
||||
// Inbound
|
||||
for (const cricket::VoiceReceiverInfo& voice_receiver_info :
|
||||
voice_media_info.receivers) {
|
||||
// TODO(nisse): SSRC == 0 currently means none. Delete check when that
|
||||
// is fixed.
|
||||
if (voice_receiver_info.ssrc() == 0)
|
||||
continue;
|
||||
std::unique_ptr<RTCInboundRTPStreamStats> inbound_audio(
|
||||
new RTCInboundRTPStreamStats(
|
||||
RTCInboundRTPStreamStatsIDFromSSRC(
|
||||
true, voice_receiver_info.ssrc()),
|
||||
timestamp_us));
|
||||
SetInboundRTPStreamStatsFromVoiceReceiverInfo(
|
||||
voice_receiver_info, inbound_audio.get());
|
||||
inbound_audio->transport_id = transport_id;
|
||||
report->AddStats(std::move(inbound_audio));
|
||||
if (media_info.voice) {
|
||||
std::string transport_id = RTCTransportStatsIDFromBaseChannel(
|
||||
session_stats.proxy_to_transport, *pc_->session()->voice_channel());
|
||||
RTC_DCHECK(!transport_id.empty());
|
||||
// Inbound
|
||||
for (const cricket::VoiceReceiverInfo& voice_receiver_info :
|
||||
media_info.voice->receivers) {
|
||||
// TODO(nisse): SSRC == 0 currently means none. Delete check when that
|
||||
// is fixed.
|
||||
if (voice_receiver_info.ssrc() == 0)
|
||||
continue;
|
||||
std::unique_ptr<RTCInboundRTPStreamStats> inbound_audio(
|
||||
new RTCInboundRTPStreamStats(
|
||||
RTCInboundRTPStreamStatsIDFromSSRC(
|
||||
true, voice_receiver_info.ssrc()),
|
||||
timestamp_us));
|
||||
SetInboundRTPStreamStatsFromVoiceReceiverInfo(
|
||||
voice_receiver_info, inbound_audio.get());
|
||||
inbound_audio->transport_id = transport_id;
|
||||
if (voice_receiver_info.codec_payload_type) {
|
||||
inbound_audio->codec_id =
|
||||
RTCCodecStatsIDFromDirectionMediaAndPayload(
|
||||
true, true, *voice_receiver_info.codec_payload_type);
|
||||
}
|
||||
// Outbound
|
||||
for (const cricket::VoiceSenderInfo& voice_sender_info :
|
||||
voice_media_info.senders) {
|
||||
// TODO(nisse): SSRC == 0 currently means none. Delete check when that
|
||||
// is fixed.
|
||||
if (voice_sender_info.ssrc() == 0)
|
||||
continue;
|
||||
std::unique_ptr<RTCOutboundRTPStreamStats> outbound_audio(
|
||||
new RTCOutboundRTPStreamStats(
|
||||
RTCOutboundRTPStreamStatsIDFromSSRC(
|
||||
true, voice_sender_info.ssrc()),
|
||||
timestamp_us));
|
||||
SetOutboundRTPStreamStatsFromVoiceSenderInfo(
|
||||
voice_sender_info, outbound_audio.get());
|
||||
outbound_audio->transport_id = transport_id;
|
||||
report->AddStats(std::move(outbound_audio));
|
||||
report->AddStats(std::move(inbound_audio));
|
||||
}
|
||||
// Outbound
|
||||
for (const cricket::VoiceSenderInfo& voice_sender_info :
|
||||
media_info.voice->senders) {
|
||||
// TODO(nisse): SSRC == 0 currently means none. Delete check when that
|
||||
// is fixed.
|
||||
if (voice_sender_info.ssrc() == 0)
|
||||
continue;
|
||||
std::unique_ptr<RTCOutboundRTPStreamStats> outbound_audio(
|
||||
new RTCOutboundRTPStreamStats(
|
||||
RTCOutboundRTPStreamStatsIDFromSSRC(
|
||||
true, voice_sender_info.ssrc()),
|
||||
timestamp_us));
|
||||
SetOutboundRTPStreamStatsFromVoiceSenderInfo(
|
||||
voice_sender_info, outbound_audio.get());
|
||||
outbound_audio->transport_id = transport_id;
|
||||
if (voice_sender_info.codec_payload_type) {
|
||||
outbound_audio->codec_id =
|
||||
RTCCodecStatsIDFromDirectionMediaAndPayload(
|
||||
false, true, *voice_sender_info.codec_payload_type);
|
||||
}
|
||||
report->AddStats(std::move(outbound_audio));
|
||||
}
|
||||
}
|
||||
// Video
|
||||
if (pc_->session()->video_channel()) {
|
||||
cricket::VideoMediaInfo video_media_info;
|
||||
if (pc_->session()->video_channel()->GetStats(&video_media_info)) {
|
||||
std::string transport_id = RTCTransportStatsIDFromBaseChannel(
|
||||
session_stats.proxy_to_transport, *pc_->session()->video_channel());
|
||||
RTC_DCHECK(!transport_id.empty());
|
||||
// Inbound
|
||||
for (const cricket::VideoReceiverInfo& video_receiver_info :
|
||||
video_media_info.receivers) {
|
||||
// TODO(nisse): SSRC == 0 currently means none. Delete check when that
|
||||
// is fixed.
|
||||
if (video_receiver_info.ssrc() == 0)
|
||||
continue;
|
||||
std::unique_ptr<RTCInboundRTPStreamStats> inbound_video(
|
||||
new RTCInboundRTPStreamStats(
|
||||
RTCInboundRTPStreamStatsIDFromSSRC(
|
||||
false, video_receiver_info.ssrc()),
|
||||
timestamp_us));
|
||||
SetInboundRTPStreamStatsFromVideoReceiverInfo(
|
||||
video_receiver_info, inbound_video.get());
|
||||
inbound_video->transport_id = transport_id;
|
||||
report->AddStats(std::move(inbound_video));
|
||||
if (media_info.video) {
|
||||
std::string transport_id = RTCTransportStatsIDFromBaseChannel(
|
||||
session_stats.proxy_to_transport, *pc_->session()->video_channel());
|
||||
RTC_DCHECK(!transport_id.empty());
|
||||
// Inbound
|
||||
for (const cricket::VideoReceiverInfo& video_receiver_info :
|
||||
media_info.video->receivers) {
|
||||
// TODO(nisse): SSRC == 0 currently means none. Delete check when that
|
||||
// is fixed.
|
||||
if (video_receiver_info.ssrc() == 0)
|
||||
continue;
|
||||
std::unique_ptr<RTCInboundRTPStreamStats> inbound_video(
|
||||
new RTCInboundRTPStreamStats(
|
||||
RTCInboundRTPStreamStatsIDFromSSRC(
|
||||
false, video_receiver_info.ssrc()),
|
||||
timestamp_us));
|
||||
SetInboundRTPStreamStatsFromVideoReceiverInfo(
|
||||
video_receiver_info, inbound_video.get());
|
||||
inbound_video->transport_id = transport_id;
|
||||
if (video_receiver_info.codec_payload_type) {
|
||||
inbound_video->codec_id =
|
||||
RTCCodecStatsIDFromDirectionMediaAndPayload(
|
||||
true, false, *video_receiver_info.codec_payload_type);
|
||||
}
|
||||
// Outbound
|
||||
for (const cricket::VideoSenderInfo& video_sender_info :
|
||||
video_media_info.senders) {
|
||||
// TODO(nisse): SSRC == 0 currently means none. Delete check when that
|
||||
// is fixed.
|
||||
if (video_sender_info.ssrc() == 0)
|
||||
continue;
|
||||
std::unique_ptr<RTCOutboundRTPStreamStats> outbound_video(
|
||||
new RTCOutboundRTPStreamStats(
|
||||
RTCOutboundRTPStreamStatsIDFromSSRC(
|
||||
false, video_sender_info.ssrc()),
|
||||
timestamp_us));
|
||||
SetOutboundRTPStreamStatsFromVideoSenderInfo(
|
||||
video_sender_info, outbound_video.get());
|
||||
outbound_video->transport_id = transport_id;
|
||||
report->AddStats(std::move(outbound_video));
|
||||
report->AddStats(std::move(inbound_video));
|
||||
}
|
||||
// Outbound
|
||||
for (const cricket::VideoSenderInfo& video_sender_info :
|
||||
media_info.video->senders) {
|
||||
// TODO(nisse): SSRC == 0 currently means none. Delete check when that
|
||||
// is fixed.
|
||||
if (video_sender_info.ssrc() == 0)
|
||||
continue;
|
||||
std::unique_ptr<RTCOutboundRTPStreamStats> outbound_video(
|
||||
new RTCOutboundRTPStreamStats(
|
||||
RTCOutboundRTPStreamStatsIDFromSSRC(
|
||||
false, video_sender_info.ssrc()),
|
||||
timestamp_us));
|
||||
SetOutboundRTPStreamStatsFromVideoSenderInfo(
|
||||
video_sender_info, outbound_video.get());
|
||||
outbound_video->transport_id = transport_id;
|
||||
if (video_sender_info.codec_payload_type) {
|
||||
outbound_video->codec_id =
|
||||
RTCCodecStatsIDFromDirectionMediaAndPayload(
|
||||
false, false, *video_sender_info.codec_payload_type);
|
||||
}
|
||||
report->AddStats(std::move(outbound_video));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -760,7 +838,7 @@ void RTCStatsCollector::ProduceTransportStats_s(
|
||||
}
|
||||
|
||||
std::map<std::string, RTCStatsCollector::CertificateStatsPair>
|
||||
RTCStatsCollector::PrepareTransportCertificateStats_s(
|
||||
RTCStatsCollector::PrepareTransportCertificateStats(
|
||||
const SessionStats& session_stats) const {
|
||||
RTC_DCHECK(signaling_thread_->IsCurrent());
|
||||
std::map<std::string, CertificateStatsPair> transport_cert_stats;
|
||||
@ -785,6 +863,26 @@ RTCStatsCollector::PrepareTransportCertificateStats_s(
|
||||
return transport_cert_stats;
|
||||
}
|
||||
|
||||
RTCStatsCollector::MediaInfo RTCStatsCollector::PrepareMediaInfo(
|
||||
const SessionStats& session_stats) const {
|
||||
MediaInfo media_info;
|
||||
if (pc_->session()->voice_channel()) {
|
||||
cricket::VoiceMediaInfo voice_media_info;
|
||||
if (pc_->session()->voice_channel()->GetStats(&voice_media_info)) {
|
||||
media_info.voice = rtc::Optional<cricket::VoiceMediaInfo>(
|
||||
std::move(voice_media_info));
|
||||
}
|
||||
}
|
||||
if (pc_->session()->video_channel()) {
|
||||
cricket::VideoMediaInfo video_media_info;
|
||||
if (pc_->session()->video_channel()->GetStats(&video_media_info)) {
|
||||
media_info.video = rtc::Optional<cricket::VideoMediaInfo>(
|
||||
std::move(video_media_info));
|
||||
}
|
||||
}
|
||||
return media_info;
|
||||
}
|
||||
|
||||
void RTCStatsCollector::OnDataChannelCreated(DataChannel* channel) {
|
||||
channel->SignalOpened.connect(this, &RTCStatsCollector::OnDataChannelOpened);
|
||||
channel->SignalClosed.connect(this, &RTCStatsCollector::OnDataChannelClosed);
|
||||
|
||||
@ -21,11 +21,13 @@
|
||||
#include "webrtc/api/stats/rtcstats_objects.h"
|
||||
#include "webrtc/api/stats/rtcstatsreport.h"
|
||||
#include "webrtc/base/asyncinvoker.h"
|
||||
#include "webrtc/base/optional.h"
|
||||
#include "webrtc/base/refcount.h"
|
||||
#include "webrtc/base/scoped_ref_ptr.h"
|
||||
#include "webrtc/base/sigslot.h"
|
||||
#include "webrtc/base/sslidentity.h"
|
||||
#include "webrtc/base/timeutils.h"
|
||||
#include "webrtc/media/base/mediachannel.h"
|
||||
|
||||
namespace cricket {
|
||||
class Candidate;
|
||||
@ -86,6 +88,10 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface,
|
||||
std::unique_ptr<rtc::SSLCertificateStats> local;
|
||||
std::unique_ptr<rtc::SSLCertificateStats> remote;
|
||||
};
|
||||
struct MediaInfo {
|
||||
rtc::Optional<cricket::VoiceMediaInfo> voice;
|
||||
rtc::Optional<cricket::VideoMediaInfo> video;
|
||||
};
|
||||
|
||||
void AddPartialResults_s(rtc::scoped_refptr<RTCStatsReport> partial_report);
|
||||
void DeliverCachedReport();
|
||||
@ -95,6 +101,10 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface,
|
||||
int64_t timestamp_us,
|
||||
const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
|
||||
RTCStatsReport* report) const;
|
||||
// Produces |RTCCodecStats|.
|
||||
void ProduceCodecStats_s(
|
||||
int64_t timestamp_us, const MediaInfo& media_info,
|
||||
RTCStatsReport* report) const;
|
||||
// Produces |RTCDataChannelStats|.
|
||||
void ProduceDataChannelStats_s(
|
||||
int64_t timestamp_us, RTCStatsReport* report) const;
|
||||
@ -111,7 +121,7 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface,
|
||||
// Produces |RTCInboundRTPStreamStats| and |RTCOutboundRTPStreamStats|.
|
||||
void ProduceRTPStreamStats_s(
|
||||
int64_t timestamp_us, const SessionStats& session_stats,
|
||||
RTCStatsReport* report) const;
|
||||
const MediaInfo& media_info, RTCStatsReport* report) const;
|
||||
// Produces |RTCTransportStats|.
|
||||
void ProduceTransportStats_s(
|
||||
int64_t timestamp_us, const SessionStats& session_stats,
|
||||
@ -120,7 +130,8 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface,
|
||||
|
||||
// Helper function to stats-producing functions.
|
||||
std::map<std::string, CertificateStatsPair>
|
||||
PrepareTransportCertificateStats_s(const SessionStats& session_stats) const;
|
||||
PrepareTransportCertificateStats(const SessionStats& session_stats) const;
|
||||
MediaInfo PrepareMediaInfo(const SessionStats& session_stats) const;
|
||||
|
||||
// Slots for signals (sigslot) that are wired up to |pc_|.
|
||||
void OnDataChannelCreated(DataChannel* channel);
|
||||
|
||||
@ -15,9 +15,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/api/jsepsessiondescription.h"
|
||||
#include "webrtc/api/mediastream.h"
|
||||
#include "webrtc/api/mediastreamtrack.h"
|
||||
#include "webrtc/api/jsepsessiondescription.h"
|
||||
#include "webrtc/api/rtpparameters.h"
|
||||
#include "webrtc/api/stats/rtcstats_objects.h"
|
||||
#include "webrtc/api/stats/rtcstatsreport.h"
|
||||
#include "webrtc/api/test/mock_datachannel.h"
|
||||
@ -52,6 +53,10 @@ void PrintTo(const RTCCertificateStats& stats, ::std::ostream* os) {
|
||||
*os << stats.ToString();
|
||||
}
|
||||
|
||||
void PrintTo(const RTCCodecStats& stats, ::std::ostream* os) {
|
||||
*os << stats.ToString();
|
||||
}
|
||||
|
||||
void PrintTo(const RTCDataChannelStats& stats, ::std::ostream* os) {
|
||||
*os << stats.ToString();
|
||||
}
|
||||
@ -806,6 +811,117 @@ TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
|
||||
ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
|
||||
}
|
||||
|
||||
TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) {
|
||||
MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
|
||||
cricket::VoiceChannel voice_channel(
|
||||
test_->worker_thread(), test_->network_thread(), test_->media_engine(),
|
||||
voice_media_channel, nullptr, "VoiceContentName", false);
|
||||
|
||||
MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel();
|
||||
cricket::VideoChannel video_channel(
|
||||
test_->worker_thread(), test_->network_thread(), video_media_channel,
|
||||
nullptr, "VideoContentName", false);
|
||||
|
||||
// Audio
|
||||
cricket::VoiceMediaInfo voice_media_info;
|
||||
|
||||
RtpCodecParameters inbound_audio_codec;
|
||||
inbound_audio_codec.payload_type = 1;
|
||||
inbound_audio_codec.mime_type = "opus";
|
||||
inbound_audio_codec.clock_rate = 1337;
|
||||
voice_media_info.receive_codecs.insert(
|
||||
std::make_pair(inbound_audio_codec.payload_type, inbound_audio_codec));
|
||||
|
||||
RtpCodecParameters outbound_audio_codec;
|
||||
outbound_audio_codec.payload_type = 2;
|
||||
outbound_audio_codec.mime_type = "isac";
|
||||
outbound_audio_codec.clock_rate = 1338;
|
||||
voice_media_info.send_codecs.insert(
|
||||
std::make_pair(outbound_audio_codec.payload_type, outbound_audio_codec));
|
||||
|
||||
EXPECT_CALL(*voice_media_channel, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true)));
|
||||
|
||||
// Video
|
||||
cricket::VideoMediaInfo video_media_info;
|
||||
|
||||
RtpCodecParameters inbound_video_codec;
|
||||
inbound_video_codec.payload_type = 3;
|
||||
inbound_video_codec.mime_type = "H264";
|
||||
inbound_video_codec.clock_rate = 1339;
|
||||
video_media_info.receive_codecs.insert(
|
||||
std::make_pair(inbound_video_codec.payload_type, inbound_video_codec));
|
||||
|
||||
RtpCodecParameters outbound_video_codec;
|
||||
outbound_video_codec.payload_type = 4;
|
||||
outbound_video_codec.mime_type = "VP8";
|
||||
outbound_video_codec.clock_rate = 1340;
|
||||
video_media_info.send_codecs.insert(
|
||||
std::make_pair(outbound_video_codec.payload_type, outbound_video_codec));
|
||||
|
||||
EXPECT_CALL(*video_media_channel, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true)));
|
||||
|
||||
SessionStats session_stats;
|
||||
session_stats.proxy_to_transport["VoiceContentName"] = "TransportName";
|
||||
session_stats.proxy_to_transport["VideoContentName"] = "TransportName";
|
||||
session_stats.transport_stats["TransportName"].transport_name =
|
||||
"TransportName";
|
||||
|
||||
EXPECT_CALL(test_->session(), GetTransportStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats), Return(true)));
|
||||
EXPECT_CALL(test_->session(), voice_channel())
|
||||
.WillRepeatedly(Return(&voice_channel));
|
||||
EXPECT_CALL(test_->session(), video_channel())
|
||||
.WillRepeatedly(Return(&video_channel));
|
||||
|
||||
rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
|
||||
|
||||
RTCCodecStats expected_inbound_audio_codec(
|
||||
"RTCCodec_InboundAudio_1", report->timestamp_us());
|
||||
expected_inbound_audio_codec.payload_type = 1;
|
||||
expected_inbound_audio_codec.codec = "audio/opus";
|
||||
expected_inbound_audio_codec.clock_rate = 1337;
|
||||
|
||||
RTCCodecStats expected_outbound_audio_codec(
|
||||
"RTCCodec_OutboundAudio_2", report->timestamp_us());
|
||||
expected_outbound_audio_codec.payload_type = 2;
|
||||
expected_outbound_audio_codec.codec = "audio/isac";
|
||||
expected_outbound_audio_codec.clock_rate = 1338;
|
||||
|
||||
RTCCodecStats expected_inbound_video_codec(
|
||||
"RTCCodec_InboundVideo_3", report->timestamp_us());
|
||||
expected_inbound_video_codec.payload_type = 3;
|
||||
expected_inbound_video_codec.codec = "video/H264";
|
||||
expected_inbound_video_codec.clock_rate = 1339;
|
||||
|
||||
RTCCodecStats expected_outbound_video_codec(
|
||||
"RTCCodec_OutboundVideo_4", report->timestamp_us());
|
||||
expected_outbound_video_codec.payload_type = 4;
|
||||
expected_outbound_video_codec.codec = "video/VP8";
|
||||
expected_outbound_video_codec.clock_rate = 1340;
|
||||
|
||||
ASSERT(report->Get(expected_inbound_audio_codec.id()));
|
||||
EXPECT_EQ(expected_inbound_audio_codec,
|
||||
report->Get(expected_inbound_audio_codec.id())->cast_to<
|
||||
RTCCodecStats>());
|
||||
|
||||
ASSERT(report->Get(expected_outbound_audio_codec.id()));
|
||||
EXPECT_EQ(expected_outbound_audio_codec,
|
||||
report->Get(expected_outbound_audio_codec.id())->cast_to<
|
||||
RTCCodecStats>());
|
||||
|
||||
ASSERT(report->Get(expected_inbound_video_codec.id()));
|
||||
EXPECT_EQ(expected_inbound_video_codec,
|
||||
report->Get(expected_inbound_video_codec.id())->cast_to<
|
||||
RTCCodecStats>());
|
||||
|
||||
ASSERT(report->Get(expected_outbound_video_codec.id()));
|
||||
EXPECT_EQ(expected_outbound_video_codec,
|
||||
report->Get(expected_outbound_video_codec.id())->cast_to<
|
||||
RTCCodecStats>());
|
||||
}
|
||||
|
||||
TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
|
||||
std::unique_ptr<CertificateInfo> audio_local_certinfo =
|
||||
CreateFakeCertificateAndInfoFromDers(
|
||||
@ -1320,14 +1436,24 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
|
||||
voice_media_channel, nullptr, "VoiceContentName", false);
|
||||
|
||||
cricket::VoiceMediaInfo voice_media_info;
|
||||
|
||||
voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo());
|
||||
voice_media_info.receivers[0].local_stats.push_back(
|
||||
cricket::SsrcReceiverInfo());
|
||||
voice_media_info.receivers[0].local_stats[0].ssrc = 1;
|
||||
voice_media_info.receivers[0].packets_rcvd = 2;
|
||||
voice_media_info.receivers[0].bytes_rcvd = 3;
|
||||
voice_media_info.receivers[0].codec_payload_type = rtc::Optional<int>(42);
|
||||
voice_media_info.receivers[0].jitter_ms = 4500;
|
||||
voice_media_info.receivers[0].fraction_lost = 5.5f;
|
||||
|
||||
RtpCodecParameters codec_parameters;
|
||||
codec_parameters.payload_type = 42;
|
||||
codec_parameters.mime_type = "dummy";
|
||||
codec_parameters.clock_rate = 0;
|
||||
voice_media_info.receive_codecs.insert(
|
||||
std::make_pair(codec_parameters.payload_type, codec_parameters));
|
||||
|
||||
EXPECT_CALL(*voice_media_channel, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true)));
|
||||
|
||||
@ -1356,6 +1482,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
|
||||
expected_audio.media_type = "audio";
|
||||
expected_audio.transport_id = "RTCTransport_TransportName_" +
|
||||
rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
||||
expected_audio.codec_id = "RTCCodec_InboundAudio_42";
|
||||
expected_audio.packets_received = 2;
|
||||
expected_audio.bytes_received = 3;
|
||||
expected_audio.jitter = 4.5;
|
||||
@ -1367,6 +1494,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
|
||||
EXPECT_EQ(audio, expected_audio);
|
||||
|
||||
EXPECT_TRUE(report->Get(*expected_audio.transport_id));
|
||||
EXPECT_TRUE(report->Get(*expected_audio.codec_id));
|
||||
}
|
||||
|
||||
TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
|
||||
@ -1376,6 +1504,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
|
||||
nullptr, "VideoContentName", false);
|
||||
|
||||
cricket::VideoMediaInfo video_media_info;
|
||||
|
||||
video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
|
||||
video_media_info.receivers[0].local_stats.push_back(
|
||||
cricket::SsrcReceiverInfo());
|
||||
@ -1383,9 +1512,18 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
|
||||
video_media_info.receivers[0].packets_rcvd = 2;
|
||||
video_media_info.receivers[0].bytes_rcvd = 3;
|
||||
video_media_info.receivers[0].fraction_lost = 4.5f;
|
||||
video_media_info.receivers[0].codec_payload_type = rtc::Optional<int>(42);
|
||||
video_media_info.receivers[0].firs_sent = 5;
|
||||
video_media_info.receivers[0].plis_sent = 6;
|
||||
video_media_info.receivers[0].nacks_sent = 7;
|
||||
|
||||
RtpCodecParameters codec_parameters;
|
||||
codec_parameters.payload_type = 42;
|
||||
codec_parameters.mime_type = "dummy";
|
||||
codec_parameters.clock_rate = 0;
|
||||
video_media_info.receive_codecs.insert(
|
||||
std::make_pair(codec_parameters.payload_type, codec_parameters));
|
||||
|
||||
EXPECT_CALL(*video_media_channel, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true)));
|
||||
|
||||
@ -1414,6 +1552,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
|
||||
expected_video.media_type = "video";
|
||||
expected_video.transport_id = "RTCTransport_TransportName_" +
|
||||
rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
||||
expected_video.codec_id = "RTCCodec_InboundVideo_42";
|
||||
expected_video.fir_count = 5;
|
||||
expected_video.pli_count = 6;
|
||||
expected_video.nack_count = 7;
|
||||
@ -1427,6 +1566,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
|
||||
EXPECT_EQ(video, expected_video);
|
||||
|
||||
EXPECT_TRUE(report->Get(*expected_video.transport_id));
|
||||
EXPECT_TRUE(report->Get(*video.codec_id));
|
||||
}
|
||||
|
||||
TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
|
||||
@ -1436,12 +1576,22 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
|
||||
voice_media_channel, nullptr, "VoiceContentName", false);
|
||||
|
||||
cricket::VoiceMediaInfo voice_media_info;
|
||||
|
||||
voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
|
||||
voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
|
||||
voice_media_info.senders[0].local_stats[0].ssrc = 1;
|
||||
voice_media_info.senders[0].packets_sent = 2;
|
||||
voice_media_info.senders[0].bytes_sent = 3;
|
||||
voice_media_info.senders[0].rtt_ms = 4500;
|
||||
voice_media_info.senders[0].codec_payload_type = rtc::Optional<int>(42);
|
||||
|
||||
RtpCodecParameters codec_parameters;
|
||||
codec_parameters.payload_type = 42;
|
||||
codec_parameters.mime_type = "dummy";
|
||||
codec_parameters.clock_rate = 0;
|
||||
voice_media_info.send_codecs.insert(
|
||||
std::make_pair(codec_parameters.payload_type, codec_parameters));
|
||||
|
||||
EXPECT_CALL(*voice_media_channel, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true)));
|
||||
|
||||
@ -1470,6 +1620,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
|
||||
expected_audio.media_type = "audio";
|
||||
expected_audio.transport_id = "RTCTransport_TransportName_" +
|
||||
rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
||||
expected_audio.codec_id = "RTCCodec_OutboundAudio_42";
|
||||
expected_audio.packets_sent = 2;
|
||||
expected_audio.bytes_sent = 3;
|
||||
expected_audio.round_trip_time = 4.5;
|
||||
@ -1480,6 +1631,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
|
||||
EXPECT_EQ(audio, expected_audio);
|
||||
|
||||
EXPECT_TRUE(report->Get(*expected_audio.transport_id));
|
||||
EXPECT_TRUE(report->Get(*expected_audio.codec_id));
|
||||
}
|
||||
|
||||
TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
|
||||
@ -1489,6 +1641,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
|
||||
nullptr, "VideoContentName", false);
|
||||
|
||||
cricket::VideoMediaInfo video_media_info;
|
||||
|
||||
video_media_info.senders.push_back(cricket::VideoSenderInfo());
|
||||
video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
|
||||
video_media_info.senders[0].local_stats[0].ssrc = 1;
|
||||
@ -1498,6 +1651,15 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
|
||||
video_media_info.senders[0].packets_sent = 5;
|
||||
video_media_info.senders[0].bytes_sent = 6;
|
||||
video_media_info.senders[0].rtt_ms = 7500;
|
||||
video_media_info.senders[0].codec_payload_type = rtc::Optional<int>(42);
|
||||
|
||||
RtpCodecParameters codec_parameters;
|
||||
codec_parameters.payload_type = 42;
|
||||
codec_parameters.mime_type = "dummy";
|
||||
codec_parameters.clock_rate = 0;
|
||||
video_media_info.send_codecs.insert(
|
||||
std::make_pair(codec_parameters.payload_type, codec_parameters));
|
||||
|
||||
EXPECT_CALL(*video_media_channel, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true)));
|
||||
|
||||
@ -1526,6 +1688,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
|
||||
expected_video.media_type = "video";
|
||||
expected_video.transport_id = "RTCTransport_TransportName_" +
|
||||
rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
||||
expected_video.codec_id = "RTCCodec_OutboundVideo_42";
|
||||
expected_video.fir_count = 2;
|
||||
expected_video.pli_count = 3;
|
||||
expected_video.nack_count = 4;
|
||||
@ -1539,6 +1702,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
|
||||
EXPECT_EQ(video, expected_video);
|
||||
|
||||
EXPECT_TRUE(report->Get(*expected_video.transport_id));
|
||||
EXPECT_TRUE(report->Get(*expected_video.codec_id));
|
||||
}
|
||||
|
||||
TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) {
|
||||
|
||||
@ -59,6 +59,30 @@ class RTCCertificateStats final : public RTCStats {
|
||||
RTCStatsMember<std::string> issuer_certificate_id;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#codec-dict*
|
||||
// Tracking bug crbug.com/659117
|
||||
// TODO(hbos): The present codec ID assignment is not sufficient to support
|
||||
// Unified Plan or unbundled connections in all cases. crbug.com/659117
|
||||
class RTCCodecStats final : public RTCStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
|
||||
RTCCodecStats(const std::string& id, int64_t timestamp_us);
|
||||
RTCCodecStats(std::string&& id, int64_t timestamp_us);
|
||||
RTCCodecStats(const RTCCodecStats& other);
|
||||
~RTCCodecStats() override;
|
||||
|
||||
RTCStatsMember<uint32_t> payload_type;
|
||||
RTCStatsMember<std::string> codec;
|
||||
RTCStatsMember<uint32_t> clock_rate;
|
||||
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659117
|
||||
RTCStatsMember<uint32_t> channels;
|
||||
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659117
|
||||
RTCStatsMember<std::string> parameters;
|
||||
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659117
|
||||
RTCStatsMember<std::string> implementation;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#dcstats-dict*
|
||||
class RTCDataChannelStats final : public RTCStats {
|
||||
public:
|
||||
@ -81,7 +105,7 @@ class RTCDataChannelStats final : public RTCStats {
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#candidatepair-dict*
|
||||
// TODO(hbos): Finish implementation. Tracking bug crbug.com/633550
|
||||
// TODO(hbos): Tracking bug crbug.com/633550
|
||||
class RTCIceCandidatePairStats final : public RTCStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
@ -184,7 +208,7 @@ class RTCRemoteIceCandidateStats final : public RTCIceCandidateStats {
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#msstats-dict*
|
||||
// TODO(hbos): Finish implementation. Tracking bug crbug.com/660827
|
||||
// TODO(hbos): Tracking bug crbug.com/660827
|
||||
class RTCMediaStreamStats final : public RTCStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
@ -199,7 +223,7 @@ class RTCMediaStreamStats final : public RTCStats {
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#mststats-dict*
|
||||
// TODO(hbos): Finish implementation. Tracking bug crbug.com/659137
|
||||
// TODO(hbos): Tracking bug crbug.com/659137
|
||||
class RTCMediaStreamTrackStats final : public RTCStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
@ -243,7 +267,7 @@ class RTCMediaStreamTrackStats final : public RTCStats {
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#pcstats-dict*
|
||||
// TODO(hbos): Finish implementation. Tracking bug crbug.com/636818
|
||||
// TODO(hbos): Tracking bug crbug.com/636818
|
||||
class RTCPeerConnectionStats final : public RTCStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
@ -262,7 +286,7 @@ class RTCPeerConnectionStats final : public RTCStats {
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#streamstats-dict*
|
||||
// TODO(hbos): Finish implementation. Tracking bug crbug.com/657854
|
||||
// TODO(hbos): Tracking bug crbug.com/657854
|
||||
class RTCRTPStreamStats : public RTCStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
@ -281,7 +305,6 @@ class RTCRTPStreamStats : public RTCStats {
|
||||
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/657854, 659137
|
||||
RTCStatsMember<std::string> media_track_id;
|
||||
RTCStatsMember<std::string> transport_id;
|
||||
// TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/657854, 659117
|
||||
RTCStatsMember<std::string> codec_id;
|
||||
// FIR and PLI counts are only defined for |media_type == "video"|.
|
||||
RTCStatsMember<uint32_t> fir_count;
|
||||
@ -299,8 +322,8 @@ class RTCRTPStreamStats : public RTCStats {
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict*
|
||||
// TODO(hbos): Finish implementation and support the remote case
|
||||
// |is_remote = true|. Tracking bug crbug.com/657855
|
||||
// Tracking bug crbug.com/657855
|
||||
// TODO(hbos): Support the remote case |is_remote = true|. crbug.com/657855
|
||||
class RTCInboundRTPStreamStats final : public RTCRTPStreamStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
@ -341,8 +364,8 @@ class RTCInboundRTPStreamStats final : public RTCRTPStreamStats {
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#outboundrtpstats-dict*
|
||||
// TODO(hbos): Finish implementation and support the remote case
|
||||
// |is_remote = true|. Tracking bug crbug.com/657856
|
||||
// Tracking bug crbug.com/657856
|
||||
// TODO(hbos): Support the remote case |is_remote = true|. crbug.com/657856
|
||||
class RTCOutboundRTPStreamStats final : public RTCRTPStreamStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
|
||||
@ -62,6 +62,44 @@ RTCCertificateStats::RTCCertificateStats(
|
||||
RTCCertificateStats::~RTCCertificateStats() {
|
||||
}
|
||||
|
||||
WEBRTC_RTCSTATS_IMPL(RTCCodecStats, RTCStats, "codec",
|
||||
&payload_type,
|
||||
&codec,
|
||||
&clock_rate,
|
||||
&channels,
|
||||
¶meters,
|
||||
&implementation);
|
||||
|
||||
RTCCodecStats::RTCCodecStats(
|
||||
const std::string& id, int64_t timestamp_us)
|
||||
: RTCCodecStats(std::string(id), timestamp_us) {
|
||||
}
|
||||
|
||||
RTCCodecStats::RTCCodecStats(
|
||||
std::string&& id, int64_t timestamp_us)
|
||||
: RTCStats(std::move(id), timestamp_us),
|
||||
payload_type("payloadType"),
|
||||
codec("codec"),
|
||||
clock_rate("clockRate"),
|
||||
channels("channels"),
|
||||
parameters("parameters"),
|
||||
implementation("implementation") {
|
||||
}
|
||||
|
||||
RTCCodecStats::RTCCodecStats(
|
||||
const RTCCodecStats& other)
|
||||
: RTCStats(other.id(), other.timestamp_us()),
|
||||
payload_type(other.payload_type),
|
||||
codec(other.codec),
|
||||
clock_rate(other.clock_rate),
|
||||
channels(other.channels),
|
||||
parameters(other.parameters),
|
||||
implementation(other.implementation) {
|
||||
}
|
||||
|
||||
RTCCodecStats::~RTCCodecStats() {
|
||||
}
|
||||
|
||||
WEBRTC_RTCSTATS_IMPL(RTCDataChannelStats, RTCStats, "data-channel",
|
||||
&label,
|
||||
&protocol,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user