diff --git a/talk/app/webrtc/statscollector.cc b/talk/app/webrtc/statscollector.cc index 149ad5c31..75ca36608 100644 --- a/talk/app/webrtc/statscollector.cc +++ b/talk/app/webrtc/statscollector.cc @@ -312,6 +312,7 @@ void ExtractStats(const cricket::VoiceReceiverInfo& info, StatsReport* report) { info.decoding_plc_cng); report->AddValue(StatsReport::kStatsValueNameCaptureStartNtpTimeMs, info.capture_start_ntp_time_ms); + report->AddValue(StatsReport::kStatsValueNameCodecName, info.codec_name); } void ExtractStats(const cricket::VoiceSenderInfo& info, StatsReport* report) { diff --git a/talk/app/webrtc/statscollector_unittest.cc b/talk/app/webrtc/statscollector_unittest.cc index 5cdc81e19..2cd716e02 100644 --- a/talk/app/webrtc/statscollector_unittest.cc +++ b/talk/app/webrtc/statscollector_unittest.cc @@ -318,6 +318,8 @@ void VerifyVoiceReceiverInfoReport( EXPECT_TRUE(GetValue( report, StatsReport::kStatsValueNameDecodingPLCCNG, &value_in_report)); EXPECT_EQ(talk_base::ToString(info.decoding_plc_cng), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameCodecName, &value_in_report)); } @@ -1254,6 +1256,7 @@ TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) { cricket::VoiceReceiverInfo voice_receiver_info; InitVoiceReceiverInfo(&voice_receiver_info); + voice_receiver_info.codec_name = "fake_codec"; // Constructs an ssrc stats update. cricket::VoiceMediaInfo stats_read; diff --git a/talk/media/base/mediachannel.h b/talk/media/base/mediachannel.h index 0bb0f04c1..35948b62f 100644 --- a/talk/media/base/mediachannel.h +++ b/talk/media/base/mediachannel.h @@ -787,6 +787,7 @@ struct MediaReceiverInfo { int packets_rcvd; int packets_lost; float fraction_lost; + std::string codec_name; std::vector local_stats; std::vector remote_stats; }; diff --git a/talk/media/webrtc/fakewebrtcvoiceengine.h b/talk/media/webrtc/fakewebrtcvoiceengine.h index 1df2195b4..7285908a2 100644 --- a/talk/media/webrtc/fakewebrtcvoiceengine.h +++ b/talk/media/webrtc/fakewebrtcvoiceengine.h @@ -36,6 +36,7 @@ #include "talk/base/gunit.h" #include "talk/base/stringutils.h" #include "talk/media/base/codec.h" +#include "talk/media/base/rtputils.h" #include "talk/media/base/voiceprocessor.h" #include "talk/media/webrtc/fakewebrtccommon.h" #include "talk/media/webrtc/webrtcvoe.h" @@ -437,7 +438,26 @@ class FakeWebRtcVoiceEngine WEBRTC_STUB(RemoveSecondarySendCodec, (int channel)); WEBRTC_STUB(GetSecondarySendCodec, (int channel, webrtc::CodecInst& codec)); - WEBRTC_STUB(GetRecCodec, (int channel, webrtc::CodecInst& codec)); + WEBRTC_FUNC(GetRecCodec, (int channel, webrtc::CodecInst& codec)) { + WEBRTC_CHECK_CHANNEL(channel); + const Channel* c = channels_[channel]; + for (std::list::const_iterator it_packet = c->packets.begin(); + it_packet != c->packets.end(); ++it_packet) { + int pltype; + if (!GetRtpPayloadType(it_packet->data(), it_packet->length(), &pltype)) { + continue; + } + for (std::vector::const_iterator it_codec = + c->recv_codecs.begin(); it_codec != c->recv_codecs.end(); + ++it_codec) { + if (it_codec->pltype == pltype) { + codec = *it_codec; + return 0; + } + } + } + return -1; + } WEBRTC_STUB(SetAMREncFormat, (int channel, webrtc::AmrMode mode)); WEBRTC_STUB(SetAMRDecFormat, (int channel, webrtc::AmrMode mode)); WEBRTC_STUB(SetAMRWbEncFormat, (int channel, webrtc::AmrMode mode)); diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc index 1bd2ffe74..d7b3c4cf3 100644 --- a/talk/media/webrtc/webrtcvoiceengine.cc +++ b/talk/media/webrtc/webrtcvoiceengine.cc @@ -3270,6 +3270,9 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) { #ifdef USE_WEBRTC_DEV_BRANCH rinfo.capture_start_ntp_time_ms = cs.capture_start_ntp_time_ms_; #endif + if (codec.pltype != -1) { + rinfo.codec_name = codec.plname; + } // Convert samples to milliseconds. if (codec.plfreq / 1000 > 0) { rinfo.jitter_ms = cs.jitterSamples / (codec.plfreq / 1000); diff --git a/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/talk/media/webrtc/webrtcvoiceengine_unittest.cc index cbc000719..5dab4ff78 100644 --- a/talk/media/webrtc/webrtcvoiceengine_unittest.cc +++ b/talk/media/webrtc/webrtcvoiceengine_unittest.cc @@ -1726,11 +1726,15 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) { EXPECT_TRUE(channel_->AddSendStream( cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); } - + // Create a receive stream to check that none of the send streams end up in + // the receive stream stats. + EXPECT_TRUE(channel_->AddRecvStream( + cricket::StreamParams::CreateLegacy(kSsrc2))); // We need send codec to be set to get all stats. std::vector codecs; codecs.push_back(kPcmuCodec); EXPECT_TRUE(channel_->SetSendCodecs(codecs)); + EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); cricket::VoiceMediaInfo info; EXPECT_EQ(true, channel_->GetStats(&info)); @@ -1747,9 +1751,19 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) { EXPECT_EQ(cricket::kIntStatValue, info.senders[i].ext_seqnum); EXPECT_EQ(cricket::kIntStatValue, info.senders[i].rtt_ms); EXPECT_EQ(cricket::kIntStatValue, info.senders[i].jitter_ms); + EXPECT_EQ(kPcmuCodec.name, info.senders[i].codec_name); } + EXPECT_EQ(0u, info.receivers.size()); + DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame)); + EXPECT_EQ(true, channel_->GetStats(&info)); + EXPECT_EQ(1u, info.receivers.size()); + EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].bytes_rcvd); + EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].packets_rcvd); + EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].packets_lost); + EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].ext_seqnum); + EXPECT_EQ(kPcmuCodec.name, info.receivers[0].codec_name); } // Test that we can add and remove receive streams, and do proper send/playout. @@ -2036,9 +2050,14 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrc) { TEST_F(WebRtcVoiceEngineTestFake, GetStats) { // Setup. We need send codec to be set to get all stats. EXPECT_TRUE(SetupEngine()); + // SetupEngine adds a send stream with kSsrc1, so the receive stream has to + // use a different SSRC. + EXPECT_TRUE(channel_->AddRecvStream( + cricket::StreamParams::CreateLegacy(kSsrc2))); std::vector codecs; codecs.push_back(kPcmuCodec); EXPECT_TRUE(channel_->SetSendCodecs(codecs)); + EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); cricket::VoiceMediaInfo info; EXPECT_EQ(true, channel_->GetStats(&info)); @@ -2052,6 +2071,7 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStats) { EXPECT_EQ(cricket::kIntStatValue, info.senders[0].ext_seqnum); EXPECT_EQ(cricket::kIntStatValue, info.senders[0].rtt_ms); EXPECT_EQ(cricket::kIntStatValue, info.senders[0].jitter_ms); + EXPECT_EQ(kPcmuCodec.name, info.senders[0].codec_name); // TODO(sriniv): Add testing for more fields. These are not populated // in FakeWebrtcVoiceEngine yet. // EXPECT_EQ(cricket::kIntStatValue, info.senders[0].audio_level); @@ -2061,8 +2081,17 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStats) { // EXPECT_EQ(cricket::kIntStatValue, // info.senders[0].echo_return_loss_enhancement); + EXPECT_EQ(0u, info.receivers.size()); + DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame)); + EXPECT_EQ(true, channel_->GetStats(&info)); EXPECT_EQ(1u, info.receivers.size()); - // TODO(sriniv): Add testing for receiver fields. + + EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].bytes_rcvd); + EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].packets_rcvd); + EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].packets_lost); + EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].ext_seqnum); + EXPECT_EQ(kPcmuCodec.name, info.receivers[0].codec_name); + // TODO(sriniv): Add testing for more receiver fields. } // Test that we can set the outgoing SSRC properly with multiple streams.