Add RtcpPacketTypeCounter stats to new API.

R=mflodman@webrtc.org, stefan@webrtc.org
BUG=1667,1788

Review URL: https://webrtc-codereview.appspot.com/37489004

Cr-Commit-Position: refs/heads/master@{#8429}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8429 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
pbos@webrtc.org 2015-02-19 12:47:00 +00:00
parent 50604128db
commit 1d0fa5d352
30 changed files with 333 additions and 128 deletions

View File

@ -1215,6 +1215,8 @@ class FakeWebRtcVideoEngine
(int, webrtc::FrameCountObserver*)); (int, webrtc::FrameCountObserver*));
WEBRTC_STUB(DeregisterSendFrameCountObserver, WEBRTC_STUB(DeregisterSendFrameCountObserver,
(int, webrtc::FrameCountObserver*)); (int, webrtc::FrameCountObserver*));
WEBRTC_STUB(RegisterRtcpPacketTypeCounterObserver,
(int, webrtc::RtcpPacketTypeCounterObserver*));
WEBRTC_STUB(StartRTPDump, (const int, const char*, webrtc::RTPDirections)); WEBRTC_STUB(StartRTPDump, (const int, const char*, webrtc::RTPDirections));
WEBRTC_STUB(StopRTPDump, (const int, webrtc::RTPDirections)); WEBRTC_STUB(StopRTPDump, (const int, webrtc::RTPDirections));

View File

@ -1762,6 +1762,9 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
info.send_frame_width = stream_stats.sent_width; info.send_frame_width = stream_stats.sent_width;
if (stream_stats.sent_height > info.send_frame_height) if (stream_stats.sent_height > info.send_frame_height)
info.send_frame_height = stream_stats.sent_height; info.send_frame_height = stream_stats.sent_height;
info.firs_rcvd += stream_stats.rtcp_packet_type_counts.fir_packets;
info.nacks_rcvd += stream_stats.rtcp_packet_type_counts.nack_packets;
info.plis_rcvd += stream_stats.rtcp_packet_type_counts.pli_packets;
} }
if (!stats.substreams.empty()) { if (!stats.substreams.empty()) {
@ -2027,10 +2030,16 @@ WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() {
info.framerate_decoded = stats.decode_frame_rate; info.framerate_decoded = stats.decode_frame_rate;
info.framerate_output = stats.render_frame_rate; info.framerate_output = stats.render_frame_rate;
{
rtc::CritScope frame_cs(&renderer_lock_); rtc::CritScope frame_cs(&renderer_lock_);
info.frame_width = last_width_; info.frame_width = last_width_;
info.frame_height = last_height_; info.frame_height = last_height_;
info.capture_start_ntp_time_ms = estimated_remote_start_ntp_time_ms_; info.capture_start_ntp_time_ms = estimated_remote_start_ntp_time_ms_;
}
info.firs_sent = stats.rtcp_packet_type_counts.fir_packets;
info.plis_sent = stats.rtcp_packet_type_counts.pli_packets;
info.nacks_sent = stats.rtcp_packet_type_counts.nack_packets;
// TODO(pbos): Support or remove the following stats. // TODO(pbos): Support or remove the following stats.
info.packets_concealed = -1; info.packets_concealed = -1;

View File

@ -196,7 +196,7 @@ void FakeVideoReceiveStream::InjectFrame(const webrtc::I420VideoFrame& frame,
} }
webrtc::VideoReceiveStream::Stats FakeVideoReceiveStream::GetStats() const { webrtc::VideoReceiveStream::Stats FakeVideoReceiveStream::GetStats() const {
return webrtc::VideoReceiveStream::Stats(); return stats_;
} }
void FakeVideoReceiveStream::Start() { void FakeVideoReceiveStream::Start() {
@ -207,6 +207,11 @@ void FakeVideoReceiveStream::Stop() {
receiving_ = false; receiving_ = false;
} }
void FakeVideoReceiveStream::SetStats(
const webrtc::VideoReceiveStream::Stats& stats) {
stats_ = stats;
}
FakeCall::FakeCall(const webrtc::Call::Config& config) FakeCall::FakeCall(const webrtc::Call::Config& config)
: config_(config), : config_(config),
network_state_(kNetworkUp), network_state_(kNetworkUp),
@ -2053,6 +2058,46 @@ TEST_F(WebRtcVideoChannel2Test, GetStatsReportsUpperResolution) {
EXPECT_EQ(90, info.senders[0].send_frame_height); EXPECT_EQ(90, info.senders[0].send_frame_height);
} }
TEST_F(WebRtcVideoChannel2Test,
GetStatsTranslatesSendRtcpPacketTypesCorrectly) {
FakeVideoSendStream* stream = AddSendStream();
webrtc::VideoSendStream::Stats stats;
stats.substreams[17].rtcp_packet_type_counts.fir_packets = 2;
stats.substreams[17].rtcp_packet_type_counts.nack_packets = 3;
stats.substreams[17].rtcp_packet_type_counts.pli_packets = 4;
stats.substreams[42].rtcp_packet_type_counts.fir_packets = 5;
stats.substreams[42].rtcp_packet_type_counts.nack_packets = 7;
stats.substreams[42].rtcp_packet_type_counts.pli_packets = 9;
stream->SetStats(stats);
cricket::VideoMediaInfo info;
ASSERT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info));
EXPECT_EQ(7, info.senders[0].firs_rcvd);
EXPECT_EQ(10, info.senders[0].nacks_rcvd);
EXPECT_EQ(13, info.senders[0].plis_rcvd);
}
TEST_F(WebRtcVideoChannel2Test,
GetStatsTranslatesReceiveRtcpPacketTypesCorrectly) {
FakeVideoReceiveStream* stream = AddRecvStream();
webrtc::VideoReceiveStream::Stats stats;
stats.rtcp_packet_type_counts.fir_packets = 2;
stats.rtcp_packet_type_counts.nack_packets = 3;
stats.rtcp_packet_type_counts.pli_packets = 4;
stream->SetStats(stats);
cricket::VideoMediaInfo info;
ASSERT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info));
EXPECT_EQ(stats.rtcp_packet_type_counts.fir_packets,
info.receivers[0].firs_sent);
EXPECT_EQ(stats.rtcp_packet_type_counts.nack_packets,
info.receivers[0].nacks_sent);
EXPECT_EQ(stats.rtcp_packet_type_counts.pli_packets,
info.receivers[0].plis_sent);
}
TEST_F(WebRtcVideoChannel2Test, TranslatesCallStatsCorrectly) { TEST_F(WebRtcVideoChannel2Test, TranslatesCallStatsCorrectly) {
AddSendStream(); AddSendStream();
AddSendStream(); AddSendStream();

View File

@ -86,6 +86,8 @@ class FakeVideoReceiveStream : public webrtc::VideoReceiveStream {
void InjectFrame(const webrtc::I420VideoFrame& frame, int time_to_render_ms); void InjectFrame(const webrtc::I420VideoFrame& frame, int time_to_render_ms);
void SetStats(const webrtc::VideoReceiveStream::Stats& stats);
private: private:
virtual webrtc::VideoReceiveStream::Stats GetStats() const OVERRIDE; virtual webrtc::VideoReceiveStream::Stats GetStats() const OVERRIDE;
@ -94,6 +96,7 @@ class FakeVideoReceiveStream : public webrtc::VideoReceiveStream {
webrtc::VideoReceiveStream::Config config_; webrtc::VideoReceiveStream::Config config_;
bool receiving_; bool receiving_;
webrtc::VideoReceiveStream::Stats stats_;
}; };
class FakeCall : public webrtc::Call { class FakeCall : public webrtc::Call {

View File

@ -241,6 +241,14 @@ struct RtcpPacketTypeCounter {
uint32_t unique_nack_requests; // Number of unique NACKed RTP packets. uint32_t unique_nack_requests; // Number of unique NACKed RTP packets.
}; };
class RtcpPacketTypeCounterObserver {
public:
virtual ~RtcpPacketTypeCounterObserver() {}
virtual void RtcpPacketTypesCounterUpdated(
uint32_t ssrc,
const RtcpPacketTypeCounter& packet_counter) = 0;
};
// Rate statistics for a stream. // Rate statistics for a stream.
struct BitrateStatistics { struct BitrateStatistics {
BitrateStatistics() : bitrate_bps(0), packet_rate(0), timestamp_ms(0) {} BitrateStatistics() : bitrate_bps(0), packet_rate(0), timestamp_ms(0) {}

View File

@ -38,6 +38,7 @@ struct SsrcStats {
int avg_delay_ms; int avg_delay_ms;
int max_delay_ms; int max_delay_ms;
StreamDataCounters rtp_stats; StreamDataCounters rtp_stats;
RtcpPacketTypeCounter rtcp_packet_type_counts;
RtcpStatistics rtcp_stats; RtcpStatistics rtcp_stats;
}; };

View File

@ -61,6 +61,7 @@ class RtpRtcp : public Module {
RtcpIntraFrameObserver* intra_frame_callback; RtcpIntraFrameObserver* intra_frame_callback;
RtcpBandwidthObserver* bandwidth_callback; RtcpBandwidthObserver* bandwidth_callback;
RtcpRttStats* rtt_stats; RtcpRttStats* rtt_stats;
RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer;
RtpAudioFeedback* audio_messages; RtpAudioFeedback* audio_messages;
RemoteBitrateEstimator* remote_bitrate_estimator; RemoteBitrateEstimator* remote_bitrate_estimator;
PacedSender* paced_sender; PacedSender* paced_sender;
@ -455,13 +456,6 @@ class RtpRtcp : public Module {
*/ */
virtual int32_t RemoveRTCPReportBlock(uint32_t SSRC) = 0; virtual int32_t RemoveRTCPReportBlock(uint32_t SSRC) = 0;
/*
* Get number of sent and received RTCP packet types.
*/
virtual void GetRtcpPacketTypeCounters(
RtcpPacketTypeCounter* packets_sent,
RtcpPacketTypeCounter* packets_received) const = 0;
/* /*
* (APP) Application specific data * (APP) Application specific data
* *

View File

@ -95,8 +95,9 @@ void RtcpFormatRembTest::SetUp() {
configuration.remote_bitrate_estimator = remote_bitrate_estimator_.get(); configuration.remote_bitrate_estimator = remote_bitrate_estimator_.get();
dummy_rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration); dummy_rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration);
rtcp_sender_ = rtcp_sender_ =
new RTCPSender(0, false, system_clock_, receive_statistics_.get()); new RTCPSender(0, false, system_clock_, receive_statistics_.get(), NULL);
rtcp_receiver_ = new RTCPReceiver(0, system_clock_, dummy_rtp_rtcp_impl_); rtcp_receiver_ =
new RTCPReceiver(0, system_clock_, NULL, dummy_rtp_rtcp_impl_);
test_transport_ = new TestTransport(rtcp_receiver_); test_transport_ = new TestTransport(rtcp_receiver_);
EXPECT_EQ(0, rtcp_sender_->RegisterSendTransport(test_transport_)); EXPECT_EQ(0, rtcp_sender_->RegisterSendTransport(test_transport_));

View File

@ -28,7 +28,11 @@ using namespace RTCPHelp;
// The number of RTCP time intervals needed to trigger a timeout. // The number of RTCP time intervals needed to trigger a timeout.
const int kRrTimeoutIntervals = 3; const int kRrTimeoutIntervals = 3;
RTCPReceiver::RTCPReceiver(int32_t id, Clock* clock, ModuleRtpRtcpImpl* owner) RTCPReceiver::RTCPReceiver(
int32_t id,
Clock* clock,
RtcpPacketTypeCounterObserver* packet_type_counter_observer,
ModuleRtpRtcpImpl* owner)
: TMMBRHelp(), : TMMBRHelp(),
_clock(clock), _clock(clock),
_method(kRtcpOff), _method(kRtcpOff),
@ -52,7 +56,8 @@ RTCPReceiver::RTCPReceiver(int32_t id, Clock* clock, ModuleRtpRtcpImpl* owner)
_packetTimeOutMS(0), _packetTimeOutMS(0),
_lastReceivedRrMs(0), _lastReceivedRrMs(0),
_lastIncreasedSequenceNumberMs(0), _lastIncreasedSequenceNumberMs(0),
stats_callback_(NULL) { stats_callback_(NULL),
packet_type_counter_observer_(packet_type_counter_observer) {
memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo)); memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
} }
@ -271,12 +276,6 @@ int32_t RTCPReceiver::StatisticsReceived(
return 0; return 0;
} }
void RTCPReceiver::GetPacketTypeCounter(
RtcpPacketTypeCounter* packet_counter) const {
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
*packet_counter = packet_type_counter_;
}
int32_t int32_t
RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation, RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
RTCPUtility::RTCPParserV2* rtcpParser) RTCPUtility::RTCPParserV2* rtcpParser)
@ -362,6 +361,12 @@ RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
} }
pktType = rtcpParser->PacketType(); pktType = rtcpParser->PacketType();
} }
if (packet_type_counter_observer_ != NULL) {
packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
main_ssrc_, packet_type_counter_);
}
return 0; return 0;
} }
@ -770,11 +775,13 @@ void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0; cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1); strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
{
CriticalSectionScoped lock(_criticalSectionFeedbacks); CriticalSectionScoped lock(_criticalSectionFeedbacks);
if (stats_callback_ != NULL) { if (stats_callback_ != NULL) {
stats_callback_->CNameChanged(rtcpPacket.CName.CName, stats_callback_->CNameChanged(rtcpPacket.CName.CName,
rtcpPacket.CName.SenderSSRC); rtcpPacket.CName.SenderSSRC);
} }
}
} }
// no need for critsect we have _criticalSectionRTCPReceiver // no need for critsect we have _criticalSectionRTCPReceiver

View File

@ -29,7 +29,10 @@ class ModuleRtpRtcpImpl;
class RTCPReceiver : public TMMBRHelp class RTCPReceiver : public TMMBRHelp
{ {
public: public:
RTCPReceiver(int32_t id, Clock* clock, ModuleRtpRtcpImpl* owner); RTCPReceiver(int32_t id,
Clock* clock,
RtcpPacketTypeCounterObserver* packet_type_counter_observer,
ModuleRtpRtcpImpl* owner);
virtual ~RTCPReceiver(); virtual ~RTCPReceiver();
RTCPMethod Status() const; RTCPMethod Status() const;
@ -83,8 +86,6 @@ public:
int32_t StatisticsReceived( int32_t StatisticsReceived(
std::vector<RTCPReportBlock>* receiveBlocks) const; std::vector<RTCPReportBlock>* receiveBlocks) const;
void GetPacketTypeCounter(RtcpPacketTypeCounter* packet_counter) const;
// Returns true if we haven't received an RTCP RR for several RTCP // Returns true if we haven't received an RTCP RR for several RTCP
// intervals, but only triggers true once. // intervals, but only triggers true once.
bool RtcpRrTimeout(int64_t rtcp_interval_ms); bool RtcpRrTimeout(int64_t rtcp_interval_ms);
@ -276,6 +277,7 @@ protected:
RtcpStatisticsCallback* stats_callback_ GUARDED_BY(_criticalSectionFeedbacks); RtcpStatisticsCallback* stats_callback_ GUARDED_BY(_criticalSectionFeedbacks);
RtcpPacketTypeCounterObserver* const packet_type_counter_observer_;
RtcpPacketTypeCounter packet_type_counter_; RtcpPacketTypeCounter packet_type_counter_;
RTCPUtility::NackStats nack_stats_; RTCPUtility::NackStats nack_stats_;

View File

@ -86,7 +86,7 @@ class RtcpReceiverTest : public ::testing::Test {
configuration.outgoing_transport = test_transport_; configuration.outgoing_transport = test_transport_;
configuration.remote_bitrate_estimator = remote_bitrate_estimator_.get(); configuration.remote_bitrate_estimator = remote_bitrate_estimator_.get();
rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration); rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration);
rtcp_receiver_ = new RTCPReceiver(0, &system_clock_, rtp_rtcp_impl_); rtcp_receiver_ = new RTCPReceiver(0, &system_clock_, NULL, rtp_rtcp_impl_);
test_transport_->SetRTCPReceiver(rtcp_receiver_); test_transport_->SetRTCPReceiver(rtcp_receiver_);
} }
~RtcpReceiverTest() { ~RtcpReceiverTest() {

View File

@ -76,10 +76,12 @@ RTCPSender::FeedbackState::FeedbackState()
remote_sr(0), remote_sr(0),
has_last_xr_rr(false) {} has_last_xr_rr(false) {}
RTCPSender::RTCPSender(int32_t id, RTCPSender::RTCPSender(
int32_t id,
bool audio, bool audio,
Clock* clock, Clock* clock,
ReceiveStatistics* receive_statistics) ReceiveStatistics* receive_statistics,
RtcpPacketTypeCounterObserver* packet_type_counter_observer)
: _id(id), : _id(id),
_audio(audio), _audio(audio),
_clock(clock), _clock(clock),
@ -129,7 +131,8 @@ RTCPSender::RTCPSender(int32_t id,
xrSendReceiverReferenceTimeEnabled_(false), xrSendReceiverReferenceTimeEnabled_(false),
_xrSendVoIPMetric(false), _xrSendVoIPMetric(false),
_xrVoIPMetric() { _xrVoIPMetric(),
packet_type_counter_observer_(packet_type_counter_observer) {
memset(_CNAME, 0, sizeof(_CNAME)); memset(_CNAME, 0, sizeof(_CNAME));
memset(_lastSendReport, 0, sizeof(_lastSendReport)); memset(_lastSendReport, 0, sizeof(_lastSendReport));
memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime)); memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
@ -466,12 +469,6 @@ bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
return true; return true;
} }
void RTCPSender::GetPacketTypeCounter(
RtcpPacketTypeCounter* packet_counter) const {
CriticalSectionScoped lock(_criticalSectionRTCPSender);
*packet_counter = packet_type_counter_;
}
int32_t RTCPSender::AddExternalReportBlock( int32_t RTCPSender::AddExternalReportBlock(
uint32_t SSRC, uint32_t SSRC,
const RTCPReportBlock* reportBlock) { const RTCPReportBlock* reportBlock) {
@ -1889,6 +1886,12 @@ int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
return position; return position;
} }
} }
if (packet_type_counter_observer_ != NULL) {
packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
_remoteSSRC, packet_type_counter_);
}
return position; return position;
} }

View File

@ -70,7 +70,8 @@ public:
RTCPSender(int32_t id, RTCPSender(int32_t id,
bool audio, bool audio,
Clock* clock, Clock* clock,
ReceiveStatistics* receive_statistics); ReceiveStatistics* receive_statistics,
RtcpPacketTypeCounterObserver* packet_type_counter_observer);
virtual ~RTCPSender(); virtual ~RTCPSender();
int32_t RegisterSendTransport(Transport* outgoingTransport); int32_t RegisterSendTransport(Transport* outgoingTransport);
@ -165,8 +166,6 @@ public:
void SetTargetBitrate(unsigned int target_bitrate); void SetTargetBitrate(unsigned int target_bitrate);
void GetPacketTypeCounter(RtcpPacketTypeCounter* packet_counter) const;
private: private:
int32_t SendToNetwork(const uint8_t* dataBuffer, size_t length); int32_t SendToNetwork(const uint8_t* dataBuffer, size_t length);
@ -341,6 +340,7 @@ private:
bool _xrSendVoIPMetric GUARDED_BY(_criticalSectionRTCPSender); bool _xrSendVoIPMetric GUARDED_BY(_criticalSectionRTCPSender);
RTCPVoIPMetric _xrVoIPMetric GUARDED_BY(_criticalSectionRTCPSender); RTCPVoIPMetric _xrVoIPMetric GUARDED_BY(_criticalSectionRTCPSender);
RtcpPacketTypeCounterObserver* const packet_type_counter_observer_;
RtcpPacketTypeCounter packet_type_counter_ RtcpPacketTypeCounter packet_type_counter_
GUARDED_BY(_criticalSectionRTCPSender); GUARDED_BY(_criticalSectionRTCPSender);

View File

@ -304,8 +304,8 @@ class RtcpSenderTest : public ::testing::Test {
rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver( rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver(
0, &clock_, test_transport_, NULL, rtp_payload_registry_.get())); 0, &clock_, test_transport_, NULL, rtp_payload_registry_.get()));
rtcp_sender_ = rtcp_sender_ =
new RTCPSender(0, false, &clock_, receive_statistics_.get()); new RTCPSender(0, false, &clock_, receive_statistics_.get(), NULL);
rtcp_receiver_ = new RTCPReceiver(0, &clock_, rtp_rtcp_impl_); rtcp_receiver_ = new RTCPReceiver(0, &clock_, NULL, rtp_rtcp_impl_);
test_transport_->SetRTCPReceiver(rtcp_receiver_); test_transport_->SetRTCPReceiver(rtcp_receiver_);
// Initialize // Initialize
EXPECT_EQ(0, rtcp_sender_->RegisterSendTransport(test_transport_)); EXPECT_EQ(0, rtcp_sender_->RegisterSendTransport(test_transport_));

View File

@ -36,6 +36,7 @@ RtpRtcp::Configuration::Configuration()
intra_frame_callback(NULL), intra_frame_callback(NULL),
bandwidth_callback(NULL), bandwidth_callback(NULL),
rtt_stats(NULL), rtt_stats(NULL),
rtcp_packet_type_counter_observer(NULL),
audio_messages(NullObjectRtpAudioFeedback()), audio_messages(NullObjectRtpAudioFeedback()),
remote_bitrate_estimator(NULL), remote_bitrate_estimator(NULL),
paced_sender(NULL), paced_sender(NULL),
@ -70,8 +71,12 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
rtcp_sender_(configuration.id, rtcp_sender_(configuration.id,
configuration.audio, configuration.audio,
configuration.clock, configuration.clock,
configuration.receive_statistics), configuration.receive_statistics,
rtcp_receiver_(configuration.id, configuration.clock, this), configuration.rtcp_packet_type_counter_observer),
rtcp_receiver_(configuration.id,
configuration.clock,
configuration.rtcp_packet_type_counter_observer,
this),
clock_(configuration.clock), clock_(configuration.clock),
id_(configuration.id), id_(configuration.id),
audio_(configuration.audio), audio_(configuration.audio),
@ -722,13 +727,6 @@ int32_t ModuleRtpRtcpImpl::RemoveRTCPReportBlock(
return rtcp_sender_.RemoveExternalReportBlock(ssrc); return rtcp_sender_.RemoveExternalReportBlock(ssrc);
} }
void ModuleRtpRtcpImpl::GetRtcpPacketTypeCounters(
RtcpPacketTypeCounter* packets_sent,
RtcpPacketTypeCounter* packets_received) const {
rtcp_sender_.GetPacketTypeCounter(packets_sent);
rtcp_receiver_.GetPacketTypeCounter(packets_received);
}
// (REMB) Receiver Estimated Max Bitrate. // (REMB) Receiver Estimated Max Bitrate.
bool ModuleRtpRtcpImpl::REMB() const { bool ModuleRtpRtcpImpl::REMB() const {
return rtcp_sender_.REMB(); return rtcp_sender_.REMB();
@ -860,8 +858,7 @@ void ModuleRtpRtcpImpl::RegisterRtcpStatisticsCallback(
rtcp_receiver_.RegisterRtcpStatisticsCallback(callback); rtcp_receiver_.RegisterRtcpStatisticsCallback(callback);
} }
RtcpStatisticsCallback* RtcpStatisticsCallback* ModuleRtpRtcpImpl::GetRtcpStatisticsCallback() {
ModuleRtpRtcpImpl::GetRtcpStatisticsCallback() {
return rtcp_receiver_.GetRtcpStatisticsCallback(); return rtcp_receiver_.GetRtcpStatisticsCallback();
} }

View File

@ -190,10 +190,6 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
virtual int32_t RemoveRTCPReportBlock(uint32_t ssrc) OVERRIDE; virtual int32_t RemoveRTCPReportBlock(uint32_t ssrc) OVERRIDE;
virtual void GetRtcpPacketTypeCounters(
RtcpPacketTypeCounter* packets_sent,
RtcpPacketTypeCounter* packets_received) const OVERRIDE;
// (REMB) Receiver Estimated Max Bitrate. // (REMB) Receiver Estimated Max Bitrate.
virtual bool REMB() const OVERRIDE; virtual bool REMB() const OVERRIDE;

View File

@ -98,7 +98,7 @@ class SendTransport : public Transport,
std::vector<uint16_t> last_nack_list_; std::vector<uint16_t> last_nack_list_;
}; };
class RtpRtcpModule { class RtpRtcpModule : public RtcpPacketTypeCounterObserver {
public: public:
RtpRtcpModule(SimulatedClock* clock) RtpRtcpModule(SimulatedClock* clock)
: receive_statistics_(ReceiveStatistics::Create(clock)) { : receive_statistics_(ReceiveStatistics::Create(clock)) {
@ -107,6 +107,7 @@ class RtpRtcpModule {
config.clock = clock; config.clock = clock;
config.outgoing_transport = &transport_; config.outgoing_transport = &transport_;
config.receive_statistics = receive_statistics_.get(); config.receive_statistics = receive_statistics_.get();
config.rtcp_packet_type_counter_observer = this;
config.rtt_stats = &rtt_stats_; config.rtt_stats = &rtt_stats_;
impl_.reset(new ModuleRtpRtcpImpl(config)); impl_.reset(new ModuleRtpRtcpImpl(config));
@ -121,14 +122,27 @@ class RtpRtcpModule {
SendTransport transport_; SendTransport transport_;
RtcpRttStatsTestImpl rtt_stats_; RtcpRttStatsTestImpl rtt_stats_;
scoped_ptr<ModuleRtpRtcpImpl> impl_; scoped_ptr<ModuleRtpRtcpImpl> impl_;
uint32_t remote_ssrc_;
void SetRemoteSsrc(uint32_t ssrc) {
remote_ssrc_ = ssrc;
impl_->SetRemoteSSRC(ssrc);
}
void RtcpPacketTypesCounterUpdated(
uint32_t ssrc,
const RtcpPacketTypeCounter& packet_counter) override {
counter_map_[ssrc] = packet_counter;
}
RtcpPacketTypeCounter RtcpSent() { RtcpPacketTypeCounter RtcpSent() {
impl_->GetRtcpPacketTypeCounters(&packets_sent_, &packets_received_); // RTCP counters for remote SSRC.
return packets_sent_; return counter_map_[remote_ssrc_];
} }
RtcpPacketTypeCounter RtcpReceived() { RtcpPacketTypeCounter RtcpReceived() {
impl_->GetRtcpPacketTypeCounters(&packets_sent_, &packets_received_); // Received RTCP stats for (own) local SSRC.
return packets_received_; return counter_map_[impl_->SSRC()];
} }
int RtpSent() { int RtpSent() {
return transport_.rtp_packets_sent_; return transport_.rtp_packets_sent_;
@ -139,6 +153,9 @@ class RtpRtcpModule {
std::vector<uint16_t> LastNackListSent() { std::vector<uint16_t> LastNackListSent() {
return transport_.last_nack_list_; return transport_.last_nack_list_;
} }
private:
std::map<uint32_t, RtcpPacketTypeCounter> counter_map_;
}; };
} // namespace } // namespace
@ -152,7 +169,7 @@ class RtpRtcpImplTest : public ::testing::Test {
EXPECT_EQ(0, sender_.impl_->SetSendingStatus(true)); EXPECT_EQ(0, sender_.impl_->SetSendingStatus(true));
sender_.impl_->SetSendingMediaStatus(true); sender_.impl_->SetSendingMediaStatus(true);
sender_.impl_->SetSSRC(kSenderSsrc); sender_.impl_->SetSSRC(kSenderSsrc);
sender_.impl_->SetRemoteSSRC(kReceiverSsrc); sender_.SetRemoteSsrc(kReceiverSsrc);
sender_.impl_->SetSequenceNumber(kSequenceNumber); sender_.impl_->SetSequenceNumber(kSequenceNumber);
sender_.impl_->SetStorePacketsStatus(true, 100); sender_.impl_->SetStorePacketsStatus(true, 100);
@ -167,7 +184,7 @@ class RtpRtcpImplTest : public ::testing::Test {
EXPECT_EQ(0, receiver_.impl_->SetSendingStatus(false)); EXPECT_EQ(0, receiver_.impl_->SetSendingStatus(false));
receiver_.impl_->SetSendingMediaStatus(false); receiver_.impl_->SetSendingMediaStatus(false);
receiver_.impl_->SetSSRC(kReceiverSsrc); receiver_.impl_->SetSSRC(kReceiverSsrc);
receiver_.impl_->SetRemoteSSRC(kSenderSsrc); receiver_.SetRemoteSsrc(kSenderSsrc);
// Transport settings. // Transport settings.
sender_.transport_.SetRtpRtcpModule(receiver_.impl_.get()); sender_.transport_.SetRtpRtcpModule(receiver_.impl_.get());
receiver_.transport_.SetRtpRtcpModule(sender_.impl_.get()); receiver_.transport_.SetRtpRtcpModule(sender_.impl_.get());

View File

@ -1564,11 +1564,9 @@ TEST_F(EndToEndTest, GetStats) {
static const int kStartBitrateBps = 3000000; static const int kStartBitrateBps = 3000000;
class StatsObserver : public test::EndToEndTest, public I420FrameCallback { class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
public: public:
StatsObserver() explicit StatsObserver(const FakeNetworkPipe::Config& config)
: EndToEndTest(kLongTimeoutMs), : EndToEndTest(kLongTimeoutMs, config),
receive_stream_(NULL),
send_stream_(NULL), send_stream_(NULL),
expected_receive_ssrc_(),
expected_send_ssrcs_(), expected_send_ssrcs_(),
check_stats_event_(EventWrapper::Create()) {} check_stats_event_(EventWrapper::Create()) {}
@ -1602,12 +1600,13 @@ TEST_F(EndToEndTest, GetStats) {
} }
bool CheckReceiveStats() { bool CheckReceiveStats() {
assert(receive_stream_ != NULL); for (size_t i = 0; i < receive_streams_.size(); ++i) {
VideoReceiveStream::Stats stats = receive_stream_->GetStats(); VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
EXPECT_EQ(expected_receive_ssrc_, stats.ssrc); EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
// Make sure all fields have been populated. // Make sure all fields have been populated.
// TODO(pbos): Use CompoundKey if/when we ever know that all stats are
// always filled for all receivers.
receive_stats_filled_["IncomingRate"] |= receive_stats_filled_["IncomingRate"] |=
stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0; stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
@ -1637,6 +1636,14 @@ TEST_F(EndToEndTest, GetStats) {
receive_stats_filled_["CName"] |= stats.c_name != ""; receive_stats_filled_["CName"] |= stats.c_name != "";
receive_stats_filled_["RtcpPacketTypeCount"] |=
stats.rtcp_packet_type_counts.fir_packets != 0 ||
stats.rtcp_packet_type_counts.nack_packets != 0 ||
stats.rtcp_packet_type_counts.pli_packets != 0 ||
stats.rtcp_packet_type_counts.nack_requests != 0 ||
stats.rtcp_packet_type_counts.unique_nack_requests != 0;
}
return AllStatsFilled(receive_stats_filled_); return AllStatsFilled(receive_stats_filled_);
} }
@ -1654,7 +1661,7 @@ TEST_F(EndToEndTest, GetStats) {
EXPECT_TRUE(expected_send_ssrcs_.find(it->first) != EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
expected_send_ssrcs_.end()); expected_send_ssrcs_.end());
send_stats_filled_[CompoundKey("IncomingRate", it->first)] |= send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
stats.input_frame_rate != 0; stats.input_frame_rate != 0;
const SsrcStats& stream_stats = it->second; const SsrcStats& stream_stats = it->second;
@ -1683,6 +1690,15 @@ TEST_F(EndToEndTest, GetStats) {
send_stats_filled_[CompoundKey("Delay", it->first)] |= send_stats_filled_[CompoundKey("Delay", it->first)] |=
stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0; stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
// TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
// report dropped packets.
send_stats_filled_["RtcpPacketTypeCount"] |=
stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
} }
return AllStatsFilled(send_stats_filled_); return AllStatsFilled(send_stats_filled_);
@ -1715,14 +1731,14 @@ TEST_F(EndToEndTest, GetStats) {
std::vector<VideoReceiveStream::Config>* receive_configs, std::vector<VideoReceiveStream::Config>* receive_configs,
VideoEncoderConfig* encoder_config) override { VideoEncoderConfig* encoder_config) override {
send_config->pre_encode_callback = this; // Used to inject delay. send_config->pre_encode_callback = this; // Used to inject delay.
send_config->rtp.c_name = "SomeCName"; expected_cname_ = send_config->rtp.c_name = "SomeCName";
expected_receive_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs; const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
for (size_t i = 0; i < ssrcs.size(); ++i) for (size_t i = 0; i < ssrcs.size(); ++i) {
expected_send_ssrcs_.insert(ssrcs[i]); expected_send_ssrcs_.insert(ssrcs[i]);
expected_receive_ssrcs_.push_back(
expected_cname_ = send_config->rtp.c_name; (*receive_configs)[i].rtp.remote_ssrc);
}
} }
virtual size_t GetNumStreams() const override { return kNumSsrcs; } virtual size_t GetNumStreams() const override { return kNumSsrcs; }
@ -1731,7 +1747,7 @@ TEST_F(EndToEndTest, GetStats) {
VideoSendStream* send_stream, VideoSendStream* send_stream,
const std::vector<VideoReceiveStream*>& receive_streams) override { const std::vector<VideoReceiveStream*>& receive_streams) override {
send_stream_ = send_stream; send_stream_ = send_stream;
receive_stream_ = receive_streams[0]; receive_streams_ = receive_streams;
} }
virtual void PerformTest() override { virtual void PerformTest() override {
@ -1776,19 +1792,23 @@ TEST_F(EndToEndTest, GetStats) {
} }
} }
VideoReceiveStream* receive_stream_; std::vector<VideoReceiveStream*> receive_streams_;
std::map<std::string, bool> receive_stats_filled_; std::map<std::string, bool> receive_stats_filled_;
VideoSendStream* send_stream_; VideoSendStream* send_stream_;
std::map<std::string, bool> send_stats_filled_; std::map<std::string, bool> send_stats_filled_;
uint32_t expected_receive_ssrc_; std::vector<uint32_t> expected_receive_ssrcs_;
std::set<uint32_t> expected_send_ssrcs_; std::set<uint32_t> expected_send_ssrcs_;
std::string expected_cname_; std::string expected_cname_;
scoped_ptr<EventWrapper> check_stats_event_; scoped_ptr<EventWrapper> check_stats_event_;
} test; };
FakeNetworkPipe::Config network_config;
network_config.loss_percent = 5;
StatsObserver test(network_config);
RunBaseTest(&test); RunBaseTest(&test);
} }

View File

@ -50,16 +50,32 @@ void ReceiveStatisticsProxy::DecoderTiming(int decode_ms,
stats_.avg_delay_ms = target_delay_ms; stats_.avg_delay_ms = target_delay_ms;
} }
void ReceiveStatisticsProxy::RtcpPacketTypesCounterUpdated(
uint32_t ssrc,
const RtcpPacketTypeCounter& packet_counter) {
CriticalSectionScoped lock(crit_.get());
if (stats_.ssrc != ssrc)
return;
stats_.rtcp_packet_type_counts = packet_counter;
}
void ReceiveStatisticsProxy::StatisticsUpdated( void ReceiveStatisticsProxy::StatisticsUpdated(
const webrtc::RtcpStatistics& statistics, const webrtc::RtcpStatistics& statistics,
uint32_t ssrc) { uint32_t ssrc) {
CriticalSectionScoped lock(crit_.get()); CriticalSectionScoped lock(crit_.get());
// TODO(pbos): Handle both local and remote ssrcs here and DCHECK that we
// receive stats from one of them.
if (stats_.ssrc != ssrc)
return;
stats_.rtcp_stats = statistics; stats_.rtcp_stats = statistics;
} }
void ReceiveStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) { void ReceiveStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) {
CriticalSectionScoped lock(crit_.get()); CriticalSectionScoped lock(crit_.get());
// TODO(pbos): Handle both local and remote ssrcs here and DCHECK that we
// receive stats from one of them.
if (stats_.ssrc != ssrc)
return;
stats_.c_name = cname; stats_.c_name = cname;
} }

View File

@ -33,6 +33,7 @@ class ViEDecoderObserver;
class ReceiveStatisticsProxy : public ViEDecoderObserver, class ReceiveStatisticsProxy : public ViEDecoderObserver,
public VCMReceiveStatisticsCallback, public VCMReceiveStatisticsCallback,
public RtcpStatisticsCallback, public RtcpStatisticsCallback,
public RtcpPacketTypeCounterObserver,
public StreamDataCountersCallback { public StreamDataCountersCallback {
public: public:
ReceiveStatisticsProxy(uint32_t ssrc, Clock* clock); ReceiveStatisticsProxy(uint32_t ssrc, Clock* clock);
@ -69,6 +70,10 @@ class ReceiveStatisticsProxy : public ViEDecoderObserver,
uint32_t ssrc) OVERRIDE; uint32_t ssrc) OVERRIDE;
virtual void CNameChanged(const char* cname, uint32_t ssrc) OVERRIDE; virtual void CNameChanged(const char* cname, uint32_t ssrc) OVERRIDE;
// Overrides RtcpPacketTypeCounterObserver
virtual void RtcpPacketTypesCounterUpdated(
uint32_t ssrc,
const RtcpPacketTypeCounter& packet_counter) OVERRIDE;
// Overrides StreamDataCountersCallback. // Overrides StreamDataCountersCallback.
virtual void DataCountersUpdated(const webrtc::StreamDataCounters& counters, virtual void DataCountersUpdated(const webrtc::StreamDataCounters& counters,
uint32_t ssrc) OVERRIDE; uint32_t ssrc) OVERRIDE;

View File

@ -105,6 +105,17 @@ void SendStatisticsProxy::OnSendEncodedImage(
update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds(); update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
} }
void SendStatisticsProxy::RtcpPacketTypesCounterUpdated(
uint32_t ssrc,
const RtcpPacketTypeCounter& packet_counter) {
CriticalSectionScoped lock(crit_.get());
SsrcStats* stats = GetStatsEntry(ssrc);
if (stats == NULL)
return;
stats->rtcp_packet_type_counts = packet_counter;
}
void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics, void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics,
uint32_t ssrc) { uint32_t ssrc) {
CriticalSectionScoped lock(crit_.get()); CriticalSectionScoped lock(crit_.get());

View File

@ -27,6 +27,7 @@ namespace webrtc {
class CriticalSectionWrapper; class CriticalSectionWrapper;
class SendStatisticsProxy : public RtcpStatisticsCallback, class SendStatisticsProxy : public RtcpStatisticsCallback,
public RtcpPacketTypeCounterObserver,
public StreamDataCountersCallback, public StreamDataCountersCallback,
public BitrateStatisticsObserver, public BitrateStatisticsObserver,
public FrameCountObserver, public FrameCountObserver,
@ -49,6 +50,10 @@ class SendStatisticsProxy : public RtcpStatisticsCallback,
virtual void StatisticsUpdated(const RtcpStatistics& statistics, virtual void StatisticsUpdated(const RtcpStatistics& statistics,
uint32_t ssrc) OVERRIDE; uint32_t ssrc) OVERRIDE;
virtual void CNameChanged(const char *cname, uint32_t ssrc) OVERRIDE; virtual void CNameChanged(const char *cname, uint32_t ssrc) OVERRIDE;
// From RtcpPacketTypeCounterObserver
virtual void RtcpPacketTypesCounterUpdated(
uint32_t ssrc,
const RtcpPacketTypeCounter& packet_counter) OVERRIDE;
// From StreamDataCountersCallback. // From StreamDataCountersCallback.
virtual void DataCountersUpdated(const StreamDataCounters& counters, virtual void DataCountersUpdated(const StreamDataCounters& counters,
uint32_t ssrc) OVERRIDE; uint32_t ssrc) OVERRIDE;

View File

@ -219,7 +219,7 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine,
} }
stats_proxy_.reset( stats_proxy_.reset(
new ReceiveStatisticsProxy(config_.rtp.local_ssrc, clock_)); new ReceiveStatisticsProxy(config_.rtp.remote_ssrc, clock_));
if (rtp_rtcp_->RegisterReceiveChannelRtcpStatisticsCallback( if (rtp_rtcp_->RegisterReceiveChannelRtcpStatisticsCallback(
channel_, stats_proxy_.get()) != 0) { channel_, stats_proxy_.get()) != 0) {
@ -231,6 +231,11 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine,
abort(); abort();
} }
if (rtp_rtcp_->RegisterRtcpPacketTypeCounterObserver(
channel_, stats_proxy_.get()) != 0) {
abort();
}
if (codec_->RegisterDecoderObserver(channel_, *stats_proxy_) != 0) { if (codec_->RegisterDecoderObserver(channel_, *stats_proxy_) != 0) {
abort(); abort();
} }
@ -301,6 +306,7 @@ VideoReceiveStream::~VideoReceiveStream() {
stats_proxy_.get()); stats_proxy_.get());
rtp_rtcp_->DeregisterReceiveChannelRtcpStatisticsCallback(channel_, rtp_rtcp_->DeregisterReceiveChannelRtcpStatisticsCallback(channel_,
stats_proxy_.get()); stats_proxy_.get());
rtp_rtcp_->RegisterRtcpPacketTypeCounterObserver(channel_, NULL);
codec_->Release(); codec_->Release();
network_->Release(); network_->Release();
render_->Release(); render_->Release();

View File

@ -229,6 +229,7 @@ VideoSendStream::VideoSendStream(
&stats_proxy_); &stats_proxy_);
rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(channel_, rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(channel_,
&stats_proxy_); &stats_proxy_);
rtp_rtcp_->RegisterRtcpPacketTypeCounterObserver(channel_, &stats_proxy_);
rtp_rtcp_->RegisterSendBitrateObserver(channel_, &stats_proxy_); rtp_rtcp_->RegisterSendBitrateObserver(channel_, &stats_proxy_);
rtp_rtcp_->RegisterSendFrameCountObserver(channel_, &stats_proxy_); rtp_rtcp_->RegisterSendFrameCountObserver(channel_, &stats_proxy_);
@ -242,6 +243,7 @@ VideoSendStream::~VideoSendStream() {
rtp_rtcp_->DeregisterSendFrameCountObserver(channel_, &stats_proxy_); rtp_rtcp_->DeregisterSendFrameCountObserver(channel_, &stats_proxy_);
rtp_rtcp_->DeregisterSendBitrateObserver(channel_, &stats_proxy_); rtp_rtcp_->DeregisterSendBitrateObserver(channel_, &stats_proxy_);
rtp_rtcp_->RegisterRtcpPacketTypeCounterObserver(channel_, NULL);
rtp_rtcp_->DeregisterSendChannelRtpStatisticsCallback(channel_, rtp_rtcp_->DeregisterSendChannelRtpStatisticsCallback(channel_,
&stats_proxy_); &stats_proxy_);
rtp_rtcp_->DeregisterSendChannelRtcpStatisticsCallback(channel_, rtp_rtcp_->DeregisterSendChannelRtcpStatisticsCallback(channel_,
@ -443,6 +445,7 @@ VideoSendStream::Stats VideoSendStream::GetStats() {
} }
void VideoSendStream::ConfigureSsrcs() { void VideoSendStream::ConfigureSsrcs() {
rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.ssrcs.front());
for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
uint32_t ssrc = config_.rtp.ssrcs[i]; uint32_t ssrc = config_.rtp.ssrcs[i];
rtp_rtcp_->SetLocalSSRC( rtp_rtcp_->SetLocalSSRC(

View File

@ -324,8 +324,8 @@ TEST_F(VideoSendStreamTest, SupportsFec) {
// Receive statistics reporting having lost 50% of the packets. // Receive statistics reporting having lost 50% of the packets.
FakeReceiveStatistics lossy_receive_stats( FakeReceiveStatistics lossy_receive_stats(
kSendSsrcs[0], header.sequenceNumber, send_count_ / 2, 127); kSendSsrcs[0], header.sequenceNumber, send_count_ / 2, 127);
RTCPSender rtcp_sender( RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(),
0, false, Clock::GetRealTimeClock(), &lossy_receive_stats); &lossy_receive_stats, nullptr);
EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_)); EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
rtcp_sender.SetRTCPStatus(kRtcpNonCompound); rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
@ -400,7 +400,7 @@ void VideoSendStreamTest::TestNackRetransmission(
nacked_sequence_number_ = nack_sequence_number; nacked_sequence_number_ = nack_sequence_number;
NullReceiveStatistics null_stats; NullReceiveStatistics null_stats;
RTCPSender rtcp_sender( RTCPSender rtcp_sender(
0, false, Clock::GetRealTimeClock(), &null_stats); 0, false, Clock::GetRealTimeClock(), &null_stats, nullptr);
EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_)); EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
rtcp_sender.SetRTCPStatus(kRtcpNonCompound); rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
@ -582,8 +582,8 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
// Receive statistics reporting having lost 50% of the packets. // Receive statistics reporting having lost 50% of the packets.
FakeReceiveStatistics lossy_receive_stats( FakeReceiveStatistics lossy_receive_stats(
kSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127); kSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
RTCPSender rtcp_sender( RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(),
0, false, Clock::GetRealTimeClock(), &lossy_receive_stats); &lossy_receive_stats, nullptr);
EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_)); EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
rtcp_sender.SetRTCPStatus(kRtcpNonCompound); rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
@ -812,7 +812,7 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
EXCLUSIVE_LOCKS_REQUIRED(crit_) { EXCLUSIVE_LOCKS_REQUIRED(crit_) {
FakeReceiveStatistics receive_stats( FakeReceiveStatistics receive_stats(
kSendSsrcs[0], last_sequence_number_, rtp_count_, 0); kSendSsrcs[0], last_sequence_number_, rtp_count_, 0);
RTCPSender rtcp_sender(0, false, clock_, &receive_stats); RTCPSender rtcp_sender(0, false, clock_, &receive_stats, nullptr);
EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_)); EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
rtcp_sender.SetRTCPStatus(kRtcpNonCompound); rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
@ -872,8 +872,8 @@ TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
observation_complete_->Set(); observation_complete_->Set();
// Receive statistics reporting having lost 50% of the packets. // Receive statistics reporting having lost 50% of the packets.
FakeReceiveStatistics receive_stats(kSendSsrcs[0], 1, 1, 0); FakeReceiveStatistics receive_stats(kSendSsrcs[0], 1, 1, 0);
RTCPSender rtcp_sender( RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(),
0, false, Clock::GetRealTimeClock(), &receive_stats); &receive_stats, nullptr);
EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_)); EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
rtcp_sender.SetRTCPStatus(kRtcpNonCompound); rtcp_sender.SetRTCPStatus(kRtcpNonCompound);

View File

@ -448,6 +448,12 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP {
virtual int DeregisterSendFrameCountObserver( virtual int DeregisterSendFrameCountObserver(
int video_channel, FrameCountObserver* observer) = 0; int video_channel, FrameCountObserver* observer) = 0;
// Called when RTCP packet type counters might have been changed. User has to
// filter on SSRCs to determine whether it's status sent or received.
virtual int RegisterRtcpPacketTypeCounterObserver(
int video_channel,
RtcpPacketTypeCounterObserver* observer) = 0;
protected: protected:
virtual ~ViERTP_RTCP() {} virtual ~ViERTP_RTCP() {}
}; };

View File

@ -1142,6 +1142,11 @@ void ViEChannel::RegisterReceiveChannelRtcpStatisticsCallback(
rtp_rtcp_->RegisterRtcpStatisticsCallback(callback); rtp_rtcp_->RegisterRtcpStatisticsCallback(callback);
} }
void ViEChannel::RegisterRtcpPacketTypeCounterObserver(
RtcpPacketTypeCounterObserver* observer) {
rtcp_packet_type_counter_observer_.Set(observer);
}
int32_t ViEChannel::GetRtpStatistics(size_t* bytes_sent, int32_t ViEChannel::GetRtpStatistics(size_t* bytes_sent,
uint32_t* packets_sent, uint32_t* packets_sent,
size_t* bytes_received, size_t* bytes_received,
@ -1241,25 +1246,24 @@ void ViEChannel::RegisterReceiveChannelRtpStatisticsCallback(
void ViEChannel::GetRtcpPacketTypeCounters( void ViEChannel::GetRtcpPacketTypeCounters(
RtcpPacketTypeCounter* packets_sent, RtcpPacketTypeCounter* packets_sent,
RtcpPacketTypeCounter* packets_received) const { RtcpPacketTypeCounter* packets_received) const {
rtp_rtcp_->GetRtcpPacketTypeCounters(packets_sent, packets_received); std::map<uint32_t, RtcpPacketTypeCounter> counter_map =
rtcp_packet_type_counter_observer_.GetPacketTypeCounterMap();
RtcpPacketTypeCounter sent_counter;
sent_counter.Add(counter_map[rtp_rtcp_->SSRC()]);
RtcpPacketTypeCounter received_counter;
received_counter.Add(counter_map[vie_receiver_.GetRemoteSsrc()]);
CriticalSectionScoped cs(rtp_rtcp_cs_.get()); CriticalSectionScoped cs(rtp_rtcp_cs_.get());
for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin(); for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
it != simulcast_rtp_rtcp_.end(); ++it) { it != simulcast_rtp_rtcp_.end(); ++it) {
RtcpPacketTypeCounter sent; sent_counter.Add(counter_map[(*it)->SSRC()]);
RtcpPacketTypeCounter received;
(*it)->GetRtcpPacketTypeCounters(&sent, &received);
packets_sent->Add(sent);
packets_received->Add(received);
} }
for (std::list<RtpRtcp*>::const_iterator it = removed_rtp_rtcp_.begin(); for (std::list<RtpRtcp*>::const_iterator it = removed_rtp_rtcp_.begin();
it != removed_rtp_rtcp_.end(); ++it) { it != removed_rtp_rtcp_.end(); ++it) {
RtcpPacketTypeCounter sent; sent_counter.Add(counter_map[(*it)->SSRC()]);
RtcpPacketTypeCounter received;
(*it)->GetRtcpPacketTypeCounters(&sent, &received);
packets_sent->Add(sent);
packets_received->Add(received);
} }
*packets_sent = sent_counter;
*packets_received = received_counter;
} }
void ViEChannel::GetBandwidthUsage(uint32_t* total_bitrate_sent, void ViEChannel::GetBandwidthUsage(uint32_t* total_bitrate_sent,
@ -1694,6 +1698,8 @@ RtpRtcp::Configuration ViEChannel::CreateRtpRtcpConfiguration() {
configuration.intra_frame_callback = intra_frame_observer_; configuration.intra_frame_callback = intra_frame_observer_;
configuration.bandwidth_callback = bandwidth_observer_.get(); configuration.bandwidth_callback = bandwidth_observer_.get();
configuration.rtt_stats = rtt_stats_; configuration.rtt_stats = rtt_stats_;
configuration.rtcp_packet_type_counter_observer =
&rtcp_packet_type_counter_observer_;
configuration.paced_sender = paced_sender_; configuration.paced_sender = paced_sender_;
configuration.send_bitrate_observer = &send_bitrate_observer_; configuration.send_bitrate_observer = &send_bitrate_observer_;
configuration.send_frame_count_observer = &send_frame_count_observer_; configuration.send_frame_count_observer = &send_frame_count_observer_;

View File

@ -358,6 +358,8 @@ class ViEChannel
EncodedImageCallback* pre_decode_callback); EncodedImageCallback* pre_decode_callback);
void RegisterSendFrameCountObserver(FrameCountObserver* observer); void RegisterSendFrameCountObserver(FrameCountObserver* observer);
void RegisterRtcpPacketTypeCounterObserver(
RtcpPacketTypeCounterObserver* observer);
void RegisterReceiveStatisticsProxy( void RegisterReceiveStatisticsProxy(
ReceiveStatisticsProxy* receive_statistics_proxy); ReceiveStatisticsProxy* receive_statistics_proxy);
void ReceivedBWEPacket(int64_t arrival_time_ms, size_t payload_size, void ReceivedBWEPacket(int64_t arrival_time_ms, size_t payload_size,
@ -455,6 +457,29 @@ class ViEChannel
} }
} send_side_delay_observer_; } send_side_delay_observer_;
class RegisterableRtcpPacketTypeCounterObserver
: public RegisterableCallback<RtcpPacketTypeCounterObserver> {
public:
virtual void RtcpPacketTypesCounterUpdated(
uint32_t ssrc,
const RtcpPacketTypeCounter& packet_counter) override {
CriticalSectionScoped cs(critsect_.get());
if (callback_)
callback_->RtcpPacketTypesCounterUpdated(ssrc, packet_counter);
counter_map_[ssrc] = packet_counter;
}
virtual std::map<uint32_t, RtcpPacketTypeCounter> GetPacketTypeCounterMap()
const {
CriticalSectionScoped cs(critsect_.get());
return counter_map_;
}
private:
std::map<uint32_t, RtcpPacketTypeCounter> counter_map_
GUARDED_BY(critsect_);
} rtcp_packet_type_counter_observer_;
int32_t channel_id_; int32_t channel_id_;
int32_t engine_id_; int32_t engine_id_;
uint32_t number_of_cores_; uint32_t number_of_cores_;

View File

@ -1019,4 +1019,18 @@ int ViERTP_RTCPImpl::DeregisterSendFrameCountObserver(
vie_channel->RegisterSendFrameCountObserver(NULL); vie_channel->RegisterSendFrameCountObserver(NULL);
return 0; return 0;
} }
int ViERTP_RTCPImpl::RegisterRtcpPacketTypeCounterObserver(
int video_channel,
RtcpPacketTypeCounterObserver* observer) {
ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
ViEChannel* vie_channel = cs.Channel(video_channel);
if (!vie_channel) {
shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
return -1;
}
vie_channel->RegisterRtcpPacketTypeCounterObserver(observer);
return 0;
}
} // namespace webrtc } // namespace webrtc

View File

@ -157,6 +157,9 @@ class ViERTP_RTCPImpl
int channel, FrameCountObserver* callback); int channel, FrameCountObserver* callback);
virtual int DeregisterSendFrameCountObserver( virtual int DeregisterSendFrameCountObserver(
int channel, FrameCountObserver* callback); int channel, FrameCountObserver* callback);
virtual int RegisterRtcpPacketTypeCounterObserver(
int video_channel,
RtcpPacketTypeCounterObserver* observer) override;
protected: protected:
explicit ViERTP_RTCPImpl(ViESharedData* shared_data); explicit ViERTP_RTCPImpl(ViESharedData* shared_data);