diff options
Diffstat (limited to 'chromium/media/cast/rtcp/rtcp.cc')
-rw-r--r-- | chromium/media/cast/rtcp/rtcp.cc | 335 |
1 files changed, 210 insertions, 125 deletions
diff --git a/chromium/media/cast/rtcp/rtcp.cc b/chromium/media/cast/rtcp/rtcp.cc index c3e2c8e4d88..4ea4bc99ba9 100644 --- a/chromium/media/cast/rtcp/rtcp.cc +++ b/chromium/media/cast/rtcp/rtcp.cc @@ -4,10 +4,10 @@ #include "media/cast/rtcp/rtcp.h" -#include "base/debug/trace_event.h" #include "base/rand_util.h" #include "media/cast/cast_config.h" #include "media/cast/cast_defines.h" +#include "media/cast/cast_environment.h" #include "media/cast/rtcp/rtcp_defines.h" #include "media/cast/rtcp/rtcp_receiver.h" #include "media/cast/rtcp/rtcp_sender.h" @@ -17,7 +17,7 @@ namespace media { namespace cast { -static const int kMaxRttMs = 1000000; // 1000 seconds. +static const int kMaxRttMs = 10000; // 10 seconds. // Time limit for received RTCP messages when we stop using it for lip-sync. static const int64 kMaxDiffSinceReceivedRtcpMs = 100000; // 100 seconds. @@ -52,11 +52,16 @@ RtcpNackMessage::~RtcpNackMessage() {} RtcpRembMessage::RtcpRembMessage() {} RtcpRembMessage::~RtcpRembMessage() {} +RtcpReceiverFrameLogMessage::RtcpReceiverFrameLogMessage(uint32 timestamp) + : rtp_timestamp_(timestamp) {} + +RtcpReceiverFrameLogMessage::~RtcpReceiverFrameLogMessage() {} class LocalRtcpReceiverFeedback : public RtcpReceiverFeedback { public: - explicit LocalRtcpReceiverFeedback(Rtcp* rtcp) - : rtcp_(rtcp) { + LocalRtcpReceiverFeedback(Rtcp* rtcp, + scoped_refptr<CastEnvironment> cast_environment) + : rtcp_(rtcp), cast_environment_(cast_environment) { } virtual void OnReceivedSenderReport( @@ -80,48 +85,128 @@ class LocalRtcpReceiverFeedback : public RtcpReceiverFeedback { rtcp_->OnReceivedSendReportRequest(); } + virtual void OnReceivedReceiverLog( + const RtcpReceiverLogMessage& receiver_log) OVERRIDE { + // Add received log messages into our log system. + RtcpReceiverLogMessage::const_iterator it = receiver_log.begin(); + + for (; it != receiver_log.end(); ++it) { + uint32 rtp_timestamp = it->rtp_timestamp_; + + RtcpReceiverEventLogMessages::const_iterator event_it = + it->event_log_messages_.begin(); + for (; event_it != it->event_log_messages_.end(); ++event_it) { + // TODO(pwestin): we need to send in the event_it->event_timestamp to + // the log system too. + switch (event_it->type) { + case kPacketReceived: + cast_environment_->Logging()->InsertPacketEvent(kPacketReceived, + rtp_timestamp, kFrameIdUnknown, event_it->packet_id, 0, 0); + break; + case kAckSent: + case kAudioFrameDecoded: + case kVideoFrameDecoded: + cast_environment_->Logging()->InsertFrameEvent(event_it->type, + rtp_timestamp, kFrameIdUnknown); + break; + case kAudioPlayoutDelay: + case kVideoRenderDelay: + cast_environment_->Logging()->InsertFrameEventWithDelay( + event_it->type, rtp_timestamp, kFrameIdUnknown, + event_it->delay_delta); + break; + default: + VLOG(2) << "Received log message via RTCP that we did not expect: " + << static_cast<int>(event_it->type); + break; + } + } + } + } + + virtual void OnReceivedSenderLog( + const RtcpSenderLogMessage& sender_log) OVERRIDE { + RtcpSenderLogMessage::const_iterator it = sender_log.begin(); + + for (; it != sender_log.end(); ++it) { + uint32 rtp_timestamp = it->rtp_timestamp; + CastLoggingEvent log_event = kUnknown; + + // These events are provided to know the status of frames that never + // reached the receiver. The timing information for these events are not + // relevant and is not sent over the wire. + switch (it->frame_status) { + case kRtcpSenderFrameStatusDroppedByFlowControl: + // A frame that have been dropped by the flow control would have + // kVideoFrameCaptured as its last event in the log. + log_event = kVideoFrameCaptured; + break; + case kRtcpSenderFrameStatusDroppedByEncoder: + // A frame that have been dropped by the encoder would have + // kVideoFrameSentToEncoder as its last event in the log. + log_event = kVideoFrameSentToEncoder; + break; + case kRtcpSenderFrameStatusSentToNetwork: + // A frame that have be encoded is always sent to the network. We + // do not add a new log entry for this. + log_event = kVideoFrameEncoded; + break; + default: + continue; + } + // TODO(pwestin): how do we handle the truncated rtp_timestamp? + // Add received log messages into our log system. + cast_environment_->Logging()->InsertFrameEvent(log_event, rtp_timestamp, + kFrameIdUnknown); + } + } + private: Rtcp* rtcp_; + scoped_refptr<CastEnvironment> cast_environment_; }; -Rtcp::Rtcp(RtcpSenderFeedback* sender_feedback, +Rtcp::Rtcp(scoped_refptr<CastEnvironment> cast_environment, + RtcpSenderFeedback* sender_feedback, PacedPacketSender* paced_packet_sender, RtpSenderStatistics* rtp_sender_statistics, RtpReceiverStatistics* rtp_receiver_statistics, RtcpMode rtcp_mode, const base::TimeDelta& rtcp_interval, - bool sending_media, uint32 local_ssrc, + uint32 remote_ssrc, const std::string& c_name) : rtcp_interval_(rtcp_interval), rtcp_mode_(rtcp_mode), - sending_media_(sending_media), local_ssrc_(local_ssrc), + remote_ssrc_(remote_ssrc), rtp_sender_statistics_(rtp_sender_statistics), rtp_receiver_statistics_(rtp_receiver_statistics), - receiver_feedback_(new LocalRtcpReceiverFeedback(this)), + receiver_feedback_(new LocalRtcpReceiverFeedback(this, cast_environment)), rtt_feedback_(new LocalRtcpRttFeedback(this)), - rtcp_sender_(new RtcpSender(paced_packet_sender, local_ssrc, c_name)), - last_report_sent_(0), + rtcp_sender_(new RtcpSender(cast_environment, paced_packet_sender, + local_ssrc, c_name)), last_report_received_(0), last_received_rtp_timestamp_(0), last_received_ntp_seconds_(0), last_received_ntp_fraction_(0), min_rtt_(base::TimeDelta::FromMilliseconds(kMaxRttMs)), number_of_rtt_in_avg_(0), - clock_(&default_tick_clock_) { - rtcp_receiver_.reset(new RtcpReceiver(sender_feedback, + cast_environment_(cast_environment) { + rtcp_receiver_.reset(new RtcpReceiver(cast_environment, + sender_feedback, receiver_feedback_.get(), rtt_feedback_.get(), local_ssrc)); + rtcp_receiver_->SetRemoteSSRC(remote_ssrc); } Rtcp::~Rtcp() {} // static -bool Rtcp::IsRtcpPacket(const uint8* packet, int length) { - DCHECK_GE(length, 8) << "Invalid RTCP packet"; - if (length < 8) return false; +bool Rtcp::IsRtcpPacket(const uint8* packet, size_t length) { + DCHECK_GE(length, kMinLengthOfRtcp) << "Invalid RTCP packet"; + if (length < kMinLengthOfRtcp) return false; uint8 packet_type = packet[1]; if (packet_type >= kPacketTypeLow && packet_type <= kPacketTypeHigh) { @@ -131,7 +216,8 @@ bool Rtcp::IsRtcpPacket(const uint8* packet, int length) { } // static -uint32 Rtcp::GetSsrcOfSender(const uint8* rtcp_buffer, int length) { +uint32 Rtcp::GetSsrcOfSender(const uint8* rtcp_buffer, size_t length) { + DCHECK_GE(length, kMinLengthOfRtcp) << "Invalid RTCP packet"; uint32 ssrc_of_sender; net::BigEndianReader big_endian_reader(rtcp_buffer, length); big_endian_reader.Skip(4); // Skip header @@ -146,11 +232,7 @@ base::TimeTicks Rtcp::TimeToSendNextRtcpReport() { return next_time_to_send_rtcp_; } -void Rtcp::SetRemoteSSRC(uint32 ssrc) { - rtcp_receiver_->SetRemoteSSRC(ssrc); -} - -void Rtcp::IncomingRtcpPacket(const uint8* rtcp_buffer, int length) { +void Rtcp::IncomingRtcpPacket(const uint8* rtcp_buffer, size_t length) { RtcpParser rtcp_parser(rtcp_buffer, length); if (!rtcp_parser.IsValid()) { // Silently ignore packet. @@ -160,99 +242,38 @@ void Rtcp::IncomingRtcpPacket(const uint8* rtcp_buffer, int length) { rtcp_receiver_->IncomingRtcpPacket(&rtcp_parser); } -void Rtcp::SendRtcpCast(const RtcpCastMessage& cast_message) { - uint32 packet_type_flags = 0; - base::TimeTicks now = clock_->NowTicks(); - - if (rtcp_mode_ == kRtcpCompound || now >= next_time_to_send_rtcp_) { - if (sending_media_) { - packet_type_flags = RtcpSender::kRtcpSr; - } else { - packet_type_flags = RtcpSender::kRtcpRr; - } - } - packet_type_flags |= RtcpSender::kRtcpCast; - - SendRtcp(now, packet_type_flags, 0, &cast_message); -} - -void Rtcp::SendRtcpPli(uint32 pli_remote_ssrc) { +void Rtcp::SendRtcpFromRtpReceiver(const RtcpCastMessage* cast_message, + RtcpReceiverLogMessage* receiver_log) { uint32 packet_type_flags = 0; - base::TimeTicks now = clock_->NowTicks(); - if (rtcp_mode_ == kRtcpCompound || now >= next_time_to_send_rtcp_) { - if (sending_media_) { - packet_type_flags = RtcpSender::kRtcpSr; - } else { - packet_type_flags = RtcpSender::kRtcpRr; - } - } - packet_type_flags |= RtcpSender::kRtcpPli; - SendRtcp(now, packet_type_flags, pli_remote_ssrc, NULL); -} + base::TimeTicks now = cast_environment_->Clock()->NowTicks(); + RtcpReportBlock report_block; + RtcpReceiverReferenceTimeReport rrtr; -void Rtcp::SendRtcpReport(uint32 media_ssrc) { - uint32 packet_type_flags; - base::TimeTicks now = clock_->NowTicks(); - if (sending_media_) { - packet_type_flags = RtcpSender::kRtcpSr; - } else { - packet_type_flags = RtcpSender::kRtcpRr; + if (cast_message) { + packet_type_flags |= RtcpSender::kRtcpCast; + cast_environment_->Logging()->InsertGenericEvent(kAckSent, + cast_message->ack_frame_id_); } - SendRtcp(now, packet_type_flags, media_ssrc, NULL); -} - -void Rtcp::SendRtcp(const base::TimeTicks& now, - uint32 packet_type_flags, - uint32 media_ssrc, - const RtcpCastMessage* cast_message) { - if (packet_type_flags & RtcpSender::kRtcpSr || - packet_type_flags & RtcpSender::kRtcpRr) { - UpdateNextTimeToSendRtcp(); + if (receiver_log) { + packet_type_flags |= RtcpSender::kRtcpReceiverLog; } - if (packet_type_flags & RtcpSender::kRtcpSr) { - RtcpSenderInfo sender_info; - - if (rtp_sender_statistics_) { - rtp_sender_statistics_->GetStatistics(now, &sender_info); - } else { - memset(&sender_info, 0, sizeof(sender_info)); - } - time_last_report_sent_ = now; - last_report_sent_ = (sender_info.ntp_seconds << 16) + - (sender_info.ntp_fraction >> 16); - - RtcpDlrrReportBlock dlrr; - if (!time_last_report_received_.is_null()) { - packet_type_flags |= RtcpSender::kRtcpDlrr; - dlrr.last_rr = last_report_received_; - uint32 delay_seconds = 0; - uint32 delay_fraction = 0; - base::TimeDelta delta = now - time_last_report_received_; - ConvertTimeToFractions(delta.InMicroseconds(), - &delay_seconds, - &delay_fraction); + if (rtcp_mode_ == kRtcpCompound || now >= next_time_to_send_rtcp_) { + packet_type_flags |= RtcpSender::kRtcpRr; - dlrr.delay_since_last_rr = - ConvertToNtpDiff(delay_seconds, delay_fraction); - } - rtcp_sender_->SendRtcp(packet_type_flags, - &sender_info, - NULL, - media_ssrc, - &dlrr, - NULL, - NULL); - } else { - RtcpReportBlock report_block; report_block.remote_ssrc = 0; // Not needed to set send side. - report_block.media_ssrc = media_ssrc; // SSRC of the RTP packet sender. + report_block.media_ssrc = remote_ssrc_; // SSRC of the RTP packet sender. if (rtp_receiver_statistics_) { rtp_receiver_statistics_->GetStatistics( &report_block.fraction_lost, &report_block.cumulative_lost, &report_block.extended_high_sequence_number, &report_block.jitter); + cast_environment_->Logging()->InsertGenericEvent(kJitterMs, + report_block.jitter); + cast_environment_->Logging()->InsertGenericEvent(kPacketLoss, + report_block.fraction_lost); + } report_block.last_sr = last_report_received_; @@ -270,26 +291,59 @@ void Rtcp::SendRtcp(const base::TimeTicks& now, } packet_type_flags |= RtcpSender::kRtcpRrtr; - RtcpReceiverReferenceTimeReport rrtr; - ConvertTimeToNtp(now, &rrtr.ntp_seconds, &rrtr.ntp_fraction); - - time_last_report_sent_ = now; - last_report_sent_ = ConvertToNtpDiff(rrtr.ntp_seconds, rrtr.ntp_fraction); - - rtcp_sender_->SendRtcp(packet_type_flags, - NULL, - &report_block, - media_ssrc, - NULL, - &rrtr, - cast_message); + ConvertTimeTicksToNtp(now, &rrtr.ntp_seconds, &rrtr.ntp_fraction); + SaveLastSentNtpTime(now, rrtr.ntp_seconds, rrtr.ntp_fraction); + UpdateNextTimeToSendRtcp(); } + rtcp_sender_->SendRtcpFromRtpReceiver(packet_type_flags, + &report_block, + &rrtr, + cast_message, + receiver_log); +} + +void Rtcp::SendRtcpFromRtpSender( + RtcpSenderLogMessage* sender_log_message) { + uint32 packet_type_flags = RtcpSender::kRtcpSr; + base::TimeTicks now = cast_environment_->Clock()->NowTicks(); + + if (sender_log_message) { + packet_type_flags |= RtcpSender::kRtcpSenderLog; + } + + RtcpSenderInfo sender_info; + if (rtp_sender_statistics_) { + rtp_sender_statistics_->GetStatistics(now, &sender_info); + } else { + memset(&sender_info, 0, sizeof(sender_info)); + } + SaveLastSentNtpTime(now, sender_info.ntp_seconds, sender_info.ntp_fraction); + + RtcpDlrrReportBlock dlrr; + if (!time_last_report_received_.is_null()) { + packet_type_flags |= RtcpSender::kRtcpDlrr; + dlrr.last_rr = last_report_received_; + uint32 delay_seconds = 0; + uint32 delay_fraction = 0; + base::TimeDelta delta = now - time_last_report_received_; + ConvertTimeToFractions(delta.InMicroseconds(), + &delay_seconds, + &delay_fraction); + + dlrr.delay_since_last_rr = ConvertToNtpDiff(delay_seconds, delay_fraction); + } + + rtcp_sender_->SendRtcpFromRtpSender(packet_type_flags, + &sender_info, + &dlrr, + sender_log_message); + UpdateNextTimeToSendRtcp(); } void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) { last_report_received_ = (ntp_seconds << 16) + (ntp_fraction >> 16); - base::TimeTicks now = clock_->NowTicks(); + base::TimeTicks now = cast_environment_->Clock()->NowTicks(); time_last_report_received_ = now; } @@ -302,7 +356,7 @@ void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp, } void Rtcp::OnReceivedSendReportRequest() { - base::TimeTicks now = clock_->NowTicks(); + base::TimeTicks now = cast_environment_->Clock()->NowTicks(); // Trigger a new RTCP report at next timer. next_time_to_send_rtcp_ = now; @@ -333,22 +387,52 @@ bool Rtcp::RtpTimestampInSenderTime(int frequency, uint32 rtp_timestamp, // Sanity check. if (abs(rtp_time_diff_ms) > kMaxDiffSinceReceivedRtcpMs) return false; - *rtp_timestamp_in_ticks = - ConvertNtpToTime(last_received_ntp_seconds_, last_received_ntp_fraction_) + - base::TimeDelta::FromMilliseconds(rtp_time_diff_ms); + *rtp_timestamp_in_ticks = ConvertNtpToTimeTicks(last_received_ntp_seconds_, + last_received_ntp_fraction_) + + base::TimeDelta::FromMilliseconds(rtp_time_diff_ms); return true; } void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc, uint32 last_report, uint32 delay_since_last_report) { - if (last_report_sent_ != last_report) return; // Feedback on another report. - if (time_last_report_sent_.is_null()) return; + RtcpSendTimeMap::iterator it = last_reports_sent_map_.find(last_report); + if (it == last_reports_sent_map_.end()) { + return; // Feedback on another report. + } - base::TimeDelta sender_delay = clock_->NowTicks() - time_last_report_sent_; + base::TimeDelta sender_delay = cast_environment_->Clock()->NowTicks() + - it->second; UpdateRtt(sender_delay, ConvertFromNtpDiff(delay_since_last_report)); } +void Rtcp::SaveLastSentNtpTime(const base::TimeTicks& now, + uint32 last_ntp_seconds, + uint32 last_ntp_fraction) { + // Make sure |now| is always greater than the last element in + // |last_reports_sent_queue_|. + if (!last_reports_sent_queue_.empty()) { + DCHECK(now >= last_reports_sent_queue_.back().second); + } + + uint32 last_report = ConvertToNtpDiff(last_ntp_seconds, last_ntp_fraction); + last_reports_sent_map_[last_report] = now; + last_reports_sent_queue_.push(std::make_pair(last_report, now)); + + base::TimeTicks timeout = now - base::TimeDelta::FromMilliseconds(kMaxRttMs); + + // Cleanup old statistics older than |timeout|. + while (!last_reports_sent_queue_.empty()) { + RtcpSendTimePair oldest_report = last_reports_sent_queue_.front(); + if (oldest_report.second < timeout) { + last_reports_sent_map_.erase(oldest_report.first); + last_reports_sent_queue_.pop(); + } else { + break; + } + } +} + void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay, const base::TimeDelta& receiver_delay) { base::TimeDelta rtt = sender_delay - receiver_delay; @@ -365,7 +449,6 @@ void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay, avg_rtt_ms_ = rtt.InMilliseconds(); } number_of_rtt_in_avg_++; - TRACE_COUNTER_ID1("cast_rtcp", "RTT", local_ssrc_, rtt.InMilliseconds()); } bool Rtcp::Rtt(base::TimeDelta* rtt, @@ -377,7 +460,9 @@ bool Rtcp::Rtt(base::TimeDelta* rtt, DCHECK(min_rtt) << "Invalid argument"; DCHECK(max_rtt) << "Invalid argument"; - if (number_of_rtt_in_avg_ == 0) return false; + if (number_of_rtt_in_avg_ == 0) return false; + cast_environment_->Logging()->InsertGenericEvent(kRttMs, + rtt->InMilliseconds()); *rtt = rtt_; *avg_rtt = base::TimeDelta::FromMilliseconds(avg_rtt_ms_); @@ -408,7 +493,7 @@ void Rtcp::UpdateNextTimeToSendRtcp() { base::TimeDelta time_to_next = (rtcp_interval_ / 2) + (rtcp_interval_ * random / 1000); - base::TimeTicks now = clock_->NowTicks(); + base::TimeTicks now = cast_environment_->Clock()->NowTicks(); next_time_to_send_rtcp_ = now + time_to_next; } |