summaryrefslogtreecommitdiffstats
path: root/media/cast
diff options
context:
space:
mode:
Diffstat (limited to 'media/cast')
-rw-r--r--media/cast/audio_receiver/audio_receiver.cc4
-rw-r--r--media/cast/rtcp/receiver_rtcp_event_subscriber.cc8
-rw-r--r--media/cast/rtcp/receiver_rtcp_event_subscriber.h4
-rw-r--r--media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc13
-rw-r--r--media/cast/rtcp/rtcp.cc13
-rw-r--r--media/cast/rtcp/rtcp.h10
-rw-r--r--media/cast/rtcp/rtcp_sender.cc224
-rw-r--r--media/cast/rtcp/rtcp_sender.h41
-rw-r--r--media/cast/rtcp/rtcp_sender_unittest.cc99
-rw-r--r--media/cast/test/sender.cc41
-rw-r--r--media/cast/video_receiver/video_receiver.cc4
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