summaryrefslogtreecommitdiffstats
path: root/chromium/media/cast/rtcp
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/media/cast/rtcp
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/media/cast/rtcp')
-rw-r--r--chromium/media/cast/rtcp/mock_rtcp_receiver_feedback.cc12
-rw-r--r--chromium/media/cast/rtcp/mock_rtcp_receiver_feedback.h6
-rw-r--r--chromium/media/cast/rtcp/mock_rtcp_sender_feedback.cc6
-rw-r--r--chromium/media/cast/rtcp/receiver_rtcp_event_subscriber.cc96
-rw-r--r--chromium/media/cast/rtcp/receiver_rtcp_event_subscriber.h79
-rw-r--r--chromium/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc131
-rw-r--r--chromium/media/cast/rtcp/rtcp.cc433
-rw-r--r--chromium/media/cast/rtcp/rtcp.gyp46
-rw-r--r--chromium/media/cast/rtcp/rtcp.h132
-rw-r--r--chromium/media/cast/rtcp/rtcp_defines.cc49
-rw-r--r--chromium/media/cast/rtcp/rtcp_defines.h118
-rw-r--r--chromium/media/cast/rtcp/rtcp_receiver.cc197
-rw-r--r--chromium/media/cast/rtcp/rtcp_receiver.h26
-rw-r--r--chromium/media/cast/rtcp/rtcp_receiver_unittest.cc256
-rw-r--r--chromium/media/cast/rtcp/rtcp_sender.cc798
-rw-r--r--chromium/media/cast/rtcp/rtcp_sender.h115
-rw-r--r--chromium/media/cast/rtcp/rtcp_sender_unittest.cc616
-rw-r--r--chromium/media/cast/rtcp/rtcp_unittest.cc509
-rw-r--r--chromium/media/cast/rtcp/rtcp_utility.cc289
-rw-r--r--chromium/media/cast/rtcp/rtcp_utility.h101
-rw-r--r--chromium/media/cast/rtcp/test_rtcp_packet_builder.cc62
-rw-r--r--chromium/media/cast/rtcp/test_rtcp_packet_builder.h30
22 files changed, 2172 insertions, 1935 deletions
diff --git a/chromium/media/cast/rtcp/mock_rtcp_receiver_feedback.cc b/chromium/media/cast/rtcp/mock_rtcp_receiver_feedback.cc
index daaa1ad0883..9ff2d48f03c 100644
--- a/chromium/media/cast/rtcp/mock_rtcp_receiver_feedback.cc
+++ b/chromium/media/cast/rtcp/mock_rtcp_receiver_feedback.cc
@@ -7,17 +7,13 @@
namespace media {
namespace cast {
-MockRtcpReceiverFeedback::MockRtcpReceiverFeedback() {
-}
+MockRtcpReceiverFeedback::MockRtcpReceiverFeedback() {}
-MockRtcpReceiverFeedback::~MockRtcpReceiverFeedback() {
-}
+MockRtcpReceiverFeedback::~MockRtcpReceiverFeedback() {}
-MockRtcpRttFeedback::MockRtcpRttFeedback() {
-}
+MockRtcpRttFeedback::MockRtcpRttFeedback() {}
-MockRtcpRttFeedback::~MockRtcpRttFeedback() {
-}
+MockRtcpRttFeedback::~MockRtcpRttFeedback() {}
} // namespace cast
} // namespace media
diff --git a/chromium/media/cast/rtcp/mock_rtcp_receiver_feedback.h b/chromium/media/cast/rtcp/mock_rtcp_receiver_feedback.h
index 0316d9819f2..56fe1ca6995 100644
--- a/chromium/media/cast/rtcp/mock_rtcp_receiver_feedback.h
+++ b/chromium/media/cast/rtcp/mock_rtcp_receiver_feedback.h
@@ -7,7 +7,9 @@
#include <vector>
+#include "media/cast/rtcp/rtcp_defines.h"
#include "media/cast/rtcp/rtcp_receiver.h"
+#include "media/cast/transport/cast_transport_defines.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace media {
@@ -19,7 +21,7 @@ class MockRtcpReceiverFeedback : public RtcpReceiverFeedback {
virtual ~MockRtcpReceiverFeedback();
MOCK_METHOD1(OnReceivedSenderReport,
- void(const RtcpSenderInfo& remote_sender_info));
+ void(const transport::RtcpSenderInfo& remote_sender_info));
MOCK_METHOD1(OnReceiverReferenceTimeReport,
void(const RtcpReceiverReferenceTimeReport& remote_time_report));
@@ -28,8 +30,6 @@ class MockRtcpReceiverFeedback : public RtcpReceiverFeedback {
MOCK_METHOD1(OnReceivedReceiverLog,
void(const RtcpReceiverLogMessage& receiver_log));
- MOCK_METHOD1(OnReceivedSenderLog,
- void(const RtcpSenderLogMessage& sender_log));
};
class MockRtcpRttFeedback : public RtcpRttFeedback {
diff --git a/chromium/media/cast/rtcp/mock_rtcp_sender_feedback.cc b/chromium/media/cast/rtcp/mock_rtcp_sender_feedback.cc
index 65c630148c2..e44e0bfdef4 100644
--- a/chromium/media/cast/rtcp/mock_rtcp_sender_feedback.cc
+++ b/chromium/media/cast/rtcp/mock_rtcp_sender_feedback.cc
@@ -7,11 +7,9 @@
namespace media {
namespace cast {
-MockRtcpSenderFeedback::MockRtcpSenderFeedback() {
-}
+MockRtcpSenderFeedback::MockRtcpSenderFeedback() {}
-MockRtcpSenderFeedback::~MockRtcpSenderFeedback() {
-}
+MockRtcpSenderFeedback::~MockRtcpSenderFeedback() {}
} // namespace cast
} // namespace media
diff --git a/chromium/media/cast/rtcp/receiver_rtcp_event_subscriber.cc b/chromium/media/cast/rtcp/receiver_rtcp_event_subscriber.cc
new file mode 100644
index 00000000000..9a9c0aeeb74
--- /dev/null
+++ b/chromium/media/cast/rtcp/receiver_rtcp_event_subscriber.cc
@@ -0,0 +1,96 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/cast/rtcp/receiver_rtcp_event_subscriber.h"
+
+#include <utility>
+
+namespace media {
+namespace cast {
+
+ReceiverRtcpEventSubscriber::ReceiverRtcpEventSubscriber(
+ const size_t max_size_to_retain, EventMediaType type)
+ : max_size_to_retain_(max_size_to_retain), type_(type) {
+ DCHECK(max_size_to_retain_ > 0u);
+ DCHECK(type_ == AUDIO_EVENT || type_ == VIDEO_EVENT);
+}
+
+ReceiverRtcpEventSubscriber::~ReceiverRtcpEventSubscriber() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void ReceiverRtcpEventSubscriber::OnReceiveFrameEvent(
+ const FrameEvent& frame_event) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (ShouldProcessEvent(frame_event.type, frame_event.media_type)) {
+ RtcpEvent rtcp_event;
+ switch (frame_event.type) {
+ case FRAME_PLAYOUT:
+ rtcp_event.delay_delta = frame_event.delay_delta;
+ case FRAME_ACK_SENT:
+ case FRAME_DECODED:
+ rtcp_event.type = frame_event.type;
+ rtcp_event.timestamp = frame_event.timestamp;
+ rtcp_events_.insert(
+ std::make_pair(frame_event.rtp_timestamp, rtcp_event));
+ break;
+ default:
+ break;
+ }
+ }
+
+ TruncateMapIfNeeded();
+
+ DCHECK(rtcp_events_.size() <= max_size_to_retain_);
+}
+
+void ReceiverRtcpEventSubscriber::OnReceivePacketEvent(
+ const PacketEvent& packet_event) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (ShouldProcessEvent(packet_event.type, packet_event.media_type)) {
+ RtcpEvent rtcp_event;
+ if (packet_event.type == PACKET_RECEIVED) {
+ rtcp_event.type = packet_event.type;
+ rtcp_event.timestamp = packet_event.timestamp;
+ rtcp_event.packet_id = packet_event.packet_id;
+ rtcp_events_.insert(
+ std::make_pair(packet_event.rtp_timestamp, rtcp_event));
+ }
+ }
+
+ TruncateMapIfNeeded();
+
+ DCHECK(rtcp_events_.size() <= max_size_to_retain_);
+}
+
+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.
+ if (rtcp_events_.size() > max_size_to_retain_) {
+ DVLOG(3) << "RTCP event map exceeded size limit; "
+ << "removing oldest entry";
+ // This is fine since we only insert elements one at a time.
+ rtcp_events_.erase(rtcp_events_.begin());
+ }
+}
+
+bool ReceiverRtcpEventSubscriber::ShouldProcessEvent(
+ CastLoggingEvent event_type, EventMediaType event_media_type) {
+ return type_ == event_media_type &&
+ (event_type == FRAME_ACK_SENT || event_type == FRAME_DECODED ||
+ event_type == FRAME_PLAYOUT || event_type == PACKET_RECEIVED);
+}
+
+} // namespace cast
+} // namespace media
diff --git a/chromium/media/cast/rtcp/receiver_rtcp_event_subscriber.h b/chromium/media/cast/rtcp/receiver_rtcp_event_subscriber.h
new file mode 100644
index 00000000000..84af7cbaf3f
--- /dev/null
+++ b/chromium/media/cast/rtcp/receiver_rtcp_event_subscriber.h
@@ -0,0 +1,79 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAST_RTCP_RECEIVER_RTCP_EVENT_SUBSCRIBER_H_
+#define MEDIA_CAST_RTCP_RECEIVER_RTCP_EVENT_SUBSCRIBER_H_
+
+#include <map>
+
+#include "base/threading/thread_checker.h"
+#include "media/cast/logging/logging_defines.h"
+#include "media/cast/logging/raw_event_subscriber.h"
+#include "media/cast/rtcp/rtcp_defines.h"
+
+namespace media {
+namespace cast {
+
+// A RawEventSubscriber implementation with the following properties:
+// - Only processes raw event types that are relevant for sending from cast
+// receiver to cast sender via RTCP.
+// - Captures information to be sent over to RTCP from raw event logs into the
+// more compact RtcpEvent struct.
+// - Orders events by RTP timestamp with a multimap.
+// - Internally, the map is capped at a maximum size configurable by the caller.
+// The subscriber only keeps the most recent events (determined by RTP
+// timestamp) up to the size limit.
+class ReceiverRtcpEventSubscriber : public RawEventSubscriber {
+ public:
+ typedef std::multimap<RtpTimestamp, RtcpEvent> RtcpEventMultiMap;
+
+ // |max_size_to_retain|: The object will keep up to |max_size_to_retain|
+ // events
+ // in the map. Once threshold has been reached, an event with the smallest
+ // RTP timestamp will be removed.
+ // |type|: Determines whether the subscriber will process only audio or video
+ // events.
+ ReceiverRtcpEventSubscriber(const size_t max_size_to_retain,
+ EventMediaType type);
+
+ virtual ~ReceiverRtcpEventSubscriber();
+
+ // RawEventSubscriber implementation.
+ virtual void OnReceiveFrameEvent(const FrameEvent& frame_event) OVERRIDE;
+ virtual void OnReceivePacketEvent(const PacketEvent& packet_event) OVERRIDE;
+
+ // 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
+ // entry (determined by RTP timestamp) so its size no greater than
+ // |max_size_to_retain_|.
+ void TruncateMapIfNeeded();
+
+ // Returns |true| if events of |event_type| and |media_type|
+ // should be processed.
+ bool ShouldProcessEvent(CastLoggingEvent event_type,
+ EventMediaType media_type);
+
+ const size_t max_size_to_retain_;
+ EventMediaType type_;
+
+ // The key should really be something more than just a RTP timestamp in order
+ // to differentiate between video and audio frames, but since the
+ // implementation doesn't mix audio and video frame events, RTP timestamp
+ // only as key is fine.
+ RtcpEventMultiMap rtcp_events_;
+
+ // Ensures methods are only called on the main thread.
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(ReceiverRtcpEventSubscriber);
+};
+
+} // namespace cast
+} // namespace media
+
+#endif // MEDIA_CAST_RTCP_RECEIVER_RTCP_EVENT_SUBSCRIBER_H_
diff --git a/chromium/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc b/chromium/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc
new file mode 100644
index 00000000000..e0d0f172160
--- /dev/null
+++ b/chromium/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc
@@ -0,0 +1,131 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/time/tick_clock.h"
+#include "media/cast/cast_environment.h"
+#include "media/cast/logging/logging_defines.h"
+#include "media/cast/rtcp/receiver_rtcp_event_subscriber.h"
+#include "media/cast/test/fake_single_thread_task_runner.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+namespace cast {
+
+namespace {
+
+const size_t kMaxEventEntries = 10u;
+const int64 kDelayMs = 20L;
+
+} // namespace
+
+class ReceiverRtcpEventSubscriberTest : public ::testing::Test {
+ protected:
+ ReceiverRtcpEventSubscriberTest()
+ : testing_clock_(new base::SimpleTestTickClock()),
+ task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
+ cast_environment_(new CastEnvironment(
+ scoped_ptr<base::TickClock>(testing_clock_).Pass(),
+ task_runner_,
+ task_runner_,
+ task_runner_)) {}
+
+ virtual ~ReceiverRtcpEventSubscriberTest() {}
+
+ virtual void TearDown() OVERRIDE {
+ if (event_subscriber_) {
+ cast_environment_->Logging()->RemoveRawEventSubscriber(
+ event_subscriber_.get());
+ }
+ }
+
+ void Init(EventMediaType type) {
+ event_subscriber_.reset(
+ new ReceiverRtcpEventSubscriber(kMaxEventEntries, type));
+ cast_environment_->Logging()->AddRawEventSubscriber(
+ event_subscriber_.get());
+ }
+
+ void InsertEvents() {
+ // Video events
+ cast_environment_->Logging()->InsertFrameEventWithDelay(
+ testing_clock_->NowTicks(), FRAME_PLAYOUT, VIDEO_EVENT,
+ /*rtp_timestamp*/ 100u, /*frame_id*/ 2u,
+ base::TimeDelta::FromMilliseconds(kDelayMs));
+ cast_environment_->Logging()->InsertFrameEvent(
+ testing_clock_->NowTicks(), FRAME_DECODED, VIDEO_EVENT,
+ /*rtp_timestamp*/ 200u, /*frame_id*/ 1u);
+ cast_environment_->Logging()->InsertPacketEvent(
+ testing_clock_->NowTicks(), PACKET_RECEIVED, VIDEO_EVENT,
+ /*rtp_timestamp */ 200u, /*frame_id*/ 2u, /*packet_id*/ 1u,
+ /*max_packet_id*/ 10u, /*size*/ 1024u);
+
+ // Audio events
+ cast_environment_->Logging()->InsertFrameEventWithDelay(
+ testing_clock_->NowTicks(), FRAME_PLAYOUT, AUDIO_EVENT,
+ /*rtp_timestamp*/ 300u, /*frame_id*/ 4u,
+ base::TimeDelta::FromMilliseconds(kDelayMs));
+ cast_environment_->Logging()->InsertFrameEvent(
+ testing_clock_->NowTicks(), FRAME_DECODED, AUDIO_EVENT,
+ /*rtp_timestamp*/ 400u, /*frame_id*/ 3u);
+ cast_environment_->Logging()->InsertPacketEvent(
+ testing_clock_->NowTicks(), PACKET_RECEIVED, AUDIO_EVENT,
+ /*rtp_timestamp */ 400u, /*frame_id*/ 5u, /*packet_id*/ 1u,
+ /*max_packet_id*/ 10u, /*size*/ 128u);
+
+ // Unrelated events
+ cast_environment_->Logging()->InsertFrameEvent(testing_clock_->NowTicks(),
+ FRAME_CAPTURE_END,
+ VIDEO_EVENT,
+ /*rtp_timestamp*/ 100u,
+ /*frame_id*/ 1u);
+ cast_environment_->Logging()->InsertFrameEvent(testing_clock_->NowTicks(),
+ FRAME_CAPTURE_END,
+ AUDIO_EVENT,
+ /*rtp_timestamp*/ 100u,
+ /*frame_id*/ 1u);
+ }
+
+ base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
+ scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
+ scoped_refptr<CastEnvironment> cast_environment_;
+ scoped_ptr<ReceiverRtcpEventSubscriber> event_subscriber_;
+};
+
+TEST_F(ReceiverRtcpEventSubscriberTest, LogVideoEvents) {
+ Init(VIDEO_EVENT);
+
+ InsertEvents();
+ ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events;
+ event_subscriber_->GetRtcpEventsAndReset(&rtcp_events);
+ EXPECT_EQ(3u, rtcp_events.size());
+}
+
+TEST_F(ReceiverRtcpEventSubscriberTest, LogAudioEvents) {
+ Init(AUDIO_EVENT);
+
+ InsertEvents();
+ ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events;
+ event_subscriber_->GetRtcpEventsAndReset(&rtcp_events);
+ EXPECT_EQ(3u, rtcp_events.size());
+}
+
+TEST_F(ReceiverRtcpEventSubscriberTest, DropEventsWhenSizeExceeded) {
+ Init(VIDEO_EVENT);
+
+ for (uint32 i = 1u; i <= 10u; ++i) {
+ cast_environment_->Logging()->InsertFrameEvent(
+ testing_clock_->NowTicks(), FRAME_DECODED, VIDEO_EVENT,
+ /*rtp_timestamp*/ i * 10, /*frame_id*/ i);
+ }
+
+ ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events;
+ event_subscriber_->GetRtcpEventsAndReset(&rtcp_events);
+ EXPECT_EQ(10u, rtcp_events.size());
+}
+
+} // namespace cast
+} // namespace media
diff --git a/chromium/media/cast/rtcp/rtcp.cc b/chromium/media/cast/rtcp/rtcp.cc
index 4ea4bc99ba9..480b2ac3990 100644
--- a/chromium/media/cast/rtcp/rtcp.cc
+++ b/chromium/media/cast/rtcp/rtcp.cc
@@ -4,6 +4,7 @@
#include "media/cast/rtcp/rtcp.h"
+#include "base/big_endian.h"
#include "base/rand_util.h"
#include "media/cast/cast_config.h"
#include "media/cast/cast_defines.h"
@@ -12,28 +13,22 @@
#include "media/cast/rtcp/rtcp_receiver.h"
#include "media/cast/rtcp/rtcp_sender.h"
#include "media/cast/rtcp/rtcp_utility.h"
-#include "net/base/big_endian.h"
+#include "media/cast/transport/cast_transport_defines.h"
namespace media {
namespace cast {
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.
+static const int kMaxDelay = 2000;
class LocalRtcpRttFeedback : public RtcpRttFeedback {
public:
- explicit LocalRtcpRttFeedback(Rtcp* rtcp)
- : rtcp_(rtcp) {
- }
+ explicit LocalRtcpRttFeedback(Rtcp* rtcp) : rtcp_(rtcp) {}
virtual void OnReceivedDelaySinceLastReport(
- uint32 receivers_ssrc,
- uint32 last_report,
+ uint32 receivers_ssrc, uint32 last_report,
uint32 delay_since_last_report) OVERRIDE {
- rtcp_->OnReceivedDelaySinceLastReport(receivers_ssrc,
- last_report,
+ rtcp_->OnReceivedDelaySinceLastReport(receivers_ssrc, last_report,
delay_since_last_report);
}
@@ -41,31 +36,14 @@ class LocalRtcpRttFeedback : public RtcpRttFeedback {
Rtcp* rtcp_;
};
-RtcpCastMessage::RtcpCastMessage(uint32 media_ssrc)
- : media_ssrc_(media_ssrc) {}
-
-RtcpCastMessage::~RtcpCastMessage() {}
-
-RtcpNackMessage::RtcpNackMessage() {}
-RtcpNackMessage::~RtcpNackMessage() {}
-
-RtcpRembMessage::RtcpRembMessage() {}
-RtcpRembMessage::~RtcpRembMessage() {}
-
-RtcpReceiverFrameLogMessage::RtcpReceiverFrameLogMessage(uint32 timestamp)
- : rtp_timestamp_(timestamp) {}
-
-RtcpReceiverFrameLogMessage::~RtcpReceiverFrameLogMessage() {}
-
class LocalRtcpReceiverFeedback : public RtcpReceiverFeedback {
public:
LocalRtcpReceiverFeedback(Rtcp* rtcp,
- scoped_refptr<CastEnvironment> cast_environment)
- : rtcp_(rtcp), cast_environment_(cast_environment) {
- }
+ scoped_refptr<CastEnvironment> cast_environment)
+ : rtcp_(rtcp), cast_environment_(cast_environment) {}
virtual void OnReceivedSenderReport(
- const RtcpSenderInfo& remote_sender_info) OVERRIDE {
+ const transport::RtcpSenderInfo& remote_sender_info) OVERRIDE {
rtcp_->OnReceivedNtp(remote_sender_info.ntp_seconds,
remote_sender_info.ntp_fraction);
if (remote_sender_info.send_packet_count != 0) {
@@ -85,80 +63,9 @@ 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);
- }
+ virtual void OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log)
+ OVERRIDE {
+ rtcp_->OnReceivedReceiverLog(receiver_log);
}
private:
@@ -168,36 +75,34 @@ class LocalRtcpReceiverFeedback : public RtcpReceiverFeedback {
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,
- uint32 local_ssrc,
- uint32 remote_ssrc,
- const std::string& c_name)
- : rtcp_interval_(rtcp_interval),
+ transport::CastTransportSender* const transport_sender,
+ transport::PacedPacketSender* paced_packet_sender,
+ RtpReceiverStatistics* rtp_receiver_statistics, RtcpMode rtcp_mode,
+ const base::TimeDelta& rtcp_interval, uint32 local_ssrc,
+ uint32 remote_ssrc, const std::string& c_name,
+ EventMediaType event_media_type)
+ : cast_environment_(cast_environment),
+ transport_sender_(transport_sender),
+ rtcp_interval_(rtcp_interval),
rtcp_mode_(rtcp_mode),
local_ssrc_(local_ssrc),
remote_ssrc_(remote_ssrc),
- rtp_sender_statistics_(rtp_sender_statistics),
+ c_name_(c_name),
+ event_media_type_(event_media_type),
rtp_receiver_statistics_(rtp_receiver_statistics),
- receiver_feedback_(new LocalRtcpReceiverFeedback(this, cast_environment)),
rtt_feedback_(new LocalRtcpRttFeedback(this)),
+ receiver_feedback_(new LocalRtcpReceiverFeedback(this, cast_environment)),
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),
+ last_report_truncated_ntp_(0),
+ local_clock_ahead_by_(ClockDriftSmoother::GetDefaultTimeConstant()),
+ lip_sync_rtp_timestamp_(0),
+ lip_sync_ntp_timestamp_(0),
min_rtt_(base::TimeDelta::FromMilliseconds(kMaxRttMs)),
- number_of_rtt_in_avg_(0),
- cast_environment_(cast_environment) {
- rtcp_receiver_.reset(new RtcpReceiver(cast_environment,
- sender_feedback,
+ number_of_rtt_in_avg_(0) {
+ rtcp_receiver_.reset(new RtcpReceiver(cast_environment, sender_feedback,
receiver_feedback_.get(),
- rtt_feedback_.get(),
- local_ssrc));
+ rtt_feedback_.get(), local_ssrc));
rtcp_receiver_->SetRemoteSSRC(remote_ssrc);
}
@@ -209,7 +114,8 @@ bool Rtcp::IsRtcpPacket(const uint8* packet, size_t length) {
if (length < kMinLengthOfRtcp) return false;
uint8 packet_type = packet[1];
- if (packet_type >= kPacketTypeLow && packet_type <= kPacketTypeHigh) {
+ if (packet_type >= transport::kPacketTypeLow &&
+ packet_type <= transport::kPacketTypeHigh) {
return true;
}
return false;
@@ -219,7 +125,8 @@ bool Rtcp::IsRtcpPacket(const uint8* packet, size_t 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);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_buffer), length);
big_endian_reader.Skip(4); // Skip header
big_endian_reader.ReadU32(&ssrc_of_sender);
return ssrc_of_sender;
@@ -242,117 +149,145 @@ void Rtcp::IncomingRtcpPacket(const uint8* rtcp_buffer, size_t length) {
rtcp_receiver_->IncomingRtcpPacket(&rtcp_parser);
}
-void Rtcp::SendRtcpFromRtpReceiver(const RtcpCastMessage* cast_message,
- RtcpReceiverLogMessage* receiver_log) {
+void Rtcp::SendRtcpFromRtpReceiver(
+ const RtcpCastMessage* cast_message,
+ const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events) {
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
uint32 packet_type_flags = 0;
base::TimeTicks now = cast_environment_->Clock()->NowTicks();
- RtcpReportBlock report_block;
+ transport::RtcpReportBlock report_block;
RtcpReceiverReferenceTimeReport rrtr;
+ // Attach our NTP to all RTCP packets; with this information a "smart" sender
+ // can make decisions based on how old the RTCP message is.
+ packet_type_flags |= transport::kRtcpRrtr;
+ ConvertTimeTicksToNtp(now, &rrtr.ntp_seconds, &rrtr.ntp_fraction);
+ SaveLastSentNtpTime(now, rrtr.ntp_seconds, rrtr.ntp_fraction);
+
if (cast_message) {
- packet_type_flags |= RtcpSender::kRtcpCast;
- cast_environment_->Logging()->InsertGenericEvent(kAckSent,
- cast_message->ack_frame_id_);
+ packet_type_flags |= transport::kRtcpCast;
}
- if (receiver_log) {
- packet_type_flags |= RtcpSender::kRtcpReceiverLog;
+ if (rtcp_events) {
+ packet_type_flags |= transport::kRtcpReceiverLog;
}
if (rtcp_mode_ == kRtcpCompound || now >= next_time_to_send_rtcp_) {
- packet_type_flags |= RtcpSender::kRtcpRr;
+ packet_type_flags |= transport::kRtcpRr;
- report_block.remote_ssrc = 0; // Not needed to set send side.
+ report_block.remote_ssrc = 0; // Not needed to set send side.
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.fraction_lost, &report_block.cumulative_lost,
+ &report_block.extended_high_sequence_number, &report_block.jitter);
}
- report_block.last_sr = last_report_received_;
+ report_block.last_sr = last_report_truncated_ntp_;
if (!time_last_report_received_.is_null()) {
uint32 delay_seconds = 0;
uint32 delay_fraction = 0;
base::TimeDelta delta = now - time_last_report_received_;
- ConvertTimeToFractions(delta.InMicroseconds(),
- &delay_seconds,
+ ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds,
&delay_fraction);
report_block.delay_since_last_sr =
ConvertToNtpDiff(delay_seconds, delay_fraction);
} else {
report_block.delay_since_last_sr = 0;
}
-
- packet_type_flags |= RtcpSender::kRtcpRrtr;
- 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);
+ rtcp_events,
+ target_delay_ms_);
}
-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;
+void Rtcp::SendRtcpFromRtpSender(base::TimeTicks current_time,
+ uint32 current_time_as_rtp_timestamp) {
+ DCHECK(transport_sender_);
+ uint32 packet_type_flags = transport::kRtcpSr;
+ uint32 current_ntp_seconds = 0;
+ uint32 current_ntp_fractions = 0;
+ ConvertTimeTicksToNtp(current_time, &current_ntp_seconds,
+ &current_ntp_fractions);
+ SaveLastSentNtpTime(current_time, current_ntp_seconds,
+ current_ntp_fractions);
+
+ transport::RtcpDlrrReportBlock dlrr;
if (!time_last_report_received_.is_null()) {
- packet_type_flags |= RtcpSender::kRtcpDlrr;
- dlrr.last_rr = last_report_received_;
+ packet_type_flags |= transport::kRtcpDlrr;
+ dlrr.last_rr = last_report_truncated_ntp_;
uint32 delay_seconds = 0;
uint32 delay_fraction = 0;
- base::TimeDelta delta = now - time_last_report_received_;
- ConvertTimeToFractions(delta.InMicroseconds(),
- &delay_seconds,
+ base::TimeDelta delta = current_time - 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);
+ transport_sender_->SendRtcpFromRtpSender(
+ packet_type_flags, current_ntp_seconds, current_ntp_fractions,
+ current_time_as_rtp_timestamp, dlrr, local_ssrc_, c_name_);
UpdateNextTimeToSendRtcp();
}
void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) {
- last_report_received_ = (ntp_seconds << 16) + (ntp_fraction >> 16);
+ last_report_truncated_ntp_ = ConvertToNtpDiff(ntp_seconds, ntp_fraction);
- base::TimeTicks now = cast_environment_->Clock()->NowTicks();
+ const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
time_last_report_received_ = now;
+
+ // TODO(miu): This clock offset calculation does not account for packet
+ // transit time over the network. End2EndTest.EvilNetwork confirms that this
+ // contributes a very significant source of error here. Fix this along with
+ // the RTT clean-up.
+ const base::TimeDelta measured_offset =
+ now - ConvertNtpToTimeTicks(ntp_seconds, ntp_fraction);
+ local_clock_ahead_by_.Update(now, measured_offset);
+ if (measured_offset < local_clock_ahead_by_.Current()) {
+ // Logically, the minimum offset between the clocks has to be the correct
+ // one. For example, the time it took to transmit the current report may
+ // have been lower than usual, and so some of the error introduced by the
+ // transmission time can be eliminated.
+ local_clock_ahead_by_.Reset(now, measured_offset);
+ }
+ VLOG(1) << "Local clock is ahead of the remote clock by: "
+ << "measured=" << measured_offset.InMicroseconds() << " usec, "
+ << "filtered=" << local_clock_ahead_by_.Current().InMicroseconds()
+ << " usec.";
}
-void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp,
- uint32 ntp_seconds,
+void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp, uint32 ntp_seconds,
uint32 ntp_fraction) {
- last_received_rtp_timestamp_ = rtp_timestamp;
- last_received_ntp_seconds_ = ntp_seconds;
- last_received_ntp_fraction_ = ntp_fraction;
+ if (ntp_seconds == 0) {
+ NOTREACHED();
+ return;
+ }
+ lip_sync_rtp_timestamp_ = rtp_timestamp;
+ lip_sync_ntp_timestamp_ =
+ (static_cast<uint64>(ntp_seconds) << 32) | ntp_fraction;
+}
+
+bool Rtcp::GetLatestLipSyncTimes(uint32* rtp_timestamp,
+ base::TimeTicks* reference_time) const {
+ if (!lip_sync_ntp_timestamp_)
+ return false;
+
+ const base::TimeTicks local_reference_time =
+ ConvertNtpToTimeTicks(static_cast<uint32>(lip_sync_ntp_timestamp_ >> 32),
+ static_cast<uint32>(lip_sync_ntp_timestamp_)) +
+ local_clock_ahead_by_.Current();
+
+ // Sanity-check: Getting regular lip sync updates?
+ DCHECK((cast_environment_->Clock()->NowTicks() - local_reference_time) <
+ base::TimeDelta::FromMinutes(1));
+
+ *rtp_timestamp = lip_sync_rtp_timestamp_;
+ *reference_time = local_reference_time;
+ return true;
}
void Rtcp::OnReceivedSendReportRequest() {
@@ -362,35 +297,13 @@ void Rtcp::OnReceivedSendReportRequest() {
next_time_to_send_rtcp_ = now;
}
-bool Rtcp::RtpTimestampInSenderTime(int frequency, uint32 rtp_timestamp,
- base::TimeTicks* rtp_timestamp_in_ticks) const {
- if (last_received_ntp_seconds_ == 0) return false;
-
- int wrap = CheckForWrapAround(rtp_timestamp, last_received_rtp_timestamp_);
- int64 rtp_timestamp_int64 = rtp_timestamp;
- int64 last_received_rtp_timestamp_int64 = last_received_rtp_timestamp_;
-
- if (wrap == 1) {
- rtp_timestamp_int64 += (1LL << 32);
- } else if (wrap == -1) {
- last_received_rtp_timestamp_int64 += (1LL << 32);
- }
- // Time since the last RTCP message.
- // Note that this can be negative since we can compare a rtp timestamp from
- // a frame older than the last received RTCP message.
- int64 rtp_timestamp_diff =
- rtp_timestamp_int64 - last_received_rtp_timestamp_int64;
-
- int frequency_khz = frequency / 1000;
- int64 rtp_time_diff_ms = rtp_timestamp_diff / frequency_khz;
-
- // Sanity check.
- if (abs(rtp_time_diff_ms) > kMaxDiffSinceReceivedRtcpMs) return false;
+void Rtcp::SetCastReceiverEventHistorySize(size_t size) {
+ rtcp_receiver_->SetCastReceiverEventHistorySize(size);
+}
- *rtp_timestamp_in_ticks = ConvertNtpToTimeTicks(last_received_ntp_seconds_,
- last_received_ntp_fraction_) +
- base::TimeDelta::FromMilliseconds(rtp_time_diff_ms);
- return true;
+void Rtcp::SetTargetDelay(base::TimeDelta target_delay) {
+ DCHECK(target_delay.InMilliseconds() < kMaxDelay);
+ target_delay_ms_ = static_cast<uint16>(target_delay.InMilliseconds());
}
void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,
@@ -401,8 +314,8 @@ void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,
return; // Feedback on another report.
}
- base::TimeDelta sender_delay = cast_environment_->Clock()->NowTicks()
- - it->second;
+ base::TimeDelta sender_delay =
+ cast_environment_->Clock()->NowTicks() - it->second;
UpdateRtt(sender_delay, ConvertFromNtpDiff(delay_since_last_report));
}
@@ -411,9 +324,8 @@ void Rtcp::SaveLastSentNtpTime(const base::TimeTicks& now,
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()) {
+ 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;
@@ -436,66 +348,85 @@ void Rtcp::SaveLastSentNtpTime(const base::TimeTicks& now,
void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay,
const base::TimeDelta& receiver_delay) {
base::TimeDelta rtt = sender_delay - receiver_delay;
+ // TODO(miu): Find out why this must be >= 1 ms, and remove the fudge if it's
+ // bogus.
rtt = std::max(rtt, base::TimeDelta::FromMilliseconds(1));
rtt_ = rtt;
min_rtt_ = std::min(min_rtt_, rtt);
max_rtt_ = std::max(max_rtt_, rtt);
+ // TODO(miu): Replace "average for all time" with an EWMA, or suitable
+ // "average over recent past" mechanism.
if (number_of_rtt_in_avg_ != 0) {
- float ac = static_cast<float>(number_of_rtt_in_avg_);
- avg_rtt_ms_= ((ac / (ac + 1.0)) * avg_rtt_ms_) +
- ((1.0 / (ac + 1.0)) * rtt.InMilliseconds());
+ const double ac = static_cast<double>(number_of_rtt_in_avg_);
+ avg_rtt_ms_ = ((ac / (ac + 1.0)) * avg_rtt_ms_) +
+ ((1.0 / (ac + 1.0)) * rtt.InMillisecondsF());
} else {
- avg_rtt_ms_ = rtt.InMilliseconds();
+ avg_rtt_ms_ = rtt.InMillisecondsF();
}
number_of_rtt_in_avg_++;
}
-bool Rtcp::Rtt(base::TimeDelta* rtt,
- base::TimeDelta* avg_rtt,
- base::TimeDelta* min_rtt,
- base::TimeDelta* max_rtt) const {
+bool Rtcp::Rtt(base::TimeDelta* rtt, base::TimeDelta* avg_rtt,
+ base::TimeDelta* min_rtt, base::TimeDelta* max_rtt) const {
DCHECK(rtt) << "Invalid argument";
DCHECK(avg_rtt) << "Invalid argument";
DCHECK(min_rtt) << "Invalid argument";
DCHECK(max_rtt) << "Invalid argument";
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_);
+ *avg_rtt = base::TimeDelta::FromMillisecondsD(avg_rtt_ms_);
*min_rtt = min_rtt_;
*max_rtt = max_rtt_;
return true;
}
-int Rtcp::CheckForWrapAround(uint32 new_timestamp,
- uint32 old_timestamp) const {
- if (new_timestamp < old_timestamp) {
- // This difference should be less than -2^31 if we have had a wrap around
- // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is
- // cast to a int32_t, it should be positive.
- if (static_cast<int32>(new_timestamp - old_timestamp) > 0) {
- return 1; // Forward wrap around.
- }
- } else if (static_cast<int32>(old_timestamp - new_timestamp) > 0) {
- // This difference should be less than -2^31 if we have had a backward wrap
- // around. Since it is cast to a int32, it should be positive.
- return -1;
- }
- return 0;
-}
-
void Rtcp::UpdateNextTimeToSendRtcp() {
int random = base::RandInt(0, 999);
- base::TimeDelta time_to_next = (rtcp_interval_ / 2) +
- (rtcp_interval_ * random / 1000);
+ base::TimeDelta time_to_next =
+ (rtcp_interval_ / 2) + (rtcp_interval_ * random / 1000);
base::TimeTicks now = cast_environment_->Clock()->NowTicks();
next_time_to_send_rtcp_ = now + time_to_next;
}
+void Rtcp::OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log) {
+ // 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) {
+ switch (event_it->type) {
+ case PACKET_RECEIVED:
+ cast_environment_->Logging()->InsertPacketEvent(
+ event_it->event_timestamp, event_it->type,
+ event_media_type_, rtp_timestamp,
+ kFrameIdUnknown, event_it->packet_id, 0, 0);
+ break;
+ case FRAME_ACK_SENT:
+ case FRAME_DECODED:
+ cast_environment_->Logging()->InsertFrameEvent(
+ event_it->event_timestamp, event_it->type, event_media_type_,
+ rtp_timestamp, kFrameIdUnknown);
+ break;
+ case FRAME_PLAYOUT:
+ cast_environment_->Logging()->InsertFrameEventWithDelay(
+ event_it->event_timestamp, event_it->type, event_media_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;
+ }
+ }
+ }
+}
+
} // namespace cast
} // namespace media
diff --git a/chromium/media/cast/rtcp/rtcp.gyp b/chromium/media/cast/rtcp/rtcp.gyp
deleted file mode 100644
index 14119988c8e..00000000000
--- a/chromium/media/cast/rtcp/rtcp.gyp
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
- 'targets': [
- {
- 'target_name': 'cast_rtcp',
- 'type': 'static_library',
- 'include_dirs': [
- '<(DEPTH)/',
- ],
- 'sources': [
- 'rtcp_defines.h',
- 'rtcp.h',
- 'rtcp.cc',
- 'rtcp_receiver.cc',
- 'rtcp_receiver.h',
- 'rtcp_sender.cc',
- 'rtcp_sender.h',
- 'rtcp_utility.cc',
- 'rtcp_utility.h',
- ], # source
- 'dependencies': [
- '<(DEPTH)/base/base.gyp:base',
- '<(DEPTH)/net/net.gyp:net',
- ],
- },
- {
- 'target_name': 'cast_rtcp_test',
- 'type': 'static_library',
- 'include_dirs': [
- '<(DEPTH)/',
- ],
- 'sources': [
- 'test_rtcp_packet_builder.cc',
- 'test_rtcp_packet_builder.h',
- ], # source
- 'dependencies': [
- 'cast_rtcp',
- '<(DEPTH)/testing/gtest.gyp:gtest',
- ],
- },
- ],
-}
-
diff --git a/chromium/media/cast/rtcp/rtcp.h b/chromium/media/cast/rtcp/rtcp.h
index aa083a5a4dd..9d0184f9033 100644
--- a/chromium/media/cast/rtcp/rtcp.h
+++ b/chromium/media/cast/rtcp/rtcp.h
@@ -5,20 +5,23 @@
#ifndef MEDIA_CAST_RTCP_RTCP_H_
#define MEDIA_CAST_RTCP_RTCP_H_
-#include <list>
#include <map>
#include <queue>
-#include <set>
#include <string>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
+#include "media/cast/base/clock_drift_smoother.h"
#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"
+#include "media/cast/transport/pacing/paced_sender.h"
namespace media {
namespace cast {
@@ -40,14 +43,6 @@ class RtcpSenderFeedback {
virtual ~RtcpSenderFeedback() {}
};
-class RtpSenderStatistics {
- public:
- virtual void GetStatistics(const base::TimeTicks& now,
- RtcpSenderInfo* sender_info) = 0;
-
- virtual ~RtpSenderStatistics() {}
-};
-
class RtpReceiverStatistics {
public:
virtual void GetStatistics(uint8* fraction_lost,
@@ -60,16 +55,20 @@ class RtpReceiverStatistics {
class Rtcp {
public:
+ // Rtcp accepts two transports, one to be used by Cast senders
+ // (CastTransportSender) only, and the other (PacedPacketSender) should only
+ // be used by the Cast receivers and test applications.
Rtcp(scoped_refptr<CastEnvironment> cast_environment,
RtcpSenderFeedback* sender_feedback,
- PacedPacketSender* paced_packet_sender,
- RtpSenderStatistics* rtp_sender_statistics,
+ transport::CastTransportSender* const transport_sender, // Send-side.
+ transport::PacedPacketSender* paced_packet_sender, // Receive side.
RtpReceiverStatistics* rtp_receiver_statistics,
RtcpMode rtcp_mode,
const base::TimeDelta& rtcp_interval,
uint32 local_ssrc,
uint32 remote_ssrc,
- const std::string& c_name);
+ const std::string& c_name,
+ EventMediaType event_media_type);
virtual ~Rtcp();
@@ -78,35 +77,55 @@ class Rtcp {
static uint32 GetSsrcOfSender(const uint8* rtcp_buffer, size_t length);
base::TimeTicks TimeToSendNextRtcpReport();
- // |sender_log_message| is optional; without it no log messages will be
- // attached to the RTCP report; instead a normal RTCP send report will be
- // sent.
- // Additionally if all messages in |sender_log_message| does
- // not fit in the packet the |sender_log_message| will contain the remaining
- // unsent messages.
- void SendRtcpFromRtpSender(RtcpSenderLogMessage* sender_log_message);
-
- // |cast_message| and |receiver_log| is optional; if |cast_message| is
+
+ // Send a RTCP sender report.
+ // |current_time| is the current time reported by a tick clock.
+ // |current_time_as_rtp_timestamp| is the corresponding RTP timestamp.
+ void SendRtcpFromRtpSender(base::TimeTicks current_time,
+ uint32 current_time_as_rtp_timestamp);
+
+ // |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 |receiver_log| is provided the RTCP receiver report will
- // append the log messages. If no argument is set a normal RTCP receiver
- // report will be sent. Additionally if all messages in |receiver_log| does
- // not fit in the packet the |receiver_log| will contain the remaining unsent
- // messages.
- void SendRtcpFromRtpReceiver(const RtcpCastMessage* cast_message,
- RtcpReceiverLogMessage* receiver_log);
+ // 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::RtcpEventMultiMap* rtcp_events);
void IncomingRtcpPacket(const uint8* rtcp_buffer, size_t length);
- bool Rtt(base::TimeDelta* rtt, base::TimeDelta* avg_rtt,
- base::TimeDelta* min_rtt, base::TimeDelta* max_rtt) const;
- bool RtpTimestampInSenderTime(int frequency,
- uint32 rtp_timestamp,
- base::TimeTicks* rtp_timestamp_in_ticks) const;
- protected:
- int CheckForWrapAround(uint32 new_timestamp,
- uint32 old_timestamp) const;
+ // TODO(miu): Clean up this method and downstream code: Only VideoSender uses
+ // this (for congestion control), and only the |rtt| and |avg_rtt| values, and
+ // it's not clear that any of the downstream code is doing the right thing
+ // with this data.
+ bool Rtt(base::TimeDelta* rtt,
+ base::TimeDelta* avg_rtt,
+ base::TimeDelta* min_rtt,
+ base::TimeDelta* max_rtt) const;
+
+ bool is_rtt_available() const { return number_of_rtt_in_avg_ > 0; }
+
+ // If available, returns true and sets the output arguments to the latest
+ // lip-sync timestamps gleaned from the sender reports. While the sender
+ // provides reference NTP times relative to its own wall clock, the
+ // |reference_time| returned here has been translated to the local
+ // CastEnvironment clock.
+ bool GetLatestLipSyncTimes(uint32* rtp_timestamp,
+ base::TimeTicks* reference_time) const;
+
+ // Set the history size to record Cast receiver events. The event history is
+ // used to remove duplicates. The history will store at most |size| events.
+ void SetCastReceiverEventHistorySize(size_t size);
+ // Update the target delay. Will be added to every report sent back to the
+ // sender.
+ // TODO(miu): Remove this deprecated functionality. The sender ignores this.
+ void SetTargetDelay(base::TimeDelta target_delay);
+
+ void OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log);
+
+ protected:
+ void OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction);
void OnReceivedLipSyncInfo(uint32 rtp_timestamp,
uint32 ntp_seconds,
uint32 ntp_fraction);
@@ -115,13 +134,6 @@ class Rtcp {
friend class LocalRtcpRttFeedback;
friend class LocalRtcpReceiverFeedback;
- void SendRtcp(const base::TimeTicks& now,
- uint32 packet_type_flags,
- uint32 media_ssrc,
- const RtcpCastMessage* cast_message);
-
- void OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction);
-
void OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,
uint32 last_report,
uint32 delay_since_last_report);
@@ -133,17 +145,20 @@ class Rtcp {
void UpdateNextTimeToSendRtcp();
- void SaveLastSentNtpTime(const base::TimeTicks& now, uint32 last_ntp_seconds,
+ void SaveLastSentNtpTime(const base::TimeTicks& now,
+ uint32 last_ntp_seconds,
uint32 last_ntp_fraction);
scoped_refptr<CastEnvironment> cast_environment_;
+ transport::CastTransportSender* const transport_sender_;
const base::TimeDelta rtcp_interval_;
const RtcpMode rtcp_mode_;
const uint32 local_ssrc_;
const uint32 remote_ssrc_;
+ const std::string c_name_;
+ const EventMediaType event_media_type_;
// Not owned by this class.
- RtpSenderStatistics* const rtp_sender_statistics_;
RtpReceiverStatistics* const rtp_receiver_statistics_;
scoped_ptr<LocalRtcpRttFeedback> rtt_feedback_;
@@ -154,18 +169,33 @@ class Rtcp {
base::TimeTicks next_time_to_send_rtcp_;
RtcpSendTimeMap last_reports_sent_map_;
RtcpSendTimeQueue last_reports_sent_queue_;
+
+ // The truncated (i.e., 64-->32-bit) NTP timestamp provided in the last report
+ // from the remote peer, along with the local time at which the report was
+ // received. These values are used for ping-pong'ing NTP timestamps between
+ // the peers so that they can estimate the network's round-trip time.
+ uint32 last_report_truncated_ntp_;
base::TimeTicks time_last_report_received_;
- uint32 last_report_received_;
- uint32 last_received_rtp_timestamp_;
- uint32 last_received_ntp_seconds_;
- uint32 last_received_ntp_fraction_;
+ // Maintains a smoothed offset between the local clock and the remote clock.
+ // Calling this member's Current() method is only valid if
+ // |time_last_report_received_| is not "null."
+ ClockDriftSmoother local_clock_ahead_by_;
+
+ // Latest "lip sync" info from the sender. The sender provides the RTP
+ // timestamp of some frame of its choosing and also a corresponding reference
+ // NTP timestamp sampled from a clock common to all media streams. It is
+ // expected that the sender will update this data regularly and in a timely
+ // manner (e.g., about once per second).
+ uint32 lip_sync_rtp_timestamp_;
+ uint64 lip_sync_ntp_timestamp_;
base::TimeDelta rtt_;
base::TimeDelta min_rtt_;
base::TimeDelta max_rtt_;
int number_of_rtt_in_avg_;
- float avg_rtt_ms_;
+ double avg_rtt_ms_;
+ uint16 target_delay_ms_;
DISALLOW_COPY_AND_ASSIGN(Rtcp);
};
diff --git a/chromium/media/cast/rtcp/rtcp_defines.cc b/chromium/media/cast/rtcp/rtcp_defines.cc
new file mode 100644
index 00000000000..214100d4d9e
--- /dev/null
+++ b/chromium/media/cast/rtcp/rtcp_defines.cc
@@ -0,0 +1,49 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/cast/rtcp/rtcp_defines.h"
+
+#include "media/cast/logging/logging_defines.h"
+
+namespace media {
+namespace cast {
+
+RtcpCastMessage::RtcpCastMessage(uint32 media_ssrc)
+ : media_ssrc_(media_ssrc), ack_frame_id_(0u), target_delay_ms_(0) {}
+RtcpCastMessage::~RtcpCastMessage() {}
+
+void RtcpCastMessage::Copy(const RtcpCastMessage& cast_message) {
+ media_ssrc_ = cast_message.media_ssrc_;
+ ack_frame_id_ = cast_message.ack_frame_id_;
+ target_delay_ms_ = cast_message.target_delay_ms_;
+ missing_frames_and_packets_ = cast_message.missing_frames_and_packets_;
+}
+
+RtcpReceiverEventLogMessage::RtcpReceiverEventLogMessage()
+ : type(UNKNOWN), packet_id(0u) {}
+RtcpReceiverEventLogMessage::~RtcpReceiverEventLogMessage() {}
+
+RtcpReceiverFrameLogMessage::RtcpReceiverFrameLogMessage(uint32 timestamp)
+ : rtp_timestamp_(timestamp) {}
+RtcpReceiverFrameLogMessage::~RtcpReceiverFrameLogMessage() {}
+
+RtcpRpsiMessage::RtcpRpsiMessage()
+ : remote_ssrc(0u), payload_type(0u), picture_id(0u) {}
+RtcpRpsiMessage::~RtcpRpsiMessage() {}
+
+RtcpNackMessage::RtcpNackMessage() : remote_ssrc(0u) {}
+RtcpNackMessage::~RtcpNackMessage() {}
+
+RtcpRembMessage::RtcpRembMessage() : remb_bitrate(0u) {}
+RtcpRembMessage::~RtcpRembMessage() {}
+
+RtcpReceiverReferenceTimeReport::RtcpReceiverReferenceTimeReport()
+ : remote_ssrc(0u), ntp_seconds(0u), ntp_fraction(0u) {}
+RtcpReceiverReferenceTimeReport::~RtcpReceiverReferenceTimeReport() {}
+
+RtcpEvent::RtcpEvent() : type(UNKNOWN), packet_id(0u) {}
+RtcpEvent::~RtcpEvent() {}
+
+} // namespace cast
+} // namespace media
diff --git a/chromium/media/cast/rtcp/rtcp_defines.h b/chromium/media/cast/rtcp/rtcp_defines.h
index 0277bd1feaf..31795648c64 100644
--- a/chromium/media/cast/rtcp/rtcp_defines.h
+++ b/chromium/media/cast/rtcp/rtcp_defines.h
@@ -5,45 +5,42 @@
#ifndef MEDIA_CAST_RTCP_RTCP_DEFINES_H_
#define MEDIA_CAST_RTCP_RTCP_DEFINES_H_
-#include <list>
#include <map>
#include <set>
#include "media/cast/cast_config.h"
#include "media/cast/cast_defines.h"
#include "media/cast/logging/logging_defines.h"
+#include "media/cast/transport/cast_transport_defines.h"
namespace media {
namespace cast {
+static const size_t kRtcpCastLogHeaderSize = 12;
+static const size_t kRtcpReceiverFrameLogSize = 8;
+static const size_t kRtcpReceiverEventLogSize = 4;
+
// Handle the per frame ACK and NACK messages.
class RtcpCastMessage {
public:
explicit RtcpCastMessage(uint32 media_ssrc);
~RtcpCastMessage();
+ void Copy(const RtcpCastMessage& cast_message);
+
uint32 media_ssrc_;
uint32 ack_frame_id_;
+ uint16 target_delay_ms_;
MissingFramesAndPacketsMap missing_frames_and_packets_;
-};
-
-// Log messages form sender to receiver.
-enum RtcpSenderFrameStatus {
- kRtcpSenderFrameStatusUnknown = 0,
- kRtcpSenderFrameStatusDroppedByEncoder = 1,
- kRtcpSenderFrameStatusDroppedByFlowControl = 2,
- kRtcpSenderFrameStatusSentToNetwork = 3,
-};
-struct RtcpSenderFrameLogMessage {
- RtcpSenderFrameStatus frame_status;
- uint32 rtp_timestamp;
+ DISALLOW_COPY_AND_ASSIGN(RtcpCastMessage);
};
-typedef std::list<RtcpSenderFrameLogMessage> RtcpSenderLogMessage;
-
// Log messages from receiver to sender.
struct RtcpReceiverEventLogMessage {
+ RtcpReceiverEventLogMessage();
+ ~RtcpReceiverEventLogMessage();
+
CastLoggingEvent type;
base::TimeTicks event_timestamp;
base::TimeDelta delay_delta;
@@ -52,99 +49,84 @@ struct RtcpReceiverEventLogMessage {
typedef std::list<RtcpReceiverEventLogMessage> RtcpReceiverEventLogMessages;
-class RtcpReceiverFrameLogMessage {
- public:
+struct RtcpReceiverFrameLogMessage {
explicit RtcpReceiverFrameLogMessage(uint32 rtp_timestamp);
~RtcpReceiverFrameLogMessage();
uint32 rtp_timestamp_;
RtcpReceiverEventLogMessages event_log_messages_;
-};
-typedef std::list<RtcpReceiverFrameLogMessage> RtcpReceiverLogMessage;
-
-struct RtcpSenderInfo {
- // First three members are used for lipsync.
- // First two members are used for rtt.
- uint32 ntp_seconds;
- uint32 ntp_fraction;
- uint32 rtp_timestamp;
- uint32 send_packet_count;
- size_t send_octet_count;
+ // TODO(mikhal): Investigate what's the best way to allow adding
+ // DISALLOW_COPY_AND_ASSIGN, as currently it contradicts the implementation
+ // and possible changes have a big impact on design.
};
-struct RtcpReportBlock {
- uint32 remote_ssrc; // SSRC of sender of this report.
- uint32 media_ssrc; // SSRC of the RTP packet sender.
- uint8 fraction_lost;
- uint32 cumulative_lost; // 24 bits valid.
- uint32 extended_high_sequence_number;
- uint32 jitter;
- uint32 last_sr;
- uint32 delay_since_last_sr;
-};
+typedef std::list<RtcpReceiverFrameLogMessage> RtcpReceiverLogMessage;
struct RtcpRpsiMessage {
+ RtcpRpsiMessage();
+ ~RtcpRpsiMessage();
+
uint32 remote_ssrc;
uint8 payload_type;
uint64 picture_id;
};
-class RtcpNackMessage {
- public:
+struct RtcpNackMessage {
RtcpNackMessage();
~RtcpNackMessage();
uint32 remote_ssrc;
std::list<uint16> nack_list;
+
+ DISALLOW_COPY_AND_ASSIGN(RtcpNackMessage);
};
-class RtcpRembMessage {
- public:
+struct RtcpRembMessage {
RtcpRembMessage();
~RtcpRembMessage();
uint32 remb_bitrate;
std::list<uint32> remb_ssrcs;
+
+ DISALLOW_COPY_AND_ASSIGN(RtcpRembMessage);
};
struct RtcpReceiverReferenceTimeReport {
+ RtcpReceiverReferenceTimeReport();
+ ~RtcpReceiverReferenceTimeReport();
+
uint32 remote_ssrc;
uint32 ntp_seconds;
uint32 ntp_fraction;
};
-struct RtcpDlrrReportBlock {
- uint32 last_rr;
- uint32 delay_since_last_rr;
-};
-
-inline bool operator==(RtcpReportBlock lhs, RtcpReportBlock rhs) {
- return lhs.remote_ssrc == rhs.remote_ssrc &&
- lhs.media_ssrc == rhs.media_ssrc &&
- lhs.fraction_lost == rhs.fraction_lost &&
- lhs.cumulative_lost == rhs.cumulative_lost &&
- lhs.extended_high_sequence_number == rhs.extended_high_sequence_number &&
- lhs.jitter == rhs.jitter &&
- lhs.last_sr == rhs.last_sr &&
- lhs.delay_since_last_sr == rhs.delay_since_last_sr;
-}
-
-inline bool operator==(RtcpSenderInfo lhs, RtcpSenderInfo rhs) {
- return lhs.ntp_seconds == rhs.ntp_seconds &&
- lhs.ntp_fraction == rhs.ntp_fraction &&
- lhs.rtp_timestamp == rhs.rtp_timestamp &&
- lhs.send_packet_count == rhs.send_packet_count &&
- lhs.send_octet_count == rhs.send_octet_count;
-}
-
inline bool operator==(RtcpReceiverReferenceTimeReport lhs,
RtcpReceiverReferenceTimeReport rhs) {
return lhs.remote_ssrc == rhs.remote_ssrc &&
- lhs.ntp_seconds == rhs.ntp_seconds &&
- lhs.ntp_fraction == rhs.ntp_fraction;
+ lhs.ntp_seconds == rhs.ntp_seconds &&
+ lhs.ntp_fraction == rhs.ntp_fraction;
}
+// Struct used by raw event subscribers as an intermediate format before
+// sending off to the other side via RTCP.
+// (i.e., {Sender,Receiver}RtcpEventSubscriber)
+struct RtcpEvent {
+ RtcpEvent();
+ ~RtcpEvent();
+
+ CastLoggingEvent type;
+
+ // Time of event logged.
+ base::TimeTicks timestamp;
+
+ // Render/playout delay. Only set for FRAME_PLAYOUT events.
+ base::TimeDelta delay_delta;
+
+ // Only set for packet events.
+ uint16 packet_id;
+};
+
} // namespace cast
} // namespace media
diff --git a/chromium/media/cast/rtcp/rtcp_receiver.cc b/chromium/media/cast/rtcp/rtcp_receiver.cc
index 152ebc00d7b..3be8e921c46 100644
--- a/chromium/media/cast/rtcp/rtcp_receiver.cc
+++ b/chromium/media/cast/rtcp/rtcp_receiver.cc
@@ -6,50 +6,31 @@
#include "base/logging.h"
#include "media/cast/rtcp/rtcp_utility.h"
+#include "media/cast/transport/cast_transport_defines.h"
namespace {
-media::cast::CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) {
- switch (event) {
- case 1:
- return media::cast::kAckSent;
- case 2:
- return media::cast::kAudioPlayoutDelay;
- case 3:
- return media::cast::kAudioFrameDecoded;
- case 4:
- return media::cast::kVideoFrameDecoded;
- case 5:
- return media::cast::kVideoRenderDelay;
- case 6:
- return media::cast::kPacketReceived;
- default:
- // If the sender adds new log messages we will end up here until we add
- // the new messages in the receiver.
- VLOG(1) << "Unexpected log message received: " << static_cast<int>(event);
- NOTREACHED();
- return media::cast::kUnknown;
- }
-}
-
-media::cast::RtcpSenderFrameStatus TranslateToFrameStatusFromWireFormat(
- uint8 status) {
- switch (status) {
- case 0:
- return media::cast::kRtcpSenderFrameStatusUnknown;
- case 1:
- return media::cast::kRtcpSenderFrameStatusDroppedByEncoder;
- case 2:
- return media::cast::kRtcpSenderFrameStatusDroppedByFlowControl;
- case 3:
- return media::cast::kRtcpSenderFrameStatusSentToNetwork;
- default:
- // If the sender adds new log messages we will end up here until we add
- // the new messages in the receiver.
- NOTREACHED();
- VLOG(1) << "Unexpected status received: " << static_cast<int>(status);
- return media::cast::kRtcpSenderFrameStatusUnknown;
- }
+// A receiver frame event is identified by frame RTP timestamp, event timestamp
+// and event type.
+// A receiver packet event is identified by all of the above plus packet id.
+// The key format is as follows:
+// First uint64:
+// bits 0-11: zeroes (unused).
+// bits 12-15: event type ID.
+// bits 16-31: packet ID if packet event, 0 otherwise.
+// bits 32-63: RTP timestamp.
+// Second uint64:
+// bits 0-63: event TimeTicks internal value.
+std::pair<uint64, uint64> GetReceiverEventKey(
+ uint32 frame_rtp_timestamp, const base::TimeTicks& event_timestamp,
+ uint8 event_type, uint16 packet_id_or_zero) {
+ uint64 value1 = event_type;
+ value1 <<= 16;
+ value1 |= packet_id_or_zero;
+ value1 <<= 32;
+ value1 |= frame_rtp_timestamp;
+ return std::make_pair(
+ value1, static_cast<uint64>(event_timestamp.ToInternalValue()));
}
} // namespace
@@ -67,12 +48,15 @@ RtcpReceiver::RtcpReceiver(scoped_refptr<CastEnvironment> cast_environment,
sender_feedback_(sender_feedback),
receiver_feedback_(receiver_feedback),
rtt_feedback_(rtt_feedback),
- cast_environment_(cast_environment) {}
+ cast_environment_(cast_environment),
+ receiver_event_history_size_(0) {}
RtcpReceiver::~RtcpReceiver() {}
-void RtcpReceiver::SetRemoteSSRC(uint32 ssrc) {
- remote_ssrc_ = ssrc;
+void RtcpReceiver::SetRemoteSSRC(uint32 ssrc) { remote_ssrc_ = ssrc; }
+
+void RtcpReceiver::SetCastReceiverEventHistorySize(size_t size) {
+ receiver_event_history_size_ = size;
}
void RtcpReceiver::IncomingRtcpPacket(RtcpParser* rtcp_parser) {
@@ -117,9 +101,6 @@ void RtcpReceiver::IncomingRtcpPacket(RtcpParser* rtcp_parser) {
case kRtcpApplicationSpecificCastReceiverLogCode:
HandleApplicationSpecificCastReceiverLog(rtcp_parser);
break;
- case kRtcpApplicationSpecificCastSenderLogCode:
- HandleApplicationSpecificCastSenderLog(rtcp_parser);
- break;
case kRtcpPayloadSpecificRembCode:
case kRtcpPayloadSpecificRembItemCode:
case kRtcpPayloadSpecificCastCode:
@@ -151,16 +132,15 @@ void RtcpReceiver::HandleSenderReport(RtcpParser* rtcp_parser) {
// Synchronization source identifier for the originator of this SR packet.
uint32 remote_ssrc = rtcp_field.sender_report.sender_ssrc;
- VLOG(1) << "Cast RTCP received SR from SSRC " << remote_ssrc;
+ VLOG(2) << "Cast RTCP received SR from SSRC " << remote_ssrc;
if (remote_ssrc_ == remote_ssrc) {
- RtcpSenderInfo remote_sender_info;
+ transport::RtcpSenderInfo remote_sender_info;
remote_sender_info.ntp_seconds =
rtcp_field.sender_report.ntp_most_significant;
remote_sender_info.ntp_fraction =
rtcp_field.sender_report.ntp_least_significant;
- remote_sender_info.rtp_timestamp =
- rtcp_field.sender_report.rtp_timestamp;
+ remote_sender_info.rtp_timestamp = rtcp_field.sender_report.rtp_timestamp;
remote_sender_info.send_packet_count =
rtcp_field.sender_report.sender_packet_count;
remote_sender_info.send_octet_count =
@@ -184,7 +164,7 @@ void RtcpReceiver::HandleReceiverReport(RtcpParser* rtcp_parser) {
uint32 remote_ssrc = rtcp_field.receiver_report.sender_ssrc;
- VLOG(1) << "Cast RTCP received RR from SSRC " << remote_ssrc;
+ VLOG(2) << "Cast RTCP received RR from SSRC " << remote_ssrc;
rtcp_field_type = rtcp_parser->Iterate();
while (rtcp_field_type == kRtcpReportBlockItemCode) {
@@ -211,13 +191,9 @@ void RtcpReceiver::HandleReportBlock(const RtcpField* rtcp_field,
// This block is not for us ignore it.
return;
}
- VLOG(1) << "Cast RTCP received RB from SSRC " << remote_ssrc;
- cast_environment_->Logging()->InsertGenericEvent(kPacketLoss,
- rb.fraction_lost);
- cast_environment_->Logging()->InsertGenericEvent(kJitterMs,
- rb.jitter);
+ VLOG(2) << "Cast RTCP received RB from SSRC " << remote_ssrc;
- RtcpReportBlock report_block;
+ transport::RtcpReportBlock report_block;
report_block.remote_ssrc = remote_ssrc;
report_block.media_ssrc = rb.ssrc;
report_block.fraction_lost = rb.fraction_lost;
@@ -229,9 +205,8 @@ void RtcpReceiver::HandleReportBlock(const RtcpField* rtcp_field,
report_block.delay_since_last_sr = rb.delay_last_sender_report;
if (rtt_feedback_) {
- rtt_feedback_->OnReceivedDelaySinceLastReport(rb.ssrc,
- rb.last_sender_report,
- rb.delay_last_sender_report);
+ rtt_feedback_->OnReceivedDelaySinceLastReport(
+ rb.ssrc, rb.last_sender_report, rb.delay_last_sender_report);
}
}
@@ -245,7 +220,7 @@ void RtcpReceiver::HandleSDES(RtcpParser* rtcp_parser) {
void RtcpReceiver::HandleSDESChunk(RtcpParser* rtcp_parser) {
const RtcpField& rtcp_field = rtcp_parser->Field();
- VLOG(1) << "Cast RTCP received SDES with cname " << rtcp_field.c_name.name;
+ VLOG(2) << "Cast RTCP received SDES with cname " << rtcp_field.c_name.name;
}
void RtcpReceiver::HandleXr(RtcpParser* rtcp_parser) {
@@ -337,7 +312,7 @@ void RtcpReceiver::HandleBYE(RtcpParser* rtcp_parser) {
const RtcpField& rtcp_field = rtcp_parser->Field();
uint32 remote_ssrc = rtcp_field.bye.sender_ssrc;
if (remote_ssrc_ == remote_ssrc) {
- VLOG(1) << "Cast RTCP received BYE from SSRC " << remote_ssrc;
+ VLOG(2) << "Cast RTCP received BYE from SSRC " << remote_ssrc;
}
rtcp_parser->Iterate();
}
@@ -346,7 +321,7 @@ void RtcpReceiver::HandlePLI(RtcpParser* rtcp_parser) {
const RtcpField& rtcp_field = rtcp_parser->Field();
if (ssrc_ == rtcp_field.pli.media_ssrc) {
// Received a signal that we need to send a new key frame.
- VLOG(1) << "Cast RTCP received PLI on our SSRC " << ssrc_;
+ VLOG(2) << "Cast RTCP received PLI on our SSRC " << ssrc_;
}
rtcp_parser->Iterate();
}
@@ -377,7 +352,7 @@ void RtcpReceiver::HandleRpsi(RtcpParser* rtcp_parser) {
}
rpsi_picture_id += (rtcp_field.rpsi.native_bit_string[bytes - 1] & 0x7f);
- VLOG(1) << "Cast RTCP received RPSI with picture_id " << rpsi_picture_id;
+ VLOG(2) << "Cast RTCP received RPSI with picture_id " << rpsi_picture_id;
}
void RtcpReceiver::HandlePayloadSpecificApp(RtcpParser* rtcp_parser) {
@@ -421,7 +396,7 @@ void RtcpReceiver::HandlePayloadSpecificRembItem(RtcpParser* rtcp_parser) {
for (int i = 0; i < rtcp_field.remb_item.number_of_ssrcs; ++i) {
if (rtcp_field.remb_item.ssrcs[i] == ssrc_) {
// Found matching ssrc.
- VLOG(1) << "Cast RTCP received REMB with received_bitrate "
+ VLOG(2) << "Cast RTCP received REMB with received_bitrate "
<< rtcp_field.remb_item.bitrate;
return;
}
@@ -450,11 +425,15 @@ void RtcpReceiver::HandleApplicationSpecificCastReceiverLog(
field_type = rtcp_parser->Iterate();
while (field_type == kRtcpApplicationSpecificCastReceiverLogEventCode) {
- HandleApplicationSpecificCastReceiverEventLog(rtcp_parser,
+ HandleApplicationSpecificCastReceiverEventLog(
+ rtcp_field.cast_receiver_log.rtp_timestamp,
+ rtcp_parser,
&frame_log.event_log_messages_);
field_type = rtcp_parser->Iterate();
}
- receiver_log.push_back(frame_log);
+
+ if (!frame_log.event_log_messages_.empty())
+ receiver_log.push_back(frame_log);
}
if (receiver_feedback_ && !receiver_log.empty()) {
@@ -463,52 +442,50 @@ void RtcpReceiver::HandleApplicationSpecificCastReceiverLog(
}
void RtcpReceiver::HandleApplicationSpecificCastReceiverEventLog(
+ uint32 frame_rtp_timestamp,
RtcpParser* rtcp_parser,
RtcpReceiverEventLogMessages* event_log_messages) {
const RtcpField& rtcp_field = rtcp_parser->Field();
- RtcpReceiverEventLogMessage event_log;
- event_log.type = TranslateToLogEventFromWireFormat(
- rtcp_field.cast_receiver_log.event);
- event_log.event_timestamp = base::TimeTicks() +
+ const uint8 event = rtcp_field.cast_receiver_log.event;
+ const CastLoggingEvent event_type = TranslateToLogEventFromWireFormat(event);
+ uint16 packet_id = event_type == PACKET_RECEIVED ?
+ rtcp_field.cast_receiver_log.delay_delta_or_packet_id.packet_id : 0;
+ const base::TimeTicks event_timestamp =
+ base::TimeTicks() +
base::TimeDelta::FromMilliseconds(
rtcp_field.cast_receiver_log.event_timestamp_base +
rtcp_field.cast_receiver_log.event_timestamp_delta);
- event_log.delay_delta = base::TimeDelta::FromMilliseconds(
- rtcp_field.cast_receiver_log.delay_delta_or_packet_id);
- event_log.packet_id =
- rtcp_field.cast_receiver_log.delay_delta_or_packet_id;
- event_log_messages->push_back(event_log);
-}
-
-void RtcpReceiver::HandleApplicationSpecificCastSenderLog(
- RtcpParser* rtcp_parser) {
- const RtcpField& rtcp_field = rtcp_parser->Field();
- uint32 remote_ssrc = rtcp_field.cast_sender_log.sender_ssrc;
- if (remote_ssrc_ != remote_ssrc) {
- RtcpFieldTypes field_type;
- // Message not to us. Iterate until we have passed this message.
- do {
- field_type = rtcp_parser->Iterate();
- } while (field_type == kRtcpApplicationSpecificCastSenderLogCode);
+ // The following code checks to see if we have already seen this event.
+ // The algorithm works by maintaining a sliding window of events. We have
+ // a queue and a set of events. We enqueue every new event and insert it
+ // into the set. When the queue becomes too big we remove the oldest event
+ // from both the queue and the set.
+ ReceiverEventKey key =
+ GetReceiverEventKey(
+ frame_rtp_timestamp, event_timestamp, event, packet_id);
+ if (receiver_event_key_set_.find(key) != receiver_event_key_set_.end()) {
return;
+ } else {
+ receiver_event_key_set_.insert(key);
+ receiver_event_key_queue_.push(key);
+
+ if (receiver_event_key_queue_.size() > receiver_event_history_size_) {
+ const ReceiverEventKey oldest_key = receiver_event_key_queue_.front();
+ receiver_event_key_queue_.pop();
+ receiver_event_key_set_.erase(oldest_key);
+ }
}
- RtcpSenderLogMessage sender_log;
- RtcpFieldTypes field_type = rtcp_parser->Iterate();
- while (field_type == kRtcpApplicationSpecificCastSenderLogCode) {
- const RtcpField& rtcp_field = rtcp_parser->Field();
- RtcpSenderFrameLogMessage frame_log;
- frame_log.frame_status =
- TranslateToFrameStatusFromWireFormat(rtcp_field.cast_sender_log.status);
- frame_log.rtp_timestamp = rtcp_field.cast_sender_log.rtp_timestamp;
- sender_log.push_back(frame_log);
- field_type = rtcp_parser->Iterate();
- }
- if (receiver_feedback_) {
- receiver_feedback_->OnReceivedSenderLog(sender_log);
- }
+ RtcpReceiverEventLogMessage event_log;
+ event_log.type = event_type;
+ event_log.event_timestamp = event_timestamp;
+ event_log.delay_delta = base::TimeDelta::FromMilliseconds(
+ rtcp_field.cast_receiver_log.delay_delta_or_packet_id.delay_delta);
+ event_log.packet_id =
+ rtcp_field.cast_receiver_log.delay_delta_or_packet_id.packet_id;
+ event_log_messages->push_back(event_log);
}
void RtcpReceiver::HandlePayloadSpecificCastItem(RtcpParser* rtcp_parser) {
@@ -516,6 +493,7 @@ void RtcpReceiver::HandlePayloadSpecificCastItem(RtcpParser* rtcp_parser) {
RtcpCastMessage cast_message(remote_ssrc_);
cast_message.ack_frame_id_ = ack_frame_id_wrap_helper_.MapTo32bitsFrameId(
rtcp_field.cast_item.last_frame_id);
+ cast_message.target_delay_ms_ = rtcp_field.cast_item.target_delay_ms;
RtcpFieldTypes packet_type = rtcp_parser->Iterate();
while (packet_type == kRtcpPayloadSpecificCastNackItemCode) {
@@ -545,15 +523,15 @@ void RtcpReceiver::HandlePayloadSpecificCastNackItem(
frame_it = ret.first;
DCHECK(frame_it != missing_frames_and_packets->end()) << "Invalid state";
}
- if (rtcp_field->cast_nack_item.packet_id == kRtcpCastAllPacketsLost) {
+ uint16 packet_id = rtcp_field->cast_nack_item.packet_id;
+ frame_it->second.insert(packet_id);
+
+ if (packet_id == kRtcpCastAllPacketsLost) {
// Special case all packets in a frame is missing.
return;
}
- uint16 packet_id = rtcp_field->cast_nack_item.packet_id;
uint8 bitmask = rtcp_field->cast_nack_item.bitmask;
- frame_it->second.insert(packet_id);
-
if (bitmask) {
for (int i = 1; i <= 8; ++i) {
if (bitmask & 1) {
@@ -576,9 +554,10 @@ void RtcpReceiver::HandleFIR(RtcpParser* rtcp_parser) {
void RtcpReceiver::HandleFIRItem(const RtcpField* rtcp_field) {
// Is it our sender that is requested to generate a new keyframe.
- if (ssrc_ != rtcp_field->fir_item.ssrc) return;
+ if (ssrc_ != rtcp_field->fir_item.ssrc)
+ return;
- VLOG(1) << "Cast RTCP received FIR on our SSRC " << ssrc_;
+ VLOG(2) << "Cast RTCP received FIR on our SSRC " << ssrc_;
}
} // namespace cast
diff --git a/chromium/media/cast/rtcp/rtcp_receiver.h b/chromium/media/cast/rtcp/rtcp_receiver.h
index 81383c4ec10..d3cef9e57b4 100644
--- a/chromium/media/cast/rtcp/rtcp_receiver.h
+++ b/chromium/media/cast/rtcp/rtcp_receiver.h
@@ -5,10 +5,13 @@
#ifndef MEDIA_CAST_RTCP_RTCP_RECEIVER_H_
#define MEDIA_CAST_RTCP_RTCP_RECEIVER_H_
-#include "media/cast/net/cast_net_defines.h"
+#include <queue>
+
+#include "base/containers/hash_tables.h"
#include "media/cast/rtcp/rtcp.h"
#include "media/cast/rtcp/rtcp_defines.h"
#include "media/cast/rtcp/rtcp_utility.h"
+#include "media/cast/transport/cast_transport_defines.h"
namespace media {
namespace cast {
@@ -16,7 +19,7 @@ namespace cast {
class RtcpReceiverFeedback {
public:
virtual void OnReceivedSenderReport(
- const RtcpSenderInfo& remote_sender_info) = 0;
+ const transport::RtcpSenderInfo& remote_sender_info) = 0;
virtual void OnReceiverReferenceTimeReport(
const RtcpReceiverReferenceTimeReport& remote_time_report) = 0;
@@ -26,9 +29,6 @@ class RtcpReceiverFeedback {
virtual void OnReceivedReceiverLog(
const RtcpReceiverLogMessage& receiver_log) = 0;
- virtual void OnReceivedSenderLog(
- const RtcpSenderLogMessage& sender_log) = 0;
-
virtual ~RtcpReceiverFeedback() {}
};
@@ -53,6 +53,10 @@ class RtcpReceiver {
void SetRemoteSSRC(uint32 ssrc);
+ // Set the history size to record Cast receiver events. Event history is
+ // used to remove duplicates. The history has no more than |size| events.
+ void SetCastReceiverEventHistorySize(size_t size);
+
void IncomingRtcpPacket(RtcpParser* rtcp_parser);
private:
@@ -60,8 +64,7 @@ class RtcpReceiver {
void HandleReceiverReport(RtcpParser* rtcp_parser);
- void HandleReportBlock(const RtcpField* rtcp_field,
- uint32 remote_ssrc);
+ void HandleReportBlock(const RtcpField* rtcp_field, uint32 remote_ssrc);
void HandleSDES(RtcpParser* rtcp_parser);
void HandleSDESChunk(RtcpParser* rtcp_parser);
@@ -100,6 +103,7 @@ class RtcpReceiver {
void HandleApplicationSpecificCastReceiverLog(RtcpParser* rtcp_parser);
void HandleApplicationSpecificCastSenderLog(RtcpParser* rtcp_parser);
void HandleApplicationSpecificCastReceiverEventLog(
+ uint32 frame_rtp_timestamp,
RtcpParser* rtcp_parser,
RtcpReceiverEventLogMessages* event_log_messages);
@@ -112,7 +116,13 @@ class RtcpReceiver {
RtcpRttFeedback* const rtt_feedback_;
scoped_refptr<CastEnvironment> cast_environment_;
- FrameIdWrapHelper ack_frame_id_wrap_helper_;
+ transport::FrameIdWrapHelper ack_frame_id_wrap_helper_;
+
+ // Maintains a history of receiver events.
+ size_t receiver_event_history_size_;
+ typedef std::pair<uint64, uint64> ReceiverEventKey;
+ base::hash_set<ReceiverEventKey> receiver_event_key_set_;
+ std::queue<ReceiverEventKey> receiver_event_key_queue_;
DISALLOW_COPY_AND_ASSIGN(RtcpReceiver);
};
diff --git a/chromium/media/cast/rtcp/rtcp_receiver_unittest.cc b/chromium/media/cast/rtcp/rtcp_receiver_unittest.cc
index b5c5d2d3889..51026d1554b 100644
--- a/chromium/media/cast/rtcp/rtcp_receiver_unittest.cc
+++ b/chromium/media/cast/rtcp/rtcp_receiver_unittest.cc
@@ -10,7 +10,8 @@
#include "media/cast/rtcp/rtcp_receiver.h"
#include "media/cast/rtcp/rtcp_utility.h"
#include "media/cast/rtcp/test_rtcp_packet_builder.h"
-#include "media/cast/test/fake_task_runner.h"
+#include "media/cast/test/fake_single_thread_task_runner.h"
+#include "media/cast/transport/cast_transport_defines.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace media {
@@ -21,6 +22,7 @@ using testing::_;
static const uint32 kSenderSsrc = 0x10203;
static const uint32 kSourceSsrc = 0x40506;
static const uint32 kUnknownSsrc = 0xDEAD;
+static const uint16 kTargetDelayMs = 100;
static const std::string kCName("test@10.1.1.1");
namespace {
@@ -28,8 +30,8 @@ class SenderFeedbackCastVerification : public RtcpSenderFeedback {
public:
SenderFeedbackCastVerification() : called_(false) {}
- virtual void OnReceivedCastFeedback(
- const RtcpCastMessage& cast_feedback) OVERRIDE {
+ virtual void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback)
+ OVERRIDE {
EXPECT_EQ(cast_feedback.media_ssrc_, kSenderSsrc);
EXPECT_EQ(cast_feedback.ack_frame_id_, kAckFrameId);
@@ -38,7 +40,8 @@ class SenderFeedbackCastVerification : public RtcpSenderFeedback {
EXPECT_TRUE(frame_it != cast_feedback.missing_frames_and_packets_.end());
EXPECT_EQ(kLostFrameId, frame_it->first);
- EXPECT_TRUE(frame_it->second.empty());
+ EXPECT_EQ(frame_it->second.size(), 1UL);
+ EXPECT_EQ(*frame_it->second.begin(), kRtcpCastAllPacketsLost);
++frame_it;
EXPECT_TRUE(frame_it != cast_feedback.missing_frames_and_packets_.end());
EXPECT_EQ(kFrameIdWithLostPackets, frame_it->first);
@@ -58,6 +61,8 @@ class SenderFeedbackCastVerification : public RtcpSenderFeedback {
private:
bool called_;
+
+ DISALLOW_COPY_AND_ASSIGN(SenderFeedbackCastVerification);
};
class RtcpReceiverCastLogVerification : public RtcpReceiverFeedback {
@@ -67,18 +72,18 @@ class RtcpReceiverCastLogVerification : public RtcpReceiverFeedback {
called_on_received_receiver_log_(false) {}
virtual void OnReceivedSenderReport(
- const RtcpSenderInfo& remote_sender_info) OVERRIDE {};
+ const transport::RtcpSenderInfo& remote_sender_info) OVERRIDE{};
virtual void OnReceiverReferenceTimeReport(
- const RtcpReceiverReferenceTimeReport& remote_time_report) OVERRIDE {};
+ const RtcpReceiverReferenceTimeReport& remote_time_report) OVERRIDE{};
- virtual void OnReceivedSendReportRequest() OVERRIDE {};
+ virtual void OnReceivedSendReportRequest() OVERRIDE{};
- virtual void OnReceivedReceiverLog(
- const RtcpReceiverLogMessage& receiver_log) OVERRIDE {
+ virtual void OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log)
+ OVERRIDE {
EXPECT_EQ(expected_receiver_log_.size(), receiver_log.size());
RtcpReceiverLogMessage::const_iterator expected_it =
- expected_receiver_log_.begin();
+ expected_receiver_log_.begin();
RtcpReceiverLogMessage::const_iterator incoming_it = receiver_log.begin();
for (; incoming_it != receiver_log.end(); ++incoming_it) {
EXPECT_EQ(expected_it->rtp_timestamp_, incoming_it->rtp_timestamp_);
@@ -94,7 +99,7 @@ class RtcpReceiverCastLogVerification : public RtcpReceiverFeedback {
EXPECT_EQ(event_expected_it->type, event_incoming_it->type);
EXPECT_EQ(event_expected_it->event_timestamp,
event_incoming_it->event_timestamp);
- if (event_expected_it->type == kPacketReceived) {
+ if (event_expected_it->type == PACKET_RECEIVED) {
EXPECT_EQ(event_expected_it->packet_id, event_incoming_it->packet_id);
} else {
EXPECT_EQ(event_expected_it->delay_delta,
@@ -107,26 +112,6 @@ class RtcpReceiverCastLogVerification : public RtcpReceiverFeedback {
called_on_received_receiver_log_ = true;
}
- virtual void OnReceivedSenderLog(
- const RtcpSenderLogMessage& sender_log) OVERRIDE {
- EXPECT_EQ(expected_sender_log_.size(), sender_log.size());
-
- RtcpSenderLogMessage::const_iterator expected_it =
- expected_sender_log_.begin();
- RtcpSenderLogMessage::const_iterator incoming_it = sender_log.begin();
- for (; expected_it != expected_sender_log_.end();
- ++expected_it, ++incoming_it) {
- EXPECT_EQ(expected_it->frame_status, incoming_it->frame_status);
- EXPECT_EQ(0xffffff & expected_it->rtp_timestamp,
- incoming_it->rtp_timestamp);
- }
- called_on_received_sender_log_ = true;
- }
-
- bool OnReceivedSenderLogCalled() {
- return called_on_received_sender_log_;
- }
-
bool OnReceivedReceiverLogCalled() {
return called_on_received_receiver_log_ && expected_receiver_log_.empty();
}
@@ -135,15 +120,12 @@ class RtcpReceiverCastLogVerification : public RtcpReceiverFeedback {
expected_receiver_log_ = receiver_log;
}
- void SetExpectedSenderLog(const RtcpSenderLogMessage& sender_log) {
- expected_sender_log_ = sender_log;
- }
-
private:
RtcpReceiverLogMessage expected_receiver_log_;
- RtcpSenderLogMessage expected_sender_log_;
bool called_on_received_sender_log_;
bool called_on_received_receiver_log_;
+
+ DISALLOW_COPY_AND_ASSIGN(RtcpReceiverCastLogVerification);
};
} // namespace
@@ -151,28 +133,26 @@ class RtcpReceiverCastLogVerification : public RtcpReceiverFeedback {
class RtcpReceiverTest : public ::testing::Test {
protected:
RtcpReceiverTest()
- : task_runner_(new test::FakeTaskRunner(&testing_clock_)),
- cast_environment_(new CastEnvironment(&testing_clock_, task_runner_,
- task_runner_, task_runner_, task_runner_, task_runner_,
- GetDefaultCastLoggingConfig())),
+ : testing_clock_(new base::SimpleTestTickClock()),
+ task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
+ cast_environment_(new CastEnvironment(
+ scoped_ptr<base::TickClock>(testing_clock_).Pass(),
+ task_runner_,
+ task_runner_,
+ task_runner_)),
rtcp_receiver_(new RtcpReceiver(cast_environment_,
&mock_sender_feedback_,
&mock_receiver_feedback_,
&mock_rtt_feedback_,
kSourceSsrc)) {
- }
-
- virtual ~RtcpReceiverTest() {}
-
- virtual void SetUp() OVERRIDE {
EXPECT_CALL(mock_receiver_feedback_, OnReceivedSenderReport(_)).Times(0);
- EXPECT_CALL(mock_receiver_feedback_,
- OnReceiverReferenceTimeReport(_)).Times(0);
- EXPECT_CALL(mock_receiver_feedback_,
- OnReceivedSendReportRequest()).Times(0);
+ EXPECT_CALL(mock_receiver_feedback_, OnReceiverReferenceTimeReport(_))
+ .Times(0);
+ EXPECT_CALL(mock_receiver_feedback_, OnReceivedSendReportRequest())
+ .Times(0);
EXPECT_CALL(mock_sender_feedback_, OnReceivedCastFeedback(_)).Times(0);
- EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(_, _, _)).Times(0);
+ EXPECT_CALL(mock_rtt_feedback_, OnReceivedDelaySinceLastReport(_, _, _))
+ .Times(0);
expected_sender_info_.ntp_seconds = kNtpHigh;
expected_sender_info_.ntp_fraction = kNtpLow;
@@ -193,22 +173,26 @@ class RtcpReceiverTest : public ::testing::Test {
expected_receiver_reference_report_.ntp_fraction = kNtpLow;
}
+ virtual ~RtcpReceiverTest() {}
+
// Injects an RTCP packet into the receiver.
void InjectRtcpPacket(const uint8* packet, uint16 length) {
RtcpParser rtcp_parser(packet, length);
rtcp_receiver_->IncomingRtcpPacket(&rtcp_parser);
}
- base::SimpleTestTickClock testing_clock_;
- scoped_refptr<test::FakeTaskRunner> task_runner_;
+ base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
+ scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
scoped_refptr<CastEnvironment> cast_environment_;
MockRtcpReceiverFeedback mock_receiver_feedback_;
MockRtcpRttFeedback mock_rtt_feedback_;
MockRtcpSenderFeedback mock_sender_feedback_;
scoped_ptr<RtcpReceiver> rtcp_receiver_;
- RtcpSenderInfo expected_sender_info_;
- RtcpReportBlock expected_report_block_;
+ transport::RtcpSenderInfo expected_sender_info_;
+ transport::RtcpReportBlock expected_report_block_;
RtcpReceiverReferenceTimeReport expected_receiver_reference_report_;
+
+ DISALLOW_COPY_AND_ASSIGN(RtcpReceiverTest);
};
TEST_F(RtcpReceiverTest, BrokenPacketIsIgnored) {
@@ -222,14 +206,14 @@ TEST_F(RtcpReceiverTest, InjectSenderReportPacket) {
// Expected to be ignored since the sender ssrc does not match our
// remote ssrc.
- InjectRtcpPacket(p.Packet(), p.Length());
+ InjectRtcpPacket(p.Data(), p.Length());
EXPECT_CALL(mock_receiver_feedback_,
OnReceivedSenderReport(expected_sender_info_)).Times(1);
rtcp_receiver_->SetRemoteSSRC(kSenderSsrc);
// Expected to be pass through since the sender ssrc match our remote ssrc.
- InjectRtcpPacket(p.Packet(), p.Length());
+ InjectRtcpPacket(p.Data(), p.Length());
}
TEST_F(RtcpReceiverTest, InjectReceiveReportPacket) {
@@ -239,19 +223,18 @@ TEST_F(RtcpReceiverTest, InjectReceiveReportPacket) {
// Expected to be ignored since the source ssrc does not match our
// local ssrc.
- InjectRtcpPacket(p1.Packet(), p1.Length());
+ InjectRtcpPacket(p1.Data(), p1.Length());
EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(kSourceSsrc,
- kLastSr,
- kDelayLastSr)).Times(1);
+ OnReceivedDelaySinceLastReport(
+ kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
TestRtcpPacketBuilder p2;
p2.AddRr(kSenderSsrc, 1);
p2.AddRb(kSourceSsrc);
// Expected to be pass through since the sender ssrc match our local ssrc.
- InjectRtcpPacket(p2.Packet(), p2.Length());
+ InjectRtcpPacket(p2.Data(), p2.Length());
}
TEST_F(RtcpReceiverTest, InjectSenderReportWithReportBlockPacket) {
@@ -263,7 +246,7 @@ TEST_F(RtcpReceiverTest, InjectSenderReportWithReportBlockPacket) {
// our remote ssrc.
// Report block expected to be ignored since the source ssrc does not match
// our local ssrc.
- InjectRtcpPacket(p1.Packet(), p1.Length());
+ InjectRtcpPacket(p1.Data(), p1.Length());
EXPECT_CALL(mock_receiver_feedback_,
OnReceivedSenderReport(expected_sender_info_)).Times(1);
@@ -273,13 +256,12 @@ TEST_F(RtcpReceiverTest, InjectSenderReportWithReportBlockPacket) {
// remote ssrc.
// Report block expected to be ignored since the source ssrc does not match
// our local ssrc.
- InjectRtcpPacket(p1.Packet(), p1.Length());
+ InjectRtcpPacket(p1.Data(), p1.Length());
EXPECT_CALL(mock_receiver_feedback_, OnReceivedSenderReport(_)).Times(0);
EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(kSourceSsrc,
- kLastSr,
- kDelayLastSr)).Times(1);
+ OnReceivedDelaySinceLastReport(
+ kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
rtcp_receiver_->SetRemoteSSRC(0);
@@ -291,14 +273,13 @@ TEST_F(RtcpReceiverTest, InjectSenderReportWithReportBlockPacket) {
// our remote ssrc.
// Receiver report expected to be pass through since the sender ssrc match
// our local ssrc.
- InjectRtcpPacket(p2.Packet(), p2.Length());
+ InjectRtcpPacket(p2.Data(), p2.Length());
EXPECT_CALL(mock_receiver_feedback_,
OnReceivedSenderReport(expected_sender_info_)).Times(1);
EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(kSourceSsrc,
- kLastSr,
- kDelayLastSr)).Times(1);
+ OnReceivedDelaySinceLastReport(
+ kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
rtcp_receiver_->SetRemoteSSRC(kSenderSsrc);
@@ -306,7 +287,7 @@ TEST_F(RtcpReceiverTest, InjectSenderReportWithReportBlockPacket) {
// remote ssrc.
// Receiver report expected to be pass through since the sender ssrc match
// our local ssrc.
- InjectRtcpPacket(p2.Packet(), p2.Length());
+ InjectRtcpPacket(p2.Data(), p2.Length());
}
TEST_F(RtcpReceiverTest, InjectSenderReportPacketWithDlrr) {
@@ -320,20 +301,19 @@ TEST_F(RtcpReceiverTest, InjectSenderReportPacketWithDlrr) {
// Expected to be ignored since the source ssrc does not match our
// local ssrc.
- InjectRtcpPacket(p.Packet(), p.Length());
+ InjectRtcpPacket(p.Data(), p.Length());
EXPECT_CALL(mock_receiver_feedback_,
OnReceivedSenderReport(expected_sender_info_)).Times(1);
EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(kSenderSsrc,
- kLastSr,
- kDelayLastSr)).Times(1);
+ OnReceivedDelaySinceLastReport(
+ kSenderSsrc, kLastSr, kDelayLastSr)).Times(1);
// Enable receiving sender report.
rtcp_receiver_->SetRemoteSSRC(kSenderSsrc);
// Expected to be pass through since the sender ssrc match our local ssrc.
- InjectRtcpPacket(p.Packet(), p.Length());
+ InjectRtcpPacket(p.Data(), p.Length());
}
TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithRrtr) {
@@ -345,14 +325,14 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithRrtr) {
// Expected to be ignored since the source ssrc does not match our
// local ssrc.
- InjectRtcpPacket(p1.Packet(), p1.Length());
+ InjectRtcpPacket(p1.Data(), p1.Length());
EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(kSourceSsrc,
- kLastSr,
- kDelayLastSr)).Times(1);
- EXPECT_CALL(mock_receiver_feedback_, OnReceiverReferenceTimeReport(
- expected_receiver_reference_report_)).Times(1);
+ OnReceivedDelaySinceLastReport(
+ kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
+ EXPECT_CALL(mock_receiver_feedback_,
+ OnReceiverReferenceTimeReport(
+ expected_receiver_reference_report_)).Times(1);
// Enable receiving reference time report.
rtcp_receiver_->SetRemoteSSRC(kSenderSsrc);
@@ -364,7 +344,7 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithRrtr) {
p2.AddXrRrtrBlock();
// Expected to be pass through since the sender ssrc match our local ssrc.
- InjectRtcpPacket(p2.Packet(), p2.Length());
+ InjectRtcpPacket(p2.Data(), p2.Length());
}
TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithIntraFrameRequest) {
@@ -375,12 +355,11 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithIntraFrameRequest) {
// Expected to be ignored since the source ssrc does not match our
// local ssrc.
- InjectRtcpPacket(p1.Packet(), p1.Length());
+ InjectRtcpPacket(p1.Data(), p1.Length());
EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(kSourceSsrc,
- kLastSr,
- kDelayLastSr)).Times(1);
+ OnReceivedDelaySinceLastReport(
+ kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
TestRtcpPacketBuilder p2;
p2.AddRr(kSenderSsrc, 1);
@@ -388,23 +367,22 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithIntraFrameRequest) {
p2.AddPli(kSenderSsrc, kSourceSsrc);
// Expected to be pass through since the sender ssrc match our local ssrc.
- InjectRtcpPacket(p2.Packet(), p2.Length());
+ InjectRtcpPacket(p2.Data(), p2.Length());
}
TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithCastFeedback) {
TestRtcpPacketBuilder p1;
p1.AddRr(kSenderSsrc, 1);
p1.AddRb(kUnknownSsrc);
- p1.AddCast(kSenderSsrc, kUnknownSsrc);
+ p1.AddCast(kSenderSsrc, kUnknownSsrc, kTargetDelayMs);
// Expected to be ignored since the source ssrc does not match our
// local ssrc.
- InjectRtcpPacket(p1.Packet(), p1.Length());
+ InjectRtcpPacket(p1.Data(), p1.Length());
EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(kSourceSsrc,
- kLastSr,
- kDelayLastSr)).Times(1);
+ OnReceivedDelaySinceLastReport(
+ kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
EXPECT_CALL(mock_sender_feedback_, OnReceivedCastFeedback(_)).Times(1);
// Enable receiving the cast feedback.
@@ -413,10 +391,10 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithCastFeedback) {
TestRtcpPacketBuilder p2;
p2.AddRr(kSenderSsrc, 1);
p2.AddRb(kSourceSsrc);
- p2.AddCast(kSenderSsrc, kSourceSsrc);
+ p2.AddCast(kSenderSsrc, kSourceSsrc, kTargetDelayMs);
// Expected to be pass through since the sender ssrc match our local ssrc.
- InjectRtcpPacket(p2.Packet(), p2.Length());
+ InjectRtcpPacket(p2.Data(), p2.Length());
}
TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithCastVerification) {
@@ -428,9 +406,8 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithCastVerification) {
kSourceSsrc);
EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(kSourceSsrc,
- kLastSr,
- kDelayLastSr)).Times(1);
+ OnReceivedDelaySinceLastReport(
+ kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
// Enable receiving the cast feedback.
rtcp_receiver.SetRemoteSSRC(kSenderSsrc);
@@ -438,48 +415,15 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithCastVerification) {
TestRtcpPacketBuilder p;
p.AddRr(kSenderSsrc, 1);
p.AddRb(kSourceSsrc);
- p.AddCast(kSenderSsrc, kSourceSsrc);
+ p.AddCast(kSenderSsrc, kSourceSsrc, kTargetDelayMs);
// Expected to be pass through since the sender ssrc match our local ssrc.
- RtcpParser rtcp_parser(p.Packet(), p.Length());
+ RtcpParser rtcp_parser(p.Data(), p.Length());
rtcp_receiver.IncomingRtcpPacket(&rtcp_parser);
EXPECT_TRUE(sender_feedback_cast_verification.called());
}
-TEST_F(RtcpReceiverTest, InjectSenderReportWithCastSenderLogVerification) {
- RtcpReceiverCastLogVerification cast_log_verification;
- RtcpReceiver rtcp_receiver(cast_environment_,
- &mock_sender_feedback_,
- &cast_log_verification,
- &mock_rtt_feedback_,
- kSourceSsrc);
- rtcp_receiver.SetRemoteSSRC(kSenderSsrc);
-
- RtcpSenderLogMessage sender_log;
- for (int j = 0; j < 359; ++j) {
- RtcpSenderFrameLogMessage sender_frame_log;
- sender_frame_log.frame_status = kRtcpSenderFrameStatusSentToNetwork;
- sender_frame_log.rtp_timestamp = kRtpTimestamp + j * 90;
- sender_log.push_back(sender_frame_log);
- }
- cast_log_verification.SetExpectedSenderLog(sender_log);
-
- TestRtcpPacketBuilder p;
- p.AddSr(kSenderSsrc, 0);
- p.AddSdesCname(kSenderSsrc, kCName);
- p.AddSenderLog(kSenderSsrc);
-
- for (int i = 0; i < 359; ++i) {
- p.AddSenderFrameLog(kRtcpSenderFrameStatusSentToNetwork,
- kRtpTimestamp + i * 90);
- }
- RtcpParser rtcp_parser(p.Packet(), p.Length());
- rtcp_receiver.IncomingRtcpPacket(&rtcp_parser);
-
- EXPECT_TRUE(cast_log_verification.OnReceivedSenderLogCalled());
-}
-
TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationBase) {
static const uint32 kTimeBaseMs = 12345678;
static const uint32 kTimeDelayMs = 10;
@@ -494,21 +438,28 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationBase) {
&mock_rtt_feedback_,
kSourceSsrc);
rtcp_receiver.SetRemoteSSRC(kSenderSsrc);
+ rtcp_receiver.SetCastReceiverEventHistorySize(100);
RtcpReceiverLogMessage receiver_log;
RtcpReceiverFrameLogMessage frame_log(kRtpTimestamp);
RtcpReceiverEventLogMessage event_log;
- event_log.type = kAckSent;
+ event_log.type = FRAME_ACK_SENT;
event_log.event_timestamp = testing_clock.NowTicks();
event_log.delay_delta = base::TimeDelta::FromMilliseconds(kDelayDeltaMs);
frame_log.event_log_messages_.push_back(event_log);
testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeDelayMs));
- event_log.type = kPacketReceived;
+ event_log.type = PACKET_RECEIVED;
event_log.event_timestamp = testing_clock.NowTicks();
event_log.packet_id = kLostPacketId1;
frame_log.event_log_messages_.push_back(event_log);
+
+ event_log.type = PACKET_RECEIVED;
+ event_log.event_timestamp = testing_clock.NowTicks();
+ event_log.packet_id = kLostPacketId2;
+ frame_log.event_log_messages_.push_back(event_log);
+
receiver_log.push_back(frame_log);
cast_log_verification.SetExpectedReceiverLog(receiver_log);
@@ -517,15 +468,22 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationBase) {
p.AddRr(kSenderSsrc, 1);
p.AddRb(kSourceSsrc);
p.AddReceiverLog(kSenderSsrc);
- p.AddReceiverFrameLog(kRtpTimestamp, 2, kTimeBaseMs);
- p.AddReceiverEventLog(kDelayDeltaMs, 1, 0);
- p.AddReceiverEventLog(kLostPacketId1, 6, kTimeDelayMs);
+ p.AddReceiverFrameLog(kRtpTimestamp, 3, kTimeBaseMs);
+ p.AddReceiverEventLog(kDelayDeltaMs, FRAME_ACK_SENT, 0);
+ p.AddReceiverEventLog(kLostPacketId1, PACKET_RECEIVED, kTimeDelayMs);
+ p.AddReceiverEventLog(kLostPacketId2, PACKET_RECEIVED, kTimeDelayMs);
+
+ // Adds duplicated receiver event.
+ p.AddReceiverFrameLog(kRtpTimestamp, 3, kTimeBaseMs);
+ p.AddReceiverEventLog(kDelayDeltaMs, FRAME_ACK_SENT, 0);
+ p.AddReceiverEventLog(kLostPacketId1, PACKET_RECEIVED, kTimeDelayMs);
+ p.AddReceiverEventLog(kLostPacketId2, PACKET_RECEIVED, kTimeDelayMs);
EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(kSourceSsrc, kLastSr, kDelayLastSr)).
- Times(1);
+ OnReceivedDelaySinceLastReport(
+ kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
- RtcpParser rtcp_parser(p.Packet(), p.Length());
+ RtcpParser rtcp_parser(p.Data(), p.Length());
rtcp_receiver.IncomingRtcpPacket(&rtcp_parser);
EXPECT_TRUE(cast_log_verification.OnReceivedReceiverLogCalled());
@@ -551,7 +509,7 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationMulti) {
for (int j = 0; j < 100; ++j) {
RtcpReceiverFrameLogMessage frame_log(kRtpTimestamp);
RtcpReceiverEventLogMessage event_log;
- event_log.type = kAckSent;
+ event_log.type = FRAME_ACK_SENT;
event_log.event_timestamp = testing_clock.NowTicks();
event_log.delay_delta = base::TimeDelta::FromMilliseconds(kDelayDeltaMs);
frame_log.event_log_messages_.push_back(event_log);
@@ -566,21 +524,19 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationMulti) {
p.AddRb(kSourceSsrc);
p.AddReceiverLog(kSenderSsrc);
for (int i = 0; i < 100; ++i) {
- p.AddReceiverFrameLog(kRtpTimestamp, 1, kTimeBaseMs + i * kTimeDelayMs);
- p.AddReceiverEventLog(kDelayDeltaMs, 1, 0);
+ p.AddReceiverFrameLog(kRtpTimestamp, 1, kTimeBaseMs + i * kTimeDelayMs);
+ p.AddReceiverEventLog(kDelayDeltaMs, FRAME_ACK_SENT, 0);
}
EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(kSourceSsrc, kLastSr, kDelayLastSr)).
- Times(1);
+ OnReceivedDelaySinceLastReport(
+ kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
- RtcpParser rtcp_parser(p.Packet(), p.Length());
+ RtcpParser rtcp_parser(p.Data(), p.Length());
rtcp_receiver.IncomingRtcpPacket(&rtcp_parser);
EXPECT_TRUE(cast_log_verification.OnReceivedReceiverLogCalled());
}
-
-
} // namespace cast
} // namespace media
diff --git a/chromium/media/cast/rtcp/rtcp_sender.cc b/chromium/media/cast/rtcp/rtcp_sender.cc
index b5cf4ce4ced..bf7d30c84c8 100644
--- a/chromium/media/cast/rtcp/rtcp_sender.cc
+++ b/chromium/media/cast/rtcp/rtcp_sender.cc
@@ -4,263 +4,226 @@
#include "media/cast/rtcp/rtcp_sender.h"
+#include <stdint.h>
+
#include <algorithm>
#include <vector>
+#include "base/big_endian.h"
#include "base/logging.h"
#include "media/cast/cast_environment.h"
-#include "media/cast/net/pacing/paced_sender.h"
+#include "media/cast/rtcp/rtcp_defines.h"
#include "media/cast/rtcp/rtcp_utility.h"
-#include "net/base/big_endian.h"
-
-static const size_t kRtcpCastLogHeaderSize = 12;
-static const size_t kRtcpSenderFrameLogSize = 4;
-static const size_t kRtcpReceiverFrameLogSize = 8;
-static const size_t kRtcpReceiverEventLogSize = 4;
+#include "media/cast/transport/cast_transport_defines.h"
+#include "media/cast/transport/pacing/paced_sender.h"
+namespace media {
+namespace cast {
namespace {
+
+// Max delta is 4095 milliseconds because we need to be able to encode it in
+// 12 bits.
+const int64 kMaxWireFormatTimeDeltaMs = INT64_C(0xfff);
+
uint16 MergeEventTypeAndTimestampForWireFormat(
- const media::cast::CastLoggingEvent& event,
+ const CastLoggingEvent& event,
const base::TimeDelta& time_delta) {
int64 time_delta_ms = time_delta.InMilliseconds();
- // Max delta is 4096 milliseconds.
- DCHECK_GE(GG_INT64_C(0xfff), time_delta_ms);
-
- uint16 event_type_and_timestamp_delta =
- static_cast<uint16>(time_delta_ms & 0xfff);
-
- uint16 event_type = 0;
- switch (event) {
- case media::cast::kAckSent:
- event_type = 1;
- break;
- case media::cast::kAudioPlayoutDelay:
- event_type = 2;
- break;
- case media::cast::kAudioFrameDecoded:
- event_type = 3;
- break;
- case media::cast::kVideoFrameDecoded:
- event_type = 4;
- break;
- case media::cast::kVideoRenderDelay:
- event_type = 5;
- break;
- case media::cast::kPacketReceived:
- event_type = 6;
- break;
- default:
- NOTREACHED();
- }
- DCHECK(!(event_type & 0xfff0));
- return (event_type << 12) + event_type_and_timestamp_delta;
-}
-bool ScanRtcpReceiverLogMessage(
- const media::cast::RtcpReceiverLogMessage& receiver_log_message,
- size_t start_size,
- size_t* number_of_frames,
- size_t* total_number_of_messages_to_send,
- size_t* rtcp_log_size) {
- if (receiver_log_message.empty()) return false;
+ DCHECK_GE(time_delta_ms, 0);
+ DCHECK_LE(time_delta_ms, kMaxWireFormatTimeDeltaMs);
- size_t remaining_space = media::cast::kIpPacketSize - start_size;
+ uint16 time_delta_12_bits =
+ static_cast<uint16>(time_delta_ms & kMaxWireFormatTimeDeltaMs);
- // We must have space for at least one message
- DCHECK_GE(remaining_space, kRtcpCastLogHeaderSize +
- kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize)
- << "Not enough buffer space";
+ uint16 event_type_4_bits = ConvertEventTypeToWireFormat(event);
+ DCHECK(event_type_4_bits);
+ DCHECK(~(event_type_4_bits & 0xfff0));
+ return (event_type_4_bits << 12) | time_delta_12_bits;
+}
- if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize +
- kRtcpReceiverEventLogSize) {
- return false;
- }
- // Account for the RTCP header for an application-defined packet.
- remaining_space -= kRtcpCastLogHeaderSize;
+bool EventTimestampLessThan(const RtcpReceiverEventLogMessage& lhs,
+ const RtcpReceiverEventLogMessage& rhs) {
+ return lhs.event_timestamp < rhs.event_timestamp;
+}
- media::cast::RtcpReceiverLogMessage::const_iterator frame_it =
- receiver_log_message.begin();
- for (; frame_it != receiver_log_message.end(); ++frame_it) {
- (*number_of_frames)++;
+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) {
+ RtcpReceiverLogMessage::const_iterator it =
+ redundancy_receiver_log_message.begin();
+ while (it != redundancy_receiver_log_message.end() &&
+ *remaining_space >=
+ kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) {
+ 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;
+ *total_number_of_messages_to_send += event_log_messages.size();
+ ++it;
+ }
+}
- remaining_space -= kRtcpReceiverFrameLogSize;
+// A class to build a string representing the NACK list in Cast message.
+//
+// The string will look like "23:3-6 25:1,5-6", meaning packets 3 to 6 in frame
+// 23 are being NACK'ed (i.e. they are missing from the receiver's point of
+// view) and packets 1, 5 and 6 are missing in frame 25. A frame that is
+// completely missing will show as "26:65535".
+class NackStringBuilder {
+ public:
+ NackStringBuilder()
+ : frame_count_(0),
+ packet_count_(0),
+ last_frame_id_(-1),
+ last_packet_id_(-1),
+ contiguous_sequence_(false) {}
+ ~NackStringBuilder() {}
+
+ bool Empty() const { return frame_count_ == 0; }
+
+ void PushFrame(int frame_id) {
+ DCHECK_GE(frame_id, 0);
+ if (frame_count_ > 0) {
+ if (frame_id == last_frame_id_) {
+ return;
+ }
+ if (contiguous_sequence_) {
+ stream_ << "-" << last_packet_id_;
+ }
+ stream_ << ", ";
+ }
+ stream_ << frame_id;
+ last_frame_id_ = frame_id;
+ packet_count_ = 0;
+ contiguous_sequence_ = false;
+ ++frame_count_;
+ }
- size_t messages_in_frame = frame_it->event_log_messages_.size();
- size_t remaining_space_in_messages =
- remaining_space / kRtcpReceiverEventLogSize;
- size_t messages_to_send = std::min(messages_in_frame,
- remaining_space_in_messages);
- if (messages_to_send > media::cast::kRtcpMaxReceiverLogMessages) {
- // We can't send more than 256 messages.
- remaining_space -= media::cast::kRtcpMaxReceiverLogMessages *
- kRtcpReceiverEventLogSize;
- *total_number_of_messages_to_send +=
- media::cast::kRtcpMaxReceiverLogMessages;
- break;
+ void PushPacket(int packet_id) {
+ DCHECK_GE(last_frame_id_, 0);
+ DCHECK_GE(packet_id, 0);
+ if (packet_count_ == 0) {
+ stream_ << ":" << packet_id;
+ } else if (packet_id == last_packet_id_ + 1) {
+ contiguous_sequence_ = true;
+ } else {
+ if (contiguous_sequence_) {
+ stream_ << "-" << last_packet_id_;
+ contiguous_sequence_ = false;
+ }
+ stream_ << "," << packet_id;
}
- remaining_space -= messages_to_send * kRtcpReceiverEventLogSize;
- *total_number_of_messages_to_send += messages_to_send;
+ ++packet_count_;
+ last_packet_id_ = packet_id;
+ }
- if (remaining_space <
- kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) {
- // Make sure that we have room for at least one more message.
- break;
+ std::string GetString() {
+ if (contiguous_sequence_) {
+ stream_ << "-" << last_packet_id_;
+ contiguous_sequence_ = false;
}
+ return stream_.str();
}
- *rtcp_log_size = kRtcpCastLogHeaderSize +
- *number_of_frames * kRtcpReceiverFrameLogSize +
- *total_number_of_messages_to_send * kRtcpReceiverEventLogSize;
- DCHECK_GE(media::cast::kIpPacketSize,
- start_size + *rtcp_log_size) << "Not enough buffer space";
- VLOG(1) << "number of frames " << *number_of_frames;
- VLOG(1) << "total messages to send " << *total_number_of_messages_to_send;
- VLOG(1) << "rtcp log size " << *rtcp_log_size;
- return true;
-}
+ private:
+ std::ostringstream stream_;
+ int frame_count_;
+ int packet_count_;
+ int last_frame_id_;
+ int last_packet_id_;
+ bool contiguous_sequence_;
+};
} // namespace
-namespace media {
-namespace cast {
-
+// TODO(mikhal): This is only used by the receiver. Consider renaming.
RtcpSender::RtcpSender(scoped_refptr<CastEnvironment> cast_environment,
- PacedPacketSender* outgoing_transport,
+ transport::PacedPacketSender* outgoing_transport,
uint32 sending_ssrc,
const std::string& c_name)
- : ssrc_(sending_ssrc),
- c_name_(c_name),
- transport_(outgoing_transport),
- cast_environment_(cast_environment) {
+ : ssrc_(sending_ssrc),
+ c_name_(c_name),
+ transport_(outgoing_transport),
+ cast_environment_(cast_environment) {
DCHECK_LT(c_name_.length(), kRtcpCnameSize) << "Invalid config";
}
RtcpSender::~RtcpSender() {}
-void RtcpSender::SendRtcpFromRtpSender(uint32 packet_type_flags,
- const RtcpSenderInfo* sender_info,
- const RtcpDlrrReportBlock* dlrr,
- RtcpSenderLogMessage* sender_log) {
- if (packet_type_flags & kRtcpRr ||
- packet_type_flags & kRtcpPli ||
- packet_type_flags & kRtcpRrtr ||
- packet_type_flags & kRtcpCast ||
- packet_type_flags & kRtcpReceiverLog ||
- packet_type_flags & kRtcpRpsi ||
- packet_type_flags & kRtcpRemb ||
- packet_type_flags & kRtcpNack) {
- NOTREACHED() << "Invalid argument";
- }
-
- std::vector<uint8> packet;
- packet.reserve(kIpPacketSize);
- if (packet_type_flags & kRtcpSr) {
- DCHECK(sender_info) << "Invalid argument";
- BuildSR(*sender_info, NULL, &packet);
- BuildSdec(&packet);
- }
- if (packet_type_flags & kRtcpBye) {
- BuildBye(&packet);
- }
- if (packet_type_flags & kRtcpDlrr) {
- DCHECK(dlrr) << "Invalid argument";
- BuildDlrrRb(dlrr, &packet);
- }
- if (packet_type_flags & kRtcpSenderLog) {
- DCHECK(sender_log) << "Invalid argument";
- BuildSenderLog(sender_log, &packet);
- }
- if (packet.empty())
- return; // Sanity don't send empty packets.
-
- transport_->SendRtcpPacket(packet);
-}
-
void RtcpSender::SendRtcpFromRtpReceiver(
uint32 packet_type_flags,
- const RtcpReportBlock* report_block,
+ const transport::RtcpReportBlock* report_block,
const RtcpReceiverReferenceTimeReport* rrtr,
const RtcpCastMessage* cast_message,
- RtcpReceiverLogMessage* receiver_log) {
- if (packet_type_flags & kRtcpSr ||
- packet_type_flags & kRtcpDlrr ||
- packet_type_flags & kRtcpSenderLog) {
+ const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events,
+ uint16 target_delay_ms) {
+ if (packet_type_flags & transport::kRtcpSr ||
+ packet_type_flags & transport::kRtcpDlrr ||
+ packet_type_flags & transport::kRtcpSenderLog) {
NOTREACHED() << "Invalid argument";
}
- if (packet_type_flags & kRtcpPli ||
- packet_type_flags & kRtcpRpsi ||
- packet_type_flags & kRtcpRemb ||
- packet_type_flags & kRtcpNack) {
+ if (packet_type_flags & transport::kRtcpPli ||
+ packet_type_flags & transport::kRtcpRpsi ||
+ packet_type_flags & transport::kRtcpRemb ||
+ packet_type_flags & transport::kRtcpNack) {
// Implement these for webrtc interop.
NOTIMPLEMENTED();
}
- std::vector<uint8> packet;
- packet.reserve(kIpPacketSize);
+ transport::PacketRef packet(new base::RefCountedData<Packet>);
+ packet->data.reserve(kMaxIpPacketSize);
- if (packet_type_flags & kRtcpRr) {
- BuildRR(report_block, &packet);
+ if (packet_type_flags & transport::kRtcpRr) {
+ BuildRR(report_block, &packet->data);
if (!c_name_.empty()) {
- BuildSdec(&packet);
+ BuildSdec(&packet->data);
}
}
- if (packet_type_flags & kRtcpBye) {
- BuildBye(&packet);
+ if (packet_type_flags & transport::kRtcpBye) {
+ BuildBye(&packet->data);
}
- if (packet_type_flags & kRtcpRrtr) {
+ if (packet_type_flags & transport::kRtcpRrtr) {
DCHECK(rrtr) << "Invalid argument";
- BuildRrtr(rrtr, &packet);
+ BuildRrtr(rrtr, &packet->data);
}
- if (packet_type_flags & kRtcpCast) {
+ if (packet_type_flags & transport::kRtcpCast) {
DCHECK(cast_message) << "Invalid argument";
- BuildCast(cast_message, &packet);
+ BuildCast(cast_message, target_delay_ms, &packet->data);
}
- if (packet_type_flags & kRtcpReceiverLog) {
- DCHECK(receiver_log) << "Invalid argument";
- BuildReceiverLog(receiver_log, &packet);
+ if (packet_type_flags & transport::kRtcpReceiverLog) {
+ DCHECK(rtcp_events) << "Invalid argument";
+ BuildReceiverLog(*rtcp_events, &packet->data);
}
- if (packet.empty()) return; // Sanity don't send empty packets.
- transport_->SendRtcpPacket(packet);
-}
-
-void RtcpSender::BuildSR(const RtcpSenderInfo& sender_info,
- const RtcpReportBlock* report_block,
- std::vector<uint8>* packet) const {
- // Sender report.
- size_t start_size = packet->size();
- DCHECK_LT(start_size + 52, kIpPacketSize) << "Not enough buffer space";
- if (start_size + 52 > kIpPacketSize) return;
-
- uint16 number_of_rows = (report_block) ? 12 : 6;
- packet->resize(start_size + 28);
-
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 28);
- big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0));
- big_endian_writer.WriteU8(kPacketTypeSenderReport);
- big_endian_writer.WriteU16(number_of_rows);
- big_endian_writer.WriteU32(ssrc_);
- big_endian_writer.WriteU32(sender_info.ntp_seconds);
- big_endian_writer.WriteU32(sender_info.ntp_fraction);
- big_endian_writer.WriteU32(sender_info.rtp_timestamp);
- big_endian_writer.WriteU32(sender_info.send_packet_count);
- big_endian_writer.WriteU32(static_cast<uint32>(sender_info.send_octet_count));
+ if (packet->data.empty())
+ return; // Sanity don't send empty packets.
- if (report_block) {
- AddReportBlocks(*report_block, packet); // Adds 24 bytes.
- }
+ transport_->SendRtcpPacket(ssrc_, packet);
}
-void RtcpSender::BuildRR(const RtcpReportBlock* report_block,
- std::vector<uint8>* packet) const {
+void RtcpSender::BuildRR(const transport::RtcpReportBlock* report_block,
+ Packet* packet) const {
size_t start_size = packet->size();
- DCHECK_LT(start_size + 32, kIpPacketSize) << "Not enough buffer space";
- if (start_size + 32 > kIpPacketSize) return;
+ DCHECK_LT(start_size + 32, kMaxIpPacketSize) << "Not enough buffer space";
+ if (start_size + 32 > kMaxIpPacketSize)
+ return;
uint16 number_of_rows = (report_block) ? 7 : 1;
packet->resize(start_size + 8);
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 8);
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 8);
big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0));
- big_endian_writer.WriteU8(kPacketTypeReceiverReport);
+ big_endian_writer.WriteU8(transport::kPacketTypeReceiverReport);
big_endian_writer.WriteU16(number_of_rows);
big_endian_writer.WriteU32(ssrc_);
@@ -269,15 +232,17 @@ void RtcpSender::BuildRR(const RtcpReportBlock* report_block,
}
}
-void RtcpSender::AddReportBlocks(const RtcpReportBlock& report_block,
- std::vector<uint8>* packet) const {
+void RtcpSender::AddReportBlocks(const transport::RtcpReportBlock& report_block,
+ Packet* packet) const {
size_t start_size = packet->size();
- DCHECK_LT(start_size + 24, kIpPacketSize) << "Not enough buffer space";
- if (start_size + 24 > kIpPacketSize) return;
+ DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space";
+ if (start_size + 24 > kMaxIpPacketSize)
+ return;
packet->resize(start_size + 24);
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24);
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 24);
big_endian_writer.WriteU32(report_block.media_ssrc);
big_endian_writer.WriteU8(report_block.fraction_lost);
big_endian_writer.WriteU8(report_block.cumulative_lost >> 16);
@@ -297,30 +262,32 @@ void RtcpSender::AddReportBlocks(const RtcpReportBlock& report_block,
big_endian_writer.WriteU32(report_block.delay_since_last_sr);
}
-void RtcpSender::BuildSdec(std::vector<uint8>* packet) const {
+void RtcpSender::BuildSdec(Packet* packet) const {
size_t start_size = packet->size();
- DCHECK_LT(start_size + 12 + c_name_.length(), kIpPacketSize)
+ DCHECK_LT(start_size + 12 + c_name_.length(), kMaxIpPacketSize)
<< "Not enough buffer space";
- if (start_size + 12 > kIpPacketSize) return;
+ if (start_size + 12 > kMaxIpPacketSize)
+ return;
// SDES Source Description.
packet->resize(start_size + 10);
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 10);
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 10);
// We always need to add one SDES CNAME.
big_endian_writer.WriteU8(0x80 + 1);
- big_endian_writer.WriteU8(kPacketTypeSdes);
+ big_endian_writer.WriteU8(transport::kPacketTypeSdes);
// Handle SDES length later on.
uint32 sdes_length_position = static_cast<uint32>(start_size) + 3;
big_endian_writer.WriteU16(0);
big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
- big_endian_writer.WriteU8(1); // CNAME = 1
+ big_endian_writer.WriteU8(1); // CNAME = 1
big_endian_writer.WriteU8(static_cast<uint8>(c_name_.length()));
size_t sdes_length = 10 + c_name_.length();
- packet->insert(packet->end(), c_name_.c_str(),
- c_name_.c_str() + c_name_.length());
+ packet->insert(
+ packet->end(), c_name_.c_str(), c_name_.c_str() + c_name_.length());
size_t padding = 0;
@@ -340,20 +307,21 @@ void RtcpSender::BuildSdec(std::vector<uint8>* packet) const {
(*packet)[sdes_length_position] = buffer_length;
}
-void RtcpSender::BuildPli(uint32 remote_ssrc,
- std::vector<uint8>* packet) const {
+void RtcpSender::BuildPli(uint32 remote_ssrc, Packet* packet) const {
size_t start_size = packet->size();
- DCHECK_LT(start_size + 12, kIpPacketSize) << "Not enough buffer space";
- if (start_size + 12 > kIpPacketSize) return;
+ DCHECK_LT(start_size + 12, kMaxIpPacketSize) << "Not enough buffer space";
+ if (start_size + 12 > kMaxIpPacketSize)
+ return;
packet->resize(start_size + 12);
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 12);
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 12);
uint8 FMT = 1; // Picture loss indicator.
big_endian_writer.WriteU8(0x80 + FMT);
- big_endian_writer.WriteU8(kPacketTypePayloadSpecific);
- big_endian_writer.WriteU16(2); // Used fixed length of 2.
- big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
+ big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
+ big_endian_writer.WriteU16(2); // Used fixed length of 2.
+ big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
big_endian_writer.WriteU32(remote_ssrc); // Add the remote SSRC.
}
@@ -366,18 +334,19 @@ void RtcpSender::BuildPli(uint32 remote_ssrc,
| defined per codec ... | Padding (0) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi,
- std::vector<uint8>* packet) const {
+void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi, Packet* packet) const {
size_t start_size = packet->size();
- DCHECK_LT(start_size + 24, kIpPacketSize) << "Not enough buffer space";
- if (start_size + 24 > kIpPacketSize) return;
+ DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space";
+ if (start_size + 24 > kMaxIpPacketSize)
+ return;
packet->resize(start_size + 24);
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24);
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 24);
uint8 FMT = 3; // Reference Picture Selection Indication.
big_endian_writer.WriteU8(0x80 + FMT);
- big_endian_writer.WriteU8(kPacketTypePayloadSpecific);
+ big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
// Calculate length.
uint32 bits_required = 7;
@@ -407,8 +376,8 @@ void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi,
// Add picture ID.
for (int i = bytes_required - 1; i > 0; i--) {
- big_endian_writer.WriteU8(
- 0x80 | static_cast<uint8>(rpsi->picture_id >> (i * 7)));
+ big_endian_writer.WriteU8(0x80 |
+ static_cast<uint8>(rpsi->picture_id >> (i * 7)));
}
// Add last byte of picture ID.
big_endian_writer.WriteU8(static_cast<uint8>(rpsi->picture_id & 0x7f));
@@ -419,38 +388,38 @@ void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi,
}
}
-void RtcpSender::BuildRemb(const RtcpRembMessage* remb,
- std::vector<uint8>* packet) const {
+void RtcpSender::BuildRemb(const RtcpRembMessage* remb, Packet* packet) const {
size_t start_size = packet->size();
size_t remb_size = 20 + 4 * remb->remb_ssrcs.size();
- DCHECK_LT(start_size + remb_size, kIpPacketSize)
+ DCHECK_LT(start_size + remb_size, kMaxIpPacketSize)
<< "Not enough buffer space";
- if (start_size + remb_size > kIpPacketSize) return;
+ if (start_size + remb_size > kMaxIpPacketSize)
+ return;
packet->resize(start_size + remb_size);
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), remb_size);
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), remb_size);
// Add application layer feedback.
uint8 FMT = 15;
big_endian_writer.WriteU8(0x80 + FMT);
- big_endian_writer.WriteU8(kPacketTypePayloadSpecific);
+ big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
big_endian_writer.WriteU8(0);
big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size() + 4));
big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
- big_endian_writer.WriteU32(0); // Remote SSRC must be 0.
+ big_endian_writer.WriteU32(0); // Remote SSRC must be 0.
big_endian_writer.WriteU32(kRemb);
big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size()));
// 6 bit exponent and a 18 bit mantissa.
uint8 bitrate_exponent;
uint32 bitrate_mantissa;
- BitrateToRembExponentBitrate(remb->remb_bitrate,
- &bitrate_exponent,
- &bitrate_mantissa);
+ BitrateToRembExponentBitrate(
+ remb->remb_bitrate, &bitrate_exponent, &bitrate_mantissa);
- big_endian_writer.WriteU8(static_cast<uint8>((bitrate_exponent << 2) +
- ((bitrate_mantissa >> 16) & 0x03)));
+ big_endian_writer.WriteU8(static_cast<uint8>(
+ (bitrate_exponent << 2) + ((bitrate_mantissa >> 16) & 0x03)));
big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa >> 8));
big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa));
@@ -458,34 +427,33 @@ void RtcpSender::BuildRemb(const RtcpRembMessage* remb,
for (; it != remb->remb_ssrcs.end(); ++it) {
big_endian_writer.WriteU32(*it);
}
- cast_environment_->Logging()->InsertGenericEvent(kRembBitrate,
- remb->remb_bitrate);
}
-void RtcpSender::BuildNack(const RtcpNackMessage* nack,
- std::vector<uint8>* packet) const {
+void RtcpSender::BuildNack(const RtcpNackMessage* nack, Packet* packet) const {
size_t start_size = packet->size();
- DCHECK_LT(start_size + 16, kIpPacketSize) << "Not enough buffer space";
- if (start_size + 16 > kIpPacketSize) return;
+ DCHECK_LT(start_size + 16, kMaxIpPacketSize) << "Not enough buffer space";
+ if (start_size + 16 > kMaxIpPacketSize)
+ return;
packet->resize(start_size + 16);
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 16);
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 16);
uint8 FMT = 1;
big_endian_writer.WriteU8(0x80 + FMT);
- big_endian_writer.WriteU8(kPacketTypeGenericRtpFeedback);
+ big_endian_writer.WriteU8(transport::kPacketTypeGenericRtpFeedback);
big_endian_writer.WriteU8(0);
size_t nack_size_pos = start_size + 3;
big_endian_writer.WriteU8(3);
- big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
+ big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
big_endian_writer.WriteU32(nack->remote_ssrc); // Add the remote SSRC.
// Build NACK bitmasks and write them to the Rtcp message.
// The nack list should be sorted and not contain duplicates.
size_t number_of_nack_fields = 0;
- size_t max_number_of_nack_fields = std::min<size_t>(kRtcpMaxNackFields,
- (kIpPacketSize - packet->size()) / 4);
+ size_t max_number_of_nack_fields = std::min<size_t>(
+ kRtcpMaxNackFields, (kMaxIpPacketSize - packet->size()) / 4);
std::list<uint16>::const_iterator it = nack->nack_list.begin();
while (it != nack->nack_list.end() &&
@@ -504,11 +472,13 @@ void RtcpSender::BuildNack(const RtcpNackMessage* nack,
}
// Write the sequence number and the bitmask to the packet.
start_size = packet->size();
- DCHECK_LT(start_size + 4, kIpPacketSize) << "Not enough buffer space";
- if (start_size + 4 > kIpPacketSize) return;
+ DCHECK_LT(start_size + 4, kMaxIpPacketSize) << "Not enough buffer space";
+ if (start_size + 4 > kMaxIpPacketSize)
+ return;
packet->resize(start_size + 4);
- net::BigEndianWriter big_endian_nack_writer(&((*packet)[start_size]), 4);
+ base::BigEndianWriter big_endian_nack_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 4);
big_endian_nack_writer.WriteU16(nack_sequence_number);
big_endian_nack_writer.WriteU16(bitmask);
number_of_nack_fields++;
@@ -517,75 +487,41 @@ void RtcpSender::BuildNack(const RtcpNackMessage* nack,
(*packet)[nack_size_pos] = static_cast<uint8>(2 + number_of_nack_fields);
}
-void RtcpSender::BuildBye(std::vector<uint8>* packet) const {
+void RtcpSender::BuildBye(Packet* packet) const {
size_t start_size = packet->size();
- DCHECK_LT(start_size + 8, kIpPacketSize) << "Not enough buffer space";
- if (start_size + 8 > kIpPacketSize) return;
+ DCHECK_LT(start_size + 8, kMaxIpPacketSize) << "Not enough buffer space";
+ if (start_size + 8 > kMaxIpPacketSize)
+ return;
packet->resize(start_size + 8);
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 8);
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 8);
big_endian_writer.WriteU8(0x80 + 1);
- big_endian_writer.WriteU8(kPacketTypeBye);
- big_endian_writer.WriteU16(1); // Length.
- big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
-}
-
-/*
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- |V=2|P|reserved | PT=XR=207 | length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | SSRC |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | BT=5 | reserved | block length |
- +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
- | SSRC_1 (SSRC of first receiver) | sub-
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
- | last RR (LRR) | 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | delay since last RR (DLRR) |
- +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-*/
-void RtcpSender::BuildDlrrRb(const RtcpDlrrReportBlock* dlrr,
- std::vector<uint8>* packet) const {
- size_t start_size = packet->size();
- DCHECK_LT(start_size + 24, kIpPacketSize) << "Not enough buffer space";
- if (start_size + 24 > kIpPacketSize) return;
-
- packet->resize(start_size + 24);
-
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24);
- big_endian_writer.WriteU8(0x80);
- big_endian_writer.WriteU8(kPacketTypeXr);
- big_endian_writer.WriteU16(5); // Length.
+ big_endian_writer.WriteU8(transport::kPacketTypeBye);
+ big_endian_writer.WriteU16(1); // Length.
big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
- big_endian_writer.WriteU8(5); // Add block type.
- big_endian_writer.WriteU8(0); // Add reserved.
- big_endian_writer.WriteU16(3); // Block length.
- big_endian_writer.WriteU32(ssrc_); // Add the media (received RTP) SSRC.
- big_endian_writer.WriteU32(dlrr->last_rr);
- big_endian_writer.WriteU32(dlrr->delay_since_last_rr);
}
void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr,
- std::vector<uint8>* packet) const {
+ Packet* packet) const {
size_t start_size = packet->size();
- DCHECK_LT(start_size + 20, kIpPacketSize) << "Not enough buffer space";
- if (start_size + 20 > kIpPacketSize) return;
+ DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space";
+ if (start_size + 20 > kMaxIpPacketSize)
+ return;
packet->resize(start_size + 20);
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 20);
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 20);
big_endian_writer.WriteU8(0x80);
- big_endian_writer.WriteU8(kPacketTypeXr);
- big_endian_writer.WriteU16(4); // Length.
+ big_endian_writer.WriteU8(transport::kPacketTypeXr);
+ big_endian_writer.WriteU16(4); // Length.
big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
- big_endian_writer.WriteU8(4); // Add block type.
- big_endian_writer.WriteU8(0); // Add reserved.
- big_endian_writer.WriteU16(2); // Block length.
+ big_endian_writer.WriteU8(4); // Add block type.
+ big_endian_writer.WriteU8(0); // Add reserved.
+ big_endian_writer.WriteU16(2); // Block length.
// Add the media (received RTP) SSRC.
big_endian_writer.WriteU32(rrtr->ntp_seconds);
@@ -593,47 +529,54 @@ void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr,
}
void RtcpSender::BuildCast(const RtcpCastMessage* cast,
- std::vector<uint8>* packet) const {
+ uint16 target_delay_ms,
+ Packet* packet) const {
size_t start_size = packet->size();
- DCHECK_LT(start_size + 20, kIpPacketSize) << "Not enough buffer space";
- if (start_size + 20 > kIpPacketSize) return;
+ DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space";
+ if (start_size + 20 > kMaxIpPacketSize)
+ return;
packet->resize(start_size + 20);
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 20);
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 20);
uint8 FMT = 15; // Application layer feedback.
big_endian_writer.WriteU8(0x80 + FMT);
- big_endian_writer.WriteU8(kPacketTypePayloadSpecific);
+ big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
big_endian_writer.WriteU8(0);
- size_t cast_size_pos = start_size + 3; // Save length position.
+ size_t cast_size_pos = start_size + 3; // Save length position.
big_endian_writer.WriteU8(4);
- big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
+ big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
big_endian_writer.WriteU32(cast->media_ssrc_); // Remote SSRC.
big_endian_writer.WriteU32(kCast);
big_endian_writer.WriteU8(static_cast<uint8>(cast->ack_frame_id_));
size_t cast_loss_field_pos = start_size + 17; // Save loss field position.
big_endian_writer.WriteU8(0); // Overwritten with number_of_loss_fields.
- big_endian_writer.WriteU8(0); // Reserved.
- big_endian_writer.WriteU8(0); // Reserved.
+ big_endian_writer.WriteU16(target_delay_ms);
size_t number_of_loss_fields = 0;
- size_t max_number_of_loss_fields = std::min<size_t>(kRtcpMaxCastLossFields,
- (kIpPacketSize - packet->size()) / 4);
+ size_t max_number_of_loss_fields = std::min<size_t>(
+ kRtcpMaxCastLossFields, (kMaxIpPacketSize - packet->size()) / 4);
MissingFramesAndPacketsMap::const_iterator frame_it =
cast->missing_frames_and_packets_.begin();
+ NackStringBuilder nack_string_builder;
for (; frame_it != cast->missing_frames_and_packets_.end() &&
- number_of_loss_fields < max_number_of_loss_fields; ++frame_it) {
+ number_of_loss_fields < max_number_of_loss_fields;
+ ++frame_it) {
+ nack_string_builder.PushFrame(frame_it->first);
// Iterate through all frames with missing packets.
if (frame_it->second.empty()) {
// Special case all packets in a frame is missing.
start_size = packet->size();
packet->resize(start_size + 4);
- net::BigEndianWriter big_endian_nack_writer(&((*packet)[start_size]), 4);
+ base::BigEndianWriter big_endian_nack_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 4);
big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first));
big_endian_nack_writer.WriteU16(kRtcpCastAllPacketsLost);
big_endian_nack_writer.WriteU8(0);
+ nack_string_builder.PushPacket(kRtcpCastAllPacketsLost);
++number_of_loss_fields;
} else {
PacketIdSet::const_iterator packet_it = frame_it->second.begin();
@@ -642,18 +585,20 @@ void RtcpSender::BuildCast(const RtcpCastMessage* cast,
start_size = packet->size();
packet->resize(start_size + 4);
- net::BigEndianWriter big_endian_nack_writer(
- &((*packet)[start_size]), 4);
+ base::BigEndianWriter big_endian_nack_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 4);
// Write frame and packet id to buffer before calculating bitmask.
big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first));
big_endian_nack_writer.WriteU16(packet_id);
+ nack_string_builder.PushPacket(packet_id);
uint8 bitmask = 0;
++packet_it;
while (packet_it != frame_it->second.end()) {
int shift = static_cast<uint8>(*packet_it - packet_id) - 1;
if (shift >= 0 && shift <= 7) {
+ nack_string_builder.PushPacket(*packet_it);
bitmask |= (1 << shift);
++packet_it;
} else {
@@ -665,80 +610,48 @@ void RtcpSender::BuildCast(const RtcpCastMessage* cast,
}
}
}
+ VLOG_IF(1, !nack_string_builder.Empty())
+ << "SSRC: " << cast->media_ssrc_
+ << ", ACK: " << cast->ack_frame_id_
+ << ", NACK: " << nack_string_builder.GetString();
DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields);
(*packet)[cast_size_pos] = static_cast<uint8>(4 + number_of_loss_fields);
(*packet)[cast_loss_field_pos] = static_cast<uint8>(number_of_loss_fields);
}
-void RtcpSender::BuildSenderLog(RtcpSenderLogMessage* sender_log_message,
- std::vector<uint8>* packet) const {
- DCHECK(sender_log_message);
- DCHECK(packet);
- size_t start_size = packet->size();
- size_t remaining_space = kIpPacketSize - start_size;
- DCHECK_GE(remaining_space, kRtcpCastLogHeaderSize + kRtcpSenderFrameLogSize)
- << "Not enough buffer space";
- if (remaining_space < kRtcpCastLogHeaderSize + kRtcpSenderFrameLogSize)
- return;
-
- size_t space_for_x_messages =
- (remaining_space - kRtcpCastLogHeaderSize) / kRtcpSenderFrameLogSize;
- size_t number_of_messages = std::min(space_for_x_messages,
- sender_log_message->size());
-
- size_t log_size = kRtcpCastLogHeaderSize +
- number_of_messages * kRtcpSenderFrameLogSize;
- packet->resize(start_size + log_size);
-
- net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), log_size);
- big_endian_writer.WriteU8(0x80 + kSenderLogSubtype);
- big_endian_writer.WriteU8(kPacketTypeApplicationDefined);
- big_endian_writer.WriteU16(static_cast<uint16>(2 + number_of_messages));
- big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
- big_endian_writer.WriteU32(kCast);
-
- for (; number_of_messages > 0; --number_of_messages) {
- DCHECK(!sender_log_message->empty());
- const RtcpSenderFrameLogMessage& message = sender_log_message->front();
- big_endian_writer.WriteU8(static_cast<uint8>(message.frame_status));
- // We send the 24 east significant bits of the RTP timestamp.
- big_endian_writer.WriteU8(static_cast<uint8>(message.rtp_timestamp >> 16));
- big_endian_writer.WriteU8(static_cast<uint8>(message.rtp_timestamp >> 8));
- big_endian_writer.WriteU8(static_cast<uint8>(message.rtp_timestamp));
- sender_log_message->pop_front();
- }
-}
-
-void RtcpSender::BuildReceiverLog(RtcpReceiverLogMessage* receiver_log_message,
- std::vector<uint8>* packet) const {
- DCHECK(receiver_log_message);
+void RtcpSender::BuildReceiverLog(
+ const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events,
+ 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;
size_t rtcp_log_size = 0;
-
- if (!ScanRtcpReceiverLogMessage(*receiver_log_message,
- packet_start_size,
- &number_of_frames,
- &total_number_of_messages_to_send,
- &rtcp_log_size)) {
+ RtcpReceiverLogMessage receiver_log_message;
+
+ if (!BuildRtcpReceiverLogMessage(rtcp_events,
+ packet_start_size,
+ &receiver_log_message,
+ &number_of_frames,
+ &total_number_of_messages_to_send,
+ &rtcp_log_size)) {
return;
}
packet->resize(packet_start_size + rtcp_log_size);
- net::BigEndianWriter big_endian_writer(&((*packet)[packet_start_size]),
- rtcp_log_size);
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[packet_start_size])), rtcp_log_size);
big_endian_writer.WriteU8(0x80 + kReceiverLogSubtype);
- big_endian_writer.WriteU8(kPacketTypeApplicationDefined);
- big_endian_writer.WriteU16(static_cast<uint16>(2 + 2 * number_of_frames +
- total_number_of_messages_to_send));
+ big_endian_writer.WriteU8(transport::kPacketTypeApplicationDefined);
+ big_endian_writer.WriteU16(static_cast<uint16>(
+ 2 + 2 * number_of_frames + total_number_of_messages_to_send));
big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
big_endian_writer.WriteU32(kCast);
- while (!receiver_log_message->empty() &&
+ while (!receiver_log_message.empty() &&
total_number_of_messages_to_send > 0) {
- RtcpReceiverFrameLogMessage& frame_log_messages =
- receiver_log_message->front();
+ RtcpReceiverFrameLogMessage& frame_log_messages(
+ receiver_log_message.front());
+
// Add our frame header.
big_endian_writer.WriteU32(frame_log_messages.rtp_timestamp_);
size_t messages_in_frame = frame_log_messages.event_log_messages_.size();
@@ -765,19 +678,18 @@ void RtcpSender::BuildReceiverLog(RtcpReceiverLogMessage* receiver_log_message,
const RtcpReceiverEventLogMessage& event_message =
frame_log_messages.event_log_messages_.front();
uint16 event_type_and_timestamp_delta =
- MergeEventTypeAndTimestampForWireFormat(event_message.type,
- event_message.event_timestamp - event_timestamp_base);
+ MergeEventTypeAndTimestampForWireFormat(
+ event_message.type,
+ event_message.event_timestamp - event_timestamp_base);
switch (event_message.type) {
- case kAckSent:
- case kAudioPlayoutDelay:
- case kAudioFrameDecoded:
- case kVideoFrameDecoded:
- case kVideoRenderDelay:
- big_endian_writer.WriteU16(static_cast<uint16>(
- event_message.delay_delta.InMilliseconds()));
+ case FRAME_ACK_SENT:
+ case FRAME_PLAYOUT:
+ case FRAME_DECODED:
+ big_endian_writer.WriteU16(
+ static_cast<uint16>(event_message.delay_delta.InMilliseconds()));
big_endian_writer.WriteU16(event_type_and_timestamp_delta);
break;
- case kPacketReceived:
+ case PACKET_RECEIVED:
big_endian_writer.WriteU16(event_message.packet_id);
big_endian_writer.WriteU16(event_type_and_timestamp_delta);
break;
@@ -789,10 +701,124 @@ void RtcpSender::BuildReceiverLog(RtcpReceiverLogMessage* receiver_log_message,
}
if (frame_log_messages.event_log_messages_.empty()) {
// We sent all messages on this frame; pop the frame header.
- receiver_log_message->pop_front();
+ receiver_log_message.pop_front();
}
}
- DCHECK_EQ(total_number_of_messages_to_send, 0);
+ 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
diff --git a/chromium/media/cast/rtcp/rtcp_sender.h b/chromium/media/cast/rtcp/rtcp_sender.h
index e931c693c0f..f09a4fb0e53 100644
--- a/chromium/media/cast/rtcp/rtcp_sender.h
+++ b/chromium/media/cast/rtcp/rtcp_sender.h
@@ -5,95 +5,96 @@
#ifndef MEDIA_CAST_RTCP_RTCP_SENDER_H_
#define MEDIA_CAST_RTCP_RTCP_SENDER_H_
+#include <deque>
#include <list>
#include <string>
#include "media/cast/cast_config.h"
#include "media/cast/cast_defines.h"
+#include "media/cast/rtcp/receiver_rtcp_event_subscriber.h"
#include "media/cast/rtcp/rtcp.h"
#include "media/cast/rtcp/rtcp_defines.h"
+#include "media/cast/transport/cast_transport_defines.h"
+#include "media/cast/transport/rtcp/rtcp_builder.h"
namespace media {
namespace cast {
+// We limit the size of receiver logs to avoid queuing up packets.
+const size_t kMaxReceiverLogBytes = 200;
+
+// 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 {
public:
RtcpSender(scoped_refptr<CastEnvironment> cast_environment,
- PacedPacketSender* const paced_packet_sender,
+ transport::PacedPacketSender* outgoing_transport,
uint32 sending_ssrc,
const std::string& c_name);
virtual ~RtcpSender();
- void SendRtcpFromRtpSender(uint32 packet_type_flags,
- const RtcpSenderInfo* sender_info,
- const RtcpDlrrReportBlock* dlrr,
- RtcpSenderLogMessage* sender_log);
-
- void SendRtcpFromRtpReceiver(uint32 packet_type_flags,
- const RtcpReportBlock* report_block,
- const RtcpReceiverReferenceTimeReport* rrtr,
- const RtcpCastMessage* cast_message,
- RtcpReceiverLogMessage* receiver_log);
-
- enum RtcpPacketType {
- kRtcpSr = 0x0002,
- kRtcpRr = 0x0004,
- kRtcpBye = 0x0008,
- kRtcpPli = 0x0010,
- kRtcpNack = 0x0020,
- kRtcpFir = 0x0040,
- kRtcpSrReq = 0x0200,
- kRtcpDlrr = 0x0400,
- kRtcpRrtr = 0x0800,
- kRtcpRpsi = 0x8000,
- kRtcpRemb = 0x10000,
- kRtcpCast = 0x20000,
- kRtcpSenderLog = 0x40000,
- kRtcpReceiverLog = 0x80000,
- };
+ void SendRtcpFromRtpReceiver(
+ uint32 packet_type_flags,
+ const transport::RtcpReportBlock* report_block,
+ const RtcpReceiverReferenceTimeReport* rrtr,
+ const RtcpCastMessage* cast_message,
+ const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events,
+ uint16 target_delay_ms);
private:
- void BuildSR(const RtcpSenderInfo& sender_info,
- const RtcpReportBlock* report_block,
- std::vector<uint8>* packet) const;
+ void BuildRR(const transport::RtcpReportBlock* report_block,
+ Packet* packet) const;
- void BuildRR(const RtcpReportBlock* report_block,
- std::vector<uint8>* packet) const;
+ void AddReportBlocks(const transport::RtcpReportBlock& report_block,
+ Packet* packet) const;
- void AddReportBlocks(const RtcpReportBlock& report_block,
- std::vector<uint8>* packet) const;
+ void BuildSdec(Packet* packet) const;
- void BuildSdec(std::vector<uint8>* packet) const;
+ void BuildPli(uint32 remote_ssrc, Packet* packet) const;
- void BuildPli(uint32 remote_ssrc,
- std::vector<uint8>* packet) const;
+ void BuildRemb(const RtcpRembMessage* remb, Packet* packet) const;
- void BuildRemb(const RtcpRembMessage* remb,
- std::vector<uint8>* packet) const;
+ void BuildRpsi(const RtcpRpsiMessage* rpsi, Packet* packet) const;
- void BuildRpsi(const RtcpRpsiMessage* rpsi,
- std::vector<uint8>* packet) const;
+ void BuildNack(const RtcpNackMessage* nack, Packet* packet) const;
- void BuildNack(const RtcpNackMessage* nack,
- std::vector<uint8>* packet) const;
-
- void BuildBye(std::vector<uint8>* packet) const;
-
- void BuildDlrrRb(const RtcpDlrrReportBlock* dlrr,
- std::vector<uint8>* packet) const;
+ void BuildBye(Packet* packet) const;
void BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr,
- std::vector<uint8>* packet) const;
+ Packet* packet) const;
void BuildCast(const RtcpCastMessage* cast_message,
- std::vector<uint8>* packet) const;
+ uint16 target_delay_ms,
+ Packet* packet) const;
- void BuildSenderLog(RtcpSenderLogMessage* sender_log_message,
- std::vector<uint8>* packet) const;
+ void BuildReceiverLog(
+ const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events,
+ Packet* packet);
- void BuildReceiverLog(RtcpReceiverLogMessage* receiver_log_message,
- std::vector<uint8>* packet) const;
+ 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,
@@ -113,9 +114,11 @@ class RtcpSender {
const std::string c_name_;
// Not owned by this class.
- PacedPacketSender* transport_;
+ transport::PacedPacketSender* const transport_;
scoped_refptr<CastEnvironment> cast_environment_;
+ std::deque<RtcpReceiverLogMessage> rtcp_events_history_;
+
DISALLOW_COPY_AND_ASSIGN(RtcpSender);
};
diff --git a/chromium/media/cast/rtcp/rtcp_sender_unittest.cc b/chromium/media/cast/rtcp/rtcp_sender_unittest.cc
index 16e9ee18ffb..0b0c7d3ab89 100644
--- a/chromium/media/cast/rtcp/rtcp_sender_unittest.cc
+++ b/chromium/media/cast/rtcp/rtcp_sender_unittest.cc
@@ -6,11 +6,13 @@
#include "base/test/simple_test_tick_clock.h"
#include "media/cast/cast_defines.h"
#include "media/cast/cast_environment.h"
-#include "media/cast/net/pacing/paced_sender.h"
+#include "media/cast/rtcp/receiver_rtcp_event_subscriber.h"
#include "media/cast/rtcp/rtcp_sender.h"
#include "media/cast/rtcp/rtcp_utility.h"
#include "media/cast/rtcp/test_rtcp_packet_builder.h"
-#include "media/cast/test/fake_task_runner.h"
+#include "media/cast/test/fake_single_thread_task_runner.h"
+#include "media/cast/transport/cast_transport_defines.h"
+#include "media/cast/transport/pacing/paced_sender.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace media {
@@ -19,95 +21,99 @@ namespace cast {
namespace {
static const uint32 kSendingSsrc = 0x12345678;
static const uint32 kMediaSsrc = 0x87654321;
+static const int16 kDefaultDelay = 100;
static const std::string kCName("test@10.1.1.1");
+
+transport::RtcpReportBlock GetReportBlock() {
+ transport::RtcpReportBlock report_block;
+ // Initialize remote_ssrc to a "clearly illegal" value.
+ report_block.remote_ssrc = 0xDEAD;
+ report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender.
+ report_block.fraction_lost = kLoss >> 24;
+ report_block.cumulative_lost = kLoss; // 24 bits valid.
+ report_block.extended_high_sequence_number = kExtendedMax;
+ report_block.jitter = kTestJitter;
+ report_block.last_sr = kLastSr;
+ report_block.delay_since_last_sr = kDelayLastSr;
+ return report_block;
+}
+
} // namespace
-class TestRtcpTransport : public PacedPacketSender {
+class TestRtcpTransport : public transport::PacedPacketSender {
public:
- TestRtcpTransport()
- : expected_packet_length_(0),
- packet_count_(0) {
- }
-
- virtual bool SendRtcpPacket(const Packet& packet) OVERRIDE {
- EXPECT_EQ(expected_packet_length_, packet.size());
- EXPECT_EQ(0, memcmp(expected_packet_, &(packet[0]), packet.size()));
+ TestRtcpTransport() : packet_count_(0) {}
+
+ virtual bool SendRtcpPacket(uint32 ssrc,
+ transport::PacketRef packet) OVERRIDE {
+ EXPECT_EQ(expected_packet_.size(), packet->data.size());
+ EXPECT_EQ(0, memcmp(expected_packet_.data(),
+ packet->data.data(),
+ packet->data.size()));
packet_count_++;
return true;
}
- virtual bool SendPackets(const PacketList& packets) OVERRIDE {
+ virtual bool SendPackets(
+ const transport::SendPacketVector& packets) OVERRIDE {
return false;
}
-
- virtual bool ResendPackets(const PacketList& packets) OVERRIDE {
+ virtual bool ResendPackets(
+ const transport::SendPacketVector& packets,
+ base::TimeDelta dedupe_window) OVERRIDE {
return false;
}
- void SetExpectedRtcpPacket(const uint8* rtcp_buffer, size_t length) {
- expected_packet_length_ = length;
- memcpy(expected_packet_, rtcp_buffer, length);
+ virtual void CancelSendingPacket(
+ const transport::PacketKey& packet_key) OVERRIDE {
+ }
+
+ void SetExpectedRtcpPacket(scoped_ptr<Packet> packet) {
+ expected_packet_.swap(*packet);
}
int packet_count() const { return packet_count_; }
private:
- uint8 expected_packet_[kIpPacketSize];
- size_t expected_packet_length_;
+ Packet expected_packet_;
int packet_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestRtcpTransport);
};
class RtcpSenderTest : public ::testing::Test {
protected:
RtcpSenderTest()
- : task_runner_(new test::FakeTaskRunner(&testing_clock_)),
- cast_environment_(new CastEnvironment(&testing_clock_, task_runner_,
- task_runner_, task_runner_, task_runner_, task_runner_,
- GetDefaultCastLoggingConfig())),
+ : testing_clock_(new base::SimpleTestTickClock()),
+ task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
+ cast_environment_(new CastEnvironment(
+ scoped_ptr<base::TickClock>(testing_clock_).Pass(),
+ task_runner_,
+ task_runner_,
+ task_runner_)),
rtcp_sender_(new RtcpSender(cast_environment_,
&test_transport_,
kSendingSsrc,
- kCName)) {
- }
+ kCName)) {}
- base::SimpleTestTickClock testing_clock_;
+ base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
TestRtcpTransport test_transport_;
- scoped_refptr<test::FakeTaskRunner> task_runner_;
+ scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
scoped_refptr<CastEnvironment> cast_environment_;
scoped_ptr<RtcpSender> rtcp_sender_;
-};
-
-TEST_F(RtcpSenderTest, RtcpSenderReport) {
- RtcpSenderInfo sender_info;
- sender_info.ntp_seconds = kNtpHigh;
- sender_info.ntp_fraction = kNtpLow;
- sender_info.rtp_timestamp = kRtpTimestamp;
- sender_info.send_packet_count = kSendPacketCount;
- sender_info.send_octet_count = kSendOctetCount;
- // Sender report + c_name.
- TestRtcpPacketBuilder p;
- p.AddSr(kSendingSsrc, 0);
- p.AddSdesCname(kSendingSsrc, kCName);
- test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length());
-
- rtcp_sender_->SendRtcpFromRtpSender(RtcpSender::kRtcpSr,
- &sender_info,
- NULL,
- NULL);
-
- EXPECT_EQ(1, test_transport_.packet_count());
-}
+ DISALLOW_COPY_AND_ASSIGN(RtcpSenderTest);
+};
TEST_F(RtcpSenderTest, RtcpReceiverReport) {
// Empty receiver report + c_name.
TestRtcpPacketBuilder p1;
p1.AddRr(kSendingSsrc, 0);
p1.AddSdesCname(kSendingSsrc, kCName);
- test_transport_.SetExpectedRtcpPacket(p1.Packet(), p1.Length());
+ test_transport_.SetExpectedRtcpPacket(p1.GetPacket());
- rtcp_sender_->SendRtcpFromRtpReceiver(RtcpSender::kRtcpRr,
- NULL, NULL, NULL, NULL);
+ rtcp_sender_->SendRtcpFromRtpReceiver(
+ transport::kRtcpRr, NULL, NULL, NULL, NULL, kDefaultDelay);
EXPECT_EQ(1, test_transport_.packet_count());
@@ -116,133 +122,16 @@ TEST_F(RtcpSenderTest, RtcpReceiverReport) {
p2.AddRr(kSendingSsrc, 1);
p2.AddRb(kMediaSsrc);
p2.AddSdesCname(kSendingSsrc, kCName);
- test_transport_.SetExpectedRtcpPacket(p2.Packet(), p2.Length());
+ test_transport_.SetExpectedRtcpPacket(p2.GetPacket().Pass());
- RtcpReportBlock report_block;
- // Initialize remote_ssrc to a "clearly illegal" value.
- report_block.remote_ssrc = 0xDEAD;
- report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender.
- report_block.fraction_lost = kLoss >> 24;
- report_block.cumulative_lost = kLoss; // 24 bits valid.
- report_block.extended_high_sequence_number = kExtendedMax;
- report_block.jitter = kTestJitter;
- report_block.last_sr = kLastSr;
- report_block.delay_since_last_sr = kDelayLastSr;
+ transport::RtcpReportBlock report_block = GetReportBlock();
- rtcp_sender_->SendRtcpFromRtpReceiver(RtcpSender::kRtcpRr, &report_block,
- NULL, NULL, NULL);
+ rtcp_sender_->SendRtcpFromRtpReceiver(
+ transport::kRtcpRr, &report_block, NULL, NULL, NULL, kDefaultDelay);
EXPECT_EQ(2, test_transport_.packet_count());
}
-TEST_F(RtcpSenderTest, RtcpSenderReportWithDlrr) {
- RtcpSenderInfo sender_info;
- sender_info.ntp_seconds = kNtpHigh;
- sender_info.ntp_fraction = kNtpLow;
- sender_info.rtp_timestamp = kRtpTimestamp;
- sender_info.send_packet_count = kSendPacketCount;
- sender_info.send_octet_count = kSendOctetCount;
-
- // Sender report + c_name + dlrr.
- TestRtcpPacketBuilder p1;
- p1.AddSr(kSendingSsrc, 0);
- p1.AddSdesCname(kSendingSsrc, kCName);
- p1.AddXrHeader(kSendingSsrc);
- p1.AddXrDlrrBlock(kSendingSsrc);
- test_transport_.SetExpectedRtcpPacket(p1.Packet(), p1.Length());
-
- RtcpDlrrReportBlock dlrr_rb;
- dlrr_rb.last_rr = kLastRr;
- dlrr_rb.delay_since_last_rr = kDelayLastRr;
-
- rtcp_sender_->SendRtcpFromRtpSender(
- RtcpSender::kRtcpSr | RtcpSender::kRtcpDlrr,
- &sender_info,
- &dlrr_rb,
- NULL);
-
- EXPECT_EQ(1, test_transport_.packet_count());
-}
-
-TEST_F(RtcpSenderTest, RtcpSenderReportWithDlrrAndLog) {
- RtcpSenderInfo sender_info;
- sender_info.ntp_seconds = kNtpHigh;
- sender_info.ntp_fraction = kNtpLow;
- sender_info.rtp_timestamp = kRtpTimestamp;
- sender_info.send_packet_count = kSendPacketCount;
- sender_info.send_octet_count = kSendOctetCount;
-
- // Sender report + c_name + dlrr + sender log.
- TestRtcpPacketBuilder p;
- p.AddSr(kSendingSsrc, 0);
- p.AddSdesCname(kSendingSsrc, kCName);
- p.AddXrHeader(kSendingSsrc);
- p.AddXrDlrrBlock(kSendingSsrc);
- p.AddSenderLog(kSendingSsrc);
- p.AddSenderFrameLog(kRtcpSenderFrameStatusSentToNetwork, kRtpTimestamp);
-
- test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length());
-
- RtcpDlrrReportBlock dlrr_rb;
- dlrr_rb.last_rr = kLastRr;
- dlrr_rb.delay_since_last_rr = kDelayLastRr;
-
- RtcpSenderFrameLogMessage sender_frame_log;
- sender_frame_log.frame_status = kRtcpSenderFrameStatusSentToNetwork;
- sender_frame_log.rtp_timestamp = kRtpTimestamp;
-
- RtcpSenderLogMessage sender_log;
- sender_log.push_back(sender_frame_log);
-
- rtcp_sender_->SendRtcpFromRtpSender(
- RtcpSender::kRtcpSr | RtcpSender::kRtcpDlrr | RtcpSender::kRtcpSenderLog,
- &sender_info,
- &dlrr_rb,
- &sender_log);
-
- EXPECT_EQ(1, test_transport_.packet_count());
- EXPECT_TRUE(sender_log.empty());
-}
-
-TEST_F(RtcpSenderTest, RtcpSenderReporWithTooManyLogFrames) {
- RtcpSenderInfo sender_info;
- sender_info.ntp_seconds = kNtpHigh;
- sender_info.ntp_fraction = kNtpLow;
- sender_info.rtp_timestamp = kRtpTimestamp;
- sender_info.send_packet_count = kSendPacketCount;
- sender_info.send_octet_count = kSendOctetCount;
-
- // Sender report + c_name + sender log.
- TestRtcpPacketBuilder p;
- p.AddSr(kSendingSsrc, 0);
- p.AddSdesCname(kSendingSsrc, kCName);
- p.AddSenderLog(kSendingSsrc);
-
- for (int i = 0; i < 359; ++i) {
- p.AddSenderFrameLog(kRtcpSenderFrameStatusSentToNetwork,
- kRtpTimestamp + i * 90);
- }
- test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length());
-
-
- RtcpSenderLogMessage sender_log;
- for (int j = 0; j < 400; ++j) {
- RtcpSenderFrameLogMessage sender_frame_log;
- sender_frame_log.frame_status = kRtcpSenderFrameStatusSentToNetwork;
- sender_frame_log.rtp_timestamp = kRtpTimestamp + j * 90;
- sender_log.push_back(sender_frame_log);
- }
-
- rtcp_sender_->SendRtcpFromRtpSender(
- RtcpSender::kRtcpSr | RtcpSender::kRtcpSenderLog,
- &sender_info,
- NULL,
- &sender_log);
-
- EXPECT_EQ(1, test_transport_.packet_count());
- EXPECT_EQ(41u, sender_log.size());
-}
-
TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtr) {
// Receiver report with report block + c_name.
TestRtcpPacketBuilder p;
@@ -251,29 +140,21 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtr) {
p.AddSdesCname(kSendingSsrc, kCName);
p.AddXrHeader(kSendingSsrc);
p.AddXrRrtrBlock();
- test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length());
+ test_transport_.SetExpectedRtcpPacket(p.GetPacket().Pass());
- RtcpReportBlock report_block;
- // Initialize remote_ssrc to a "clearly illegal" value.
- report_block.remote_ssrc = 0xDEAD;
- report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender.
- report_block.fraction_lost = kLoss >> 24;
- report_block.cumulative_lost = kLoss; // 24 bits valid.
- report_block.extended_high_sequence_number = kExtendedMax;
- report_block.jitter = kTestJitter;
- report_block.last_sr = kLastSr;
- report_block.delay_since_last_sr = kDelayLastSr;
+ transport::RtcpReportBlock report_block = GetReportBlock();
RtcpReceiverReferenceTimeReport rrtr;
rrtr.ntp_seconds = kNtpHigh;
rrtr.ntp_fraction = kNtpLow;
rtcp_sender_->SendRtcpFromRtpReceiver(
- RtcpSender::kRtcpRr | RtcpSender::kRtcpRrtr,
+ transport::kRtcpRr | transport::kRtcpRrtr,
&report_block,
&rrtr,
NULL,
- NULL);
+ NULL,
+ kDefaultDelay);
EXPECT_EQ(1, test_transport_.packet_count());
}
@@ -284,19 +165,10 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithCast) {
p.AddRr(kSendingSsrc, 1);
p.AddRb(kMediaSsrc);
p.AddSdesCname(kSendingSsrc, kCName);
- p.AddCast(kSendingSsrc, kMediaSsrc);
- test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length());
+ p.AddCast(kSendingSsrc, kMediaSsrc, kDefaultDelay);
+ test_transport_.SetExpectedRtcpPacket(p.GetPacket().Pass());
- RtcpReportBlock report_block;
- // Initialize remote_ssrc to a "clearly illegal" value.
- report_block.remote_ssrc = 0xDEAD;
- report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender.
- report_block.fraction_lost = kLoss >> 24;
- report_block.cumulative_lost = kLoss; // 24 bits valid.
- report_block.extended_high_sequence_number = kExtendedMax;
- report_block.jitter = kTestJitter;
- report_block.last_sr = kLastSr;
- report_block.delay_since_last_sr = kDelayLastSr;
+ transport::RtcpReportBlock report_block = GetReportBlock();
RtcpCastMessage cast_message(kMediaSsrc);
cast_message.ack_frame_id_ = kAckFrameId;
@@ -310,11 +182,12 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithCast) {
missing_packets;
rtcp_sender_->SendRtcpFromRtpReceiver(
- RtcpSender::kRtcpRr | RtcpSender::kRtcpCast,
+ transport::kRtcpRr | transport::kRtcpCast,
&report_block,
NULL,
&cast_message,
- NULL);
+ NULL,
+ kDefaultDelay);
EXPECT_EQ(1, test_transport_.packet_count());
}
@@ -326,19 +199,10 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtraAndCastMessage) {
p.AddSdesCname(kSendingSsrc, kCName);
p.AddXrHeader(kSendingSsrc);
p.AddXrRrtrBlock();
- p.AddCast(kSendingSsrc, kMediaSsrc);
- test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length());
+ p.AddCast(kSendingSsrc, kMediaSsrc, kDefaultDelay);
+ test_transport_.SetExpectedRtcpPacket(p.GetPacket().Pass());
- RtcpReportBlock report_block;
- // Initialize remote_ssrc to a "clearly illegal" value.
- report_block.remote_ssrc = 0xDEAD;
- report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender.
- report_block.fraction_lost = kLoss >> 24;
- report_block.cumulative_lost = kLoss; // 24 bits valid.
- report_block.extended_high_sequence_number = kExtendedMax;
- report_block.jitter = kTestJitter;
- report_block.last_sr = kLastSr;
- report_block.delay_since_last_sr = kDelayLastSr;
+ transport::RtcpReportBlock report_block = GetReportBlock();
RtcpReceiverReferenceTimeReport rrtr;
rrtr.ntp_seconds = kNtpHigh;
@@ -356,11 +220,12 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtraAndCastMessage) {
missing_packets;
rtcp_sender_->SendRtcpFromRtpReceiver(
- RtcpSender::kRtcpRr | RtcpSender::kRtcpRrtr | RtcpSender::kRtcpCast,
+ transport::kRtcpRr | transport::kRtcpRrtr | transport::kRtcpCast,
&report_block,
&rrtr,
&cast_message,
- NULL);
+ NULL,
+ kDefaultDelay);
EXPECT_EQ(1, test_transport_.packet_count());
}
@@ -368,7 +233,6 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtraAndCastMessage) {
TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtrCastMessageAndLog) {
static const uint32 kTimeBaseMs = 12345678;
static const uint32 kTimeDelayMs = 10;
- static const uint32 kDelayDeltaMs = 123;
TestRtcpPacketBuilder p;
p.AddRr(kSendingSsrc, 1);
@@ -376,19 +240,10 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtrCastMessageAndLog) {
p.AddSdesCname(kSendingSsrc, kCName);
p.AddXrHeader(kSendingSsrc);
p.AddXrRrtrBlock();
- p.AddCast(kSendingSsrc, kMediaSsrc);
- test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length());
+ p.AddCast(kSendingSsrc, kMediaSsrc, kDefaultDelay);
+ test_transport_.SetExpectedRtcpPacket(p.GetPacket().Pass());
- RtcpReportBlock report_block;
- // Initialize remote_ssrc to a "clearly illegal" value.
- report_block.remote_ssrc = 0xDEAD;
- report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender.
- report_block.fraction_lost = kLoss >> 24;
- report_block.cumulative_lost = kLoss; // 24 bits valid.
- report_block.extended_high_sequence_number = kExtendedMax;
- report_block.jitter = kTestJitter;
- report_block.last_sr = kLastSr;
- report_block.delay_since_last_sr = kDelayLastSr;
+ transport::RtcpReportBlock report_block = GetReportBlock();
RtcpReceiverReferenceTimeReport rrtr;
rrtr.ntp_seconds = kNtpHigh;
@@ -405,185 +260,296 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtrCastMessageAndLog) {
cast_message.missing_frames_and_packets_[kFrameIdWithLostPackets] =
missing_packets;
- // Test empty Log message.
- RtcpReceiverLogMessage receiver_log;
+ ReceiverRtcpEventSubscriber event_subscriber(500, VIDEO_EVENT);
+ ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events;
- VLOG(0) << " Test empty Log " ;
rtcp_sender_->SendRtcpFromRtpReceiver(
- RtcpSender::kRtcpRr | RtcpSender::kRtcpRrtr | RtcpSender::kRtcpCast |
- RtcpSender::kRtcpReceiverLog,
+ transport::kRtcpRr | transport::kRtcpRrtr | transport::kRtcpCast |
+ transport::kRtcpReceiverLog,
&report_block,
&rrtr,
&cast_message,
- &receiver_log);
-
+ &rtcp_events,
+ kDefaultDelay);
base::SimpleTestTickClock testing_clock;
testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeBaseMs));
p.AddReceiverLog(kSendingSsrc);
p.AddReceiverFrameLog(kRtpTimestamp, 2, kTimeBaseMs);
- p.AddReceiverEventLog(kDelayDeltaMs, 1, 0);
- p.AddReceiverEventLog(kLostPacketId1, 6, kTimeDelayMs);
-
- test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length());
+ p.AddReceiverEventLog(0, FRAME_ACK_SENT, 0);
+ p.AddReceiverEventLog(kLostPacketId1, PACKET_RECEIVED, kTimeDelayMs);
- RtcpReceiverFrameLogMessage frame_log(kRtpTimestamp);
- RtcpReceiverEventLogMessage event_log;
-
- event_log.type = kAckSent;
- event_log.event_timestamp = testing_clock.NowTicks();
- event_log.delay_delta = base::TimeDelta::FromMilliseconds(kDelayDeltaMs);
- frame_log.event_log_messages_.push_back(event_log);
+ test_transport_.SetExpectedRtcpPacket(p.GetPacket().Pass());
+ FrameEvent frame_event;
+ frame_event.rtp_timestamp = kRtpTimestamp;
+ frame_event.type = FRAME_ACK_SENT;
+ frame_event.media_type = VIDEO_EVENT;
+ frame_event.timestamp = testing_clock.NowTicks();
+ event_subscriber.OnReceiveFrameEvent(frame_event);
testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeDelayMs));
- event_log.type = kPacketReceived;
- event_log.event_timestamp = testing_clock.NowTicks();
- event_log.packet_id = kLostPacketId1;
- frame_log.event_log_messages_.push_back(event_log);
- receiver_log.push_back(frame_log);
+ PacketEvent packet_event;
+ packet_event.rtp_timestamp = kRtpTimestamp;
+ packet_event.type = PACKET_RECEIVED;
+ packet_event.media_type = VIDEO_EVENT;
+ packet_event.timestamp = testing_clock.NowTicks();
+ packet_event.packet_id = kLostPacketId1;
+ event_subscriber.OnReceivePacketEvent(packet_event);
+ event_subscriber.GetRtcpEventsAndReset(&rtcp_events);
+ EXPECT_EQ(2u, rtcp_events.size());
- VLOG(0) << " Test Log " ;
rtcp_sender_->SendRtcpFromRtpReceiver(
- RtcpSender::kRtcpRr | RtcpSender::kRtcpRrtr | RtcpSender::kRtcpCast |
- RtcpSender::kRtcpReceiverLog,
+ transport::kRtcpRr | transport::kRtcpRrtr | transport::kRtcpCast |
+ transport::kRtcpReceiverLog,
&report_block,
&rrtr,
&cast_message,
- &receiver_log);
+ &rtcp_events,
+ kDefaultDelay);
- EXPECT_TRUE(receiver_log.empty());
EXPECT_EQ(2, test_transport_.packet_count());
}
TEST_F(RtcpSenderTest, RtcpReceiverReportWithOversizedFrameLog) {
static const uint32 kTimeBaseMs = 12345678;
static const uint32 kTimeDelayMs = 10;
- static const uint32 kDelayDeltaMs = 123;
TestRtcpPacketBuilder p;
p.AddRr(kSendingSsrc, 1);
p.AddRb(kMediaSsrc);
p.AddSdesCname(kSendingSsrc, kCName);
- RtcpReportBlock report_block;
- // Initialize remote_ssrc to a "clearly illegal" value.
- report_block.remote_ssrc = 0xDEAD;
- report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender.
- report_block.fraction_lost = kLoss >> 24;
- report_block.cumulative_lost = kLoss; // 24 bits valid.
- report_block.extended_high_sequence_number = kExtendedMax;
- report_block.jitter = kTestJitter;
- report_block.last_sr = kLastSr;
- report_block.delay_since_last_sr = kDelayLastSr;
+ transport::RtcpReportBlock report_block = GetReportBlock();
base::SimpleTestTickClock testing_clock;
testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeBaseMs));
p.AddReceiverLog(kSendingSsrc);
- p.AddReceiverFrameLog(kRtpTimestamp, 1, kTimeBaseMs);
- p.AddReceiverEventLog(kDelayDeltaMs, 1, 0);
- p.AddReceiverFrameLog(kRtpTimestamp + 2345,
- kRtcpMaxReceiverLogMessages, kTimeBaseMs);
-
- for (size_t i = 0; i < kRtcpMaxReceiverLogMessages; ++i) {
+ int remaining_bytes = kMaxReceiverLogBytes;
+ remaining_bytes -= kRtcpCastLogHeaderSize;
+
+ remaining_bytes -= kRtcpReceiverFrameLogSize;
+ int num_events = remaining_bytes / kRtcpReceiverEventLogSize;
+ EXPECT_LE(num_events, static_cast<int>(kRtcpMaxReceiverLogMessages));
+ // Only the last |num_events| events are sent due to receiver log size cap.
+ p.AddReceiverFrameLog(
+ kRtpTimestamp + 2345,
+ num_events,
+ kTimeBaseMs + (kRtcpMaxReceiverLogMessages - num_events) * kTimeDelayMs);
+ for (int i = 0; i < num_events; i++) {
p.AddReceiverEventLog(
- kLostPacketId1, 6, static_cast<uint16>(kTimeDelayMs * i));
+ kLostPacketId1, PACKET_RECEIVED,
+ static_cast<uint16>(kTimeDelayMs * i));
}
- test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length());
-
- RtcpReceiverFrameLogMessage frame_1_log(kRtpTimestamp);
- RtcpReceiverEventLogMessage event_log;
-
- event_log.type = kAckSent;
- event_log.event_timestamp = testing_clock.NowTicks();
- event_log.delay_delta = base::TimeDelta::FromMilliseconds(kDelayDeltaMs);
- frame_1_log.event_log_messages_.push_back(event_log);
+ test_transport_.SetExpectedRtcpPacket(p.GetPacket().Pass());
- RtcpReceiverLogMessage receiver_log;
- receiver_log.push_back(frame_1_log);
+ ReceiverRtcpEventSubscriber event_subscriber(500, VIDEO_EVENT);
+ FrameEvent frame_event;
+ frame_event.rtp_timestamp = kRtpTimestamp;
+ frame_event.type = FRAME_ACK_SENT;
+ frame_event.media_type = VIDEO_EVENT;
+ frame_event.timestamp = testing_clock.NowTicks();
+ event_subscriber.OnReceiveFrameEvent(frame_event);
- RtcpReceiverFrameLogMessage frame_2_log(kRtpTimestamp + 2345);
-
- for (int j = 0; j < 300; ++j) {
- event_log.type = kPacketReceived;
- event_log.event_timestamp = testing_clock.NowTicks();
- event_log.packet_id = kLostPacketId1;
- frame_2_log.event_log_messages_.push_back(event_log);
+ for (size_t i = 0; i < kRtcpMaxReceiverLogMessages; ++i) {
+ PacketEvent packet_event;
+ packet_event.rtp_timestamp = kRtpTimestamp + 2345;
+ packet_event.type = PACKET_RECEIVED;
+ packet_event.media_type = VIDEO_EVENT;
+ packet_event.timestamp = testing_clock.NowTicks();
+ packet_event.packet_id = kLostPacketId1;
+ event_subscriber.OnReceivePacketEvent(packet_event);
testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeDelayMs));
}
- receiver_log.push_back(frame_2_log);
+
+ ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events;
+ event_subscriber.GetRtcpEventsAndReset(&rtcp_events);
rtcp_sender_->SendRtcpFromRtpReceiver(
- RtcpSender::kRtcpRr | RtcpSender::kRtcpReceiverLog,
+ transport::kRtcpRr | transport::kRtcpReceiverLog,
&report_block,
NULL,
NULL,
- &receiver_log);
+ &rtcp_events,
+ kDefaultDelay);
EXPECT_EQ(1, test_transport_.packet_count());
- EXPECT_EQ(1u, receiver_log.size());
- EXPECT_EQ(300u - kRtcpMaxReceiverLogMessages,
- receiver_log.front().event_log_messages_.size());
}
TEST_F(RtcpSenderTest, RtcpReceiverReportWithTooManyLogFrames) {
static const uint32 kTimeBaseMs = 12345678;
static const uint32 kTimeDelayMs = 10;
- static const uint32 kDelayDeltaMs = 123;
TestRtcpPacketBuilder p;
p.AddRr(kSendingSsrc, 1);
p.AddRb(kMediaSsrc);
p.AddSdesCname(kSendingSsrc, kCName);
- RtcpReportBlock report_block;
- // Initialize remote_ssrc to a "clearly illegal" value.
- report_block.remote_ssrc = 0xDEAD;
- report_block.media_ssrc = kMediaSsrc; // SSRC of the RTP packet sender.
- report_block.fraction_lost = kLoss >> 24;
- report_block.cumulative_lost = kLoss; // 24 bits valid.
- report_block.extended_high_sequence_number = kExtendedMax;
- report_block.jitter = kTestJitter;
- report_block.last_sr = kLastSr;
- report_block.delay_since_last_sr = kDelayLastSr;
+ transport::RtcpReportBlock report_block = GetReportBlock();
base::SimpleTestTickClock testing_clock;
testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeBaseMs));
p.AddReceiverLog(kSendingSsrc);
- for (int i = 0; i < 119; ++i) {
- p.AddReceiverFrameLog(kRtpTimestamp, 1, kTimeBaseMs + i * kTimeDelayMs);
- p.AddReceiverEventLog(kDelayDeltaMs, 1, 0);
- }
- test_transport_.SetExpectedRtcpPacket(p.Packet(), p.Length());
+ int remaining_bytes = kMaxReceiverLogBytes;
+ remaining_bytes -= kRtcpCastLogHeaderSize;
+
+ int num_events =
+ remaining_bytes / (kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize);
- RtcpReceiverLogMessage receiver_log;
+ // The last |num_events| events are sent due to receiver log size cap.
+ for (size_t i = kRtcpMaxReceiverLogMessages - num_events;
+ i < kRtcpMaxReceiverLogMessages;
+ ++i) {
+ p.AddReceiverFrameLog(kRtpTimestamp + i, 1, kTimeBaseMs + i * kTimeDelayMs);
+ p.AddReceiverEventLog(0, FRAME_ACK_SENT, 0);
+ }
+ test_transport_.SetExpectedRtcpPacket(p.GetPacket().Pass());
- for (int j = 0; j < 200; ++j) {
- RtcpReceiverFrameLogMessage frame_log(kRtpTimestamp);
- RtcpReceiverEventLogMessage event_log;
+ ReceiverRtcpEventSubscriber event_subscriber(500, VIDEO_EVENT);
- event_log.type = kAckSent;
- event_log.event_timestamp = testing_clock.NowTicks();
- event_log.delay_delta = base::TimeDelta::FromMilliseconds(kDelayDeltaMs);
- frame_log.event_log_messages_.push_back(event_log);
- receiver_log.push_back(frame_log);
+ for (size_t i = 0; i < kRtcpMaxReceiverLogMessages; ++i) {
+ FrameEvent frame_event;
+ frame_event.rtp_timestamp = kRtpTimestamp + static_cast<int>(i);
+ frame_event.type = FRAME_ACK_SENT;
+ frame_event.media_type = VIDEO_EVENT;
+ frame_event.timestamp = testing_clock.NowTicks();
+ event_subscriber.OnReceiveFrameEvent(frame_event);
testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeDelayMs));
}
+
+ ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events;
+ event_subscriber.GetRtcpEventsAndReset(&rtcp_events);
+
rtcp_sender_->SendRtcpFromRtpReceiver(
- RtcpSender::kRtcpRr | RtcpSender::kRtcpReceiverLog,
+ transport::kRtcpRr | transport::kRtcpReceiverLog,
&report_block,
NULL,
NULL,
- &receiver_log);
+ &rtcp_events,
+ kDefaultDelay);
EXPECT_EQ(1, test_transport_.packet_count());
- EXPECT_EQ(81u, receiver_log.size());
+}
+
+TEST_F(RtcpSenderTest, RtcpReceiverReportWithOldLogFrames) {
+ static const uint32 kTimeBaseMs = 12345678;
+
+ TestRtcpPacketBuilder p;
+ p.AddRr(kSendingSsrc, 1);
+ p.AddRb(kMediaSsrc);
+ p.AddSdesCname(kSendingSsrc, kCName);
+
+ transport::RtcpReportBlock report_block = GetReportBlock();
+
+ base::SimpleTestTickClock testing_clock;
+ testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeBaseMs));
+
+ p.AddReceiverLog(kSendingSsrc);
+
+ // Log 11 events for a single frame, each |kTimeBetweenEventsMs| apart.
+ // Only last 10 events will be sent because the first event is more than
+ // 4095 milliseconds away from latest event.
+ const int kTimeBetweenEventsMs = 410;
+ p.AddReceiverFrameLog(kRtpTimestamp, 10, kTimeBaseMs + kTimeBetweenEventsMs);
+ for (int i = 0; i < 10; ++i) {
+ p.AddReceiverEventLog(0, FRAME_ACK_SENT, i * kTimeBetweenEventsMs);
+ }
+ test_transport_.SetExpectedRtcpPacket(p.GetPacket().Pass());
+
+ ReceiverRtcpEventSubscriber event_subscriber(500, VIDEO_EVENT);
+ for (int i = 0; i < 11; ++i) {
+ FrameEvent frame_event;
+ frame_event.rtp_timestamp = kRtpTimestamp;
+ frame_event.type = FRAME_ACK_SENT;
+ frame_event.media_type = VIDEO_EVENT;
+ frame_event.timestamp = testing_clock.NowTicks();
+ event_subscriber.OnReceiveFrameEvent(frame_event);
+ testing_clock.Advance(
+ base::TimeDelta::FromMilliseconds(kTimeBetweenEventsMs));
+ }
+
+ ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events;
+ event_subscriber.GetRtcpEventsAndReset(&rtcp_events);
+
+ rtcp_sender_->SendRtcpFromRtpReceiver(
+ transport::kRtcpRr | transport::kRtcpReceiverLog,
+ &report_block,
+ NULL,
+ NULL,
+ &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, VIDEO_EVENT);
+ 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, FRAME_ACK_SENT, 0);
+ }
+ if (i >= kFirstRedundancyOffset) {
+ p.AddReceiverFrameLog(
+ kRtpTimestamp,
+ 1,
+ time_base_ms - kFirstRedundancyOffset * kTimeBetweenEventsMs);
+ p.AddReceiverEventLog(0, FRAME_ACK_SENT, 0);
+ }
+ p.AddReceiverFrameLog(kRtpTimestamp, 1, time_base_ms);
+ p.AddReceiverEventLog(0, FRAME_ACK_SENT, 0);
+
+ test_transport_.SetExpectedRtcpPacket(p.GetPacket().Pass());
+
+ FrameEvent frame_event;
+ frame_event.rtp_timestamp = kRtpTimestamp;
+ frame_event.type = FRAME_ACK_SENT;
+ frame_event.media_type = VIDEO_EVENT;
+ 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
diff --git a/chromium/media/cast/rtcp/rtcp_unittest.cc b/chromium/media/cast/rtcp/rtcp_unittest.cc
index 535f3c34f83..095e6d24df9 100644
--- a/chromium/media/cast/rtcp/rtcp_unittest.cc
+++ b/chromium/media/cast/rtcp/rtcp_unittest.cc
@@ -2,15 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <stdint.h>
+
#include "base/test/simple_test_tick_clock.h"
#include "media/cast/cast_defines.h"
#include "media/cast/cast_environment.h"
-#include "media/cast/net/pacing/paced_sender.h"
#include "media/cast/rtcp/mock_rtcp_receiver_feedback.h"
#include "media/cast/rtcp/mock_rtcp_sender_feedback.h"
#include "media/cast/rtcp/rtcp.h"
#include "media/cast/rtcp/test_rtcp_packet_builder.h"
-#include "media/cast/test/fake_task_runner.h"
+#include "media/cast/test/fake_single_thread_task_runner.h"
+#include "media/cast/transport/cast_transport_config.h"
+#include "media/cast/transport/cast_transport_sender_impl.h"
+#include "media/cast/transport/pacing/paced_sender.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace media {
@@ -22,60 +26,109 @@ static const uint32 kSenderSsrc = 0x10203;
static const uint32 kReceiverSsrc = 0x40506;
static const std::string kCName("test@10.1.1.1");
static const uint32 kRtcpIntervalMs = 500;
-static const int64 kStartMillisecond = GG_INT64_C(12345678900000);
static const int64 kAddedDelay = 123;
-static const int64 kAddedShortDelay= 100;
+static const int64 kAddedShortDelay = 100;
-class LocalRtcpTransport : public PacedPacketSender {
+class RtcpTestPacketSender : public transport::PacketSender {
public:
- explicit LocalRtcpTransport(scoped_refptr<CastEnvironment> cast_environment,
- base::SimpleTestTickClock* testing_clock)
+ explicit RtcpTestPacketSender(base::SimpleTestTickClock* testing_clock)
: drop_packets_(false),
short_delay_(false),
+ rtcp_receiver_(NULL),
testing_clock_(testing_clock) {}
+ virtual ~RtcpTestPacketSender() {}
+ // Packet lists imply a RTP packet.
+ void set_rtcp_receiver(Rtcp* rtcp) { rtcp_receiver_ = rtcp; }
+
+ void set_short_delay() { short_delay_ = true; }
+
+ void set_drop_packets(bool drop_packets) { drop_packets_ = drop_packets; }
+
+ // A singular packet implies a RTCP packet.
+ virtual bool SendPacket(transport::PacketRef packet,
+ const base::Closure& cb) OVERRIDE {
+ if (short_delay_) {
+ testing_clock_->Advance(
+ base::TimeDelta::FromMilliseconds(kAddedShortDelay));
+ } else {
+ testing_clock_->Advance(base::TimeDelta::FromMilliseconds(kAddedDelay));
+ }
+ if (drop_packets_)
+ return true;
+
+ rtcp_receiver_->IncomingRtcpPacket(&packet->data[0], packet->data.size());
+ return true;
+ }
- void SetRtcpReceiver(Rtcp* rtcp) { rtcp_ = rtcp; }
+ private:
+ bool drop_packets_;
+ bool short_delay_;
+ Rtcp* rtcp_receiver_;
+ base::SimpleTestTickClock* testing_clock_;
- void SetShortDelay() { short_delay_ = true; }
+ DISALLOW_COPY_AND_ASSIGN(RtcpTestPacketSender);
+};
- void SetDropPackets(bool drop_packets) { drop_packets_ = drop_packets; }
+class LocalRtcpTransport : public transport::PacedPacketSender {
+ public:
+ LocalRtcpTransport(scoped_refptr<CastEnvironment> cast_environment,
+ base::SimpleTestTickClock* testing_clock)
+ : drop_packets_(false),
+ short_delay_(false),
+ testing_clock_(testing_clock) {}
+ void set_rtcp_receiver(Rtcp* rtcp) { rtcp_ = rtcp; }
- virtual bool SendRtcpPacket(const std::vector<uint8>& packet) OVERRIDE {
+ void set_short_delay() { short_delay_ = true; }
+
+ void set_drop_packets(bool drop_packets) { drop_packets_ = drop_packets; }
+
+ virtual bool SendRtcpPacket(uint32 ssrc,
+ transport::PacketRef packet) OVERRIDE {
if (short_delay_) {
testing_clock_->Advance(
base::TimeDelta::FromMilliseconds(kAddedShortDelay));
} else {
testing_clock_->Advance(base::TimeDelta::FromMilliseconds(kAddedDelay));
}
- if (drop_packets_) return true;
+ if (drop_packets_)
+ return true;
- rtcp_->IncomingRtcpPacket(&(packet[0]), packet.size());
+ rtcp_->IncomingRtcpPacket(&packet->data[0], packet->data.size());
return true;
}
- virtual bool SendPackets(const PacketList& packets) OVERRIDE {
+ virtual bool SendPackets(
+ const transport::SendPacketVector& packets) OVERRIDE {
return false;
}
- virtual bool ResendPackets(const PacketList& packets) OVERRIDE {
+ virtual bool ResendPackets(
+ const transport::SendPacketVector& packets,
+ base::TimeDelta dedupe_window) OVERRIDE {
return false;
}
+ virtual void CancelSendingPacket(
+ const transport::PacketKey& packet_key) OVERRIDE {
+ }
+
private:
bool drop_packets_;
bool short_delay_;
Rtcp* rtcp_;
base::SimpleTestTickClock* testing_clock_;
scoped_refptr<CastEnvironment> cast_environment_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocalRtcpTransport);
};
class RtcpPeer : public Rtcp {
public:
RtcpPeer(scoped_refptr<CastEnvironment> cast_environment,
RtcpSenderFeedback* sender_feedback,
- PacedPacketSender* const paced_packet_sender,
- RtpSenderStatistics* rtp_sender_statistics,
+ transport::CastTransportSender* const transport_sender,
+ transport::PacedPacketSender* paced_packet_sender,
RtpReceiverStatistics* rtp_receiver_statistics,
RtcpMode rtcp_mode,
const base::TimeDelta& rtcp_interval,
@@ -84,95 +137,129 @@ class RtcpPeer : public Rtcp {
const std::string& c_name)
: Rtcp(cast_environment,
sender_feedback,
+ transport_sender,
paced_packet_sender,
- rtp_sender_statistics,
rtp_receiver_statistics,
rtcp_mode,
rtcp_interval,
local_ssrc,
remote_ssrc,
- c_name) {
- }
+ c_name,
+ AUDIO_EVENT) {}
- using Rtcp::CheckForWrapAround;
+ using Rtcp::OnReceivedNtp;
using Rtcp::OnReceivedLipSyncInfo;
};
class RtcpTest : public ::testing::Test {
protected:
RtcpTest()
- : task_runner_(new test::FakeTaskRunner(&testing_clock_)),
- cast_environment_(new CastEnvironment(&testing_clock_, task_runner_,
- task_runner_, task_runner_, task_runner_, task_runner_,
- GetDefaultCastLoggingConfig())),
- transport_(cast_environment_, &testing_clock_) {
- testing_clock_.Advance(
- base::TimeDelta::FromMilliseconds(kStartMillisecond));
+ : testing_clock_(new base::SimpleTestTickClock()),
+ task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
+ cast_environment_(new CastEnvironment(
+ scoped_ptr<base::TickClock>(testing_clock_).Pass(),
+ task_runner_,
+ task_runner_,
+ task_runner_)),
+ sender_to_receiver_(testing_clock_),
+ receiver_to_sender_(cast_environment_, testing_clock_) {
+ testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
+ net::IPEndPoint dummy_endpoint;
+ transport_sender_.reset(new transport::CastTransportSenderImpl(
+ NULL,
+ testing_clock_,
+ dummy_endpoint,
+ base::Bind(&UpdateCastTransportStatus),
+ transport::BulkRawEventsCallback(),
+ base::TimeDelta(),
+ task_runner_,
+ &sender_to_receiver_));
+ transport::CastTransportAudioConfig config;
+ config.rtp.config.ssrc = kSenderSsrc;
+ config.rtp.max_outstanding_frames = 1;
+ transport_sender_->InitializeAudio(config);
+ EXPECT_CALL(mock_sender_feedback_, OnReceivedCastFeedback(_)).Times(0);
}
virtual ~RtcpTest() {}
- virtual void SetUp() {
- EXPECT_CALL(mock_sender_feedback_, OnReceivedCastFeedback(_)).Times(0);
+ static void UpdateCastTransportStatus(transport::CastTransportStatus status) {
+ bool result = (status == transport::TRANSPORT_AUDIO_INITIALIZED ||
+ status == transport::TRANSPORT_VIDEO_INITIALIZED);
+ EXPECT_TRUE(result);
+ }
+
+ void RunTasks(int during_ms) {
+ for (int i = 0; i < during_ms; ++i) {
+ // Call process the timers every 1 ms.
+ testing_clock_->Advance(base::TimeDelta::FromMilliseconds(1));
+ task_runner_->RunTasks();
+ }
}
- base::SimpleTestTickClock testing_clock_;
- scoped_refptr<test::FakeTaskRunner> task_runner_;
+ base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
+ scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
scoped_refptr<CastEnvironment> cast_environment_;
- LocalRtcpTransport transport_;
+ RtcpTestPacketSender sender_to_receiver_;
+ scoped_ptr<transport::CastTransportSenderImpl> transport_sender_;
+ LocalRtcpTransport receiver_to_sender_;
MockRtcpSenderFeedback mock_sender_feedback_;
+
+ DISALLOW_COPY_AND_ASSIGN(RtcpTest);
};
TEST_F(RtcpTest, TimeToSend) {
- base::TimeTicks start_time;
- start_time += base::TimeDelta::FromMilliseconds(kStartMillisecond);
+ const base::TimeTicks start_time = testing_clock_->NowTicks();
Rtcp rtcp(cast_environment_,
&mock_sender_feedback_,
- &transport_,
- NULL,
+ transport_sender_.get(),
+ &receiver_to_sender_,
NULL,
kRtcpCompound,
base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kSenderSsrc,
kReceiverSsrc,
- kCName);
- transport_.SetRtcpReceiver(&rtcp);
+ kCName,
+ AUDIO_EVENT);
+ receiver_to_sender_.set_rtcp_receiver(&rtcp);
EXPECT_LE(start_time, rtcp.TimeToSendNextRtcpReport());
- EXPECT_GE(start_time + base::TimeDelta::FromMilliseconds(
- kRtcpIntervalMs * 3 / 2),
- rtcp.TimeToSendNextRtcpReport());
+ EXPECT_GE(
+ start_time + base::TimeDelta::FromMilliseconds(kRtcpIntervalMs * 3 / 2),
+ rtcp.TimeToSendNextRtcpReport());
base::TimeDelta delta = rtcp.TimeToSendNextRtcpReport() - start_time;
- testing_clock_.Advance(delta);
- EXPECT_EQ(testing_clock_.NowTicks(), rtcp.TimeToSendNextRtcpReport());
+ testing_clock_->Advance(delta);
+ EXPECT_EQ(testing_clock_->NowTicks(), rtcp.TimeToSendNextRtcpReport());
}
TEST_F(RtcpTest, BasicSenderReport) {
Rtcp rtcp(cast_environment_,
&mock_sender_feedback_,
- &transport_,
+ transport_sender_.get(),
NULL,
NULL,
kRtcpCompound,
base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kSenderSsrc,
kReceiverSsrc,
- kCName);
- transport_.SetRtcpReceiver(&rtcp);
- rtcp.SendRtcpFromRtpSender(NULL);
+ kCName,
+ AUDIO_EVENT);
+ sender_to_receiver_.set_rtcp_receiver(&rtcp);
+ rtcp.SendRtcpFromRtpSender(base::TimeTicks(), 0);
}
TEST_F(RtcpTest, BasicReceiverReport) {
Rtcp rtcp(cast_environment_,
&mock_sender_feedback_,
- &transport_,
NULL,
+ &receiver_to_sender_,
NULL,
kRtcpCompound,
base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kSenderSsrc,
kReceiverSsrc,
- kCName);
- transport_.SetRtcpReceiver(&rtcp);
+ kCName,
+ AUDIO_EVENT);
+ receiver_to_sender_.set_rtcp_receiver(&rtcp);
rtcp.SendRtcpFromRtpReceiver(NULL, NULL);
}
@@ -182,20 +269,20 @@ TEST_F(RtcpTest, BasicCast) {
// Media receiver.
Rtcp rtcp(cast_environment_,
&mock_sender_feedback_,
- &transport_,
NULL,
+ &receiver_to_sender_,
NULL,
kRtcpReducedSize,
base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kSenderSsrc,
kSenderSsrc,
- kCName);
- transport_.SetRtcpReceiver(&rtcp);
+ kCName,
+ AUDIO_EVENT);
+ receiver_to_sender_.set_rtcp_receiver(&rtcp);
RtcpCastMessage cast_message(kSenderSsrc);
cast_message.ack_frame_id_ = kAckFrameId;
PacketIdSet missing_packets;
- cast_message.missing_frames_and_packets_[
- kLostFrameId] = missing_packets;
+ cast_message.missing_frames_and_packets_[kLostFrameId] = missing_packets;
missing_packets.insert(kLostPacketId1);
missing_packets.insert(kLostPacketId2);
@@ -207,334 +294,254 @@ TEST_F(RtcpTest, BasicCast) {
TEST_F(RtcpTest, RttReducedSizeRtcp) {
// Media receiver.
- LocalRtcpTransport receiver_transport(cast_environment_, &testing_clock_);
Rtcp rtcp_receiver(cast_environment_,
&mock_sender_feedback_,
- &receiver_transport,
NULL,
+ &receiver_to_sender_,
NULL,
kRtcpReducedSize,
base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kReceiverSsrc,
kSenderSsrc,
- kCName);
+ kCName,
+ AUDIO_EVENT);
// Media sender.
- LocalRtcpTransport sender_transport(cast_environment_, &testing_clock_);
Rtcp rtcp_sender(cast_environment_,
&mock_sender_feedback_,
- &sender_transport,
+ transport_sender_.get(),
NULL,
NULL,
kRtcpReducedSize,
base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kSenderSsrc,
kReceiverSsrc,
- kCName);
+ kCName,
+ AUDIO_EVENT);
- receiver_transport.SetRtcpReceiver(&rtcp_sender);
- sender_transport.SetRtcpReceiver(&rtcp_receiver);
+ sender_to_receiver_.set_rtcp_receiver(&rtcp_receiver);
+ receiver_to_sender_.set_rtcp_receiver(&rtcp_sender);
base::TimeDelta rtt;
base::TimeDelta avg_rtt;
base::TimeDelta min_rtt;
base::TimeDelta max_rtt;
- EXPECT_FALSE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_FALSE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_FALSE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_FALSE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- rtcp_sender.SendRtcpFromRtpSender(NULL);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 1);
+ RunTasks(33);
rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
- EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_FALSE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_NEAR(2 * kAddedDelay, rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, avg_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, min_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 1);
- rtcp_sender.SendRtcpFromRtpSender(NULL);
- EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
-
- EXPECT_NEAR(2 * kAddedDelay, rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, avg_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, min_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 1);
+ EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_FALSE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_NEAR(2 * kAddedDelay, rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, avg_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, min_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 2);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 2);
+ RunTasks(33);
+ EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+
+ EXPECT_NEAR(2 * kAddedDelay, rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, avg_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, min_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 2);
}
TEST_F(RtcpTest, Rtt) {
// Media receiver.
- LocalRtcpTransport receiver_transport(cast_environment_, &testing_clock_);
Rtcp rtcp_receiver(cast_environment_,
&mock_sender_feedback_,
- &receiver_transport,
NULL,
+ &receiver_to_sender_,
NULL,
kRtcpCompound,
base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kReceiverSsrc,
kSenderSsrc,
- kCName);
+ kCName,
+ AUDIO_EVENT);
// Media sender.
- LocalRtcpTransport sender_transport(cast_environment_, &testing_clock_);
Rtcp rtcp_sender(cast_environment_,
&mock_sender_feedback_,
- &sender_transport,
+ transport_sender_.get(),
NULL,
NULL,
kRtcpCompound,
base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kSenderSsrc,
kReceiverSsrc,
- kCName);
+ kCName,
+ AUDIO_EVENT);
- receiver_transport.SetRtcpReceiver(&rtcp_sender);
- sender_transport.SetRtcpReceiver(&rtcp_receiver);
+ receiver_to_sender_.set_rtcp_receiver(&rtcp_sender);
+ sender_to_receiver_.set_rtcp_receiver(&rtcp_receiver);
base::TimeDelta rtt;
base::TimeDelta avg_rtt;
base::TimeDelta min_rtt;
base::TimeDelta max_rtt;
- EXPECT_FALSE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_FALSE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_FALSE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_FALSE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- rtcp_sender.SendRtcpFromRtpSender(NULL);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 1);
+ RunTasks(33);
rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
- EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_FALSE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_NEAR(2 * kAddedDelay, rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, avg_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, min_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 1);
- rtcp_sender.SendRtcpFromRtpSender(NULL);
- EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_NEAR(2 * kAddedDelay, rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, avg_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, min_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 1);
+ EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ RunTasks(33);
- receiver_transport.SetShortDelay();
- sender_transport.SetShortDelay();
- rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
- EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_NEAR(kAddedDelay + kAddedShortDelay, rtt.InMilliseconds(), 1);
- EXPECT_NEAR((kAddedShortDelay + 3 * kAddedDelay) / 2,
- avg_rtt.InMilliseconds(),
- 1);
- EXPECT_NEAR(kAddedDelay + kAddedShortDelay, min_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 1);
+ EXPECT_FALSE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ RunTasks(33);
- rtcp_sender.SendRtcpFromRtpSender(NULL);
- EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_NEAR(2 * kAddedDelay, rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, avg_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, min_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 2);
+
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 2);
+ RunTasks(33);
+ EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_NEAR(2 * kAddedDelay, rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, avg_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, min_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 2);
+
+ receiver_to_sender_.set_short_delay();
+ sender_to_receiver_.set_short_delay();
+ rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
+ EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_NEAR(kAddedDelay + kAddedShortDelay, rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(
+ (kAddedShortDelay + 3 * kAddedDelay) / 2, avg_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(kAddedDelay + kAddedShortDelay, min_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 2);
+
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 3);
+ RunTasks(33);
+ EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
EXPECT_NEAR(2 * kAddedShortDelay, rtt.InMilliseconds(), 1);
EXPECT_NEAR((2 * kAddedShortDelay + 2 * kAddedDelay) / 2,
- avg_rtt.InMilliseconds(),
- 1);
- EXPECT_NEAR(2 * kAddedShortDelay, min_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 1);
+ avg_rtt.InMilliseconds(),
+ 1);
+ EXPECT_NEAR(2 * kAddedShortDelay, min_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 2);
rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
- EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_NEAR(2 * kAddedShortDelay, rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedShortDelay, min_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 1);
+ EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_NEAR(2 * kAddedShortDelay, rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedShortDelay, min_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 2);
rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
- EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_NEAR(2 * kAddedShortDelay, rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedShortDelay, min_rtt.InMilliseconds(), 1);
- EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 1);
+ EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_NEAR(2 * kAddedShortDelay, rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedShortDelay, min_rtt.InMilliseconds(), 2);
+ EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 2);
}
TEST_F(RtcpTest, RttWithPacketLoss) {
// Media receiver.
- LocalRtcpTransport receiver_transport(cast_environment_, &testing_clock_);
Rtcp rtcp_receiver(cast_environment_,
&mock_sender_feedback_,
- &receiver_transport,
NULL,
+ &receiver_to_sender_,
NULL,
kRtcpReducedSize,
base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
- kSenderSsrc,
kReceiverSsrc,
- kCName);
+ kSenderSsrc,
+ kCName,
+ AUDIO_EVENT);
// Media sender.
- LocalRtcpTransport sender_transport(cast_environment_, &testing_clock_);
Rtcp rtcp_sender(cast_environment_,
&mock_sender_feedback_,
- &sender_transport,
+ transport_sender_.get(),
NULL,
NULL,
kRtcpReducedSize,
base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
- kReceiverSsrc,
kSenderSsrc,
- kCName);
+ kReceiverSsrc,
+ kCName,
+ AUDIO_EVENT);
- receiver_transport.SetRtcpReceiver(&rtcp_sender);
- sender_transport.SetRtcpReceiver(&rtcp_receiver);
+ receiver_to_sender_.set_rtcp_receiver(&rtcp_sender);
+ sender_to_receiver_.set_rtcp_receiver(&rtcp_receiver);
rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
- rtcp_sender.SendRtcpFromRtpSender(NULL);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 0);
+ RunTasks(33);
base::TimeDelta rtt;
base::TimeDelta avg_rtt;
base::TimeDelta min_rtt;
base::TimeDelta max_rtt;
- EXPECT_FALSE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_FALSE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
EXPECT_NEAR(2 * kAddedDelay, rtt.InMilliseconds(), 1);
EXPECT_NEAR(2 * kAddedDelay, avg_rtt.InMilliseconds(), 1);
EXPECT_NEAR(2 * kAddedDelay, min_rtt.InMilliseconds(), 1);
EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 1);
- receiver_transport.SetShortDelay();
- sender_transport.SetShortDelay();
- receiver_transport.SetDropPackets(true);
+ receiver_to_sender_.set_short_delay();
+ sender_to_receiver_.set_short_delay();
+ receiver_to_sender_.set_drop_packets(true);
rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
- rtcp_sender.SendRtcpFromRtpSender(NULL);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 1);
+ RunTasks(33);
- EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
- EXPECT_NEAR(kAddedDelay + kAddedShortDelay, rtt.InMilliseconds(), 1);
+ EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
+ EXPECT_NEAR(kAddedDelay + kAddedShortDelay, rtt.InMilliseconds(), 2);
}
TEST_F(RtcpTest, NtpAndTime) {
- const int64 kSecondsbetweenYear1900and2010 = GG_INT64_C(40176 * 24 * 60 * 60);
- const int64 kSecondsbetweenYear1900and2030 = GG_INT64_C(47481 * 24 * 60 * 60);
+ const int64 kSecondsbetweenYear1900and2010 = INT64_C(40176 * 24 * 60 * 60);
+ const int64 kSecondsbetweenYear1900and2030 = INT64_C(47481 * 24 * 60 * 60);
uint32 ntp_seconds_1 = 0;
- uint32 ntp_fractions_1 = 0;
+ uint32 ntp_fraction_1 = 0;
base::TimeTicks input_time = base::TimeTicks::Now();
- ConvertTimeTicksToNtp(input_time, &ntp_seconds_1, &ntp_fractions_1);
+ ConvertTimeTicksToNtp(input_time, &ntp_seconds_1, &ntp_fraction_1);
// Verify absolute value.
EXPECT_GT(ntp_seconds_1, kSecondsbetweenYear1900and2010);
EXPECT_LT(ntp_seconds_1, kSecondsbetweenYear1900and2030);
- base::TimeTicks out_1 = ConvertNtpToTimeTicks(ntp_seconds_1, ntp_fractions_1);
+ base::TimeTicks out_1 = ConvertNtpToTimeTicks(ntp_seconds_1, ntp_fraction_1);
EXPECT_EQ(input_time, out_1); // Verify inverse.
base::TimeDelta time_delta = base::TimeDelta::FromMilliseconds(1000);
input_time += time_delta;
uint32 ntp_seconds_2 = 0;
- uint32 ntp_fractions_2 = 0;
+ uint32 ntp_fraction_2 = 0;
- ConvertTimeTicksToNtp(input_time, &ntp_seconds_2, &ntp_fractions_2);
- base::TimeTicks out_2 = ConvertNtpToTimeTicks(ntp_seconds_2, ntp_fractions_2);
+ ConvertTimeTicksToNtp(input_time, &ntp_seconds_2, &ntp_fraction_2);
+ base::TimeTicks out_2 = ConvertNtpToTimeTicks(ntp_seconds_2, ntp_fraction_2);
EXPECT_EQ(input_time, out_2); // Verify inverse.
// Verify delta.
EXPECT_EQ((out_2 - out_1), time_delta);
- EXPECT_EQ((ntp_seconds_2 - ntp_seconds_1), GG_UINT32_C(1));
- EXPECT_NEAR(ntp_fractions_2, ntp_fractions_1, 1);
+ EXPECT_EQ((ntp_seconds_2 - ntp_seconds_1), UINT32_C(1));
+ EXPECT_NEAR(ntp_fraction_2, ntp_fraction_1, 1);
time_delta = base::TimeDelta::FromMilliseconds(500);
input_time += time_delta;
uint32 ntp_seconds_3 = 0;
- uint32 ntp_fractions_3 = 0;
+ uint32 ntp_fraction_3 = 0;
- ConvertTimeTicksToNtp(input_time, &ntp_seconds_3, &ntp_fractions_3);
- base::TimeTicks out_3 = ConvertNtpToTimeTicks(ntp_seconds_3, ntp_fractions_3);
+ ConvertTimeTicksToNtp(input_time, &ntp_seconds_3, &ntp_fraction_3);
+ base::TimeTicks out_3 = ConvertNtpToTimeTicks(ntp_seconds_3, ntp_fraction_3);
EXPECT_EQ(input_time, out_3); // Verify inverse.
// Verify delta.
EXPECT_EQ((out_3 - out_2), time_delta);
- EXPECT_NEAR((ntp_fractions_3 - ntp_fractions_2), 0xffffffff / 2, 1);
-}
-
-TEST_F(RtcpTest, WrapAround) {
- RtcpPeer rtcp_peer(cast_environment_,
- &mock_sender_feedback_,
- NULL,
- NULL,
- NULL,
- kRtcpReducedSize,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
- kReceiverSsrc,
- kSenderSsrc,
- kCName);
- uint32 new_timestamp = 0;
- uint32 old_timestamp = 0;
- EXPECT_EQ(0, rtcp_peer.CheckForWrapAround(new_timestamp, old_timestamp));
- new_timestamp = 1234567890;
- old_timestamp = 1234567000;
- EXPECT_EQ(0, rtcp_peer.CheckForWrapAround(new_timestamp, old_timestamp));
- new_timestamp = 1234567000;
- old_timestamp = 1234567890;
- EXPECT_EQ(0, rtcp_peer.CheckForWrapAround(new_timestamp, old_timestamp));
- new_timestamp = 123;
- old_timestamp = 4234567890u;
- EXPECT_EQ(1, rtcp_peer.CheckForWrapAround(new_timestamp, old_timestamp));
- new_timestamp = 4234567890u;
- old_timestamp = 123;
- EXPECT_EQ(-1, rtcp_peer.CheckForWrapAround(new_timestamp, old_timestamp));
-}
-
-TEST_F(RtcpTest, RtpTimestampInSenderTime) {
- RtcpPeer rtcp_peer(cast_environment_,
- &mock_sender_feedback_,
- NULL,
- NULL,
- NULL,
- kRtcpReducedSize,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
- kReceiverSsrc,
- kSenderSsrc,
- kCName);
- int frequency = 32000;
- uint32 rtp_timestamp = 64000;
- base::TimeTicks rtp_timestamp_in_ticks;
-
- // Test fail before we get a OnReceivedLipSyncInfo.
- EXPECT_FALSE(rtcp_peer.RtpTimestampInSenderTime(frequency, rtp_timestamp,
- &rtp_timestamp_in_ticks));
-
- uint32 ntp_seconds = 0;
- uint32 ntp_fractions = 0;
- uint64 input_time_us = 12345678901000LL;
- base::TimeTicks input_time;
- input_time += base::TimeDelta::FromMicroseconds(input_time_us);
-
- // Test exact match.
- ConvertTimeTicksToNtp(input_time, &ntp_seconds, &ntp_fractions);
- rtcp_peer.OnReceivedLipSyncInfo(rtp_timestamp, ntp_seconds, ntp_fractions);
- EXPECT_TRUE(rtcp_peer.RtpTimestampInSenderTime(frequency, rtp_timestamp,
- &rtp_timestamp_in_ticks));
- EXPECT_EQ(input_time, rtp_timestamp_in_ticks);
-
- // Test older rtp_timestamp.
- rtp_timestamp = 32000;
- EXPECT_TRUE(rtcp_peer.RtpTimestampInSenderTime(frequency, rtp_timestamp,
- &rtp_timestamp_in_ticks));
- EXPECT_EQ(input_time - base::TimeDelta::FromMilliseconds(1000),
- rtp_timestamp_in_ticks);
-
- // Test older rtp_timestamp with wrap.
- rtp_timestamp = 4294903296u;
- EXPECT_TRUE(rtcp_peer.RtpTimestampInSenderTime(frequency, rtp_timestamp,
- &rtp_timestamp_in_ticks));
- EXPECT_EQ(input_time - base::TimeDelta::FromMilliseconds(4000),
- rtp_timestamp_in_ticks);
-
- // Test newer rtp_timestamp.
- rtp_timestamp = 128000;
- EXPECT_TRUE(rtcp_peer.RtpTimestampInSenderTime(frequency, rtp_timestamp,
- &rtp_timestamp_in_ticks));
- EXPECT_EQ(input_time + base::TimeDelta::FromMilliseconds(2000),
- rtp_timestamp_in_ticks);
-
- // Test newer rtp_timestamp with wrap.
- rtp_timestamp = 4294903296u;
- rtcp_peer.OnReceivedLipSyncInfo(rtp_timestamp, ntp_seconds, ntp_fractions);
- rtp_timestamp = 64000;
- EXPECT_TRUE(rtcp_peer.RtpTimestampInSenderTime(frequency, rtp_timestamp,
- &rtp_timestamp_in_ticks));
- EXPECT_EQ(input_time + base::TimeDelta::FromMilliseconds(4000),
- rtp_timestamp_in_ticks);
+ EXPECT_NEAR((ntp_fraction_3 - ntp_fraction_2), 0xffffffff / 2, 1);
}
} // namespace cast
diff --git a/chromium/media/cast/rtcp/rtcp_utility.cc b/chromium/media/cast/rtcp/rtcp_utility.cc
index daeaa8aaceb..e29f82e9cf9 100644
--- a/chromium/media/cast/rtcp/rtcp_utility.cc
+++ b/chromium/media/cast/rtcp/rtcp_utility.cc
@@ -4,8 +4,9 @@
#include "media/cast/rtcp/rtcp_utility.h"
+#include "base/big_endian.h"
#include "base/logging.h"
-#include "net/base/big_endian.h"
+#include "media/cast/transport/cast_transport_defines.h"
namespace media {
namespace cast {
@@ -19,18 +20,15 @@ RtcpParser::RtcpParser(const uint8* rtcpData, size_t rtcpDataLength)
state_(kStateTopLevel),
number_of_blocks_(0),
field_type_(kRtcpNotValidCode) {
+ memset(&field_, 0, sizeof(field_));
Validate();
}
RtcpParser::~RtcpParser() {}
-RtcpFieldTypes RtcpParser::FieldType() const {
- return field_type_;
-}
+RtcpFieldTypes RtcpParser::FieldType() const { return field_type_; }
-const RtcpField& RtcpParser::Field() const {
- return field_;
-}
+const RtcpField& RtcpParser::Field() const { return field_; }
RtcpFieldTypes RtcpParser::Begin() {
rtcp_data_ = rtcp_data_begin_;
@@ -41,7 +39,8 @@ RtcpFieldTypes RtcpParser::Iterate() {
// Reset packet type
field_type_ = kRtcpNotValidCode;
- if (!IsValid()) return kRtcpNotValidCode;
+ if (!IsValid())
+ return kRtcpNotValidCode;
switch (state_) {
case kStateTopLevel:
@@ -62,9 +61,6 @@ RtcpFieldTypes RtcpParser::Iterate() {
case kStateApplicationSpecificCastReceiverEventLog:
IterateCastReceiverLogEvent();
break;
- case kStateApplicationSpecificCastSenderLog:
- IterateCastSenderLog();
- break;
case kStateExtendedReportBlock:
IterateExtendedReportItem();
break;
@@ -101,51 +97,53 @@ void RtcpParser::IterateTopLevel() {
RtcpCommonHeader header;
bool success = RtcpParseCommonHeader(rtcp_data_, rtcp_data_end_, &header);
- if (!success) return;
+ if (!success)
+ return;
rtcp_block_end_ = rtcp_data_ + header.length_in_octets;
- if (rtcp_block_end_ > rtcp_data_end_) return; // Bad block!
+ if (rtcp_block_end_ > rtcp_data_end_)
+ return; // Bad block!
switch (header.PT) {
- case kPacketTypeSenderReport:
+ case transport::kPacketTypeSenderReport:
// number of Report blocks
number_of_blocks_ = header.IC;
ParseSR();
return;
- case kPacketTypeReceiverReport:
+ case transport::kPacketTypeReceiverReport:
// number of Report blocks
number_of_blocks_ = header.IC;
ParseRR();
return;
- case kPacketTypeSdes:
+ case transport::kPacketTypeSdes:
// number of Sdes blocks
number_of_blocks_ = header.IC;
if (!ParseSdes()) {
break; // Nothing supported found, continue to next block!
}
return;
- case kPacketTypeBye:
+ case transport::kPacketTypeBye:
number_of_blocks_ = header.IC;
if (!ParseBye()) {
// Nothing supported found, continue to next block!
break;
}
return;
- case kPacketTypeApplicationDefined:
+ case transport::kPacketTypeApplicationDefined:
if (!ParseApplicationDefined(header.IC)) {
// Nothing supported found, continue to next block!
break;
}
return;
- case kPacketTypeGenericRtpFeedback: // Fall through!
- case kPacketTypePayloadSpecific:
+ case transport::kPacketTypeGenericRtpFeedback: // Fall through!
+ case transport::kPacketTypePayloadSpecific:
if (!ParseFeedBackCommon(header)) {
// Nothing supported found, continue to next block!
break;
}
return;
- case kPacketTypeXr:
+ case transport::kPacketTypeXr:
if (!ParseExtendedReport()) {
break; // Nothing supported found, continue to next block!
}
@@ -160,103 +158,111 @@ void RtcpParser::IterateTopLevel() {
void RtcpParser::IterateReportBlockItem() {
bool success = ParseReportBlockItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IterateSdesItem() {
bool success = ParseSdesItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IterateByeItem() {
bool success = ParseByeItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IterateExtendedReportItem() {
bool success = ParseExtendedReportItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IterateExtendedReportDelaySinceLastReceiverReportItem() {
bool success = ParseExtendedReportDelaySinceLastReceiverReport();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IterateNackItem() {
bool success = ParseNackItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IterateRpsiItem() {
bool success = ParseRpsiItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IterateFirItem() {
bool success = ParseFirItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IteratePayloadSpecificAppItem() {
bool success = ParsePayloadSpecificAppItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IteratePayloadSpecificRembItem() {
bool success = ParsePayloadSpecificRembItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IteratePayloadSpecificCastItem() {
bool success = ParsePayloadSpecificCastItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IteratePayloadSpecificCastNackItem() {
bool success = ParsePayloadSpecificCastNackItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IterateCastReceiverLogFrame() {
bool success = ParseCastReceiverLogFrameItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::IterateCastReceiverLogEvent() {
bool success = ParseCastReceiverLogEventItem();
- if (!success) Iterate();
-}
-
-void RtcpParser::IterateCastSenderLog() {
- bool success = ParseCastSenderLogItem();
- if (!success) Iterate();
+ if (!success)
+ Iterate();
}
void RtcpParser::Validate() {
- if (rtcp_data_ == NULL) return; // NOT VALID
+ if (rtcp_data_ == NULL)
+ return; // NOT VALID
RtcpCommonHeader header;
- bool success = RtcpParseCommonHeader(rtcp_data_begin_, rtcp_data_end_,
- &header);
+ bool success =
+ RtcpParseCommonHeader(rtcp_data_begin_, rtcp_data_end_, &header);
- if (!success) return; // NOT VALID!
+ if (!success)
+ return; // NOT VALID!
valid_packet_ = true;
}
-bool RtcpParser::IsValid() const {
- return valid_packet_;
-}
+bool RtcpParser::IsValid() const { return valid_packet_; }
-void RtcpParser::EndCurrentBlock() {
- rtcp_data_ = rtcp_block_end_;
-}
+void RtcpParser::EndCurrentBlock() { rtcp_data_ = rtcp_block_end_; }
bool RtcpParser::RtcpParseCommonHeader(const uint8* data_begin,
const uint8* data_end,
RtcpCommonHeader* parsed_header) const {
- if (!data_begin || !data_end) return false;
+ if (!data_begin || !data_end)
+ return false;
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -266,31 +272,36 @@ bool RtcpParser::RtcpParseCommonHeader(const uint8* data_begin,
//
// Common header for all Rtcp packets, 4 octets.
- if ((data_end - data_begin) < 4) return false;
+ if ((data_end - data_begin) < 4)
+ return false;
- parsed_header->V = data_begin[0] >> 6;
- parsed_header->P = ((data_begin[0] & 0x20) == 0) ? false : true;
+ parsed_header->V = data_begin[0] >> 6;
+ parsed_header->P = ((data_begin[0] & 0x20) == 0) ? false : true;
parsed_header->IC = data_begin[0] & 0x1f;
parsed_header->PT = data_begin[1];
parsed_header->length_in_octets =
((data_begin[2] << 8) + data_begin[3] + 1) * 4;
- if (parsed_header->length_in_octets == 0) return false;
+ if (parsed_header->length_in_octets == 0)
+ return false;
// Check if RTP version field == 2.
- if (parsed_header->V != 2) return false;
+ if (parsed_header->V != 2)
+ return false;
return true;
}
bool RtcpParser::ParseRR() {
ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 8) return false;
+ if (length < 8)
+ return false;
field_type_ = kRtcpRrCode;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.Skip(4); // Skip header
big_endian_reader.ReadU32(&field_.receiver_report.sender_ssrc);
field_.receiver_report.number_of_report_blocks = number_of_blocks_;
@@ -309,7 +320,8 @@ bool RtcpParser::ParseSR() {
}
field_type_ = kRtcpSrCode;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.Skip(4); // Skip header
big_endian_reader.ReadU32(&field_.sender_report.sender_ssrc);
big_endian_reader.ReadU32(&field_.sender_report.ntp_most_significant);
@@ -339,7 +351,8 @@ bool RtcpParser::ParseReportBlockItem() {
return false;
}
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU32(&field_.report_block_item.ssrc);
big_endian_reader.ReadU8(&field_.report_block_item.fraction_lost);
@@ -399,7 +412,8 @@ bool RtcpParser::ParseSdesItem() {
}
uint32 ssrc;
- net::BigEndianReader big_endian_reader(rtcp_data_, data_length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), data_length);
big_endian_reader.ReadU32(&ssrc);
rtcp_data_ += 4;
@@ -418,7 +432,8 @@ bool RtcpParser::ParseSdesTypes() {
// Only the c_name item is mandatory. RFC 3550 page 46.
bool found_c_name = false;
ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
while (big_endian_reader.remaining() > 0) {
uint8 tag;
@@ -484,7 +499,8 @@ bool RtcpParser::ParseByeItem() {
field_type_ = kRtcpByeCode;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU32(&field_.bye.sender_ssrc);
rtcp_data_ += 4;
@@ -498,8 +514,7 @@ bool RtcpParser::ParseByeItem() {
bool RtcpParser::ParseApplicationDefined(uint8 subtype) {
ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 16 ||
- !(subtype == kSenderLogSubtype || subtype == kReceiverLogSubtype)) {
+ if (length < 16 || subtype != kReceiverLogSubtype) {
state_ = kStateTopLevel;
EndCurrentBlock();
return false;
@@ -508,7 +523,8 @@ bool RtcpParser::ParseApplicationDefined(uint8 subtype) {
uint32 sender_ssrc;
uint32 name;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.Skip(4); // Skip header.
big_endian_reader.ReadU32(&sender_ssrc);
big_endian_reader.ReadU32(&name);
@@ -520,11 +536,6 @@ bool RtcpParser::ParseApplicationDefined(uint8 subtype) {
}
rtcp_data_ += 12;
switch (subtype) {
- case kSenderLogSubtype:
- state_ = kStateApplicationSpecificCastSenderLog;
- field_type_ = kRtcpApplicationSpecificCastSenderLogCode;
- field_.cast_sender_log.sender_ssrc = sender_ssrc;
- break;
case kReceiverLogSubtype:
state_ = kStateApplicationSpecificCastReceiverFrameLog;
field_type_ = kRtcpApplicationSpecificCastReceiverLogCode;
@@ -545,7 +556,8 @@ bool RtcpParser::ParseCastReceiverLogFrameItem() {
}
uint32 rtp_timestamp;
uint32 data;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU32(&rtp_timestamp);
big_endian_reader.ReadU32(&data);
@@ -577,7 +589,8 @@ bool RtcpParser::ParseCastReceiverLogEventItem() {
uint16 delay_delta_or_packet_id;
uint16 event_type_and_timestamp_delta;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU16(&delay_delta_or_packet_id);
big_endian_reader.ReadU16(&event_type_and_timestamp_delta);
@@ -585,7 +598,9 @@ bool RtcpParser::ParseCastReceiverLogEventItem() {
field_.cast_receiver_log.event =
static_cast<uint8>(event_type_and_timestamp_delta >> 12);
- field_.cast_receiver_log.delay_delta_or_packet_id = delay_delta_or_packet_id;
+ // delay_delta is in union'ed with packet_id.
+ field_.cast_receiver_log.delay_delta_or_packet_id.packet_id =
+ delay_delta_or_packet_id;
field_.cast_receiver_log.event_timestamp_delta =
event_type_and_timestamp_delta & 0xfff;
@@ -593,30 +608,10 @@ bool RtcpParser::ParseCastReceiverLogEventItem() {
return true;
}
-bool RtcpParser::ParseCastSenderLogItem() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
-
- if (length < 4) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- uint32 data;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
- big_endian_reader.ReadU32(&data);
-
- rtcp_data_ += 4;
-
- field_.cast_sender_log.status = static_cast<uint8>(data >> 24);
- // We have 24 LSB of the RTP timestamp on the wire.
- field_.cast_sender_log.rtp_timestamp = data & 0xffffff;
- field_type_ = kRtcpApplicationSpecificCastSenderLogCode;
- return true;
-}
-
bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
- DCHECK((header.PT == kPacketTypeGenericRtpFeedback) ||
- (header.PT == kPacketTypePayloadSpecific)) << "Invalid state";
+ DCHECK((header.PT == transport::kPacketTypeGenericRtpFeedback) ||
+ (header.PT == transport::kPacketTypePayloadSpecific))
+ << "Invalid state";
ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
@@ -627,21 +622,22 @@ bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
uint32 sender_ssrc;
uint32 media_ssrc;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.Skip(4); // Skip header.
big_endian_reader.ReadU32(&sender_ssrc);
big_endian_reader.ReadU32(&media_ssrc);
rtcp_data_ += 12;
- if (header.PT == kPacketTypeGenericRtpFeedback) {
+ if (header.PT == transport::kPacketTypeGenericRtpFeedback) {
// Transport layer feedback
switch (header.IC) {
case 1:
// Nack
field_type_ = kRtcpGenericRtpFeedbackNackCode;
field_.nack.sender_ssrc = sender_ssrc;
- field_.nack.media_ssrc = media_ssrc;
+ field_.nack.media_ssrc = media_ssrc;
state_ = kStateGenericRtpFeedbackNack;
return true;
case 2:
@@ -667,14 +663,14 @@ bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
EndCurrentBlock();
return false;
- } else if (header.PT == kPacketTypePayloadSpecific) {
+ } else if (header.PT == transport::kPacketTypePayloadSpecific) {
// Payload specific feedback
switch (header.IC) {
case 1:
// PLI
field_type_ = kRtcpPayloadSpecificPliCode;
field_.pli.sender_ssrc = sender_ssrc;
- field_.pli.media_ssrc = media_ssrc;
+ field_.pli.media_ssrc = media_ssrc;
// Note: No state transition, PLI FCI is empty!
return true;
@@ -684,7 +680,7 @@ bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
case 3:
field_type_ = kRtcpPayloadSpecificRpsiCode;
field_.rpsi.sender_ssrc = sender_ssrc;
- field_.rpsi.media_ssrc = media_ssrc;
+ field_.rpsi.media_ssrc = media_ssrc;
state_ = kStatePayloadSpecificRpsi;
return true;
case 4:
@@ -693,7 +689,7 @@ bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
case 15:
field_type_ = kRtcpPayloadSpecificAppCode;
field_.application_specific.sender_ssrc = sender_ssrc;
- field_.application_specific.media_ssrc = media_ssrc;
+ field_.application_specific.media_ssrc = media_ssrc;
state_ = kStatePayloadSpecificApplication;
return true;
default:
@@ -736,7 +732,8 @@ bool RtcpParser::ParseRpsiItem() {
field_type_ = kRtcpPayloadSpecificRpsiCode;
uint8 padding_bits;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU8(&padding_bits);
big_endian_reader.ReadU8(&field_.rpsi.payload_type);
big_endian_reader.ReadBytes(&field_.rpsi.native_bit_string, length - 2);
@@ -759,7 +756,8 @@ bool RtcpParser::ParseNackItem() {
field_type_ = kRtcpGenericRtpFeedbackNackItemCode;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU16(&field_.nack_item.packet_id);
big_endian_reader.ReadU16(&field_.nack_item.bitmask);
rtcp_data_ += 4;
@@ -775,7 +773,8 @@ bool RtcpParser::ParsePayloadSpecificAppItem() {
return false;
}
uint32 name;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU32(&name);
rtcp_data_ += 4;
@@ -802,7 +801,8 @@ bool RtcpParser::ParsePayloadSpecificRembItem() {
return false;
}
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU8(&field_.remb_item.number_of_ssrcs);
uint8 byte_1;
@@ -841,9 +841,11 @@ bool RtcpParser::ParsePayloadSpecificCastItem() {
}
field_type_ = kRtcpPayloadSpecificCastCode;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU8(&field_.cast_item.last_frame_id);
big_endian_reader.ReadU8(&field_.cast_item.number_of_lost_fields);
+ big_endian_reader.ReadU16(&field_.cast_item.target_delay_ms);
rtcp_data_ += 4;
@@ -867,7 +869,8 @@ bool RtcpParser::ParsePayloadSpecificCastNackItem() {
}
field_type_ = kRtcpPayloadSpecificCastNackItemCode;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU8(&field_.cast_nack_item.frame_id);
big_endian_reader.ReadU16(&field_.cast_nack_item.packet_id);
big_endian_reader.ReadU8(&field_.cast_nack_item.bitmask);
@@ -887,7 +890,8 @@ bool RtcpParser::ParseFirItem() {
}
field_type_ = kRtcpPayloadSpecificFirItemCode;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU32(&field_.fir_item.ssrc);
big_endian_reader.ReadU8(&field_.fir_item.command_sequence_number);
@@ -897,11 +901,13 @@ bool RtcpParser::ParseFirItem() {
bool RtcpParser::ParseExtendedReport() {
ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 8) return false;
+ if (length < 8)
+ return false;
field_type_ = kRtcpXrCode;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.Skip(4); // Skip header.
big_endian_reader.ReadU32(&field_.extended_report.sender_ssrc);
@@ -921,7 +927,8 @@ bool RtcpParser::ParseExtendedReportItem() {
uint8 block_type;
uint16 block_length;
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU8(&block_type);
big_endian_reader.Skip(1); // Ignore reserved.
big_endian_reader.ReadU16(&block_length);
@@ -970,7 +977,8 @@ bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport() {
return false;
}
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU32(&field_.rrtr.ntp_most_significant);
big_endian_reader.ReadU32(&field_.rrtr.ntp_least_significant);
@@ -993,7 +1001,8 @@ bool RtcpParser::ParseExtendedReportDelaySinceLastReceiverReport() {
return false;
}
- net::BigEndianReader big_endian_reader(rtcp_data_, length);
+ base::BigEndianReader big_endian_reader(
+ reinterpret_cast<const char*>(rtcp_data_), length);
big_endian_reader.ReadU32(&field_.dlrr.receivers_ssrc);
big_endian_reader.ReadU32(&field_.dlrr.last_receiver_report);
big_endian_reader.ReadU32(&field_.dlrr.delay_last_receiver_report);
@@ -1005,5 +1014,53 @@ bool RtcpParser::ParseExtendedReportDelaySinceLastReceiverReport() {
return true;
}
+// Converts a log event type to an integer value.
+// NOTE: We have only allocated 4 bits to represent the type of event over the
+// wire. Therefore, this function can only return values from 0 to 15.
+uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event) {
+ switch (event) {
+ case FRAME_ACK_SENT:
+ return 11;
+ case FRAME_PLAYOUT:
+ return 12;
+ case FRAME_DECODED:
+ return 13;
+ case PACKET_RECEIVED:
+ return 14;
+ default:
+ return 0; // Not an interesting event.
+ }
+}
+
+CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) {
+ // TODO(imcheng): Remove the old mappings once they are no longer used.
+ switch (event) {
+ case 1: // AudioAckSent
+ case 5: // VideoAckSent
+ case 11: // Unified
+ return FRAME_ACK_SENT;
+ case 2: // AudioPlayoutDelay
+ case 7: // VideoRenderDelay
+ case 12: // Unified
+ return FRAME_PLAYOUT;
+ case 3: // AudioFrameDecoded
+ case 6: // VideoFrameDecoded
+ case 13: // Unified
+ return FRAME_DECODED;
+ case 4: // AudioPacketReceived
+ case 8: // VideoPacketReceived
+ case 14: // Unified
+ return PACKET_RECEIVED;
+ case 9: // DuplicateAudioPacketReceived
+ case 10: // DuplicateVideoPacketReceived
+ default:
+ // If the sender adds new log messages we will end up here until we add
+ // the new messages in the receiver.
+ VLOG(1) << "Unexpected log message received: " << static_cast<int>(event);
+ NOTREACHED();
+ return UNKNOWN;
+ }
+}
+
} // namespace cast
} // namespace media
diff --git a/chromium/media/cast/rtcp/rtcp_utility.h b/chromium/media/cast/rtcp/rtcp_utility.h
index 5cf55d91060..34f3f25a889 100644
--- a/chromium/media/cast/rtcp/rtcp_utility.h
+++ b/chromium/media/cast/rtcp/rtcp_utility.h
@@ -7,6 +7,7 @@
#include "media/cast/cast_config.h"
#include "media/cast/cast_defines.h"
+#include "media/cast/logging/logging_defines.h"
#include "media/cast/rtcp/rtcp_defines.h"
namespace media {
@@ -21,7 +22,6 @@ static const int kRtcpMaxNumberOfRembFeedbackSsrcs = 255;
static const uint32 kRemb = ('R' << 24) + ('E' << 16) + ('M' << 8) + 'B';
static const uint32 kCast = ('C' << 24) + ('A' << 16) + ('S' << 8) + 'T';
-static const uint8 kSenderLogSubtype = 1;
static const uint8 kReceiverLogSubtype = 2;
static const size_t kRtcpMaxReceiverLogMessages = 256;
@@ -37,7 +37,7 @@ struct RtcpFieldReceiverReport {
struct RtcpFieldSenderReport {
// RFC 3550.
uint32 sender_ssrc;
- uint8 number_of_report_blocks;
+ uint8 number_of_report_blocks;
uint32 ntp_most_significant;
uint32 ntp_least_significant;
uint32 rtp_timestamp;
@@ -48,7 +48,7 @@ struct RtcpFieldSenderReport {
struct RtcpFieldReportBlockItem {
// RFC 3550.
uint32 ssrc;
- uint8 fraction_lost;
+ uint8 fraction_lost;
uint32 cumulative_number_of_packets_lost;
uint32 extended_highest_sequence_number;
uint32 jitter;
@@ -101,9 +101,9 @@ struct RtcpFieldPayloadSpecificRpsi {
// RFC 4585.
uint32 sender_ssrc;
uint32 media_ssrc;
- uint8 payload_type;
+ uint8 payload_type;
uint16 number_of_valid_bits;
- uint8 native_bit_string[kRtcpRpsiDataSize];
+ uint8 native_bit_string[kRtcpRpsiDataSize];
};
struct RtcpFieldXr {
@@ -138,6 +138,7 @@ struct RtcpFieldPayloadSpecificRembItem {
struct RtcpFieldPayloadSpecificCastItem {
uint8 last_frame_id;
uint8 number_of_lost_fields;
+ uint16 target_delay_ms;
};
struct RtcpFieldPayloadSpecificCastNackItem {
@@ -151,41 +152,37 @@ struct RtcpFieldApplicationSpecificCastReceiverLogItem {
uint32 rtp_timestamp;
uint32 event_timestamp_base;
uint8 event;
- uint16 delay_delta_or_packet_id;
+ union {
+ uint16 packet_id;
+ int16 delay_delta;
+ } delay_delta_or_packet_id;
uint16 event_timestamp_delta;
};
-struct RtcpFieldApplicationSpecificCastSenderLogItem {
- uint32 sender_ssrc;
- uint8 status;
- uint32 rtp_timestamp;
-};
-
union RtcpField {
- RtcpFieldReceiverReport receiver_report;
- RtcpFieldSenderReport sender_report;
- RtcpFieldReportBlockItem report_block_item;
- RtcpFieldSdesCName c_name;
- RtcpFieldBye bye;
-
- RtcpFieldXr extended_report;
- RtcpFieldXrRrtr rrtr;
- RtcpFieldXrDlrr dlrr;
-
- RtcpFieldGenericRtpFeedbackNack nack;
- RtcpFieldGenericRtpFeedbackNackItem nack_item;
-
- RtcpFieldPayloadSpecificPli pli;
- RtcpFieldPayloadSpecificRpsi rpsi;
- RtcpFieldPayloadSpecificFir fir;
- RtcpFieldPayloadSpecificFirItem fir_item;
- RtcpFieldPayloadSpecificApplication application_specific;
- RtcpFieldPayloadSpecificRembItem remb_item;
- RtcpFieldPayloadSpecificCastItem cast_item;
- RtcpFieldPayloadSpecificCastNackItem cast_nack_item;
+ RtcpFieldReceiverReport receiver_report;
+ RtcpFieldSenderReport sender_report;
+ RtcpFieldReportBlockItem report_block_item;
+ RtcpFieldSdesCName c_name;
+ RtcpFieldBye bye;
+
+ RtcpFieldXr extended_report;
+ RtcpFieldXrRrtr rrtr;
+ RtcpFieldXrDlrr dlrr;
+
+ RtcpFieldGenericRtpFeedbackNack nack;
+ RtcpFieldGenericRtpFeedbackNackItem nack_item;
+
+ RtcpFieldPayloadSpecificPli pli;
+ RtcpFieldPayloadSpecificRpsi rpsi;
+ RtcpFieldPayloadSpecificFir fir;
+ RtcpFieldPayloadSpecificFirItem fir_item;
+ RtcpFieldPayloadSpecificApplication application_specific;
+ RtcpFieldPayloadSpecificRembItem remb_item;
+ RtcpFieldPayloadSpecificCastItem cast_item;
+ RtcpFieldPayloadSpecificCastNackItem cast_nack_item;
RtcpFieldApplicationSpecificCastReceiverLogItem cast_receiver_log;
- RtcpFieldApplicationSpecificCastSenderLogItem cast_sender_log;
};
enum RtcpFieldTypes {
@@ -195,7 +192,6 @@ enum RtcpFieldTypes {
kRtcpRrCode,
kRtcpSrCode,
kRtcpReportBlockItemCode,
-
kRtcpSdesCode,
kRtcpSdesChunkCode,
kRtcpByeCode,
@@ -209,7 +205,6 @@ enum RtcpFieldTypes {
// RFC 4585.
kRtcpGenericRtpFeedbackNackCode,
kRtcpGenericRtpFeedbackNackItemCode,
-
kRtcpPayloadSpecificPliCode,
kRtcpPayloadSpecificRpsiCode,
kRtcpPayloadSpecificAppCode,
@@ -222,7 +217,6 @@ enum RtcpFieldTypes {
kRtcpApplicationSpecificCastReceiverLogCode,
kRtcpApplicationSpecificCastReceiverLogFrameCode,
kRtcpApplicationSpecificCastReceiverLogEventCode,
- kRtcpApplicationSpecificCastSenderLogCode,
// RFC 5104.
kRtcpPayloadSpecificFirCode,
@@ -233,27 +227,13 @@ enum RtcpFieldTypes {
};
struct RtcpCommonHeader {
- uint8 V; // Version.
- bool P; // Padding.
- uint8 IC; // Item count / subtype.
- uint8 PT; // Packet Type.
+ uint8 V; // Version.
+ bool P; // Padding.
+ uint8 IC; // Item count / subtype.
+ uint8 PT; // Packet Type.
uint16 length_in_octets;
};
-enum RtcpPacketTypes {
- kPacketTypeLow = 194, // SMPTE time-code mapping.
- kPacketTypeInterArrivalJitterReport = 195,
- kPacketTypeSenderReport = 200,
- kPacketTypeReceiverReport = 201,
- kPacketTypeSdes = 202,
- kPacketTypeBye = 203,
- kPacketTypeApplicationDefined = 204,
- kPacketTypeGenericRtpFeedback = 205,
- kPacketTypePayloadSpecific = 206,
- kPacketTypeXr = 207,
- kPacketTypeHigh = 210, // Port Mapping.
-};
-
class RtcpParser {
public:
RtcpParser(const uint8* rtcp_data, size_t rtcp_length);
@@ -275,7 +255,6 @@ class RtcpParser {
kStateBye,
kStateApplicationSpecificCastReceiverFrameLog,
kStateApplicationSpecificCastReceiverEventLog,
- kStateApplicationSpecificCastSenderLog,
kStateExtendedReportBlock,
kStateExtendedReportDelaySinceLastReceiverReport,
kStateGenericRtpFeedbackNack,
@@ -297,7 +276,6 @@ class RtcpParser {
void IterateByeItem();
void IterateCastReceiverLogFrame();
void IterateCastReceiverLogEvent();
- void IterateCastSenderLog();
void IterateExtendedReportItem();
void IterateExtendedReportDelaySinceLastReceiverReportItem();
void IterateNackItem();
@@ -323,7 +301,6 @@ class RtcpParser {
bool ParseApplicationDefined(uint8 subtype);
bool ParseCastReceiverLogFrameItem();
bool ParseCastReceiverLogEventItem();
- bool ParseCastSenderLogItem();
bool ParseExtendedReport();
bool ParseExtendedReportItem();
@@ -355,6 +332,14 @@ class RtcpParser {
DISALLOW_COPY_AND_ASSIGN(RtcpParser);
};
+// Converts a log event type to an integer value.
+// NOTE: We have only allocated 4 bits to represent the type of event over the
+// wire. Therefore, this function can only return values from 0 to 15.
+uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event);
+
+// The inverse of |ConvertEventTypeToWireFormat()|.
+CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event);
+
} // namespace cast
} // namespace media
diff --git a/chromium/media/cast/rtcp/test_rtcp_packet_builder.cc b/chromium/media/cast/rtcp/test_rtcp_packet_builder.cc
index f4117f53dec..8d0809d928e 100644
--- a/chromium/media/cast/rtcp/test_rtcp_packet_builder.cc
+++ b/chromium/media/cast/rtcp/test_rtcp_packet_builder.cc
@@ -5,14 +5,14 @@
#include "media/cast/rtcp/test_rtcp_packet_builder.h"
#include "base/logging.h"
+#include "media/cast/rtcp/rtcp_utility.h"
namespace media {
namespace cast {
TestRtcpPacketBuilder::TestRtcpPacketBuilder()
: ptr_of_length_(NULL),
- big_endian_writer_(buffer_, kIpPacketSize) {
-}
+ big_endian_writer_(reinterpret_cast<char*>(buffer_), kMaxIpPacketSize) {}
void TestRtcpPacketBuilder::AddSr(uint32 sender_ssrc,
int number_of_report_blocks) {
@@ -91,8 +91,8 @@ void TestRtcpPacketBuilder::AddXrHeader(uint32 sender_ssrc) {
}
void TestRtcpPacketBuilder::AddXrUnknownBlock() {
- big_endian_writer_.WriteU8(9); // Block type.
- big_endian_writer_.WriteU8(0); // Reserved.
+ big_endian_writer_.WriteU8(9); // Block type.
+ big_endian_writer_.WriteU8(0); // Reserved.
big_endian_writer_.WriteU16(4); // Block length.
// First receiver same as sender of this report.
big_endian_writer_.WriteU32(0);
@@ -102,8 +102,8 @@ void TestRtcpPacketBuilder::AddXrUnknownBlock() {
}
void TestRtcpPacketBuilder::AddXrDlrrBlock(uint32 sender_ssrc) {
- big_endian_writer_.WriteU8(5); // Block type.
- big_endian_writer_.WriteU8(0); // Reserved.
+ big_endian_writer_.WriteU8(5); // Block type.
+ big_endian_writer_.WriteU8(0); // Reserved.
big_endian_writer_.WriteU16(3); // Block length.
// First receiver same as sender of this report.
@@ -113,8 +113,8 @@ void TestRtcpPacketBuilder::AddXrDlrrBlock(uint32 sender_ssrc) {
}
void TestRtcpPacketBuilder::AddXrExtendedDlrrBlock(uint32 sender_ssrc) {
- big_endian_writer_.WriteU8(5); // Block type.
- big_endian_writer_.WriteU8(0); // Reserved.
+ big_endian_writer_.WriteU8(5); // Block type.
+ big_endian_writer_.WriteU8(0); // Reserved.
big_endian_writer_.WriteU16(9); // Block length.
big_endian_writer_.WriteU32(0xaaaaaaaa);
big_endian_writer_.WriteU32(0xaaaaaaaa);
@@ -130,8 +130,8 @@ void TestRtcpPacketBuilder::AddXrExtendedDlrrBlock(uint32 sender_ssrc) {
}
void TestRtcpPacketBuilder::AddXrRrtrBlock() {
- big_endian_writer_.WriteU8(4); // Block type.
- big_endian_writer_.WriteU8(0); // Reserved.
+ big_endian_writer_.WriteU8(4); // Block type.
+ big_endian_writer_.WriteU8(0); // Reserved.
big_endian_writer_.WriteU16(2); // Block length.
big_endian_writer_.WriteU32(kNtpHigh);
big_endian_writer_.WriteU32(kNtpLow);
@@ -167,8 +167,8 @@ void TestRtcpPacketBuilder::AddRpsi(uint32 sender_ssrc, uint32 media_ssrc) {
uint64 picture_id = kPictureId;
for (int i = 9; i > 0; i--) {
- big_endian_writer_.WriteU8(
- 0x80 | static_cast<uint8>(picture_id >> (i * 7)));
+ big_endian_writer_.WriteU8(0x80 |
+ static_cast<uint8>(picture_id >> (i * 7)));
}
// Add last byte of picture ID.
big_endian_writer_.WriteU8(static_cast<uint8>(picture_id & 0x7f));
@@ -189,7 +189,9 @@ void TestRtcpPacketBuilder::AddRemb(uint32 sender_ssrc, uint32 media_ssrc) {
big_endian_writer_.WriteU32(media_ssrc);
}
-void TestRtcpPacketBuilder::AddCast(uint32 sender_ssrc, uint32 media_ssrc) {
+void TestRtcpPacketBuilder::AddCast(uint32 sender_ssrc,
+ uint32 media_ssrc,
+ uint16 target_delay_ms) {
AddRtcpHeader(206, 15);
big_endian_writer_.WriteU32(sender_ssrc);
big_endian_writer_.WriteU32(media_ssrc);
@@ -198,8 +200,8 @@ void TestRtcpPacketBuilder::AddCast(uint32 sender_ssrc, uint32 media_ssrc) {
big_endian_writer_.WriteU8('S');
big_endian_writer_.WriteU8('T');
big_endian_writer_.WriteU8(kAckFrameId);
- big_endian_writer_.WriteU8(3); // Loss fields.
- big_endian_writer_.WriteU16(0); // Reserved.
+ big_endian_writer_.WriteU8(3); // Loss fields.
+ big_endian_writer_.WriteU16(target_delay_ms);
big_endian_writer_.WriteU8(kLostFrameId);
big_endian_writer_.WriteU16(kRtcpCastAllPacketsLost);
big_endian_writer_.WriteU8(0); // Lost packet id mask.
@@ -211,21 +213,6 @@ void TestRtcpPacketBuilder::AddCast(uint32 sender_ssrc, uint32 media_ssrc) {
big_endian_writer_.WriteU8(0); // Lost packet id mask.
}
-void TestRtcpPacketBuilder::AddSenderLog(uint32 sender_ssrc) {
- AddRtcpHeader(204, 1);
- big_endian_writer_.WriteU32(sender_ssrc);
- big_endian_writer_.WriteU8('C');
- big_endian_writer_.WriteU8('A');
- big_endian_writer_.WriteU8('S');
- big_endian_writer_.WriteU8('T');
-}
-
-void TestRtcpPacketBuilder::AddSenderFrameLog(uint8 event_id,
- uint32 rtp_timestamp) {
- big_endian_writer_.WriteU32(
- (static_cast<uint32>(event_id) << 24) + (rtp_timestamp & 0xffffff));
-}
-
void TestRtcpPacketBuilder::AddReceiverLog(uint32 sender_ssrc) {
AddRtcpHeader(204, 2);
big_endian_writer_.WriteU32(sender_ssrc);
@@ -236,7 +223,8 @@ void TestRtcpPacketBuilder::AddReceiverLog(uint32 sender_ssrc) {
}
void TestRtcpPacketBuilder::AddReceiverFrameLog(uint32 rtp_timestamp,
- int num_events, uint32 event_timesamp_base) {
+ int num_events,
+ uint32 event_timesamp_base) {
big_endian_writer_.WriteU32(rtp_timestamp);
big_endian_writer_.WriteU8(static_cast<uint8>(num_events - 1));
big_endian_writer_.WriteU8(static_cast<uint8>(event_timesamp_base >> 16));
@@ -245,14 +233,22 @@ void TestRtcpPacketBuilder::AddReceiverFrameLog(uint32 rtp_timestamp,
}
void TestRtcpPacketBuilder::AddReceiverEventLog(uint16 event_data,
- uint8 event_id, uint16 event_timesamp_delta) {
+ CastLoggingEvent event,
+ uint16 event_timesamp_delta) {
big_endian_writer_.WriteU16(event_data);
+ uint8 event_id = ConvertEventTypeToWireFormat(event);
uint16 type_and_delta = static_cast<uint16>(event_id) << 12;
type_and_delta += event_timesamp_delta & 0x0fff;
big_endian_writer_.WriteU16(type_and_delta);
}
-const uint8* TestRtcpPacketBuilder::Packet() {
+scoped_ptr<media::cast::Packet> TestRtcpPacketBuilder::GetPacket() {
+ PatchLengthField();
+ return scoped_ptr<media::cast::Packet>(
+ new media::cast::Packet(buffer_, buffer_ + Length()));
+}
+
+const uint8* TestRtcpPacketBuilder::Data() {
PatchLengthField();
return buffer_;
}
diff --git a/chromium/media/cast/rtcp/test_rtcp_packet_builder.h b/chromium/media/cast/rtcp/test_rtcp_packet_builder.h
index 9b63a37fa4a..d4266670aba 100644
--- a/chromium/media/cast/rtcp/test_rtcp_packet_builder.h
+++ b/chromium/media/cast/rtcp/test_rtcp_packet_builder.h
@@ -7,8 +7,9 @@
#ifndef MEDIA_CAST_RTCP_TEST_RTCP_PACKET_BUILDER_H_
#define MEDIA_CAST_RTCP_TEST_RTCP_PACKET_BUILDER_H_
+#include "base/big_endian.h"
+#include "media/cast/cast_config.h"
#include "media/cast/rtcp/rtcp_defines.h"
-#include "net/base/big_endian.h"
namespace media {
namespace cast {
@@ -58,7 +59,9 @@ class TestRtcpPacketBuilder {
TestRtcpPacketBuilder();
void AddSr(uint32 sender_ssrc, int number_of_report_blocks);
- void AddSrWithNtp(uint32 sender_ssrc, uint32 ntp_high, uint32 ntp_low,
+ void AddSrWithNtp(uint32 sender_ssrc,
+ uint32 ntp_high,
+ uint32 ntp_low,
uint32 rtp_timestamp);
void AddRr(uint32 sender_ssrc, int number_of_report_blocks);
void AddRb(uint32 rtp_ssrc);
@@ -76,17 +79,18 @@ class TestRtcpPacketBuilder {
void AddPli(uint32 sender_ssrc, uint32 media_ssrc);
void AddRpsi(uint32 sender_ssrc, uint32 media_ssrc);
void AddRemb(uint32 sender_ssrc, uint32 media_ssrc);
- void AddCast(uint32 sender_ssrc, uint32 media_ssrc);
- void AddSenderLog(uint32 sender_ssrc);
- void AddSenderFrameLog(uint8 event_id, uint32 rtp_timestamp);
+ void AddCast(uint32 sender_ssrc, uint32 media_ssrc, uint16 target_delay_ms);
void AddReceiverLog(uint32 sender_ssrc);
- void AddReceiverFrameLog(uint32 rtp_timestamp, int num_events,
+ void AddReceiverFrameLog(uint32 rtp_timestamp,
+ int num_events,
uint32 event_timesamp_base);
- void AddReceiverEventLog(uint16 event_data, uint8 event_id,
+ void AddReceiverEventLog(uint16 event_data,
+ CastLoggingEvent event,
uint16 event_timesamp_delta);
- const uint8* Packet();
- int Length() { return kIpPacketSize - big_endian_writer_.remaining(); }
+ scoped_ptr<Packet> GetPacket();
+ const uint8* Data();
+ int Length() { return kMaxIpPacketSize - big_endian_writer_.remaining(); }
private:
void AddRtcpHeader(int payload, int format_or_count);
@@ -94,12 +98,14 @@ class TestRtcpPacketBuilder {
// Where the length field of the current packet is.
// Note: 0 is not a legal value, it is used for "uninitialized".
- uint8 buffer_[kIpPacketSize];
+ uint8 buffer_[kMaxIpPacketSize];
char* ptr_of_length_;
- net::BigEndianWriter big_endian_writer_;
+ base::BigEndianWriter big_endian_writer_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestRtcpPacketBuilder);
};
} // namespace cast
} // namespace media
-#endif // MEDIA_CAST_RTCP_TEST_RTCP_PACKET_BUILDER_H_
+#endif // MEDIA_CAST_RTCP_TEST_RTCP_PACKET_BUILDER_H_