diff options
Diffstat (limited to 'media/cast')
-rw-r--r-- | media/cast/audio_receiver/audio_receiver.cc | 4 | ||||
-rw-r--r-- | media/cast/rtcp/receiver_rtcp_event_subscriber.cc | 8 | ||||
-rw-r--r-- | media/cast/rtcp/receiver_rtcp_event_subscriber.h | 4 | ||||
-rw-r--r-- | media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc | 13 | ||||
-rw-r--r-- | media/cast/rtcp/rtcp.cc | 13 | ||||
-rw-r--r-- | media/cast/rtcp/rtcp.h | 10 | ||||
-rw-r--r-- | media/cast/rtcp/rtcp_sender.cc | 224 | ||||
-rw-r--r-- | media/cast/rtcp/rtcp_sender.h | 41 | ||||
-rw-r--r-- | media/cast/rtcp/rtcp_sender_unittest.cc | 99 | ||||
-rw-r--r-- | media/cast/test/sender.cc | 41 | ||||
-rw-r--r-- | media/cast/video_receiver/video_receiver.cc | 4 |
11 files changed, 314 insertions, 147 deletions
diff --git a/media/cast/audio_receiver/audio_receiver.cc b/media/cast/audio_receiver/audio_receiver.cc index b214c52..b01a54f 100644 --- a/media/cast/audio_receiver/audio_receiver.cc +++ b/media/cast/audio_receiver/audio_receiver.cc @@ -271,7 +271,9 @@ void AudioReceiver::CastFeedback(const RtcpCastMessage& cast_message) { cast_environment_->Logging()->InsertFrameEvent( now, kAudioAckSent, rtp_timestamp, cast_message.ack_frame_id_); - rtcp_.SendRtcpFromRtpReceiver(&cast_message, &event_subscriber_); + ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; + event_subscriber_.GetRtcpEventsAndReset(&rtcp_events); + rtcp_.SendRtcpFromRtpReceiver(&cast_message, &rtcp_events); } base::TimeTicks AudioReceiver::GetPlayoutTime(base::TimeTicks now, diff --git a/media/cast/rtcp/receiver_rtcp_event_subscriber.cc b/media/cast/rtcp/receiver_rtcp_event_subscriber.cc index e23783c..d16aacd 100644 --- a/media/cast/rtcp/receiver_rtcp_event_subscriber.cc +++ b/media/cast/rtcp/receiver_rtcp_event_subscriber.cc @@ -79,6 +79,14 @@ void ReceiverRtcpEventSubscriber::OnReceiveGenericEvent( // Do nothing as RTP receiver is not interested in generic events for RTCP. } +void ReceiverRtcpEventSubscriber::GetRtcpEventsAndReset( + RtcpEventMultiMap* rtcp_events) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(rtcp_events); + rtcp_events->swap(rtcp_events_); + rtcp_events_.clear(); +} + void ReceiverRtcpEventSubscriber::TruncateMapIfNeeded() { // If map size has exceeded |max_size_to_retain_|, remove entry with // the smallest RTP timestamp. diff --git a/media/cast/rtcp/receiver_rtcp_event_subscriber.h b/media/cast/rtcp/receiver_rtcp_event_subscriber.h index 4a98735..665ffcf 100644 --- a/media/cast/rtcp/receiver_rtcp_event_subscriber.h +++ b/media/cast/rtcp/receiver_rtcp_event_subscriber.h @@ -55,7 +55,9 @@ class ReceiverRtcpEventSubscriber : public RawEventSubscriber { virtual void OnReceiveGenericEvent(const GenericEvent& generic_event) OVERRIDE; - const RtcpEventMultiMap& get_rtcp_events() const { return rtcp_events_; } + // Assigns events collected to |rtcp_events| and clears them from this + // object. + void GetRtcpEventsAndReset(RtcpEventMultiMap* rtcp_events); private: // If |rtcp_events_.size()| exceeds |max_size_to_retain_|, remove an oldest diff --git a/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc b/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc index 41411c3..5b86879 100644 --- a/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc +++ b/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc @@ -95,14 +95,18 @@ TEST_F(ReceiverRtcpEventSubscriberTest, LogVideoEvents) { Init(ReceiverRtcpEventSubscriber::kVideoEventSubscriber); InsertEvents(); - EXPECT_EQ(3u, event_subscriber_->get_rtcp_events().size()); + ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; + event_subscriber_->GetRtcpEventsAndReset(&rtcp_events); + EXPECT_EQ(3u, rtcp_events.size()); } TEST_F(ReceiverRtcpEventSubscriberTest, LogAudioEvents) { Init(ReceiverRtcpEventSubscriber::kAudioEventSubscriber); InsertEvents(); - EXPECT_EQ(3u, event_subscriber_->get_rtcp_events().size()); + ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; + event_subscriber_->GetRtcpEventsAndReset(&rtcp_events); + EXPECT_EQ(3u, rtcp_events.size()); } TEST_F(ReceiverRtcpEventSubscriberTest, DropEventsWhenSizeExceeded) { @@ -113,7 +117,10 @@ TEST_F(ReceiverRtcpEventSubscriberTest, DropEventsWhenSizeExceeded) { testing_clock_->NowTicks(), kVideoFrameDecoded, /*rtp_timestamp*/ i * 10, /*frame_id*/ i); } - EXPECT_EQ(10u, event_subscriber_->get_rtcp_events().size()); + + ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; + event_subscriber_->GetRtcpEventsAndReset(&rtcp_events); + EXPECT_EQ(10u, rtcp_events.size()); } } // namespace cast diff --git a/media/cast/rtcp/rtcp.cc b/media/cast/rtcp/rtcp.cc index c5fbbad..a8842f1 100644 --- a/media/cast/rtcp/rtcp.cc +++ b/media/cast/rtcp/rtcp.cc @@ -230,7 +230,7 @@ void Rtcp::IncomingRtcpPacket(const uint8* rtcp_buffer, size_t length) { void Rtcp::SendRtcpFromRtpReceiver( const RtcpCastMessage* cast_message, - const ReceiverRtcpEventSubscriber* event_subscriber) { + const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events) { DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); uint32 packet_type_flags = 0; @@ -247,7 +247,7 @@ void Rtcp::SendRtcpFromRtpReceiver( if (cast_message) { packet_type_flags |= transport::kRtcpCast; } - if (event_subscriber) { + if (rtcp_events) { packet_type_flags |= transport::kRtcpReceiverLog; } if (rtcp_mode_ == kRtcpCompound || now >= next_time_to_send_rtcp_) { @@ -279,9 +279,12 @@ void Rtcp::SendRtcpFromRtpReceiver( } UpdateNextTimeToSendRtcp(); } - rtcp_sender_->SendRtcpFromRtpReceiver( - packet_type_flags, &report_block, &rrtr, cast_message, event_subscriber, - target_delay_ms_); + rtcp_sender_->SendRtcpFromRtpReceiver(packet_type_flags, + &report_block, + &rrtr, + cast_message, + rtcp_events, + target_delay_ms_); } void Rtcp::SendRtcpFromRtpSender( diff --git a/media/cast/rtcp/rtcp.h b/media/cast/rtcp/rtcp.h index 30a155d..15bbe11 100644 --- a/media/cast/rtcp/rtcp.h +++ b/media/cast/rtcp/rtcp.h @@ -18,6 +18,7 @@ #include "media/cast/cast_config.h" #include "media/cast/cast_defines.h" #include "media/cast/cast_environment.h" +#include "media/cast/rtcp/receiver_rtcp_event_subscriber.h" #include "media/cast/rtcp/rtcp_defines.h" #include "media/cast/transport/cast_transport_defines.h" #include "media/cast/transport/cast_transport_sender.h" @@ -29,7 +30,6 @@ namespace cast { class LocalRtcpReceiverFeedback; class LocalRtcpRttFeedback; class PacedPacketSender; -class ReceiverRtcpEventSubscriber; class RtcpReceiver; class RtcpSender; @@ -87,13 +87,13 @@ class Rtcp { const transport::RtcpSenderLogMessage& sender_log_message, transport::RtcpSenderInfo sender_info); - // |cast_message| and |event_subscriber| is optional; if |cast_message| is + // |cast_message| and |rtcp_events| is optional; if |cast_message| is // provided the RTCP receiver report will append a Cast message containing - // Acks and Nacks; if |event_subscriber| is provided the RTCP receiver report - // will append the log messages from the subscriber. + // Acks and Nacks; if |rtcp_events| is provided the RTCP receiver report + // will append the log messages. void SendRtcpFromRtpReceiver( const RtcpCastMessage* cast_message, - const ReceiverRtcpEventSubscriber* event_subscriber); + const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events); void IncomingRtcpPacket(const uint8* rtcp_buffer, size_t length); bool Rtt(base::TimeDelta* rtt, diff --git a/media/cast/rtcp/rtcp_sender.cc b/media/cast/rtcp/rtcp_sender.cc index 1175945..d723f72 100644 --- a/media/cast/rtcp/rtcp_sender.cc +++ b/media/cast/rtcp/rtcp_sender.cc @@ -77,88 +77,31 @@ bool EventTimestampLessThan(const RtcpReceiverEventLogMessage& lhs, return lhs.event_timestamp < rhs.event_timestamp; } -bool BuildRtcpReceiverLogMessage( - const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, - size_t start_size, +void AddReceiverLog( + const RtcpReceiverLogMessage& redundancy_receiver_log_message, RtcpReceiverLogMessage* receiver_log_message, + size_t* remaining_space, size_t* number_of_frames, - size_t* total_number_of_messages_to_send, - size_t* rtcp_log_size) { - size_t remaining_space = - std::min(kMaxReceiverLogBytes, kMaxIpPacketSize - start_size); - if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize + - kRtcpReceiverEventLogSize) { - return false; - } - - // We use this to do event timestamp sorting and truncating for events of - // a single frame. - std::vector<RtcpReceiverEventLogMessage> sorted_log_messages; - - // Account for the RTCP header for an application-defined packet. - remaining_space -= kRtcpCastLogHeaderSize; - - ReceiverRtcpEventSubscriber::RtcpEventMultiMap::const_reverse_iterator rit = - rtcp_events.rbegin(); - - while (rit != rtcp_events.rend() && - remaining_space >= + size_t* total_number_of_messages_to_send) { + RtcpReceiverLogMessage::const_iterator it = + redundancy_receiver_log_message.begin(); + while (it != redundancy_receiver_log_message.end() && + *remaining_space >= kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) { - const RtpTimestamp rtp_timestamp = rit->first; - RtcpReceiverFrameLogMessage frame_log(rtp_timestamp); - remaining_space -= kRtcpReceiverFrameLogSize; + receiver_log_message->push_front(*it); + size_t num_event_logs = (*remaining_space - kRtcpReceiverFrameLogSize) / + kRtcpReceiverEventLogSize; + RtcpReceiverEventLogMessages& event_log_messages = + receiver_log_message->front().event_log_messages_; + if (num_event_logs < event_log_messages.size()) + event_log_messages.resize(num_event_logs); + + *remaining_space -= kRtcpReceiverFrameLogSize + + event_log_messages.size() * kRtcpReceiverEventLogSize; ++*number_of_frames; - - // Get all events of a single frame. - sorted_log_messages.clear(); - do { - RtcpReceiverEventLogMessage event_log_message; - event_log_message.type = rit->second.type; - event_log_message.event_timestamp = rit->second.timestamp; - event_log_message.delay_delta = rit->second.delay_delta; - event_log_message.packet_id = rit->second.packet_id; - sorted_log_messages.push_back(event_log_message); - ++rit; - } while (rit != rtcp_events.rend() && rit->first == rtp_timestamp); - - std::sort(sorted_log_messages.begin(), - sorted_log_messages.end(), - &EventTimestampLessThan); - - // From |sorted_log_messages|, only take events that are no greater than - // |kMaxWireFormatTimeDeltaMs| seconds away from the latest event. Events - // older than that cannot be encoded over the wire. - std::vector<RtcpReceiverEventLogMessage>::reverse_iterator sorted_rit = - sorted_log_messages.rbegin(); - base::TimeTicks first_event_timestamp = sorted_rit->event_timestamp; - size_t events_in_frame = 0; - while (sorted_rit != sorted_log_messages.rend() && - events_in_frame < kRtcpMaxReceiverLogMessages && - remaining_space >= kRtcpReceiverEventLogSize) { - base::TimeDelta delta(first_event_timestamp - - sorted_rit->event_timestamp); - if (delta.InMilliseconds() > kMaxWireFormatTimeDeltaMs) - break; - frame_log.event_log_messages_.push_front(*sorted_rit); - ++events_in_frame; - ++*total_number_of_messages_to_send; - remaining_space -= kRtcpReceiverEventLogSize; - ++sorted_rit; - } - - receiver_log_message->push_front(frame_log); + *total_number_of_messages_to_send += event_log_messages.size(); + ++it; } - - *rtcp_log_size = - kRtcpCastLogHeaderSize + *number_of_frames * kRtcpReceiverFrameLogSize + - *total_number_of_messages_to_send * kRtcpReceiverEventLogSize; - DCHECK_GE(kMaxIpPacketSize, start_size + *rtcp_log_size) - << "Not enough buffer space."; - - VLOG(3) << "number of frames: " << *number_of_frames; - VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send; - VLOG(3) << "rtcp log size: " << *rtcp_log_size; - return *number_of_frames > 0; } // A class to build a string representing the NACK list in Cast message. @@ -247,17 +190,12 @@ RtcpSender::RtcpSender(scoped_refptr<CastEnvironment> cast_environment, RtcpSender::~RtcpSender() {} -// static -bool RtcpSender::IsReceiverEvent(const CastLoggingEvent& event) { - return ConvertEventTypeToWireFormat(event) != 0; -} - void RtcpSender::SendRtcpFromRtpReceiver( uint32 packet_type_flags, const transport::RtcpReportBlock* report_block, const RtcpReceiverReferenceTimeReport* rrtr, const RtcpCastMessage* cast_message, - const ReceiverRtcpEventSubscriber* event_subscriber, + const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events, uint16 target_delay_ms) { if (packet_type_flags & transport::kRtcpSr || packet_type_flags & transport::kRtcpDlrr || @@ -292,8 +230,8 @@ void RtcpSender::SendRtcpFromRtpReceiver( BuildCast(cast_message, target_delay_ms, &packet); } if (packet_type_flags & transport::kRtcpReceiverLog) { - DCHECK(event_subscriber) << "Invalid argument"; - BuildReceiverLog(event_subscriber->get_rtcp_events(), &packet); + DCHECK(rtcp_events) << "Invalid argument"; + BuildReceiverLog(*rtcp_events, &packet); } if (packet.empty()) @@ -716,7 +654,7 @@ void RtcpSender::BuildCast(const RtcpCastMessage* cast, void RtcpSender::BuildReceiverLog( const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, - Packet* packet) const { + Packet* packet) { const size_t packet_start_size = packet->size(); size_t number_of_frames = 0; size_t total_number_of_messages_to_send = 0; @@ -808,5 +746,119 @@ void RtcpSender::BuildReceiverLog( DCHECK_EQ(total_number_of_messages_to_send, 0u); } +bool RtcpSender::BuildRtcpReceiverLogMessage( + const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, + size_t start_size, + RtcpReceiverLogMessage* receiver_log_message, + size_t* number_of_frames, + size_t* total_number_of_messages_to_send, + size_t* rtcp_log_size) { + size_t remaining_space = + std::min(kMaxReceiverLogBytes, kMaxIpPacketSize - start_size); + if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize + + kRtcpReceiverEventLogSize) { + return false; + } + + // We use this to do event timestamp sorting and truncating for events of + // a single frame. + std::vector<RtcpReceiverEventLogMessage> sorted_log_messages; + + // Account for the RTCP header for an application-defined packet. + remaining_space -= kRtcpCastLogHeaderSize; + + ReceiverRtcpEventSubscriber::RtcpEventMultiMap::const_reverse_iterator rit = + rtcp_events.rbegin(); + + while (rit != rtcp_events.rend() && + remaining_space >= + kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) { + const RtpTimestamp rtp_timestamp = rit->first; + RtcpReceiverFrameLogMessage frame_log(rtp_timestamp); + remaining_space -= kRtcpReceiverFrameLogSize; + ++*number_of_frames; + + // Get all events of a single frame. + sorted_log_messages.clear(); + do { + RtcpReceiverEventLogMessage event_log_message; + event_log_message.type = rit->second.type; + event_log_message.event_timestamp = rit->second.timestamp; + event_log_message.delay_delta = rit->second.delay_delta; + event_log_message.packet_id = rit->second.packet_id; + sorted_log_messages.push_back(event_log_message); + ++rit; + } while (rit != rtcp_events.rend() && rit->first == rtp_timestamp); + + std::sort(sorted_log_messages.begin(), + sorted_log_messages.end(), + &EventTimestampLessThan); + + // From |sorted_log_messages|, only take events that are no greater than + // |kMaxWireFormatTimeDeltaMs| seconds away from the latest event. Events + // older than that cannot be encoded over the wire. + std::vector<RtcpReceiverEventLogMessage>::reverse_iterator sorted_rit = + sorted_log_messages.rbegin(); + base::TimeTicks first_event_timestamp = sorted_rit->event_timestamp; + size_t events_in_frame = 0; + while (sorted_rit != sorted_log_messages.rend() && + events_in_frame < kRtcpMaxReceiverLogMessages && + remaining_space >= kRtcpReceiverEventLogSize) { + base::TimeDelta delta(first_event_timestamp - + sorted_rit->event_timestamp); + if (delta.InMilliseconds() > kMaxWireFormatTimeDeltaMs) + break; + frame_log.event_log_messages_.push_front(*sorted_rit); + ++events_in_frame; + ++*total_number_of_messages_to_send; + remaining_space -= kRtcpReceiverEventLogSize; + ++sorted_rit; + } + + receiver_log_message->push_front(frame_log); + } + + rtcp_events_history_.push_front(*receiver_log_message); + + // We don't try to match RTP timestamps of redundancy frame logs with those + // from the newest set (which would save the space of an extra RTP timestamp + // over the wire). Unless the redundancy frame logs are very recent, it's + // unlikely there will be a match anyway. + if (rtcp_events_history_.size() > kFirstRedundancyOffset) { + // Add first redundnacy messages, if enough space remaining + AddReceiverLog(rtcp_events_history_[kFirstRedundancyOffset], + receiver_log_message, + &remaining_space, + number_of_frames, + total_number_of_messages_to_send); + } + + if (rtcp_events_history_.size() > kSecondRedundancyOffset) { + // Add second redundancy messages, if enough space remaining + AddReceiverLog(rtcp_events_history_[kSecondRedundancyOffset], + receiver_log_message, + &remaining_space, + number_of_frames, + total_number_of_messages_to_send); + } + + if (rtcp_events_history_.size() > kReceiveLogMessageHistorySize) { + rtcp_events_history_.pop_back(); + } + + DCHECK_LE(rtcp_events_history_.size(), kReceiveLogMessageHistorySize); + + *rtcp_log_size = + kRtcpCastLogHeaderSize + *number_of_frames * kRtcpReceiverFrameLogSize + + *total_number_of_messages_to_send * kRtcpReceiverEventLogSize; + DCHECK_GE(kMaxIpPacketSize, start_size + *rtcp_log_size) + << "Not enough buffer space."; + + VLOG(3) << "number of frames: " << *number_of_frames; + VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send; + VLOG(3) << "rtcp log size: " << *rtcp_log_size; + return *number_of_frames > 0; +} + } // namespace cast } // namespace media diff --git a/media/cast/rtcp/rtcp_sender.h b/media/cast/rtcp/rtcp_sender.h index dbc93a8..f09a4fb 100644 --- a/media/cast/rtcp/rtcp_sender.h +++ b/media/cast/rtcp/rtcp_sender.h @@ -5,6 +5,7 @@ #ifndef MEDIA_CAST_RTCP_RTCP_SENDER_H_ #define MEDIA_CAST_RTCP_RTCP_SENDER_H_ +#include <deque> #include <list> #include <string> @@ -19,13 +20,25 @@ namespace media { namespace cast { -// We limit the size of receiver logs to avoid queuing up packets. We also -// do not need the amount of redundancy that results from filling up every -// RTCP packet with log messages. This number should give a redundancy of -// about 2-3 per log message. +// We limit the size of receiver logs to avoid queuing up packets. const size_t kMaxReceiverLogBytes = 200; -class ReceiverRtcpEventSubscriber; +// The determines how long to hold receiver log events, based on how +// many "receiver log message reports" ago the events were sent. +const size_t kReceiveLogMessageHistorySize = 20; + +// This determines when to send events the second time. +const size_t kFirstRedundancyOffset = 10; +COMPILE_ASSERT(kFirstRedundancyOffset > 0 && + kFirstRedundancyOffset <= kReceiveLogMessageHistorySize, + redundancy_offset_out_of_range); + +// When to send events the third time. +const size_t kSecondRedundancyOffset = 20; +COMPILE_ASSERT(kSecondRedundancyOffset > + kFirstRedundancyOffset && kSecondRedundancyOffset <= + kReceiveLogMessageHistorySize, + redundancy_offset_out_of_range); // TODO(mikhal): Resolve duplication between this and RtcpBuilder. class RtcpSender { @@ -37,16 +50,12 @@ class RtcpSender { virtual ~RtcpSender(); - // Returns true if |event| is an interesting receiver event. - // Such an event should be sent via RTCP. - static bool IsReceiverEvent(const media::cast::CastLoggingEvent& event); - void SendRtcpFromRtpReceiver( uint32 packet_type_flags, const transport::RtcpReportBlock* report_block, const RtcpReceiverReferenceTimeReport* rrtr, const RtcpCastMessage* cast_message, - const ReceiverRtcpEventSubscriber* event_subscriber, + const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events, uint16 target_delay_ms); private: @@ -77,7 +86,15 @@ class RtcpSender { void BuildReceiverLog( const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, - Packet* packet) const; + Packet* packet); + + bool BuildRtcpReceiverLogMessage( + const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, + size_t start_size, + RtcpReceiverLogMessage* receiver_log_message, + size_t* number_of_frames, + size_t* total_number_of_messages_to_send, + size_t* rtcp_log_size); inline void BitrateToRembExponentBitrate(uint32 bitrate, uint8* exponent, @@ -100,6 +117,8 @@ class RtcpSender { transport::PacedPacketSender* const transport_; scoped_refptr<CastEnvironment> cast_environment_; + std::deque<RtcpReceiverLogMessage> rtcp_events_history_; + DISALLOW_COPY_AND_ASSIGN(RtcpSender); }; diff --git a/media/cast/rtcp/rtcp_sender_unittest.cc b/media/cast/rtcp/rtcp_sender_unittest.cc index 8e6ceb2..cd8ca72 100644 --- a/media/cast/rtcp/rtcp_sender_unittest.cc +++ b/media/cast/rtcp/rtcp_sender_unittest.cc @@ -251,6 +251,7 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtrCastMessageAndLog) { ReceiverRtcpEventSubscriber event_subscriber( 500, ReceiverRtcpEventSubscriber::kVideoEventSubscriber); + ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; rtcp_sender_->SendRtcpFromRtpReceiver( transport::kRtcpRr | transport::kRtcpRrtr | transport::kRtcpCast | @@ -258,7 +259,7 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtrCastMessageAndLog) { &report_block, &rrtr, &cast_message, - &event_subscriber, + &rtcp_events, kDefaultDelay); base::SimpleTestTickClock testing_clock; @@ -284,7 +285,8 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtrCastMessageAndLog) { packet_event.timestamp = testing_clock.NowTicks(); packet_event.packet_id = kLostPacketId1; event_subscriber.OnReceivePacketEvent(packet_event); - EXPECT_EQ(2u, event_subscriber.get_rtcp_events().size()); + event_subscriber.GetRtcpEventsAndReset(&rtcp_events); + EXPECT_EQ(2u, rtcp_events.size()); rtcp_sender_->SendRtcpFromRtpReceiver( transport::kRtcpRr | transport::kRtcpRrtr | transport::kRtcpCast | @@ -292,22 +294,10 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtrCastMessageAndLog) { &report_block, &rrtr, &cast_message, - &event_subscriber, + &rtcp_events, kDefaultDelay); EXPECT_EQ(2, test_transport_.packet_count()); - - // We expect to see the same packet because we send redundant events. - rtcp_sender_->SendRtcpFromRtpReceiver( - transport::kRtcpRr | transport::kRtcpRrtr | transport::kRtcpCast | - transport::kRtcpReceiverLog, - &report_block, - &rrtr, - &cast_message, - &event_subscriber, - kDefaultDelay); - - EXPECT_EQ(3, test_transport_.packet_count()); } TEST_F(RtcpSenderTest, RtcpReceiverReportWithOversizedFrameLog) { @@ -362,12 +352,15 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithOversizedFrameLog) { testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeDelayMs)); } + ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; + event_subscriber.GetRtcpEventsAndReset(&rtcp_events); + rtcp_sender_->SendRtcpFromRtpReceiver( transport::kRtcpRr | transport::kRtcpReceiverLog, &report_block, NULL, NULL, - &event_subscriber, + &rtcp_events, kDefaultDelay); EXPECT_EQ(1, test_transport_.packet_count()); @@ -416,12 +409,15 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithTooManyLogFrames) { testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeDelayMs)); } + ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; + event_subscriber.GetRtcpEventsAndReset(&rtcp_events); + rtcp_sender_->SendRtcpFromRtpReceiver( transport::kRtcpRr | transport::kRtcpReceiverLog, &report_block, NULL, NULL, - &event_subscriber, + &rtcp_events, kDefaultDelay); EXPECT_EQ(1, test_transport_.packet_count()); @@ -464,16 +460,83 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithOldLogFrames) { base::TimeDelta::FromMilliseconds(kTimeBetweenEventsMs)); } + ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; + event_subscriber.GetRtcpEventsAndReset(&rtcp_events); + rtcp_sender_->SendRtcpFromRtpReceiver( transport::kRtcpRr | transport::kRtcpReceiverLog, &report_block, NULL, NULL, - &event_subscriber, + &rtcp_events, kDefaultDelay); EXPECT_EQ(1, test_transport_.packet_count()); } +TEST_F(RtcpSenderTest, RtcpReceiverReportRedundancy) { + uint32 time_base_ms = 12345678; + int kTimeBetweenEventsMs = 10; + + transport::RtcpReportBlock report_block = GetReportBlock(); + + base::SimpleTestTickClock testing_clock; + testing_clock.Advance(base::TimeDelta::FromMilliseconds(time_base_ms)); + + ReceiverRtcpEventSubscriber event_subscriber( + 500, ReceiverRtcpEventSubscriber::kVideoEventSubscriber); + size_t packet_count = kReceiveLogMessageHistorySize + 10; + for (size_t i = 0; i < packet_count; i++) { + TestRtcpPacketBuilder p; + p.AddRr(kSendingSsrc, 1); + p.AddRb(kMediaSsrc); + p.AddSdesCname(kSendingSsrc, kCName); + + p.AddReceiverLog(kSendingSsrc); + + if (i >= kSecondRedundancyOffset) { + p.AddReceiverFrameLog( + kRtpTimestamp, + 1, + time_base_ms - kSecondRedundancyOffset * kTimeBetweenEventsMs); + p.AddReceiverEventLog(0, 5, 0); + } + if (i >= kFirstRedundancyOffset) { + p.AddReceiverFrameLog( + kRtpTimestamp, + 1, + time_base_ms - kFirstRedundancyOffset * kTimeBetweenEventsMs); + p.AddReceiverEventLog(0, 5, 0); + } + p.AddReceiverFrameLog(kRtpTimestamp, 1, time_base_ms); + p.AddReceiverEventLog(0, 5, 0); + + test_transport_.SetExpectedRtcpPacket(p.GetPacket().Pass()); + + FrameEvent frame_event; + frame_event.rtp_timestamp = kRtpTimestamp; + frame_event.type = media::cast::kVideoAckSent; + frame_event.timestamp = testing_clock.NowTicks(); + event_subscriber.OnReceiveFrameEvent(frame_event); + + ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; + event_subscriber.GetRtcpEventsAndReset(&rtcp_events); + + rtcp_sender_->SendRtcpFromRtpReceiver( + transport::kRtcpRr | transport::kRtcpReceiverLog, + &report_block, + NULL, + NULL, + &rtcp_events, + kDefaultDelay); + + testing_clock.Advance( + base::TimeDelta::FromMilliseconds(kTimeBetweenEventsMs)); + time_base_ms += kTimeBetweenEventsMs; + } + + EXPECT_EQ(static_cast<int>(packet_count), test_transport_.packet_count()); +} + } // namespace cast } // namespace media diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc index 8c2681b..1accf4b 100644 --- a/media/cast/test/sender.cc +++ b/media/cast/test/sender.cc @@ -371,17 +371,11 @@ net::IPEndPoint CreateUDPAddress(std::string ip_str, int port) { return net::IPEndPoint(ip_number, port); } -void DumpLoggingData( - scoped_ptr<media::cast::EncodingEventSubscriber> event_subscriber, - base::ScopedFILE log_file, - bool compress) { - media::cast::FrameEventMap frame_events; - media::cast::PacketEventMap packet_events; - media::cast::proto::LogMetadata log_metadata; - - event_subscriber->GetEventsAndReset( - &log_metadata, &frame_events, &packet_events); - +void DumpLoggingData(const media::cast::proto::LogMetadata& log_metadata, + const media::cast::FrameEventMap& frame_events, + const media::cast::PacketEventMap& packet_events, + bool compress, + base::ScopedFILE log_file) { VLOG(0) << "Frame map size: " << frame_events.size(); VLOG(0) << "Packet map size: " << packet_events.size(); @@ -412,19 +406,33 @@ void WriteLogsToFileAndStopSubscribing( base::ScopedFILE video_log_file, base::ScopedFILE audio_log_file, bool compress) { - // Serialize video events. cast_environment->Logging()->RemoveRawEventSubscriber( video_event_subscriber.get()); cast_environment->Logging()->RemoveRawEventSubscriber( audio_event_subscriber.get()); VLOG(0) << "Dumping logging data for video stream."; - DumpLoggingData( - video_event_subscriber.Pass(), video_log_file.Pass(), compress); + media::cast::proto::LogMetadata log_metadata; + media::cast::FrameEventMap frame_events; + media::cast::PacketEventMap packet_events; + video_event_subscriber->GetEventsAndReset( + &log_metadata, &frame_events, &packet_events); + + DumpLoggingData(log_metadata, + frame_events, + packet_events, + compress, + video_log_file.Pass()); VLOG(0) << "Dumping logging data for audio stream."; - DumpLoggingData( - audio_event_subscriber.Pass(), audio_log_file.Pass(), compress); + audio_event_subscriber->GetEventsAndReset( + &log_metadata, &frame_events, &packet_events); + + DumpLoggingData(log_metadata, + frame_events, + packet_events, + compress, + audio_log_file.Pass()); } } // namespace @@ -460,6 +468,7 @@ int main(int argc, char** argv) { net::IPEndPoint remote_endpoint = CreateUDPAddress(remote_ip_address, remote_port); transport_audio_config.base.ssrc = audio_config.sender_ssrc; + VLOG(0) << "Audio ssrc: " << transport_audio_config.base.ssrc; transport_audio_config.base.rtp_config = audio_config.rtp_config; transport_video_config.base.ssrc = video_config.sender_ssrc; transport_video_config.base.rtp_config = video_config.rtp_config; diff --git a/media/cast/video_receiver/video_receiver.cc b/media/cast/video_receiver/video_receiver.cc index 95b1d51..bb07b79 100644 --- a/media/cast/video_receiver/video_receiver.cc +++ b/media/cast/video_receiver/video_receiver.cc @@ -447,7 +447,9 @@ void VideoReceiver::CastFeedback(const RtcpCastMessage& cast_message) { cast_environment_->Logging()->InsertFrameEvent( now, kVideoAckSent, rtp_timestamp, cast_message.ack_frame_id_); - rtcp_->SendRtcpFromRtpReceiver(&cast_message, &event_subscriber_); + ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; + event_subscriber_.GetRtcpEventsAndReset(&rtcp_events); + rtcp_->SendRtcpFromRtpReceiver(&cast_message, &rtcp_events); } // Cast messages should be sent within a maximum interval. Schedule a call |