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:
hbos 2016-11-23 02:32:06 -08:00 committed by Commit bot
parent 71caaca254
commit 0adb8285b1
5 changed files with 427 additions and 93 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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();

View File

@ -62,6 +62,44 @@ RTCCertificateStats::RTCCertificateStats(
RTCCertificateStats::~RTCCertificateStats() {
}
WEBRTC_RTCSTATS_IMPL(RTCCodecStats, RTCStats, "codec",
&payload_type,
&codec,
&clock_rate,
&channels,
&parameters,
&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,