diff --git a/webrtc/modules/rtp_rtcp/interface/fec_receiver.h b/webrtc/modules/rtp_rtcp/interface/fec_receiver.h index da54bf6927..3608165dab 100644 --- a/webrtc/modules/rtp_rtcp/interface/fec_receiver.h +++ b/webrtc/modules/rtp_rtcp/interface/fec_receiver.h @@ -16,6 +16,17 @@ namespace webrtc { +struct FecPacketCounter { + FecPacketCounter() + : num_packets(0), + num_fec_packets(0), + num_recovered_packets(0) {} + + size_t num_packets; // Number of received packets. + size_t num_fec_packets; // Number of received FEC packets. + size_t num_recovered_packets; // Number of recovered media packets using FEC. +}; + class FecReceiver { public: static FecReceiver* Create(RtpData* callback); @@ -28,6 +39,8 @@ class FecReceiver { uint8_t ulpfec_payload_type) = 0; virtual int32_t ProcessReceivedFec() = 0; + + virtual FecPacketCounter GetPacketCounter() const = 0; }; } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_FEC_RECEIVER_H_ diff --git a/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.cc b/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.cc index 0fcb6f7c4c..c64a3c42bb 100644 --- a/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.cc @@ -15,8 +15,8 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/logging.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" // RFC 5109 namespace webrtc { @@ -41,6 +41,11 @@ FecReceiverImpl::~FecReceiverImpl() { } } +FecPacketCounter FecReceiverImpl::GetPacketCounter() const { + CriticalSectionScoped cs(crit_sect_.get()); + return packet_counter_; +} + // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -125,6 +130,7 @@ int32_t FecReceiverImpl::AddReceivedRedPacket( return -1; } } + ++packet_counter_.num_packets; ForwardErrorCorrection::ReceivedPacket* second_received_packet = NULL; if (blockLength > 0) { @@ -153,6 +159,7 @@ int32_t FecReceiverImpl::AddReceivedRedPacket( second_received_packet->is_fec = true; second_received_packet->seq_num = header.sequenceNumber; + ++packet_counter_.num_fec_packets; // copy the FEC payload data memcpy(second_received_packet->pkt->data, @@ -164,6 +171,7 @@ int32_t FecReceiverImpl::AddReceivedRedPacket( payload_data_length - REDHeaderLength - blockLength; } else if (received_packet->is_fec) { + ++packet_counter_.num_fec_packets; // everything behind the RED header memcpy( received_packet->pkt->data, @@ -233,6 +241,7 @@ int32_t FecReceiverImpl::ProcessReceivedFec() { if ((*it)->returned) // Already sent to the VCM and the jitter buffer. continue; ForwardErrorCorrection::Packet* packet = (*it)->pkt; + ++packet_counter_.num_recovered_packets; crit_sect_->Leave(); if (!recovered_packet_callback_->OnRecoveredPacket(packet->data, packet->length)) { diff --git a/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h b/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h index 8dd02b35f8..d8b9f42a99 100644 --- a/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h +++ b/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h @@ -35,6 +35,8 @@ class FecReceiverImpl : public FecReceiver { virtual int32_t ProcessReceivedFec() OVERRIDE; + virtual FecPacketCounter GetPacketCounter() const OVERRIDE; + private: scoped_ptr crit_sect_; RtpData* recovered_packet_callback_; @@ -44,6 +46,7 @@ class FecReceiverImpl : public FecReceiver { // arrives. We should remove the list. ForwardErrorCorrection::ReceivedPacketList received_packet_list_; ForwardErrorCorrection::RecoveredPacketList recovered_packet_list_; + FecPacketCounter packet_counter_; }; } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc index 2a3b15554d..6c53a3732b 100644 --- a/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc @@ -18,6 +18,7 @@ #include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h" #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" using ::testing::_; using ::testing::Args; @@ -29,15 +30,9 @@ namespace webrtc { class ReceiverFecTest : public ::testing::Test { protected: virtual void SetUp() { - fec_ = new ForwardErrorCorrection(); - receiver_fec_ = FecReceiver::Create(&rtp_data_callback_); - generator_ = new FrameGenerator(); - } - - virtual void TearDown() { - delete fec_; - delete receiver_fec_; - delete generator_; + fec_.reset(new ForwardErrorCorrection()); + receiver_fec_.reset(FecReceiver::Create(&rtp_data_callback_)); + generator_.reset(new FrameGenerator()); } void GenerateFEC(std::list* media_packets, @@ -86,10 +81,10 @@ class ReceiverFecTest : public ::testing::Test { delete red_packet; } - ForwardErrorCorrection* fec_; MockRtpData rtp_data_callback_; - FecReceiver* receiver_fec_; - FrameGenerator* generator_; + scoped_ptr fec_; + scoped_ptr receiver_fec_; + scoped_ptr generator_; }; void DeletePackets(std::list* packets) { @@ -120,6 +115,11 @@ TEST_F(ReceiverFecTest, TwoMediaOneFec) { VerifyReconstructedMediaPacket(*it, 1); EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); + FecPacketCounter counter = receiver_fec_->GetPacketCounter(); + EXPECT_EQ(2U, counter.num_packets); + EXPECT_EQ(1U, counter.num_fec_packets); + EXPECT_EQ(1U, counter.num_recovered_packets); + DeletePackets(&media_packets); } diff --git a/webrtc/video_engine/vie_receiver.cc b/webrtc/video_engine/vie_receiver.cc index 6adcffdb66..7e1034f39c 100644 --- a/webrtc/video_engine/vie_receiver.cc +++ b/webrtc/video_engine/vie_receiver.cc @@ -24,6 +24,7 @@ #include "webrtc/modules/video_coding/main/interface/video_coding.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/logging.h" +#include "webrtc/system_wrappers/interface/metrics.h" #include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/system_wrappers/interface/timestamp_extrapolator.h" #include "webrtc/system_wrappers/interface/trace.h" @@ -62,6 +63,7 @@ ViEReceiver::ViEReceiver(const int32_t channel_id, } ViEReceiver::~ViEReceiver() { + UpdateHistograms(); if (rtp_dump_) { rtp_dump_->Stop(); RtpDump::DestroyRtpDump(rtp_dump_); @@ -69,6 +71,19 @@ ViEReceiver::~ViEReceiver() { } } +void ViEReceiver::UpdateHistograms() { + FecPacketCounter counter = fec_receiver_->GetPacketCounter(); + if (counter.num_packets > 0) { + RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedFecPacketsInPercent", + counter.num_fec_packets * 100 / counter.num_packets); + } + if (counter.num_fec_packets > 0) { + RTC_HISTOGRAM_PERCENTAGE( + "WebRTC.Video.RecoveredMediaPacketsInPercentOfFec", + counter.num_recovered_packets * 100 / counter.num_fec_packets); + } +} + bool ViEReceiver::SetReceiveCodec(const VideoCodec& video_codec) { int8_t old_pltype = -1; if (rtp_payload_registry_->ReceivePayloadType(video_codec.plName, diff --git a/webrtc/video_engine/vie_receiver.h b/webrtc/video_engine/vie_receiver.h index 39a85e4c2b..6354d68726 100644 --- a/webrtc/video_engine/vie_receiver.h +++ b/webrtc/video_engine/vie_receiver.h @@ -104,6 +104,7 @@ class ViEReceiver : public RtpData { int InsertRTCPPacket(const uint8_t* rtcp_packet, size_t rtcp_packet_length); bool IsPacketInOrder(const RTPHeader& header) const; bool IsPacketRetransmitted(const RTPHeader& header, bool in_order) const; + void UpdateHistograms(); scoped_ptr receive_cs_; Clock* clock_;