summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/cast/cast.gyp4
-rw-r--r--media/cast/cast_config.cc3
-rw-r--r--media/cast/cast_config.h6
-rw-r--r--media/cast/cast_sender.h4
-rw-r--r--media/cast/cast_sender_impl.cc68
-rw-r--r--media/cast/cast_sender_impl.h2
-rw-r--r--media/cast/cast_testing.gypi2
-rw-r--r--media/cast/net/cast_transport_config.cc6
-rw-r--r--media/cast/net/cast_transport_config.h24
-rw-r--r--media/cast/net/cast_transport_sender.h46
-rw-r--r--media/cast/net/cast_transport_sender_impl.cc183
-rw-r--r--media/cast/net/cast_transport_sender_impl.h79
-rw-r--r--media/cast/net/cast_transport_sender_impl_unittest.cc22
-rw-r--r--media/cast/net/rtcp/mock_rtcp_receiver_feedback.cc4
-rw-r--r--media/cast/net/rtcp/mock_rtcp_receiver_feedback.h16
-rw-r--r--media/cast/net/rtcp/rtcp.cc245
-rw-r--r--media/cast/net/rtcp/rtcp.h106
-rw-r--r--media/cast/net/rtcp/rtcp_defines.cc16
-rw-r--r--media/cast/net/rtcp/rtcp_defines.h36
-rw-r--r--media/cast/net/rtcp/rtcp_receiver.cc93
-rw-r--r--media/cast/net/rtcp/rtcp_receiver.h31
-rw-r--r--media/cast/net/rtcp/rtcp_receiver_unittest.cc193
-rw-r--r--media/cast/net/rtcp/rtcp_sender.cc136
-rw-r--r--media/cast/net/rtcp/rtcp_sender.h33
-rw-r--r--media/cast/net/rtcp/rtcp_sender_unittest.cc76
-rw-r--r--media/cast/net/rtcp/rtcp_unittest.cc298
-rw-r--r--media/cast/net/rtp/cast_message_builder.cc20
-rw-r--r--media/cast/net/rtp/cast_message_builder_unittest.cc8
-rw-r--r--media/cast/receiver/cast_receiver_impl.cc5
-rw-r--r--media/cast/receiver/frame_receiver.cc31
-rw-r--r--media/cast/receiver/frame_receiver.h3
-rw-r--r--media/cast/sender/audio_sender.cc102
-rw-r--r--media/cast/sender/audio_sender.h34
-rw-r--r--media/cast/sender/audio_sender_unittest.cc4
-rw-r--r--media/cast/sender/frame_sender.cc72
-rw-r--r--media/cast/sender/frame_sender.h77
-rw-r--r--media/cast/sender/video_sender.cc128
-rw-r--r--media/cast/sender/video_sender.h35
-rw-r--r--media/cast/sender/video_sender_unittest.cc59
-rw-r--r--media/cast/test/cast_benchmarks.cc71
-rw-r--r--media/cast/test/end2end_unittest.cc33
-rw-r--r--media/cast/test/sender.cc15
-rw-r--r--media/cast/test/simulator.cc17
43 files changed, 1235 insertions, 1211 deletions
diff --git a/media/cast/cast.gyp b/media/cast/cast.gyp
index fb1ee64..eb00855 100644
--- a/media/cast/cast.gyp
+++ b/media/cast/cast.gyp
@@ -149,6 +149,8 @@
'sender/external_video_encoder.cc',
'sender/fake_software_video_encoder.h',
'sender/fake_software_video_encoder.cc',
+ 'sender/frame_sender.cc',
+ 'sender/frame_sender.h',
'sender/rtp_timestamp_helper.cc',
'sender/rtp_timestamp_helper.h',
'sender/software_video_encoder.h',
@@ -182,8 +184,6 @@
'net/pacing/paced_sender.cc',
'net/pacing/paced_sender.h',
'net/rtcp/receiver_rtcp_event_subscriber.cc',
- 'net/rtcp/rtcp_builder.cc',
- 'net/rtcp/rtcp_builder.h',
'net/rtcp/rtcp_defines.cc',
'net/rtcp/rtcp_defines.h',
'net/rtcp/rtcp.h',
diff --git a/media/cast/cast_config.cc b/media/cast/cast_config.cc
index f741216..b0e0828 100644
--- a/media/cast/cast_config.cc
+++ b/media/cast/cast_config.cc
@@ -25,7 +25,6 @@ VideoSenderConfig::VideoSenderConfig()
: ssrc(0),
incoming_feedback_ssrc(0),
rtcp_interval(kDefaultRtcpIntervalMs),
- rtcp_mode(kRtcpReducedSize),
target_playout_delay(
base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs)),
rtp_payload_type(0),
@@ -49,7 +48,6 @@ AudioSenderConfig::AudioSenderConfig()
: ssrc(0),
incoming_feedback_ssrc(0),
rtcp_interval(kDefaultRtcpIntervalMs),
- rtcp_mode(kRtcpReducedSize),
target_playout_delay(
base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs)),
rtp_payload_type(0),
@@ -65,7 +63,6 @@ FrameReceiverConfig::FrameReceiverConfig()
: feedback_ssrc(0),
incoming_ssrc(0),
rtcp_interval(kDefaultRtcpIntervalMs),
- rtcp_mode(kRtcpReducedSize),
rtp_max_delay_ms(kDefaultRtpMaxDelayMs),
rtp_payload_type(0),
frequency(0),
diff --git a/media/cast/cast_config.h b/media/cast/cast_config.h
index c2e797b6..c2d8db3 100644
--- a/media/cast/cast_config.h
+++ b/media/cast/cast_config.h
@@ -37,7 +37,6 @@ struct AudioSenderConfig {
int rtcp_interval;
std::string rtcp_c_name;
- RtcpMode rtcp_mode;
// The total amount of time between a frame's capture/recording on the sender
// and its playback on the receiver (i.e., shown to a user). This is fixed as
@@ -75,7 +74,6 @@ struct VideoSenderConfig {
int rtcp_interval;
std::string rtcp_c_name;
- RtcpMode rtcp_mode;
// The total amount of time between a frame's capture/recording on the sender
// and its playback on the receiver (i.e., shown to a user). This is fixed as
@@ -130,10 +128,6 @@ struct FrameReceiverConfig {
// the transport layer).
std::string rtcp_c_name;
- // Determines amount of detail in RTCP reports.
- // TODO(miu): Remove this since it's never anything but kRtcpReducedSize.
- RtcpMode rtcp_mode;
-
// The total amount of time between a frame's capture/recording on the sender
// and its playback on the receiver (i.e., shown to a user). This is fixed as
// a value large enough to give the system sufficient time to encode,
diff --git a/media/cast/cast_sender.h b/media/cast/cast_sender.h
index abe0a01..c9bad7a 100644
--- a/media/cast/cast_sender.h
+++ b/media/cast/cast_sender.h
@@ -73,10 +73,6 @@ class CastSender {
// All audio frames for the session should be inserted to this object.
virtual scoped_refptr<AudioFrameInput> audio_frame_input() = 0;
- // All RTCP packets for the session should be inserted to this object.
- // This function and the callback must be called on the main thread.
- virtual PacketReceiverCallback packet_receiver() = 0;
-
// Initialize the audio stack. Must be called in order to send audio frames.
// Status of the initialization will be returned on cast_initialization_cb.
virtual void InitializeAudio(
diff --git a/media/cast/cast_sender_impl.cc b/media/cast/cast_sender_impl.cc
index a120d3a..c684858 100644
--- a/media/cast/cast_sender_impl.cc
+++ b/media/cast/cast_sender_impl.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "media/base/video_frame.h"
+#include "media/cast/net/rtcp/rtcp_receiver.h"
namespace media {
namespace cast {
@@ -142,68 +143,6 @@ CastSenderImpl::~CastSenderImpl() {
VLOG(1) << "CastSenderImpl@" << this << "::~CastSenderImpl()";
}
-// ReceivedPacket handle the incoming packets to the cast sender
-// it's only expected to receive RTCP feedback packets from the remote cast
-// receiver. The class verifies that that it is a RTCP packet and based on the
-// SSRC of the incoming packet route the packet to the correct sender; audio or
-// video.
-//
-// Definition of SSRC as defined in RFC 3550.
-// Synchronization source (SSRC): The source of a stream of RTP
-// packets, identified by a 32-bit numeric SSRC identifier carried in
-// the RTP header so as not to be dependent upon the network address.
-// All packets from a synchronization source form part of the same
-// timing and sequence number space, so a receiver groups packets by
-// synchronization source for playback. Examples of synchronization
-// sources include the sender of a stream of packets derived from a
-// signal source such as a microphone or a camera, or an RTP mixer
-// (see below). A synchronization source may change its data format,
-// e.g., audio encoding, over time. The SSRC identifier is a
-// randomly chosen value meant to be globally unique within a
-// particular RTP session (see Section 8). A participant need not
-// use the same SSRC identifier for all the RTP sessions in a
-// multimedia session; the binding of the SSRC identifiers is
-// provided through RTCP (see Section 6.5.1). If a participant
-// generates multiple streams in one RTP session, for example from
-// separate video cameras, each MUST be identified as a different
-// SSRC.
-void CastSenderImpl::ReceivedPacket(scoped_ptr<Packet> packet) {
- DCHECK(cast_environment_);
- size_t length = packet->size();
- const uint8_t* data = &packet->front();
- if (!Rtcp::IsRtcpPacket(data, length)) {
- VLOG(1) << "CastSenderImpl@" << this << "::ReceivedPacket() -- "
- << "Received an invalid (non-RTCP?) packet in the cast sender.";
- return;
- }
- uint32 ssrc_of_sender = Rtcp::GetSsrcOfSender(data, length);
- if (ssrc_of_sender == ssrc_of_audio_sender_) {
- if (!audio_sender_) {
- NOTREACHED();
- return;
- }
- cast_environment_->PostTask(CastEnvironment::MAIN,
- FROM_HERE,
- base::Bind(&AudioSender::IncomingRtcpPacket,
- audio_sender_->AsWeakPtr(),
- base::Passed(&packet)));
- } else if (ssrc_of_sender == ssrc_of_video_sender_) {
- if (!video_sender_) {
- NOTREACHED();
- return;
- }
- cast_environment_->PostTask(CastEnvironment::MAIN,
- FROM_HERE,
- base::Bind(&VideoSender::IncomingRtcpPacket,
- video_sender_->AsWeakPtr(),
- base::Passed(&packet)));
- } else {
- VLOG(1) << "CastSenderImpl@" << this << "::ReceivedPacket() -- "
- << "Received a RTCP packet with a non matching sender SSRC "
- << ssrc_of_sender;
- }
-}
-
scoped_refptr<AudioFrameInput> CastSenderImpl::audio_frame_input() {
return audio_frame_input_;
}
@@ -212,10 +151,5 @@ scoped_refptr<VideoFrameInput> CastSenderImpl::video_frame_input() {
return video_frame_input_;
}
-PacketReceiverCallback CastSenderImpl::packet_receiver() {
- return base::Bind(&CastSenderImpl::ReceivedPacket,
- weak_factory_.GetWeakPtr());
-}
-
} // namespace cast
} // namespace media
diff --git a/media/cast/cast_sender_impl.h b/media/cast/cast_sender_impl.h
index bc320f7..c34fccf 100644
--- a/media/cast/cast_sender_impl.h
+++ b/media/cast/cast_sender_impl.h
@@ -42,8 +42,6 @@ class CastSenderImpl : public CastSender {
virtual scoped_refptr<AudioFrameInput> audio_frame_input() OVERRIDE;
virtual scoped_refptr<VideoFrameInput> video_frame_input() OVERRIDE;
- virtual PacketReceiverCallback packet_receiver() OVERRIDE;
-
private:
void ReceivedPacket(scoped_ptr<Packet> packet);
diff --git a/media/cast/cast_testing.gypi b/media/cast/cast_testing.gypi
index 97e831e..58dc642 100644
--- a/media/cast/cast_testing.gypi
+++ b/media/cast/cast_testing.gypi
@@ -85,8 +85,6 @@
'net/pacing/paced_sender_unittest.cc',
'net/rtcp/mock_rtcp_receiver_feedback.cc',
'net/rtcp/mock_rtcp_receiver_feedback.h',
- 'net/rtcp/mock_rtcp_sender_feedback.cc',
- 'net/rtcp/mock_rtcp_sender_feedback.h',
'net/rtcp/rtcp_receiver_unittest.cc',
'net/rtcp/rtcp_sender_unittest.cc',
'net/rtcp/rtcp_unittest.cc',
diff --git a/media/cast/net/cast_transport_config.cc b/media/cast/net/cast_transport_config.cc
index ae8ec60..a607f6f 100644
--- a/media/cast/net/cast_transport_config.cc
+++ b/media/cast/net/cast_transport_config.cc
@@ -8,7 +8,7 @@ namespace media {
namespace cast {
CastTransportRtpConfig::CastTransportRtpConfig()
- : ssrc(0), rtp_payload_type(0), stored_frames(0) {}
+ : ssrc(0), feedback_ssrc(0), rtp_payload_type(0), stored_frames(0) {}
CastTransportRtpConfig::~CastTransportRtpConfig() {}
@@ -52,9 +52,5 @@ RtcpDlrrReportBlock::RtcpDlrrReportBlock()
: last_rr(0), delay_since_last_rr(0) {}
RtcpDlrrReportBlock::~RtcpDlrrReportBlock() {}
-SendRtcpFromRtpSenderData::SendRtcpFromRtpSenderData()
- : packet_type_flags(0), sending_ssrc(0) {}
-SendRtcpFromRtpSenderData::~SendRtcpFromRtpSenderData() {}
-
} // namespace cast
} // namespace media
diff --git a/media/cast/net/cast_transport_config.h b/media/cast/net/cast_transport_config.h
index db87b8c..088aa62 100644
--- a/media/cast/net/cast_transport_config.h
+++ b/media/cast/net/cast_transport_config.h
@@ -18,11 +18,6 @@
namespace media {
namespace cast {
-enum RtcpMode {
- kRtcpCompound, // Compound RTCP mode is described by RFC 4585.
- kRtcpReducedSize, // Reduced-size RTCP mode is described by RFC 5506.
-};
-
enum Codec {
CODEC_UNKNOWN,
CODEC_AUDIO_OPUS,
@@ -40,6 +35,12 @@ struct CastTransportRtpConfig {
// Identifier refering to this sender.
uint32 ssrc;
+ // Identifier for incoming RTCP traffic.
+ uint32 feedback_ssrc;
+
+ // Identifier for this stream.
+ std::string c_name;
+
// RTP payload type enum: Specifies the type/encoding of frame data.
int rtp_payload_type;
@@ -172,19 +173,6 @@ struct RtcpDlrrReportBlock {
uint32 delay_since_last_rr;
};
-// This is only needed because IPC messages don't support more than
-// 5 arguments.
-struct SendRtcpFromRtpSenderData {
- SendRtcpFromRtpSenderData();
- ~SendRtcpFromRtpSenderData();
- uint32 packet_type_flags;
- uint32 sending_ssrc;
- std::string c_name;
- uint32 ntp_seconds;
- uint32 ntp_fraction;
- uint32 rtp_timestamp;
-};
-
inline bool operator==(RtcpSenderInfo lhs, RtcpSenderInfo rhs) {
return lhs.ntp_seconds == rhs.ntp_seconds &&
lhs.ntp_fraction == rhs.ntp_fraction &&
diff --git a/media/cast/net/cast_transport_sender.h b/media/cast/net/cast_transport_sender.h
index 3f8a119..31166f5 100644
--- a/media/cast/net/cast_transport_sender.h
+++ b/media/cast/net/cast_transport_sender.h
@@ -10,15 +10,10 @@
// in the following order:
// 1. Create CastTransportSender.
// 2. Create CastSender (accepts CastTransportSender as an input).
-// 3. Call CastTransportSender::SetPacketReceiver to ensure that the packets
-// received by the CastTransportSender will be sent to the CastSender.
-// Steps 3 can be done interchangeably.
// Destruction: The CastTransportSender is assumed to be valid as long as the
// CastSender is alive. Therefore the CastSender should be destructed before the
// CastTransportSender.
-// This also works when the CastSender acts as a receiver for the RTCP packets
-// due to the weak pointers in the ReceivedPacket method in cast_sender_impl.cc.
#ifndef MEDIA_CAST_NET_CAST_TRANSPORT_SENDER_H_
#define MEDIA_CAST_NET_CAST_TRANSPORT_SENDER_H_
@@ -31,6 +26,8 @@
#include "media/cast/logging/logging_defines.h"
#include "media/cast/net/cast_transport_config.h"
#include "media/cast/net/cast_transport_defines.h"
+#include "media/cast/net/rtcp/receiver_rtcp_event_subscriber.h"
+#include "media/cast/net/rtcp/rtcp_defines.h"
#include "net/base/ip_endpoint.h"
namespace net {
@@ -45,7 +42,8 @@ namespace cast {
typedef base::Callback<void(CastTransportStatus status)>
CastTransportStatusCallback;
-typedef base::Callback<void(const std::vector<PacketEvent>&)>
+typedef base::Callback<void(const std::vector<PacketEvent>&,
+ const std::vector<FrameEvent>&)>
BulkRawEventsCallback;
// The application should only trigger this class from the transport thread.
@@ -64,14 +62,13 @@ class CastTransportSender : public base::NonThreadSafe {
// Audio/Video initialization.
// Encoded frames cannot be transmitted until the relevant initialize method
- // is called. Usually called by CastSender.
- virtual void InitializeAudio(const CastTransportRtpConfig& config) = 0;
- virtual void InitializeVideo(const CastTransportRtpConfig& config) = 0;
-
- // Sets the Cast packet receiver. Should be called after creation on the
- // Cast sender. Packets won't be received until this function is called.
- virtual void SetPacketReceiver(
- const PacketReceiverCallback& packet_receiver) = 0;
+ // is called.
+ virtual void InitializeAudio(const CastTransportRtpConfig& config,
+ const RtcpCastMessageCallback& cast_message_cb,
+ const RtcpRttCallback& rtt_cb) = 0;
+ virtual void InitializeVideo(const CastTransportRtpConfig& config,
+ const RtcpCastMessageCallback& cast_message_cb,
+ const RtcpRttCallback& rtt_cb) = 0;
// The following two functions handle the encoded media frames (audio and
// video) to be processed.
@@ -79,16 +76,14 @@ class CastTransportSender : public base::NonThreadSafe {
virtual void InsertCodedAudioFrame(const EncodedFrame& audio_frame) = 0;
virtual void InsertCodedVideoFrame(const EncodedFrame& video_frame) = 0;
- // Builds an RTCP packet and sends it to the network.
- // |ntp_seconds|, |ntp_fraction| and |rtp_timestamp| are used in the
- // RTCP Sender Report.
- virtual void SendRtcpFromRtpSender(uint32 packet_type_flags,
- uint32 ntp_seconds,
- uint32 ntp_fraction,
- uint32 rtp_timestamp,
- const RtcpDlrrReportBlock& dlrr,
- uint32 sending_ssrc,
- const std::string& c_name) = 0;
+ // Sends a RTCP sender report to the receiver.
+ // |ssrc| is the SSRC for this report.
+ // |current_time| is the current time reported by a tick clock.
+ // |current_time_as_rtp_timestamp| is the corresponding RTP timestamp.
+ virtual void SendSenderReport(
+ uint32 ssrc,
+ base::TimeTicks current_time,
+ uint32 current_time_as_rtp_timestamp) = 0;
// Retransmission request.
// |missing_packets| includes the list of frames and packets in each
@@ -103,6 +98,9 @@ class CastTransportSender : public base::NonThreadSafe {
const MissingFramesAndPacketsMap& missing_packets,
bool cancel_rtx_if_not_in_list,
base::TimeDelta dedupe_window) = 0;
+
+ // Returns a callback for receiving packets for testing purposes.
+ virtual PacketReceiverCallback PacketReceiverForTesting();
};
} // namespace cast
diff --git a/media/cast/net/cast_transport_sender_impl.cc b/media/cast/net/cast_transport_sender_impl.cc
index 973f341..a13be94 100644
--- a/media/cast/net/cast_transport_sender_impl.cc
+++ b/media/cast/net/cast_transport_sender_impl.cc
@@ -32,6 +32,10 @@ scoped_ptr<CastTransportSender> CastTransportSender::Create(
NULL));
}
+PacketReceiverCallback CastTransportSender::PacketReceiverForTesting() {
+ return PacketReceiverCallback();
+}
+
CastTransportSenderImpl::CastTransportSenderImpl(
net::NetLog* net_log,
base::TickClock* clock,
@@ -50,22 +54,23 @@ CastTransportSenderImpl::CastTransportSenderImpl(
net::IPEndPoint(),
remote_end_point,
status_callback)),
- logging_(),
pacer_(clock,
&logging_,
external_transport ? external_transport : transport_.get(),
transport_task_runner),
- rtcp_builder_(&pacer_),
- raw_events_callback_(raw_events_callback) {
+ raw_events_callback_(raw_events_callback),
+ raw_events_callback_interval_(raw_events_callback_interval),
+ weak_factory_(this) {
DCHECK(clock_);
if (!raw_events_callback_.is_null()) {
DCHECK(raw_events_callback_interval > base::TimeDelta());
event_subscriber_.reset(new SimpleEventSubscriber);
logging_.AddRawEventSubscriber(event_subscriber_.get());
- raw_events_timer_.Start(FROM_HERE,
- raw_events_callback_interval,
- this,
- &CastTransportSenderImpl::SendRawEvents);
+ transport_task_runner->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&CastTransportSenderImpl::SendRawEvents,
+ weak_factory_.GetWeakPtr()),
+ raw_events_callback_interval);
}
if (transport_) {
// The default DSCP value for cast is AF41. Which gives it a higher
@@ -80,13 +85,16 @@ CastTransportSenderImpl::~CastTransportSenderImpl() {
}
void CastTransportSenderImpl::InitializeAudio(
- const CastTransportRtpConfig& config) {
+ const CastTransportRtpConfig& config,
+ const RtcpCastMessageCallback& cast_message_cb,
+ const RtcpRttCallback& rtt_cb) {
LOG_IF(WARNING, config.aes_key.empty() || config.aes_iv_mask.empty())
<< "Unsafe to send audio with encryption DISABLED.";
if (!audio_encryptor_.Initialize(config.aes_key, config.aes_iv_mask)) {
status_callback_.Run(TRANSPORT_AUDIO_UNINITIALIZED);
return;
}
+
audio_sender_.reset(new RtpSender(clock_, transport_task_runner_, &pacer_));
if (audio_sender_->Initialize(config)) {
// Audio packets have a higher priority.
@@ -96,30 +104,61 @@ void CastTransportSenderImpl::InitializeAudio(
} else {
audio_sender_.reset();
status_callback_.Run(TRANSPORT_AUDIO_UNINITIALIZED);
+ return;
}
+
+ audio_rtcp_session_.reset(
+ new Rtcp(cast_message_cb,
+ rtt_cb,
+ base::Bind(&CastTransportSenderImpl::OnReceivedLogMessage,
+ weak_factory_.GetWeakPtr(), AUDIO_EVENT),
+ clock_,
+ &pacer_,
+ config.ssrc,
+ config.feedback_ssrc,
+ config.c_name));
+ pacer_.RegisterAudioSsrc(config.ssrc);
+
+ // Only start receiving once.
+ if (!video_sender_)
+ StartReceiving();
+ status_callback_.Run(TRANSPORT_AUDIO_INITIALIZED);
}
void CastTransportSenderImpl::InitializeVideo(
- const CastTransportRtpConfig& config) {
+ const CastTransportRtpConfig& config,
+ const RtcpCastMessageCallback& cast_message_cb,
+ const RtcpRttCallback& rtt_cb) {
LOG_IF(WARNING, config.aes_key.empty() || config.aes_iv_mask.empty())
<< "Unsafe to send video with encryption DISABLED.";
if (!video_encryptor_.Initialize(config.aes_key, config.aes_iv_mask)) {
status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED);
return;
}
+
video_sender_.reset(new RtpSender(clock_, transport_task_runner_, &pacer_));
- if (video_sender_->Initialize(config)) {
- pacer_.RegisterVideoSsrc(config.ssrc);
- status_callback_.Run(TRANSPORT_VIDEO_INITIALIZED);
- } else {
+ if (!video_sender_->Initialize(config)) {
video_sender_.reset();
status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED);
+ return;
}
-}
-void CastTransportSenderImpl::SetPacketReceiver(
- const PacketReceiverCallback& packet_receiver) {
- transport_->StartReceiving(packet_receiver);
+ video_rtcp_session_.reset(
+ new Rtcp(cast_message_cb,
+ rtt_cb,
+ base::Bind(&CastTransportSenderImpl::OnReceivedLogMessage,
+ weak_factory_.GetWeakPtr(), VIDEO_EVENT),
+ clock_,
+ &pacer_,
+ config.ssrc,
+ config.feedback_ssrc,
+ config.c_name));
+ pacer_.RegisterVideoSsrc(config.ssrc);
+
+ // Only start receiving once.
+ if (!audio_sender_)
+ StartReceiving();
+ status_callback_.Run(TRANSPORT_VIDEO_INITIALIZED);
}
namespace {
@@ -153,30 +192,21 @@ void CastTransportSenderImpl::InsertCodedVideoFrame(
EncryptAndSendFrame(video_frame, &video_encryptor_, video_sender_.get());
}
-void CastTransportSenderImpl::SendRtcpFromRtpSender(
- uint32 packet_type_flags,
- uint32 ntp_seconds,
- uint32 ntp_fraction,
- uint32 rtp_timestamp,
- const RtcpDlrrReportBlock& dlrr,
- uint32 sending_ssrc,
- const std::string& c_name) {
- RtcpSenderInfo sender_info;
- sender_info.ntp_seconds = ntp_seconds;
- sender_info.ntp_fraction = ntp_fraction;
- sender_info.rtp_timestamp = rtp_timestamp;
- if (audio_sender_ && audio_sender_->ssrc() == sending_ssrc) {
- sender_info.send_packet_count = audio_sender_->send_packet_count();
- sender_info.send_octet_count = audio_sender_->send_octet_count();
- } else if (video_sender_ && video_sender_->ssrc() == sending_ssrc) {
- sender_info.send_packet_count = video_sender_->send_packet_count();
- sender_info.send_octet_count = video_sender_->send_octet_count();
+void CastTransportSenderImpl::SendSenderReport(
+ uint32 ssrc,
+ base::TimeTicks current_time,
+ uint32 current_time_as_rtp_timestamp) {
+ if (audio_sender_ && ssrc == audio_sender_->ssrc()) {
+ audio_rtcp_session_->SendRtcpFromRtpSender(
+ current_time, current_time_as_rtp_timestamp,
+ audio_sender_->send_packet_count(), audio_sender_->send_octet_count());
+ } else if (video_sender_ && ssrc == video_sender_->ssrc()) {
+ video_rtcp_session_->SendRtcpFromRtpSender(
+ current_time, current_time_as_rtp_timestamp,
+ video_sender_->send_packet_count(), video_sender_->send_octet_count());
} else {
- LOG(ERROR) << "Sending RTCP with an invalid SSRC.";
- return;
+ NOTREACHED() << "Invalid request for sending RTCP packet.";
}
- rtcp_builder_.SendRtcpFromRtpSender(
- packet_type_flags, sender_info, dlrr, sending_ssrc, c_name);
}
void CastTransportSenderImpl::ResendPackets(
@@ -197,12 +227,85 @@ void CastTransportSenderImpl::ResendPackets(
}
}
+PacketReceiverCallback CastTransportSenderImpl::PacketReceiverForTesting() {
+ return base::Bind(&CastTransportSenderImpl::OnReceivedPacket,
+ weak_factory_.GetWeakPtr());
+}
+
void CastTransportSenderImpl::SendRawEvents() {
DCHECK(event_subscriber_.get());
DCHECK(!raw_events_callback_.is_null());
std::vector<PacketEvent> packet_events;
+ std::vector<FrameEvent> frame_events;
event_subscriber_->GetPacketEventsAndReset(&packet_events);
- raw_events_callback_.Run(packet_events);
+ event_subscriber_->GetFrameEventsAndReset(&frame_events);
+ raw_events_callback_.Run(packet_events, frame_events);
+
+ transport_task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&CastTransportSenderImpl::SendRawEvents,
+ weak_factory_.GetWeakPtr()),
+ raw_events_callback_interval_);
+}
+
+void CastTransportSenderImpl::StartReceiving() {
+ if (!transport_)
+ return;
+ transport_->StartReceiving(
+ base::Bind(&CastTransportSenderImpl::OnReceivedPacket,
+ weak_factory_.GetWeakPtr()));
+}
+
+void CastTransportSenderImpl::OnReceivedPacket(scoped_ptr<Packet> packet) {
+ if (audio_rtcp_session_ &&
+ audio_rtcp_session_->IncomingRtcpPacket(&packet->front(),
+ packet->size())) {
+ return;
+ }
+ if (video_rtcp_session_ &&
+ video_rtcp_session_->IncomingRtcpPacket(&packet->front(),
+ packet->size())) {
+ return;
+ }
+ VLOG(1) << "Stale packet received.";
+}
+
+void CastTransportSenderImpl::OnReceivedLogMessage(
+ EventMediaType media_type,
+ const RtcpReceiverLogMessage& log) {
+ // Add received log messages into our log system.
+ RtcpReceiverLogMessage::const_iterator it = log.begin();
+ for (; it != 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:
+ logging_.InsertPacketEvent(
+ event_it->event_timestamp, event_it->type,
+ media_type, rtp_timestamp,
+ kFrameIdUnknown, event_it->packet_id, 0, 0);
+ break;
+ case FRAME_ACK_SENT:
+ case FRAME_DECODED:
+ logging_.InsertFrameEvent(
+ event_it->event_timestamp, event_it->type, media_type,
+ rtp_timestamp, kFrameIdUnknown);
+ break;
+ case FRAME_PLAYOUT:
+ logging_.InsertFrameEventWithDelay(
+ event_it->event_timestamp, event_it->type, 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
diff --git a/media/cast/net/cast_transport_sender_impl.h b/media/cast/net/cast_transport_sender_impl.h
index 5d34fde..9cc3b46 100644
--- a/media/cast/net/cast_transport_sender_impl.h
+++ b/media/cast/net/cast_transport_sender_impl.h
@@ -2,12 +2,32 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// This class maintains a send transport for audio and video in a Cast
+// Streaming session.
+// Audio, video frames and RTCP messages are submitted to this object
+// and then packetized and paced to the underlying UDP socket.
+//
+// The hierarchy of send transport in a Cast Streaming session:
+//
+// CastTransportSender RTP RTCP
+// ------------------------------------------------------------------
+// TransportEncryptionHandler (A/V)
+// RtpSender (A/V) Rtcp (A/V)
+// PacedSender (Shared)
+// UdpTransport (Shared)
+//
+// There are objects of TransportEncryptionHandler, RtpSender and Rtcp
+// for each audio and video stream.
+// PacedSender and UdpTransport are shared between all RTP and RTCP
+// streams.
+
#ifndef MEDIA_CAST_NET_CAST_TRANSPORT_IMPL_H_
#define MEDIA_CAST_NET_CAST_TRANSPORT_IMPL_H_
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -17,7 +37,7 @@
#include "media/cast/net/cast_transport_config.h"
#include "media/cast/net/cast_transport_sender.h"
#include "media/cast/net/pacing/paced_sender.h"
-#include "media/cast/net/rtcp/rtcp_builder.h"
+#include "media/cast/net/rtcp/rtcp.h"
#include "media/cast/net/rtp/rtp_sender.h"
namespace media {
@@ -27,9 +47,7 @@ class UdpTransport;
class CastTransportSenderImpl : public CastTransportSender {
public:
- // external_transport is only used for testing.
- // Note that SetPacketReceiver does not work if an external
- // transport is provided.
+ // |external_transport| is only used for testing.
// |raw_events_callback|: Raw events will be returned on this callback
// which will be invoked every |raw_events_callback_interval|.
// This can be a null callback, i.e. if user is not interested in raw events.
@@ -47,23 +65,19 @@ class CastTransportSenderImpl : public CastTransportSender {
virtual ~CastTransportSenderImpl();
- virtual void InitializeAudio(const CastTransportRtpConfig& config) OVERRIDE;
- virtual void InitializeVideo(const CastTransportRtpConfig& config) OVERRIDE;
-
- // CastTransportSender implementation.
- virtual void SetPacketReceiver(const PacketReceiverCallback& packet_receiver)
- OVERRIDE;
-
+ virtual void InitializeAudio(const CastTransportRtpConfig& config,
+ const RtcpCastMessageCallback& cast_message_cb,
+ const RtcpRttCallback& rtt_cb) OVERRIDE;
+ virtual void InitializeVideo(const CastTransportRtpConfig& config,
+ const RtcpCastMessageCallback& cast_message_cb,
+ const RtcpRttCallback& rtt_cb) OVERRIDE;
virtual void InsertCodedAudioFrame(const EncodedFrame& audio_frame) OVERRIDE;
virtual void InsertCodedVideoFrame(const EncodedFrame& video_frame) OVERRIDE;
- virtual void SendRtcpFromRtpSender(uint32 packet_type_flags,
- uint32 ntp_seconds,
- uint32 ntp_fraction,
- uint32 rtp_timestamp,
- const RtcpDlrrReportBlock& dlrr,
- uint32 sending_ssrc,
- const std::string& c_name) OVERRIDE;
+ virtual void SendSenderReport(
+ uint32 ssrc,
+ base::TimeTicks current_time,
+ uint32 current_time_as_rtp_timestamp) OVERRIDE;
virtual void ResendPackets(bool is_audio,
const MissingFramesAndPacketsMap& missing_packets,
@@ -71,22 +85,43 @@ class CastTransportSenderImpl : public CastTransportSender {
base::TimeDelta dedupe_window)
OVERRIDE;
+ virtual PacketReceiverCallback PacketReceiverForTesting() OVERRIDE;
+
private:
// If |raw_events_callback_| is non-null, calls it with events collected
// by |event_subscriber_| since last call.
void SendRawEvents();
+ // Start receiving packets.
+ void StartReceiving();
+
+ // Called when a packet is received.
+ void OnReceivedPacket(scoped_ptr<Packet> packet);
+
+ // Called when a log message is received.
+ void OnReceivedLogMessage(EventMediaType media_type,
+ const RtcpReceiverLogMessage& log);
+
base::TickClock* clock_; // Not owned by this class.
CastTransportStatusCallback status_callback_;
scoped_refptr<base::SingleThreadTaskRunner> transport_task_runner_;
- scoped_ptr<UdpTransport> transport_;
LoggingImpl logging_;
+
+ // Interface to a UDP socket.
+ scoped_ptr<UdpTransport> transport_;
+
+ // Packet sender that performs pacing.
PacedSender pacer_;
- RtcpBuilder rtcp_builder_;
+
+ // Packetizer for audio and video frames.
scoped_ptr<RtpSender> audio_sender_;
scoped_ptr<RtpSender> video_sender_;
+ // Maintains RTCP session for audio and video.
+ scoped_ptr<Rtcp> audio_rtcp_session_;
+ scoped_ptr<Rtcp> video_rtcp_session_;
+
// Encrypts data in EncodedFrames before they are sent. Note that it's
// important for the encryption to happen here, in code that would execute in
// the main browser process, for security reasons. This helps to mitigate
@@ -96,9 +131,11 @@ class CastTransportSenderImpl : public CastTransportSender {
// This is non-null iff |raw_events_callback_| is non-null.
scoped_ptr<SimpleEventSubscriber> event_subscriber_;
- base::RepeatingTimer<CastTransportSenderImpl> raw_events_timer_;
BulkRawEventsCallback raw_events_callback_;
+ base::TimeDelta raw_events_callback_interval_;
+
+ base::WeakPtrFactory<CastTransportSenderImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CastTransportSenderImpl);
};
diff --git a/media/cast/net/cast_transport_sender_impl_unittest.cc b/media/cast/net/cast_transport_sender_impl_unittest.cc
index b1d29b9..b8a49cc 100644
--- a/media/cast/net/cast_transport_sender_impl_unittest.cc
+++ b/media/cast/net/cast_transport_sender_impl_unittest.cc
@@ -8,8 +8,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
#include "base/test/simple_test_tick_clock.h"
#include "media/cast/cast_config.h"
#include "media/cast/net/cast_transport_config.h"
@@ -70,11 +68,9 @@ class CastTransportSenderImplTest : public ::testing::Test {
task_runner_->RunTasks();
}
- void LogRawEvents(const std::vector<PacketEvent>& packet_events) {
+ void LogRawEvents(const std::vector<PacketEvent>& packet_events,
+ const std::vector<FrameEvent>& frame_events) {
num_times_callback_called_++;
- if (num_times_callback_called_ == 3) {
- run_loop_.Quit();
- }
}
static void UpdateCastTransportStatus(CastTransportStatus status) {
@@ -84,27 +80,19 @@ class CastTransportSenderImplTest : public ::testing::Test {
scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
scoped_ptr<CastTransportSenderImpl> transport_sender_;
FakePacketSender transport_;
- base::MessageLoopForIO message_loop_;
- base::RunLoop run_loop_;
int num_times_callback_called_;
};
TEST_F(CastTransportSenderImplTest, InitWithoutLogging) {
InitWithoutLogging();
- message_loop_.PostDelayedTask(FROM_HERE,
- run_loop_.QuitClosure(),
- base::TimeDelta::FromMilliseconds(50));
- run_loop_.Run();
+ task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50));
EXPECT_EQ(0, num_times_callback_called_);
}
TEST_F(CastTransportSenderImplTest, InitWithLogging) {
InitWithLogging();
- message_loop_.PostDelayedTask(FROM_HERE,
- run_loop_.QuitClosure(),
- base::TimeDelta::FromMilliseconds(50));
- run_loop_.Run();
- EXPECT_GT(num_times_callback_called_, 1);
+ task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50));
+ EXPECT_EQ(5, num_times_callback_called_);
}
} // namespace cast
diff --git a/media/cast/net/rtcp/mock_rtcp_receiver_feedback.cc b/media/cast/net/rtcp/mock_rtcp_receiver_feedback.cc
index 0ea6606..d9818ff 100644
--- a/media/cast/net/rtcp/mock_rtcp_receiver_feedback.cc
+++ b/media/cast/net/rtcp/mock_rtcp_receiver_feedback.cc
@@ -11,9 +11,5 @@ MockRtcpReceiverFeedback::MockRtcpReceiverFeedback() {}
MockRtcpReceiverFeedback::~MockRtcpReceiverFeedback() {}
-MockRtcpRttFeedback::MockRtcpRttFeedback() {}
-
-MockRtcpRttFeedback::~MockRtcpRttFeedback() {}
-
} // namespace cast
} // namespace media
diff --git a/media/cast/net/rtcp/mock_rtcp_receiver_feedback.h b/media/cast/net/rtcp/mock_rtcp_receiver_feedback.h
index 38bf0ee..ae6b96e 100644
--- a/media/cast/net/rtcp/mock_rtcp_receiver_feedback.h
+++ b/media/cast/net/rtcp/mock_rtcp_receiver_feedback.h
@@ -15,7 +15,8 @@
namespace media {
namespace cast {
-class MockRtcpReceiverFeedback : public RtcpReceiverFeedback {
+// TODO(hclam): Should be renamed to MockRtcpMessageHandler.
+class MockRtcpReceiverFeedback : public RtcpMessageHandler {
public:
MockRtcpReceiverFeedback();
virtual ~MockRtcpReceiverFeedback();
@@ -30,17 +31,12 @@ class MockRtcpReceiverFeedback : public RtcpReceiverFeedback {
MOCK_METHOD1(OnReceivedReceiverLog,
void(const RtcpReceiverLogMessage& receiver_log));
-};
-class MockRtcpRttFeedback : public RtcpRttFeedback {
- public:
- MockRtcpRttFeedback();
- virtual ~MockRtcpRttFeedback();
+ MOCK_METHOD2(OnReceivedDelaySinceLastReport,
+ void(uint32 last_report, uint32 delay_since_last_report));
- MOCK_METHOD3(OnReceivedDelaySinceLastReport,
- void(uint32 media_ssrc,
- uint32 last_report,
- uint32 delay_since_last_report));
+ MOCK_METHOD1(OnReceivedCastFeedback,
+ void(const RtcpCastMessage& cast_message));
};
} // namespace cast
diff --git a/media/cast/net/rtcp/rtcp.cc b/media/cast/net/rtcp/rtcp.cc
index c0e6c19..92abb3e 100644
--- a/media/cast/net/rtcp/rtcp.cc
+++ b/media/cast/net/rtcp/rtcp.cc
@@ -4,7 +4,6 @@
#include "media/cast/net/rtcp/rtcp.h"
-#include "base/big_endian.h"
#include "media/cast/cast_config.h"
#include "media/cast/cast_defines.h"
#include "media/cast/cast_environment.h"
@@ -20,28 +19,11 @@ namespace media {
namespace cast {
static const int32 kMaxRttMs = 10000; // 10 seconds.
-static const int32 kMaxDelayMs = 2000; // 2 seconds.
-class LocalRtcpRttFeedback : public RtcpRttFeedback {
+class Rtcp::RtcpMessageHandlerImpl : public RtcpMessageHandler {
public:
- explicit LocalRtcpRttFeedback(Rtcp* rtcp) : rtcp_(rtcp) {}
-
- virtual void OnReceivedDelaySinceLastReport(
- uint32 receivers_ssrc, uint32 last_report,
- uint32 delay_since_last_report) OVERRIDE {
- rtcp_->OnReceivedDelaySinceLastReport(receivers_ssrc, last_report,
- delay_since_last_report);
- }
-
- private:
- Rtcp* rtcp_;
-};
-
-class LocalRtcpReceiverFeedback : public RtcpReceiverFeedback {
- public:
- LocalRtcpReceiverFeedback(Rtcp* rtcp,
- scoped_refptr<CastEnvironment> cast_environment)
- : rtcp_(rtcp), cast_environment_(cast_environment) {}
+ explicit RtcpMessageHandlerImpl(Rtcp* rtcp)
+ : rtcp_(rtcp) {}
virtual void OnReceivedSenderReport(
const RtcpSenderInfo& remote_sender_info) OVERRIDE {
@@ -60,103 +42,91 @@ class LocalRtcpReceiverFeedback : public RtcpReceiverFeedback {
remote_time_report.ntp_fraction);
}
- virtual void OnReceivedSendReportRequest() OVERRIDE {
- rtcp_->OnReceivedSendReportRequest();
- }
-
virtual void OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log)
OVERRIDE {
rtcp_->OnReceivedReceiverLog(receiver_log);
}
+ virtual void OnReceivedDelaySinceLastReport(
+ uint32 last_report,
+ uint32 delay_since_last_report) OVERRIDE {
+ rtcp_->OnReceivedDelaySinceLastReport(last_report, delay_since_last_report);
+ }
+
+ virtual void OnReceivedCastFeedback(
+ const RtcpCastMessage& cast_message) OVERRIDE {
+ rtcp_->OnReceivedCastFeedback(cast_message);
+ }
+
private:
Rtcp* rtcp_;
- scoped_refptr<CastEnvironment> cast_environment_;
};
-Rtcp::Rtcp(scoped_refptr<CastEnvironment> cast_environment,
- RtcpSenderFeedback* sender_feedback,
- CastTransportSender* const transport_sender,
- 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),
+Rtcp::Rtcp(const RtcpCastMessageCallback& cast_callback,
+ const RtcpRttCallback& rtt_callback,
+ const RtcpLogMessageCallback& log_callback,
+ base::TickClock* clock,
+ PacedPacketSender* packet_sender,
+ uint32 local_ssrc,
+ uint32 remote_ssrc, const std::string& c_name)
+ : cast_callback_(cast_callback),
+ rtt_callback_(rtt_callback),
+ log_callback_(log_callback),
+ clock_(clock),
+ rtcp_sender_(new RtcpSender(packet_sender, local_ssrc, c_name)),
local_ssrc_(local_ssrc),
remote_ssrc_(remote_ssrc),
c_name_(c_name),
- event_media_type_(event_media_type),
- rtp_receiver_statistics_(rtp_receiver_statistics),
- 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)),
+ handler_(new RtcpMessageHandlerImpl(this)),
+ rtcp_receiver_(new RtcpReceiver(handler_.get(), local_ssrc)),
last_report_truncated_ntp_(0),
local_clock_ahead_by_(ClockDriftSmoother::GetDefaultTimeConstant()),
lip_sync_rtp_timestamp_(0),
lip_sync_ntp_timestamp_(0),
min_rtt_(TimeDelta::FromMilliseconds(kMaxRttMs)),
number_of_rtt_in_avg_(0) {
- rtcp_receiver_.reset(new RtcpReceiver(cast_environment, sender_feedback,
- receiver_feedback_.get(),
- rtt_feedback_.get(), local_ssrc));
rtcp_receiver_->SetRemoteSSRC(remote_ssrc);
+
+ // This value is the same in FrameReceiver.
+ rtcp_receiver_->SetCastReceiverEventHistorySize(
+ kReceiverRtcpEventHistorySize);
}
Rtcp::~Rtcp() {}
-// static
-bool Rtcp::IsRtcpPacket(const uint8* packet, size_t length) {
- DCHECK_GE(length, kMinLengthOfRtcp) << "Invalid RTCP packet";
- if (length < kMinLengthOfRtcp) return false;
-
- uint8 packet_type = packet[1];
- if (packet_type >= kPacketTypeLow &&
- packet_type <= kPacketTypeHigh) {
- return true;
+bool Rtcp::IncomingRtcpPacket(const uint8* data, size_t length) {
+ // Check if this is a valid RTCP packet.
+ if (!RtcpReceiver::IsRtcpPacket(data, length)) {
+ VLOG(1) << "Rtcp@" << this << "::IncomingRtcpPacket() -- "
+ << "Received an invalid (non-RTCP?) packet.";
+ return false;
}
- return false;
-}
-
-// static
-uint32 Rtcp::GetSsrcOfSender(const uint8* rtcp_buffer, size_t length) {
- DCHECK_GE(length, kMinLengthOfRtcp) << "Invalid RTCP packet";
- uint32 ssrc_of_sender;
- 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;
-}
-base::TimeTicks Rtcp::TimeToSendNextRtcpReport() {
- if (next_time_to_send_rtcp_.is_null()) {
- UpdateNextTimeToSendRtcp();
+ // Check if this packet is to us.
+ uint32 ssrc_of_sender = RtcpReceiver::GetSsrcOfSender(data, length);
+ if (ssrc_of_sender != remote_ssrc_) {
+ return false;
}
- return next_time_to_send_rtcp_;
-}
-void Rtcp::IncomingRtcpPacket(const uint8* rtcp_buffer, size_t length) {
- RtcpParser rtcp_parser(rtcp_buffer, length);
+ // Parse this packet.
+ RtcpParser rtcp_parser(data, length);
if (!rtcp_parser.IsValid()) {
// Silently ignore packet.
- DLOG(ERROR) << "Received invalid RTCP packet";
- return;
+ VLOG(1) << "Received invalid RTCP packet";
+ return false;
}
rtcp_receiver_->IncomingRtcpPacket(&rtcp_parser);
+ return true;
}
void Rtcp::SendRtcpFromRtpReceiver(
const RtcpCastMessage* cast_message,
- const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events) {
- DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
+ base::TimeDelta target_delay,
+ const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events,
+ RtpReceiverStatistics* rtp_receiver_statistics) {
uint32 packet_type_flags = 0;
- base::TimeTicks now = cast_environment_->Clock()->NowTicks();
+ base::TimeTicks now = clock_->NowTicks();
RtcpReportBlock report_block;
RtcpReceiverReferenceTimeReport rrtr;
@@ -172,13 +142,14 @@ void Rtcp::SendRtcpFromRtpReceiver(
if (rtcp_events) {
packet_type_flags |= kRtcpReceiverLog;
}
- if (rtcp_mode_ == kRtcpCompound || now >= next_time_to_send_rtcp_) {
+ // If RTCP is in compound mode then we always send a RR.
+ if (rtp_receiver_statistics) {
packet_type_flags |= kRtcpRr;
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(
+ 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);
}
@@ -188,6 +159,14 @@ void Rtcp::SendRtcpFromRtpReceiver(
uint32 delay_seconds = 0;
uint32 delay_fraction = 0;
base::TimeDelta delta = now - time_last_report_received_;
+
+ // TODO(hclam): DLRR is not used by any receiver. Consider removing
+ // it. There is one race condition in the computation of the time for
+ // DLRR: current time is submitted to this method while
+ // |time_last_report_received_| is updated just before that. This can
+ // happen if current time is not submitted synchronously.
+ if (delta < base::TimeDelta())
+ delta = base::TimeDelta();
ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds,
&delay_fraction);
report_block.delay_since_last_sr =
@@ -195,19 +174,19 @@ void Rtcp::SendRtcpFromRtpReceiver(
} else {
report_block.delay_since_last_sr = 0;
}
- UpdateNextTimeToSendRtcp();
}
rtcp_sender_->SendRtcpFromRtpReceiver(packet_type_flags,
&report_block,
&rrtr,
cast_message,
rtcp_events,
- target_delay_);
+ target_delay);
}
void Rtcp::SendRtcpFromRtpSender(base::TimeTicks current_time,
- uint32 current_time_as_rtp_timestamp) {
- DCHECK(transport_sender_);
+ uint32 current_time_as_rtp_timestamp,
+ uint32 send_packet_count,
+ size_t send_octet_count) {
uint32 packet_type_flags = kRtcpSr;
uint32 current_ntp_seconds = 0;
uint32 current_ntp_fractions = 0;
@@ -229,16 +208,20 @@ void Rtcp::SendRtcpFromRtpSender(base::TimeTicks current_time,
dlrr.delay_since_last_rr = ConvertToNtpDiff(delay_seconds, delay_fraction);
}
- transport_sender_->SendRtcpFromRtpSender(
- packet_type_flags, current_ntp_seconds, current_ntp_fractions,
- current_time_as_rtp_timestamp, dlrr, local_ssrc_, c_name_);
- UpdateNextTimeToSendRtcp();
+ RtcpSenderInfo sender_info;
+ sender_info.ntp_seconds = current_ntp_seconds;
+ sender_info.ntp_fraction = current_ntp_fractions;
+ sender_info.rtp_timestamp = current_time_as_rtp_timestamp;
+ sender_info.send_packet_count = send_packet_count;
+ sender_info.send_octet_count = send_octet_count;
+
+ rtcp_sender_->SendRtcpFromRtpSender(packet_type_flags, sender_info, dlrr);
}
void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) {
last_report_truncated_ntp_ = ConvertToNtpDiff(ntp_seconds, ntp_fraction);
- const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
+ const base::TimeTicks now = clock_->NowTicks();
time_last_report_received_ = now;
// TODO(miu): This clock offset calculation does not account for packet
@@ -283,43 +266,31 @@ bool Rtcp::GetLatestLipSyncTimes(uint32* rtp_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));
+ DCHECK((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() {
- base::TimeTicks now = cast_environment_->Clock()->NowTicks();
-
- // Trigger a new RTCP report at next timer.
- next_time_to_send_rtcp_ = now;
-}
-
-void Rtcp::SetCastReceiverEventHistorySize(size_t size) {
- rtcp_receiver_->SetCastReceiverEventHistorySize(size);
-}
-
-void Rtcp::SetTargetDelay(base::TimeDelta target_delay) {
- DCHECK(target_delay < TimeDelta::FromMilliseconds(kMaxDelayMs));
- target_delay_ = target_delay;
-}
-
-void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,
- uint32 last_report,
+void Rtcp::OnReceivedDelaySinceLastReport(uint32 last_report,
uint32 delay_since_last_report) {
RtcpSendTimeMap::iterator it = last_reports_sent_map_.find(last_report);
if (it == last_reports_sent_map_.end()) {
return; // Feedback on another report.
}
- base::TimeDelta sender_delay =
- cast_environment_->Clock()->NowTicks() - it->second;
+ base::TimeDelta sender_delay = clock_->NowTicks() - it->second;
UpdateRtt(sender_delay, ConvertFromNtpDiff(delay_since_last_report));
}
+void Rtcp::OnReceivedCastFeedback(const RtcpCastMessage& cast_message) {
+ if (cast_callback_.is_null())
+ return;
+ cast_callback_.Run(cast_message);
+}
+
void Rtcp::SaveLastSentNtpTime(const base::TimeTicks& now,
uint32 last_ntp_seconds,
uint32 last_ntp_fraction) {
@@ -367,6 +338,9 @@ void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay,
avg_rtt_ = rtt;
}
number_of_rtt_in_avg_++;
+
+ if (!rtt_callback_.is_null())
+ rtt_callback_.Run(rtt, avg_rtt_, min_rtt_, max_rtt_);
}
bool Rtcp::Rtt(base::TimeDelta* rtt, base::TimeDelta* avg_rtt,
@@ -385,45 +359,10 @@ bool Rtcp::Rtt(base::TimeDelta* rtt, base::TimeDelta* avg_rtt,
return true;
}
-void Rtcp::UpdateNextTimeToSendRtcp() {
- base::TimeTicks now = cast_environment_->Clock()->NowTicks();
- next_time_to_send_rtcp_ = now + rtcp_interval_;
-}
-
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;
- }
- }
- }
+ if (log_callback_.is_null())
+ return;
+ log_callback_.Run(receiver_log);
}
} // namespace cast
diff --git a/media/cast/net/rtcp/rtcp.h b/media/cast/net/rtcp/rtcp.h
index 2bf0367..b84998b 100644
--- a/media/cast/net/rtcp/rtcp.h
+++ b/media/cast/net/rtcp/rtcp.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// This class maintains a bi-directional RTCP connection with a remote
+// peer.
+
#ifndef MEDIA_CAST_RTCP_RTCP_H_
#define MEDIA_CAST_RTCP_RTCP_H_
@@ -11,15 +14,14 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "media/cast/cast_config.h"
#include "media/cast/cast_defines.h"
-#include "media/cast/cast_environment.h"
#include "media/cast/common/clock_drift_smoother.h"
#include "media/cast/net/cast_transport_defines.h"
#include "media/cast/net/cast_transport_sender.h"
-#include "media/cast/net/pacing/paced_sender.h"
#include "media/cast/net/rtcp/receiver_rtcp_event_subscriber.h"
#include "media/cast/net/rtcp/rtcp_defines.h"
@@ -27,7 +29,6 @@ namespace media {
namespace cast {
class LocalRtcpReceiverFeedback;
-class LocalRtcpRttFeedback;
class PacedPacketSender;
class RtcpReceiver;
class RtcpSender;
@@ -36,13 +37,6 @@ typedef std::pair<uint32, base::TimeTicks> RtcpSendTimePair;
typedef std::map<uint32, base::TimeTicks> RtcpSendTimeMap;
typedef std::queue<RtcpSendTimePair> RtcpSendTimeQueue;
-class RtcpSenderFeedback {
- public:
- virtual void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) = 0;
-
- virtual ~RtcpSenderFeedback() {}
-};
-
class RtpReceiverStatistics {
public:
virtual void GetStatistics(uint8* fraction_lost,
@@ -53,46 +47,47 @@ class RtpReceiverStatistics {
virtual ~RtpReceiverStatistics() {}
};
+// TODO(hclam): This should be renamed to RtcpSession.
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,
- CastTransportSender* const transport_sender, // Send-side.
- PacedPacketSender* paced_packet_sender, // Receive side.
- RtpReceiverStatistics* rtp_receiver_statistics,
- RtcpMode rtcp_mode,
- const base::TimeDelta& rtcp_interval,
+ Rtcp(const RtcpCastMessageCallback& cast_callback,
+ const RtcpRttCallback& rtt_callback,
+ const RtcpLogMessageCallback& log_callback,
+ base::TickClock* clock, // Not owned.
+ PacedPacketSender* packet_sender, // Not owned.
uint32 local_ssrc,
uint32 remote_ssrc,
- const std::string& c_name,
- EventMediaType event_media_type);
+ const std::string& c_name);
virtual ~Rtcp();
- static bool IsRtcpPacket(const uint8* rtcp_buffer, size_t length);
-
- static uint32 GetSsrcOfSender(const uint8* rtcp_buffer, size_t length);
-
- base::TimeTicks TimeToSendNextRtcpReport();
-
// 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);
+ // |send_packet_count| is the number of packets sent.
+ // |send_octet_count| is the number of octets sent.
+ void SendRtcpFromRtpSender(
+ base::TimeTicks current_time,
+ uint32 current_time_as_rtp_timestamp,
+ uint32 send_packet_count,
+ size_t send_octet_count);
// |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 |rtcp_events| is provided the RTCP receiver report
- // will append the log messages.
+ // Acks and Nacks; |target_delay| is sent together with |cast_message|.
+ // 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);
+ base::TimeDelta target_delay,
+ const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events,
+ RtpReceiverStatistics* rtp_receiver_statistics);
- void IncomingRtcpPacket(const uint8* rtcp_buffer, size_t length);
+ // Submit a received packet to this object. The packet will be parsed
+ // and used to maintain a RTCP session.
+ // Returns false if this is not a RTCP packet or it is not directed to
+ // this session, e.g. SSRC doesn't match.
+ bool IncomingRtcpPacket(const uint8* data, size_t length);
// 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
@@ -103,8 +98,6 @@ class Rtcp {
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
@@ -113,15 +106,6 @@ class Rtcp {
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:
@@ -131,42 +115,31 @@ class Rtcp {
uint32 ntp_fraction);
private:
- friend class LocalRtcpRttFeedback;
- friend class LocalRtcpReceiverFeedback;
+ class RtcpMessageHandlerImpl;
- void OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,
- uint32 last_report,
+ void OnReceivedDelaySinceLastReport(uint32 last_report,
uint32 delay_since_last_report);
- void OnReceivedSendReportRequest();
+ void OnReceivedCastFeedback(const RtcpCastMessage& cast_message);
void UpdateRtt(const base::TimeDelta& sender_delay,
const base::TimeDelta& receiver_delay);
- void UpdateNextTimeToSendRtcp();
-
void SaveLastSentNtpTime(const base::TimeTicks& now,
uint32 last_ntp_seconds,
uint32 last_ntp_fraction);
- scoped_refptr<CastEnvironment> cast_environment_;
- CastTransportSender* const transport_sender_;
- const base::TimeDelta rtcp_interval_;
- const RtcpMode rtcp_mode_;
+ const RtcpCastMessageCallback cast_callback_;
+ const RtcpRttCallback rtt_callback_;
+ const RtcpLogMessageCallback log_callback_;
+ base::TickClock* const clock_; // Not owned by this class.
+ const scoped_ptr<RtcpSender> rtcp_sender_;
const uint32 local_ssrc_;
const uint32 remote_ssrc_;
const std::string c_name_;
- const EventMediaType event_media_type_;
-
- // Not owned by this class.
- RtpReceiverStatistics* const rtp_receiver_statistics_;
-
- scoped_ptr<LocalRtcpRttFeedback> rtt_feedback_;
- scoped_ptr<LocalRtcpReceiverFeedback> receiver_feedback_;
- scoped_ptr<RtcpSender> rtcp_sender_;
- scoped_ptr<RtcpReceiver> rtcp_receiver_;
+ const scoped_ptr<RtcpMessageHandlerImpl> handler_;
+ const scoped_ptr<RtcpReceiver> rtcp_receiver_;
- base::TimeTicks next_time_to_send_rtcp_;
RtcpSendTimeMap last_reports_sent_map_;
RtcpSendTimeQueue last_reports_sent_queue_;
@@ -195,7 +168,6 @@ class Rtcp {
base::TimeDelta max_rtt_;
int number_of_rtt_in_avg_;
base::TimeDelta avg_rtt_;
- base::TimeDelta target_delay_;
DISALLOW_COPY_AND_ASSIGN(Rtcp);
};
diff --git a/media/cast/net/rtcp/rtcp_defines.cc b/media/cast/net/rtcp/rtcp_defines.cc
index 63799a9..9012468 100644
--- a/media/cast/net/rtcp/rtcp_defines.cc
+++ b/media/cast/net/rtcp/rtcp_defines.cc
@@ -9,17 +9,12 @@
namespace media {
namespace cast {
-RtcpCastMessage::RtcpCastMessage(uint32 media_ssrc)
- : media_ssrc_(media_ssrc), ack_frame_id_(0u), target_delay_ms_(0) {}
+RtcpCastMessage::RtcpCastMessage(uint32 ssrc)
+ : media_ssrc(ssrc), ack_frame_id(0u), target_delay_ms(0) {}
+RtcpCastMessage::RtcpCastMessage()
+ : media_ssrc(0), 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() {}
@@ -45,5 +40,8 @@ RtcpReceiverReferenceTimeReport::~RtcpReceiverReferenceTimeReport() {}
RtcpEvent::RtcpEvent() : type(UNKNOWN), packet_id(0u) {}
RtcpEvent::~RtcpEvent() {}
+RtcpRttReport::RtcpRttReport() {}
+RtcpRttReport::~RtcpRttReport() {}
+
} // namespace cast
} // namespace media
diff --git a/media/cast/net/rtcp/rtcp_defines.h b/media/cast/net/rtcp/rtcp_defines.h
index 28f69e1..0207edc 100644
--- a/media/cast/net/rtcp/rtcp_defines.h
+++ b/media/cast/net/rtcp/rtcp_defines.h
@@ -21,19 +21,15 @@ 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);
+struct RtcpCastMessage {
+ explicit RtcpCastMessage(uint32 ssrc);
+ RtcpCastMessage();
~RtcpCastMessage();
- void Copy(const RtcpCastMessage& cast_message);
-
- uint32 media_ssrc_;
- uint32 ack_frame_id_;
- uint16 target_delay_ms_;
- MissingFramesAndPacketsMap missing_frames_and_packets_;
-
- DISALLOW_COPY_AND_ASSIGN(RtcpCastMessage);
+ uint32 media_ssrc;
+ uint32 ack_frame_id;
+ uint16 target_delay_ms;
+ MissingFramesAndPacketsMap missing_frames_and_packets;
};
// Log messages from receiver to sender.
@@ -127,6 +123,24 @@ struct RtcpEvent {
uint16 packet_id;
};
+struct RtcpRttReport {
+ RtcpRttReport();
+ ~RtcpRttReport();
+
+ base::TimeDelta rtt;
+ base::TimeDelta avg_rtt;
+ base::TimeDelta min_rtt;
+ base::TimeDelta max_rtt;
+};
+
+typedef base::Callback<void(const RtcpCastMessage&)> RtcpCastMessageCallback;
+typedef base::Callback<void(base::TimeDelta,
+ base::TimeDelta,
+ base::TimeDelta,
+ base::TimeDelta)> RtcpRttCallback;
+typedef
+base::Callback<void(const RtcpReceiverLogMessage&)> RtcpLogMessageCallback;
+
} // namespace cast
} // namespace media
diff --git a/media/cast/net/rtcp/rtcp_receiver.cc b/media/cast/net/rtcp/rtcp_receiver.cc
index 99fd917..d8b81b1 100644
--- a/media/cast/net/rtcp/rtcp_receiver.cc
+++ b/media/cast/net/rtcp/rtcp_receiver.cc
@@ -4,6 +4,7 @@
#include "media/cast/net/rtcp/rtcp_receiver.h"
+#include "base/big_endian.h"
#include "base/logging.h"
#include "media/cast/net/cast_transport_defines.h"
#include "media/cast/net/rtcp/rtcp_utility.h"
@@ -38,21 +39,44 @@ std::pair<uint64, uint64> GetReceiverEventKey(
namespace media {
namespace cast {
-RtcpReceiver::RtcpReceiver(scoped_refptr<CastEnvironment> cast_environment,
- RtcpSenderFeedback* sender_feedback,
- RtcpReceiverFeedback* receiver_feedback,
- RtcpRttFeedback* rtt_feedback,
+RtcpReceiver::RtcpReceiver(RtcpMessageHandler* handler,
uint32 local_ssrc)
: ssrc_(local_ssrc),
remote_ssrc_(0),
- sender_feedback_(sender_feedback),
- receiver_feedback_(receiver_feedback),
- rtt_feedback_(rtt_feedback),
- cast_environment_(cast_environment),
- receiver_event_history_size_(0) {}
+ handler_(handler),
+ receiver_event_history_size_(0) {
+ DCHECK(handler_);
+}
RtcpReceiver::~RtcpReceiver() {}
+// static
+bool RtcpReceiver::IsRtcpPacket(const uint8* packet, size_t length) {
+ if (length < kMinLengthOfRtcp) {
+ LOG(ERROR) << "Invalid RTCP packet received.";
+ return false;
+ }
+
+ uint8 packet_type = packet[1];
+ if (packet_type >= kPacketTypeLow &&
+ packet_type <= kPacketTypeHigh) {
+ return true;
+ }
+ return false;
+}
+
+// static
+uint32 RtcpReceiver::GetSsrcOfSender(const uint8* rtcp_buffer, size_t length) {
+ if (length < kMinLengthOfRtcp)
+ return 0;
+ uint32 ssrc_of_sender;
+ 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;
+}
+
void RtcpReceiver::SetRemoteSSRC(uint32 ssrc) { remote_ssrc_ = ssrc; }
void RtcpReceiver::SetCastReceiverEventHistorySize(size_t size) {
@@ -83,9 +107,6 @@ void RtcpReceiver::IncomingRtcpPacket(RtcpParser* rtcp_parser) {
case kRtcpGenericRtpFeedbackNackCode:
HandleNACK(rtcp_parser);
break;
- case kRtcpGenericRtpFeedbackSrReqCode:
- HandleSendReportRequest(rtcp_parser);
- break;
case kRtcpPayloadSpecificPliCode:
HandlePLI(rtcp_parser);
break;
@@ -110,6 +131,7 @@ void RtcpReceiver::IncomingRtcpPacket(RtcpParser* rtcp_parser) {
case kRtcpNotValidCode:
case kRtcpReportBlockItemCode:
case kRtcpSdesChunkCode:
+ case kRtcpGenericRtpFeedbackSrReqCode:
case kRtcpGenericRtpFeedbackNackItemCode:
case kRtcpPayloadSpecificFirItemCode:
case kRtcpXrRrtrCode:
@@ -145,9 +167,7 @@ void RtcpReceiver::HandleSenderReport(RtcpParser* rtcp_parser) {
rtcp_field.sender_report.sender_packet_count;
remote_sender_info.send_octet_count =
rtcp_field.sender_report.sender_octet_count;
- if (receiver_feedback_) {
- receiver_feedback_->OnReceivedSenderReport(remote_sender_info);
- }
+ handler_->OnReceivedSenderReport(remote_sender_info);
}
rtcp_field_type = rtcp_parser->Iterate();
while (rtcp_field_type == kRtcpReportBlockItemCode) {
@@ -203,11 +223,8 @@ void RtcpReceiver::HandleReportBlock(const RtcpField* rtcp_field,
report_block.jitter = rb.jitter;
report_block.last_sr = rb.last_sender_report;
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);
- }
+ handler_->OnReceivedDelaySinceLastReport(
+ rb.last_sender_report, rb.delay_last_sender_report);
}
void RtcpReceiver::HandleSDES(RtcpParser* rtcp_parser) {
@@ -254,10 +271,7 @@ void RtcpReceiver::HandleRrtr(RtcpParser* rtcp_parser, uint32 remote_ssrc) {
remote_time_report.remote_ssrc = remote_ssrc;
remote_time_report.ntp_seconds = rtcp_field.rrtr.ntp_most_significant;
remote_time_report.ntp_fraction = rtcp_field.rrtr.ntp_least_significant;
-
- if (receiver_feedback_) {
- receiver_feedback_->OnReceiverReferenceTimeReport(remote_time_report);
- }
+ handler_->OnReceiverReferenceTimeReport(remote_time_report);
}
void RtcpReceiver::HandleDlrr(RtcpParser* rtcp_parser) {
@@ -266,12 +280,9 @@ void RtcpReceiver::HandleDlrr(RtcpParser* rtcp_parser) {
// Not to us.
return;
}
- if (rtt_feedback_) {
- rtt_feedback_->OnReceivedDelaySinceLastReport(
- rtcp_field.dlrr.receivers_ssrc,
- rtcp_field.dlrr.last_receiver_report,
- rtcp_field.dlrr.delay_last_receiver_report);
- }
+ handler_->OnReceivedDelaySinceLastReport(
+ rtcp_field.dlrr.last_receiver_report,
+ rtcp_field.dlrr.delay_last_receiver_report);
}
void RtcpReceiver::HandleNACK(RtcpParser* rtcp_parser) {
@@ -326,13 +337,6 @@ void RtcpReceiver::HandlePLI(RtcpParser* rtcp_parser) {
rtcp_parser->Iterate();
}
-void RtcpReceiver::HandleSendReportRequest(RtcpParser* rtcp_parser) {
- if (receiver_feedback_) {
- receiver_feedback_->OnReceivedSendReportRequest();
- }
- rtcp_parser->Iterate();
-}
-
void RtcpReceiver::HandleRpsi(RtcpParser* rtcp_parser) {
const RtcpField& rtcp_field = rtcp_parser->Field();
if (rtcp_parser->Iterate() != kRtcpPayloadSpecificRpsiCode) {
@@ -436,9 +440,8 @@ void RtcpReceiver::HandleApplicationSpecificCastReceiverLog(
receiver_log.push_back(frame_log);
}
- if (receiver_feedback_ && !receiver_log.empty()) {
- receiver_feedback_->OnReceivedReceiverLog(receiver_log);
- }
+ if (!receiver_log.empty())
+ handler_->OnReceivedReceiverLog(receiver_log);
}
void RtcpReceiver::HandleApplicationSpecificCastReceiverEventLog(
@@ -491,20 +494,18 @@ void RtcpReceiver::HandleApplicationSpecificCastReceiverEventLog(
void RtcpReceiver::HandlePayloadSpecificCastItem(RtcpParser* rtcp_parser) {
const RtcpField& rtcp_field = rtcp_parser->Field();
RtcpCastMessage cast_message(remote_ssrc_);
- cast_message.ack_frame_id_ = ack_frame_id_wrap_helper_.MapTo32bitsFrameId(
+ 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;
+ cast_message.target_delay_ms = rtcp_field.cast_item.target_delay_ms;
RtcpFieldTypes packet_type = rtcp_parser->Iterate();
while (packet_type == kRtcpPayloadSpecificCastNackItemCode) {
const RtcpField& rtcp_field = rtcp_parser->Field();
HandlePayloadSpecificCastNackItem(
- &rtcp_field, &cast_message.missing_frames_and_packets_);
+ &rtcp_field, &cast_message.missing_frames_and_packets);
packet_type = rtcp_parser->Iterate();
}
- if (sender_feedback_) {
- sender_feedback_->OnReceivedCastFeedback(cast_message);
- }
+ handler_->OnReceivedCastFeedback(cast_message);
}
void RtcpReceiver::HandlePayloadSpecificCastNackItem(
diff --git a/media/cast/net/rtcp/rtcp_receiver.h b/media/cast/net/rtcp/rtcp_receiver.h
index aea4584..9cd39ff 100644
--- a/media/cast/net/rtcp/rtcp_receiver.h
+++ b/media/cast/net/rtcp/rtcp_receiver.h
@@ -16,7 +16,8 @@
namespace media {
namespace cast {
-class RtcpReceiverFeedback {
+// Interface for receiving RTCP messages.
+class RtcpMessageHandler {
public:
virtual void OnReceivedSenderReport(
const RtcpSenderInfo& remote_sender_info) = 0;
@@ -24,33 +25,28 @@ class RtcpReceiverFeedback {
virtual void OnReceiverReferenceTimeReport(
const RtcpReceiverReferenceTimeReport& remote_time_report) = 0;
- virtual void OnReceivedSendReportRequest() = 0;
-
virtual void OnReceivedReceiverLog(
const RtcpReceiverLogMessage& receiver_log) = 0;
- virtual ~RtcpReceiverFeedback() {}
-};
-
-class RtcpRttFeedback {
- public:
virtual void OnReceivedDelaySinceLastReport(
- uint32 receivers_ssrc,
uint32 last_report,
uint32 delay_since_last_report) = 0;
- virtual ~RtcpRttFeedback() {}
+ virtual void OnReceivedCastFeedback(
+ const RtcpCastMessage& cast_message) = 0;
+
+ virtual ~RtcpMessageHandler() {}
};
class RtcpReceiver {
public:
- explicit RtcpReceiver(scoped_refptr<CastEnvironment> cast_environment,
- RtcpSenderFeedback* sender_feedback,
- RtcpReceiverFeedback* receiver_feedback,
- RtcpRttFeedback* rtt_feedback,
- uint32 local_ssrc);
+ RtcpReceiver(RtcpMessageHandler* handler, uint32 local_ssrc);
virtual ~RtcpReceiver();
+ static bool IsRtcpPacket(const uint8* rtcp_buffer, size_t length);
+
+ static uint32 GetSsrcOfSender(const uint8* rtcp_buffer, size_t length);
+
void SetRemoteSSRC(uint32 ssrc);
// Set the history size to record Cast receiver events. Event history is
@@ -111,10 +107,7 @@ class RtcpReceiver {
uint32 remote_ssrc_;
// Not owned by this class.
- RtcpSenderFeedback* const sender_feedback_;
- RtcpReceiverFeedback* const receiver_feedback_;
- RtcpRttFeedback* const rtt_feedback_;
- scoped_refptr<CastEnvironment> cast_environment_;
+ RtcpMessageHandler* const handler_;
FrameIdWrapHelper ack_frame_id_wrap_helper_;
diff --git a/media/cast/net/rtcp/rtcp_receiver_unittest.cc b/media/cast/net/rtcp/rtcp_receiver_unittest.cc
index f4010cb..47ae24b 100644
--- a/media/cast/net/rtcp/rtcp_receiver_unittest.cc
+++ b/media/cast/net/rtcp/rtcp_receiver_unittest.cc
@@ -7,7 +7,6 @@
#include "media/cast/cast_environment.h"
#include "media/cast/net/cast_transport_defines.h"
#include "media/cast/net/rtcp/mock_rtcp_receiver_feedback.h"
-#include "media/cast/net/rtcp/mock_rtcp_sender_feedback.h"
#include "media/cast/net/rtcp/rtcp_receiver.h"
#include "media/cast/net/rtcp/rtcp_utility.h"
#include "media/cast/net/rtcp/test_rtcp_packet_builder.h"
@@ -27,58 +26,13 @@ static const base::TimeDelta kTargetDelay =
static const std::string kCName("test@10.1.1.1");
namespace {
-class SenderFeedbackCastVerification : public RtcpSenderFeedback {
- public:
- SenderFeedbackCastVerification() : called_(false) {}
-
- virtual void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback)
- OVERRIDE {
- EXPECT_EQ(cast_feedback.media_ssrc_, kSenderSsrc);
- EXPECT_EQ(cast_feedback.ack_frame_id_, kAckFrameId);
-
- MissingFramesAndPacketsMap::const_iterator frame_it =
- cast_feedback.missing_frames_and_packets_.begin();
- EXPECT_TRUE(frame_it != cast_feedback.missing_frames_and_packets_.end());
- EXPECT_EQ(kLostFrameId, frame_it->first);
- 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);
- EXPECT_EQ(3UL, frame_it->second.size());
- PacketIdSet::const_iterator packet_it = frame_it->second.begin();
- EXPECT_EQ(kLostPacketId1, *packet_it);
- ++packet_it;
- EXPECT_EQ(kLostPacketId2, *packet_it);
- ++packet_it;
- EXPECT_EQ(kLostPacketId3, *packet_it);
- ++frame_it;
- EXPECT_EQ(frame_it, cast_feedback.missing_frames_and_packets_.end());
- called_ = true;
- }
-
- bool called() const { return called_; }
-
- private:
- bool called_;
-
- DISALLOW_COPY_AND_ASSIGN(SenderFeedbackCastVerification);
-};
-
-class RtcpReceiverCastLogVerification : public RtcpReceiverFeedback {
+class RtcpMessageVerification : public MockRtcpReceiverFeedback {
public:
- RtcpReceiverCastLogVerification()
+ RtcpMessageVerification()
: called_on_received_sender_log_(false),
- called_on_received_receiver_log_(false) {}
-
- virtual void OnReceivedSenderReport(
- const RtcpSenderInfo& remote_sender_info) OVERRIDE{};
-
- virtual void OnReceiverReferenceTimeReport(
- const RtcpReceiverReferenceTimeReport& remote_time_report) OVERRIDE{};
-
- virtual void OnReceivedSendReportRequest() OVERRIDE{};
+ called_on_received_receiver_log_(false),
+ called_on_received_cast_message_(false) {}
virtual void OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log)
OVERRIDE {
@@ -113,10 +67,41 @@ class RtcpReceiverCastLogVerification : public RtcpReceiverFeedback {
called_on_received_receiver_log_ = true;
}
- bool OnReceivedReceiverLogCalled() {
+ virtual void OnReceivedCastFeedback(const RtcpCastMessage& cast_message)
+ OVERRIDE {
+ EXPECT_EQ(cast_message.media_ssrc, kSenderSsrc);
+ EXPECT_EQ(cast_message.ack_frame_id, kAckFrameId);
+
+ MissingFramesAndPacketsMap::const_iterator frame_it =
+ cast_message.missing_frames_and_packets.begin();
+
+ EXPECT_TRUE(frame_it != cast_message.missing_frames_and_packets.end());
+ EXPECT_EQ(kLostFrameId, frame_it->first);
+ EXPECT_EQ(frame_it->second.size(), 1UL);
+ EXPECT_EQ(*frame_it->second.begin(), kRtcpCastAllPacketsLost);
+ ++frame_it;
+ EXPECT_TRUE(frame_it != cast_message.missing_frames_and_packets.end());
+ EXPECT_EQ(kFrameIdWithLostPackets, frame_it->first);
+ EXPECT_EQ(3UL, frame_it->second.size());
+ PacketIdSet::const_iterator packet_it = frame_it->second.begin();
+ EXPECT_EQ(kLostPacketId1, *packet_it);
+ ++packet_it;
+ EXPECT_EQ(kLostPacketId2, *packet_it);
+ ++packet_it;
+ EXPECT_EQ(kLostPacketId3, *packet_it);
+ ++frame_it;
+ EXPECT_EQ(frame_it, cast_message.missing_frames_and_packets.end());
+ called_on_received_cast_message_ = true;
+ }
+
+ bool OnReceivedReceiverLogCalled() const {
return called_on_received_receiver_log_ && expected_receiver_log_.empty();
}
+ bool OnReceivedCastFeedbackCalled() const {
+ return called_on_received_cast_message_;
+ }
+
void SetExpectedReceiverLog(const RtcpReceiverLogMessage& receiver_log) {
expected_receiver_log_ = receiver_log;
}
@@ -125,8 +110,9 @@ class RtcpReceiverCastLogVerification : public RtcpReceiverFeedback {
RtcpReceiverLogMessage expected_receiver_log_;
bool called_on_received_sender_log_;
bool called_on_received_receiver_log_;
+ bool called_on_received_cast_message_;
- DISALLOW_COPY_AND_ASSIGN(RtcpReceiverCastLogVerification);
+ DISALLOW_COPY_AND_ASSIGN(RtcpMessageVerification);
};
} // namespace
@@ -136,23 +122,13 @@ class RtcpReceiverTest : public ::testing::Test {
RtcpReceiverTest()
: 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_,
+ rtcp_receiver_(new RtcpReceiver(&mock_receiver_feedback_,
kSourceSsrc)) {
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_sender_feedback_, OnReceivedCastFeedback(_)).Times(0);
- EXPECT_CALL(mock_rtt_feedback_, OnReceivedDelaySinceLastReport(_, _, _))
+ EXPECT_CALL(mock_receiver_feedback_, OnReceivedCastFeedback(_)).Times(0);
+ EXPECT_CALL(mock_receiver_feedback_, OnReceivedDelaySinceLastReport(_, _))
.Times(0);
expected_sender_info_.ntp_seconds = kNtpHigh;
@@ -184,10 +160,7 @@ class RtcpReceiverTest : public ::testing::Test {
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_;
@@ -226,9 +199,8 @@ TEST_F(RtcpReceiverTest, InjectReceiveReportPacket) {
// local ssrc.
InjectRtcpPacket(p1.Data(), p1.Length());
- EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(
- kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
+ EXPECT_CALL(mock_receiver_feedback_,
+ OnReceivedDelaySinceLastReport(kLastSr, kDelayLastSr)).Times(1);
TestRtcpPacketBuilder p2;
p2.AddRr(kSenderSsrc, 1);
@@ -260,9 +232,8 @@ TEST_F(RtcpReceiverTest, InjectSenderReportWithReportBlockPacket) {
InjectRtcpPacket(p1.Data(), p1.Length());
EXPECT_CALL(mock_receiver_feedback_, OnReceivedSenderReport(_)).Times(0);
- EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(
- kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
+ EXPECT_CALL(mock_receiver_feedback_,
+ OnReceivedDelaySinceLastReport(kLastSr, kDelayLastSr)).Times(1);
rtcp_receiver_->SetRemoteSSRC(0);
@@ -278,9 +249,8 @@ TEST_F(RtcpReceiverTest, InjectSenderReportWithReportBlockPacket) {
EXPECT_CALL(mock_receiver_feedback_,
OnReceivedSenderReport(expected_sender_info_)).Times(1);
- EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(
- kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
+ EXPECT_CALL(mock_receiver_feedback_,
+ OnReceivedDelaySinceLastReport(kLastSr, kDelayLastSr)).Times(1);
rtcp_receiver_->SetRemoteSSRC(kSenderSsrc);
@@ -306,9 +276,8 @@ TEST_F(RtcpReceiverTest, InjectSenderReportPacketWithDlrr) {
EXPECT_CALL(mock_receiver_feedback_,
OnReceivedSenderReport(expected_sender_info_)).Times(1);
- EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(
- kSenderSsrc, kLastSr, kDelayLastSr)).Times(1);
+ EXPECT_CALL(mock_receiver_feedback_,
+ OnReceivedDelaySinceLastReport(kLastSr, kDelayLastSr)).Times(1);
// Enable receiving sender report.
rtcp_receiver_->SetRemoteSSRC(kSenderSsrc);
@@ -328,9 +297,8 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithRrtr) {
// local ssrc.
InjectRtcpPacket(p1.Data(), p1.Length());
- EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(
- kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
+ EXPECT_CALL(mock_receiver_feedback_,
+ OnReceivedDelaySinceLastReport(kLastSr, kDelayLastSr)).Times(1);
EXPECT_CALL(mock_receiver_feedback_,
OnReceiverReferenceTimeReport(
expected_receiver_reference_report_)).Times(1);
@@ -358,9 +326,8 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithIntraFrameRequest) {
// local ssrc.
InjectRtcpPacket(p1.Data(), p1.Length());
- EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(
- kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
+ EXPECT_CALL(mock_receiver_feedback_,
+ OnReceivedDelaySinceLastReport(kLastSr, kDelayLastSr)).Times(1);
TestRtcpPacketBuilder p2;
p2.AddRr(kSenderSsrc, 1);
@@ -381,10 +348,9 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithCastFeedback) {
// local ssrc.
InjectRtcpPacket(p1.Data(), p1.Length());
- EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(
- kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
- EXPECT_CALL(mock_sender_feedback_, OnReceivedCastFeedback(_)).Times(1);
+ EXPECT_CALL(mock_receiver_feedback_,
+ OnReceivedDelaySinceLastReport(kLastSr, kDelayLastSr)).Times(1);
+ EXPECT_CALL(mock_receiver_feedback_, OnReceivedCastFeedback(_)).Times(1);
// Enable receiving the cast feedback.
rtcp_receiver_->SetRemoteSSRC(kSenderSsrc);
@@ -399,16 +365,11 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithCastFeedback) {
}
TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithCastVerification) {
- SenderFeedbackCastVerification sender_feedback_cast_verification;
- RtcpReceiver rtcp_receiver(cast_environment_,
- &sender_feedback_cast_verification,
- &mock_receiver_feedback_,
- &mock_rtt_feedback_,
- kSourceSsrc);
+ RtcpMessageVerification verification;
+ RtcpReceiver rtcp_receiver(&verification, kSourceSsrc);
- EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(
- kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
+ EXPECT_CALL(verification,
+ OnReceivedDelaySinceLastReport(kLastSr, kDelayLastSr)).Times(1);
// Enable receiving the cast feedback.
rtcp_receiver.SetRemoteSSRC(kSenderSsrc);
@@ -422,7 +383,7 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportPacketWithCastVerification) {
RtcpParser rtcp_parser(p.Data(), p.Length());
rtcp_receiver.IncomingRtcpPacket(&rtcp_parser);
- EXPECT_TRUE(sender_feedback_cast_verification.called());
+ EXPECT_TRUE(verification.OnReceivedCastFeedbackCalled());
}
TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationBase) {
@@ -432,11 +393,8 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationBase) {
base::SimpleTestTickClock testing_clock;
testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeBaseMs));
- RtcpReceiverCastLogVerification cast_log_verification;
- RtcpReceiver rtcp_receiver(cast_environment_,
- &mock_sender_feedback_,
- &cast_log_verification,
- &mock_rtt_feedback_,
+ RtcpMessageVerification verification;
+ RtcpReceiver rtcp_receiver(&verification,
kSourceSsrc);
rtcp_receiver.SetRemoteSSRC(kSenderSsrc);
rtcp_receiver.SetCastReceiverEventHistorySize(100);
@@ -463,7 +421,7 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationBase) {
receiver_log.push_back(frame_log);
- cast_log_verification.SetExpectedReceiverLog(receiver_log);
+ verification.SetExpectedReceiverLog(receiver_log);
TestRtcpPacketBuilder p;
p.AddRr(kSenderSsrc, 1);
@@ -480,14 +438,13 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationBase) {
p.AddReceiverEventLog(kLostPacketId1, PACKET_RECEIVED, kTimeDelayMs);
p.AddReceiverEventLog(kLostPacketId2, PACKET_RECEIVED, kTimeDelayMs);
- EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(
- kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
+ EXPECT_CALL(verification,
+ OnReceivedDelaySinceLastReport(kLastSr, kDelayLastSr)).Times(1);
RtcpParser rtcp_parser(p.Data(), p.Length());
rtcp_receiver.IncomingRtcpPacket(&rtcp_parser);
- EXPECT_TRUE(cast_log_verification.OnReceivedReceiverLogCalled());
+ EXPECT_TRUE(verification.OnReceivedReceiverLogCalled());
}
TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationMulti) {
@@ -497,11 +454,8 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationMulti) {
base::SimpleTestTickClock testing_clock;
testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeBaseMs));
- RtcpReceiverCastLogVerification cast_log_verification;
- RtcpReceiver rtcp_receiver(cast_environment_,
- &mock_sender_feedback_,
- &cast_log_verification,
- &mock_rtt_feedback_,
+ RtcpMessageVerification verification;
+ RtcpReceiver rtcp_receiver(&verification,
kSourceSsrc);
rtcp_receiver.SetRemoteSSRC(kSenderSsrc);
@@ -518,7 +472,7 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationMulti) {
testing_clock.Advance(base::TimeDelta::FromMilliseconds(kTimeDelayMs));
}
- cast_log_verification.SetExpectedReceiverLog(receiver_log);
+ verification.SetExpectedReceiverLog(receiver_log);
TestRtcpPacketBuilder p;
p.AddRr(kSenderSsrc, 1);
@@ -529,14 +483,13 @@ TEST_F(RtcpReceiverTest, InjectReceiverReportWithReceiverLogVerificationMulti) {
p.AddReceiverEventLog(kDelayDeltaMs, FRAME_ACK_SENT, 0);
}
- EXPECT_CALL(mock_rtt_feedback_,
- OnReceivedDelaySinceLastReport(
- kSourceSsrc, kLastSr, kDelayLastSr)).Times(1);
+ EXPECT_CALL(verification,
+ OnReceivedDelaySinceLastReport(kLastSr, kDelayLastSr)).Times(1);
RtcpParser rtcp_parser(p.Data(), p.Length());
rtcp_receiver.IncomingRtcpPacket(&rtcp_parser);
- EXPECT_TRUE(cast_log_verification.OnReceivedReceiverLogCalled());
+ EXPECT_TRUE(verification.OnReceivedReceiverLogCalled());
}
} // namespace cast
diff --git a/media/cast/net/rtcp/rtcp_sender.cc b/media/cast/net/rtcp/rtcp_sender.cc
index a44f87e..61f620f 100644
--- a/media/cast/net/rtcp/rtcp_sender.cc
+++ b/media/cast/net/rtcp/rtcp_sender.cc
@@ -11,7 +11,6 @@
#include "base/big_endian.h"
#include "base/logging.h"
-#include "media/cast/cast_environment.h"
#include "media/cast/net/cast_transport_defines.h"
#include "media/cast/net/pacing/paced_sender.h"
#include "media/cast/net/rtcp/rtcp_defines.h"
@@ -146,15 +145,12 @@ class NackStringBuilder {
};
} // namespace
-// TODO(mikhal): This is only used by the receiver. Consider renaming.
-RtcpSender::RtcpSender(scoped_refptr<CastEnvironment> cast_environment,
- PacedPacketSender* outgoing_transport,
+RtcpSender::RtcpSender(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) {
+ transport_(outgoing_transport) {
DCHECK_LT(c_name_.length(), kRtcpCnameSize) << "Invalid config";
}
@@ -181,7 +177,6 @@ void RtcpSender::SendRtcpFromRtpReceiver(
}
PacketRef packet(new base::RefCountedData<Packet>);
packet->data.reserve(kMaxIpPacketSize);
-
if (packet_type_flags & kRtcpRr) {
BuildRR(report_block, &packet->data);
if (!c_name_.empty()) {
@@ -204,8 +199,44 @@ void RtcpSender::SendRtcpFromRtpReceiver(
BuildReceiverLog(*rtcp_events, &packet->data);
}
- if (packet->data.empty())
+ if (packet->data.empty()) {
+ NOTREACHED() << "Empty packet.";
return; // Sanity don't send empty packets.
+ }
+
+ transport_->SendRtcpPacket(ssrc_, packet);
+}
+
+void RtcpSender::SendRtcpFromRtpSender(
+ uint32 packet_type_flags,
+ const RtcpSenderInfo& sender_info,
+ const RtcpDlrrReportBlock& dlrr) {
+ 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";
+ }
+ PacketRef packet(new base::RefCountedData<Packet>);
+ packet->data.reserve(kMaxIpPacketSize);
+ if (packet_type_flags & kRtcpSr) {
+ BuildSR(sender_info, &packet->data);
+ BuildSdec(&packet->data);
+ }
+ if (packet_type_flags & kRtcpBye) {
+ BuildBye(&packet->data);
+ }
+ if (packet_type_flags & kRtcpDlrr) {
+ BuildDlrrRb(dlrr, &packet->data);
+ }
+ if (packet->data.empty()) {
+ NOTREACHED() << "Empty packet.";
+ return; // Sanity - don't send empty packets.
+ }
transport_->SendRtcpPacket(ssrc_, packet);
}
@@ -334,7 +365,8 @@ void RtcpSender::BuildPli(uint32 remote_ssrc, Packet* packet) const {
| defined per codec ... | Padding (0) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi, Packet* packet) const {
+void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi,
+ Packet* packet) const {
size_t start_size = packet->size();
DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space";
if (start_size + 24 > kMaxIpPacketSize)
@@ -388,7 +420,8 @@ void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi, Packet* packet) const {
}
}
-void RtcpSender::BuildRemb(const RtcpRembMessage* remb, Packet* 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, kMaxIpPacketSize)
@@ -429,7 +462,8 @@ void RtcpSender::BuildRemb(const RtcpRembMessage* remb, Packet* packet) const {
}
}
-void RtcpSender::BuildNack(const RtcpNackMessage* nack, Packet* packet) const {
+void RtcpSender::BuildNack(const RtcpNackMessage* nack,
+ Packet* packet) const {
size_t start_size = packet->size();
DCHECK_LT(start_size + 16, kMaxIpPacketSize) << "Not enough buffer space";
if (start_size + 16 > kMaxIpPacketSize)
@@ -547,9 +581,9 @@ void RtcpSender::BuildCast(const RtcpCastMessage* cast,
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(cast->media_ssrc_); // Remote 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_));
+ 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.
DCHECK_LE(target_delay.InMilliseconds(),
@@ -561,10 +595,10 @@ void RtcpSender::BuildCast(const RtcpCastMessage* cast,
kRtcpMaxCastLossFields, (kMaxIpPacketSize - packet->size()) / 4);
MissingFramesAndPacketsMap::const_iterator frame_it =
- cast->missing_frames_and_packets_.begin();
+ cast->missing_frames_and_packets.begin();
NackStringBuilder nack_string_builder;
- for (; frame_it != cast->missing_frames_and_packets_.end() &&
+ for (; frame_it != cast->missing_frames_and_packets.end() &&
number_of_loss_fields < max_number_of_loss_fields;
++frame_it) {
nack_string_builder.PushFrame(frame_it->first);
@@ -613,14 +647,82 @@ void RtcpSender::BuildCast(const RtcpCastMessage* cast,
}
}
VLOG_IF(1, !nack_string_builder.Empty())
- << "SSRC: " << cast->media_ssrc_
- << ", ACK: " << cast->ack_frame_id_
+ << "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::BuildSR(const RtcpSenderInfo& sender_info,
+ Packet* packet) const {
+ // Sender report.
+ size_t start_size = packet->size();
+ if (start_size + 52 > kMaxIpPacketSize) {
+ DLOG(FATAL) << "Not enough buffer space";
+ return;
+ }
+
+ uint16 number_of_rows = 6;
+ packet->resize(start_size + 28);
+
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 28);
+ big_endian_writer.WriteU8(0x80);
+ 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));
+ return;
+}
+
+/*
+ 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 |
+ +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ | SSRC1 (SSRC of first receiver) | sub-
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
+ | last RR (LRR) | 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | delay since last RR (DLRR) |
+ +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+*/
+void RtcpSender::BuildDlrrRb(const RtcpDlrrReportBlock& dlrr,
+ Packet* packet) const {
+ size_t start_size = packet->size();
+ if (start_size + 24 > kMaxIpPacketSize) {
+ DLOG(FATAL) << "Not enough buffer space";
+ return;
+ }
+
+ packet->resize(start_size + 24);
+
+ base::BigEndianWriter big_endian_writer(
+ reinterpret_cast<char*>(&((*packet)[start_size])), 24);
+ big_endian_writer.WriteU8(0x80);
+ big_endian_writer.WriteU8(kPacketTypeXr);
+ big_endian_writer.WriteU16(5); // 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);
+ return;
+}
+
void RtcpSender::BuildReceiverLog(
const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events,
Packet* packet) {
diff --git a/media/cast/net/rtcp/rtcp_sender.h b/media/cast/net/rtcp/rtcp_sender.h
index fe5af0d..e55d5f4 100644
--- a/media/cast/net/rtcp/rtcp_sender.h
+++ b/media/cast/net/rtcp/rtcp_sender.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MEDIA_CAST_RTCP_RTCP_SENDER_H_
-#define MEDIA_CAST_RTCP_RTCP_SENDER_H_
+#ifndef MEDIA_CAST_NET_RTCP_RTCP_SENDER_H_
+#define MEDIA_CAST_NET_RTCP_RTCP_SENDER_H_
#include <deque>
#include <list>
@@ -13,8 +13,6 @@
#include "media/cast/cast_defines.h"
#include "media/cast/net/cast_transport_defines.h"
#include "media/cast/net/rtcp/receiver_rtcp_event_subscriber.h"
-#include "media/cast/net/rtcp/rtcp.h"
-#include "media/cast/net/rtcp/rtcp_builder.h"
#include "media/cast/net/rtcp/rtcp_defines.h"
namespace media {
@@ -40,16 +38,19 @@ COMPILE_ASSERT(kSecondRedundancyOffset >
kReceiveLogMessageHistorySize,
redundancy_offset_out_of_range);
-// TODO(mikhal): Resolve duplication between this and RtcpBuilder.
+class PacedPacketSender;
+
+// TODO(hclam): This should be renamed to RtcpPacketBuilder. The function
+// of this class is to only to build a RTCP packet but not to send it.
class RtcpSender {
public:
- RtcpSender(scoped_refptr<CastEnvironment> cast_environment,
- PacedPacketSender* outgoing_transport,
+ RtcpSender(PacedPacketSender* outgoing_transport,
uint32 sending_ssrc,
const std::string& c_name);
+ ~RtcpSender();
- virtual ~RtcpSender();
-
+ // TODO(hclam): This method should be to build a packet instead of
+ // sending it.
void SendRtcpFromRtpReceiver(
uint32 packet_type_flags,
const RtcpReportBlock* report_block,
@@ -58,6 +59,12 @@ class RtcpSender {
const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events,
base::TimeDelta target_delay);
+ // TODO(hclam): This method should be to build a packet instead of
+ // sending it.
+ void SendRtcpFromRtpSender(uint32 packet_type_flags,
+ const RtcpSenderInfo& sender_info,
+ const RtcpDlrrReportBlock& dlrr);
+
private:
void BuildRR(const RtcpReportBlock* report_block,
Packet* packet) const;
@@ -84,6 +91,10 @@ class RtcpSender {
base::TimeDelta target_delay,
Packet* packet) const;
+ void BuildSR(const RtcpSenderInfo& sender_info, Packet* packet) const;
+
+ void BuildDlrrRb(const RtcpDlrrReportBlock& dlrr, Packet* packet) const;
+
void BuildReceiverLog(
const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events,
Packet* packet);
@@ -115,7 +126,6 @@ class RtcpSender {
// Not owned by this class.
PacedPacketSender* const transport_;
- scoped_refptr<CastEnvironment> cast_environment_;
std::deque<RtcpReceiverLogMessage> rtcp_events_history_;
@@ -124,4 +134,5 @@ class RtcpSender {
} // namespace cast
} // namespace media
-#endif // MEDIA_CAST_RTCP_RTCP_SENDER_H_
+
+#endif // MEDIA_CAST_NET_RTCP_RTCP_SENDER_H_
diff --git a/media/cast/net/rtcp/rtcp_sender_unittest.cc b/media/cast/net/rtcp/rtcp_sender_unittest.cc
index c0c321e..b78915d 100644
--- a/media/cast/net/rtcp/rtcp_sender_unittest.cc
+++ b/media/cast/net/rtcp/rtcp_sender_unittest.cc
@@ -92,10 +92,7 @@ class RtcpSenderTest : public ::testing::Test {
task_runner_,
task_runner_,
task_runner_)),
- rtcp_sender_(new RtcpSender(cast_environment_,
- &test_transport_,
- kSendingSsrc,
- kCName)) {}
+ rtcp_sender_(new RtcpSender(&test_transport_, kSendingSsrc, kCName)) {}
base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
TestRtcpTransport test_transport_;
@@ -172,14 +169,14 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithCast) {
RtcpReportBlock report_block = GetReportBlock();
RtcpCastMessage cast_message(kMediaSsrc);
- cast_message.ack_frame_id_ = kAckFrameId;
+ 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);
missing_packets.insert(kLostPacketId3);
- cast_message.missing_frames_and_packets_[kFrameIdWithLostPackets] =
+ cast_message.missing_frames_and_packets[kFrameIdWithLostPackets] =
missing_packets;
rtcp_sender_->SendRtcpFromRtpReceiver(
@@ -210,14 +207,14 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtraAndCastMessage) {
rrtr.ntp_fraction = kNtpLow;
RtcpCastMessage cast_message(kMediaSsrc);
- cast_message.ack_frame_id_ = kAckFrameId;
+ 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);
missing_packets.insert(kLostPacketId3);
- cast_message.missing_frames_and_packets_[kFrameIdWithLostPackets] =
+ cast_message.missing_frames_and_packets[kFrameIdWithLostPackets] =
missing_packets;
rtcp_sender_->SendRtcpFromRtpReceiver(
@@ -251,14 +248,14 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportWithRrtrCastMessageAndLog) {
rrtr.ntp_fraction = kNtpLow;
RtcpCastMessage cast_message(kMediaSsrc);
- cast_message.ack_frame_id_ = kAckFrameId;
+ 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);
missing_packets.insert(kLostPacketId3);
- cast_message.missing_frames_and_packets_[kFrameIdWithLostPackets] =
+ cast_message.missing_frames_and_packets[kFrameIdWithLostPackets] =
missing_packets;
ReceiverRtcpEventSubscriber event_subscriber(500, VIDEO_EVENT);
@@ -553,5 +550,58 @@ TEST_F(RtcpSenderTest, RtcpReceiverReportRedundancy) {
EXPECT_EQ(static_cast<int>(packet_count), test_transport_.packet_count());
}
+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;
+
+ RtcpDlrrReportBlock dlrr_rb;
+ dlrr_rb.last_rr = kLastRr;
+ dlrr_rb.delay_since_last_rr = kDelayLastRr;
+
+ // Sender report + c_name.
+ TestRtcpPacketBuilder p;
+ p.AddSr(kSendingSsrc, 0);
+ p.AddSdesCname(kSendingSsrc, kCName);
+ test_transport_.SetExpectedRtcpPacket(p.GetPacket().Pass());
+
+ rtcp_sender_->SendRtcpFromRtpSender(kRtcpSr,
+ sender_info,
+ dlrr_rb);
+
+ EXPECT_EQ(1, 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.GetPacket().Pass());
+
+ RtcpDlrrReportBlock dlrr_rb;
+ dlrr_rb.last_rr = kLastRr;
+ dlrr_rb.delay_since_last_rr = kDelayLastRr;
+
+ rtcp_sender_->SendRtcpFromRtpSender(
+ kRtcpSr | kRtcpDlrr,
+ sender_info,
+ dlrr_rb);
+
+ EXPECT_EQ(1, test_transport_.packet_count());
+}
+
} // namespace cast
} // namespace media
diff --git a/media/cast/net/rtcp/rtcp_unittest.cc b/media/cast/net/rtcp/rtcp_unittest.cc
index 25d05b2..fa232a9 100644
--- a/media/cast/net/rtcp/rtcp_unittest.cc
+++ b/media/cast/net/rtcp/rtcp_unittest.cc
@@ -6,12 +6,10 @@
#include "base/test/simple_test_tick_clock.h"
#include "media/cast/cast_defines.h"
-#include "media/cast/cast_environment.h"
#include "media/cast/net/cast_transport_config.h"
#include "media/cast/net/cast_transport_sender_impl.h"
#include "media/cast/net/pacing/paced_sender.h"
#include "media/cast/net/rtcp/mock_rtcp_receiver_feedback.h"
-#include "media/cast/net/rtcp/mock_rtcp_sender_feedback.h"
#include "media/cast/net/rtcp/rtcp.h"
#include "media/cast/net/rtcp/test_rtcp_packet_builder.h"
#include "media/cast/test/fake_single_thread_task_runner.h"
@@ -25,7 +23,6 @@ using testing::_;
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 kAddedDelay = 123;
static const int64 kAddedShortDelay = 100;
@@ -71,8 +68,7 @@ class RtcpTestPacketSender : public PacketSender {
class LocalRtcpTransport : public PacedPacketSender {
public:
- LocalRtcpTransport(scoped_refptr<CastEnvironment> cast_environment,
- base::SimpleTestTickClock* testing_clock)
+ explicit LocalRtcpTransport(base::SimpleTestTickClock* testing_clock)
: drop_packets_(false),
short_delay_(false),
testing_clock_(testing_clock) {}
@@ -118,37 +114,43 @@ class LocalRtcpTransport : public PacedPacketSender {
bool short_delay_;
Rtcp* rtcp_;
base::SimpleTestTickClock* testing_clock_;
- scoped_refptr<CastEnvironment> cast_environment_;
DISALLOW_COPY_AND_ASSIGN(LocalRtcpTransport);
};
-class RtcpPeer : public Rtcp {
+class MockReceiverStats : public RtpReceiverStatistics {
public:
- RtcpPeer(scoped_refptr<CastEnvironment> cast_environment,
- RtcpSenderFeedback* sender_feedback,
- CastTransportSender* const transport_sender,
- 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)
- : Rtcp(cast_environment,
- sender_feedback,
- transport_sender,
- paced_packet_sender,
- rtp_receiver_statistics,
- rtcp_mode,
- rtcp_interval,
- local_ssrc,
- remote_ssrc,
- c_name,
- AUDIO_EVENT) {}
-
- using Rtcp::OnReceivedNtp;
- using Rtcp::OnReceivedLipSyncInfo;
+ MockReceiverStats() {}
+ virtual ~MockReceiverStats() {}
+
+ virtual void GetStatistics(uint8* fraction_lost,
+ uint32* cumulative_lost,
+ uint32* extended_high_sequence_number,
+ uint32* jitter) OVERRIDE {
+ *fraction_lost = 0;
+ *cumulative_lost = 0;
+ *extended_high_sequence_number = 0;
+ *jitter = 0;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockReceiverStats);
+};
+
+class MockFrameSender {
+ public:
+ MockFrameSender() {}
+ virtual ~MockFrameSender() {}
+
+ MOCK_METHOD1(OnReceivedCastFeedback,
+ void(const RtcpCastMessage& cast_message));
+ MOCK_METHOD4(OnReceivedRtt,
+ void(base::TimeDelta rtt,
+ base::TimeDelta avg_rtt,
+ base::TimeDelta min_rtt,
+ base::TimeDelta max_rtt));
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockFrameSender);
};
class RtcpTest : public ::testing::Test {
@@ -156,30 +158,9 @@ class RtcpTest : public ::testing::Test {
RtcpTest()
: 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_) {
+ receiver_to_sender_(testing_clock_) {
testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
- net::IPEndPoint dummy_endpoint;
- transport_sender_.reset(new CastTransportSenderImpl(
- NULL,
- testing_clock_,
- dummy_endpoint,
- base::Bind(&UpdateCastTransportStatus),
- BulkRawEventsCallback(),
- base::TimeDelta(),
- task_runner_,
- &sender_to_receiver_));
- CastTransportRtpConfig config;
- config.ssrc = kSenderSsrc;
- config.rtp_payload_type = 127;
- config.stored_frames = 1;
- transport_sender_->InitializeAudio(config);
- EXPECT_CALL(mock_sender_feedback_, OnReceivedCastFeedback(_)).Times(0);
}
virtual ~RtcpTest() {}
@@ -200,125 +181,94 @@ class RtcpTest : public ::testing::Test {
base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
- scoped_refptr<CastEnvironment> cast_environment_;
- RtcpTestPacketSender sender_to_receiver_;
- scoped_ptr<CastTransportSenderImpl> transport_sender_;
+ LocalRtcpTransport sender_to_receiver_;
LocalRtcpTransport receiver_to_sender_;
- MockRtcpSenderFeedback mock_sender_feedback_;
+ MockFrameSender mock_frame_sender_;
+ MockReceiverStats stats_;
DISALLOW_COPY_AND_ASSIGN(RtcpTest);
};
-TEST_F(RtcpTest, TimeToSend) {
- const base::TimeTicks start_time = testing_clock_->NowTicks();
- Rtcp rtcp(cast_environment_,
- &mock_sender_feedback_,
- transport_sender_.get(),
- &receiver_to_sender_,
- NULL,
- kRtcpCompound,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
- kSenderSsrc,
- kReceiverSsrc,
- 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());
- base::TimeDelta delta = rtcp.TimeToSendNextRtcpReport() - start_time;
- testing_clock_->Advance(delta);
- EXPECT_EQ(testing_clock_->NowTicks(), rtcp.TimeToSendNextRtcpReport());
-}
-
TEST_F(RtcpTest, BasicSenderReport) {
- Rtcp rtcp(cast_environment_,
- &mock_sender_feedback_,
- transport_sender_.get(),
- NULL,
- NULL,
- kRtcpCompound,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
+ Rtcp rtcp(base::Bind(&MockFrameSender::OnReceivedCastFeedback,
+ base::Unretained(&mock_frame_sender_)),
+ base::Bind(&MockFrameSender::OnReceivedRtt,
+ base::Unretained(&mock_frame_sender_)),
+ RtcpLogMessageCallback(),
+ testing_clock_,
+ &sender_to_receiver_,
kSenderSsrc,
kReceiverSsrc,
- kCName,
- AUDIO_EVENT);
+ kCName);
sender_to_receiver_.set_rtcp_receiver(&rtcp);
- rtcp.SendRtcpFromRtpSender(base::TimeTicks(), 0);
+ rtcp.SendRtcpFromRtpSender(base::TimeTicks(), 0, 1, 1);
}
TEST_F(RtcpTest, BasicReceiverReport) {
- Rtcp rtcp(cast_environment_,
- &mock_sender_feedback_,
- NULL,
+ Rtcp rtcp(base::Bind(&MockFrameSender::OnReceivedCastFeedback,
+ base::Unretained(&mock_frame_sender_)),
+ base::Bind(&MockFrameSender::OnReceivedRtt,
+ base::Unretained(&mock_frame_sender_)),
+ RtcpLogMessageCallback(),
+ testing_clock_,
&receiver_to_sender_,
- NULL,
- kRtcpCompound,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kSenderSsrc,
kReceiverSsrc,
- kCName,
- AUDIO_EVENT);
+ kCName);
receiver_to_sender_.set_rtcp_receiver(&rtcp);
- rtcp.SendRtcpFromRtpReceiver(NULL, NULL);
+ rtcp.SendRtcpFromRtpReceiver(NULL, base::TimeDelta(), NULL, &stats_);
}
TEST_F(RtcpTest, BasicCast) {
- EXPECT_CALL(mock_sender_feedback_, OnReceivedCastFeedback(_)).Times(1);
+ EXPECT_CALL(mock_frame_sender_, OnReceivedCastFeedback(_)).Times(1);
- // Media receiver.
- Rtcp rtcp(cast_environment_,
- &mock_sender_feedback_,
- NULL,
+ // Media sender.
+ Rtcp rtcp(base::Bind(&MockFrameSender::OnReceivedCastFeedback,
+ base::Unretained(&mock_frame_sender_)),
+ base::Bind(&MockFrameSender::OnReceivedRtt,
+ base::Unretained(&mock_frame_sender_)),
+ RtcpLogMessageCallback(),
+ testing_clock_,
&receiver_to_sender_,
- NULL,
- kRtcpReducedSize,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kSenderSsrc,
kSenderSsrc,
- kCName,
- AUDIO_EVENT);
+ kCName);
receiver_to_sender_.set_rtcp_receiver(&rtcp);
RtcpCastMessage cast_message(kSenderSsrc);
- cast_message.ack_frame_id_ = kAckFrameId;
+ 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);
missing_packets.insert(kLostPacketId3);
- cast_message.missing_frames_and_packets_[kFrameIdWithLostPackets] =
+ cast_message.missing_frames_and_packets[kFrameIdWithLostPackets] =
missing_packets;
- rtcp.SendRtcpFromRtpReceiver(&cast_message, NULL);
+ rtcp.SendRtcpFromRtpReceiver(&cast_message, base::TimeDelta(), NULL, NULL);
}
TEST_F(RtcpTest, RttReducedSizeRtcp) {
// Media receiver.
- Rtcp rtcp_receiver(cast_environment_,
- &mock_sender_feedback_,
- NULL,
+ Rtcp rtcp_receiver(RtcpCastMessageCallback(),
+ RtcpRttCallback(),
+ RtcpLogMessageCallback(),
+ testing_clock_,
&receiver_to_sender_,
- NULL,
- kRtcpReducedSize,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kReceiverSsrc,
kSenderSsrc,
- kCName,
- AUDIO_EVENT);
+ kCName);
// Media sender.
- Rtcp rtcp_sender(cast_environment_,
- &mock_sender_feedback_,
- transport_sender_.get(),
- NULL,
- NULL,
- kRtcpReducedSize,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
+ Rtcp rtcp_sender(base::Bind(&MockFrameSender::OnReceivedCastFeedback,
+ base::Unretained(&mock_frame_sender_)),
+ base::Bind(&MockFrameSender::OnReceivedRtt,
+ base::Unretained(&mock_frame_sender_)),
+ RtcpLogMessageCallback(),
+ testing_clock_,
+ &sender_to_receiver_,
kSenderSsrc,
kReceiverSsrc,
- kCName,
- AUDIO_EVENT);
+ kCName);
sender_to_receiver_.set_rtcp_receiver(&rtcp_receiver);
receiver_to_sender_.set_rtcp_receiver(&rtcp_sender);
@@ -330,16 +280,16 @@ TEST_F(RtcpTest, RttReducedSizeRtcp) {
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(testing_clock_->NowTicks(), 1);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 1, 1, 1);
RunTasks(33);
- rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
+ rtcp_receiver.SendRtcpFromRtpReceiver(NULL, base::TimeDelta(), NULL, &stats_);
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);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 2, 1, 1);
RunTasks(33);
EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
@@ -351,30 +301,26 @@ TEST_F(RtcpTest, RttReducedSizeRtcp) {
TEST_F(RtcpTest, Rtt) {
// Media receiver.
- Rtcp rtcp_receiver(cast_environment_,
- &mock_sender_feedback_,
- NULL,
+ Rtcp rtcp_receiver(RtcpCastMessageCallback(),
+ RtcpRttCallback(),
+ RtcpLogMessageCallback(),
+ testing_clock_,
&receiver_to_sender_,
- NULL,
- kRtcpCompound,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kReceiverSsrc,
kSenderSsrc,
- kCName,
- AUDIO_EVENT);
+ kCName);
// Media sender.
- Rtcp rtcp_sender(cast_environment_,
- &mock_sender_feedback_,
- transport_sender_.get(),
- NULL,
- NULL,
- kRtcpCompound,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
+ Rtcp rtcp_sender(base::Bind(&MockFrameSender::OnReceivedCastFeedback,
+ base::Unretained(&mock_frame_sender_)),
+ base::Bind(&MockFrameSender::OnReceivedRtt,
+ base::Unretained(&mock_frame_sender_)),
+ RtcpLogMessageCallback(),
+ testing_clock_,
+ &sender_to_receiver_,
kSenderSsrc,
kReceiverSsrc,
- kCName,
- AUDIO_EVENT);
+ kCName);
receiver_to_sender_.set_rtcp_receiver(&rtcp_sender);
sender_to_receiver_.set_rtcp_receiver(&rtcp_receiver);
@@ -386,9 +332,9 @@ TEST_F(RtcpTest, 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(testing_clock_->NowTicks(), 1);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 1, 1, 1);
RunTasks(33);
- rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
+ rtcp_receiver.SendRtcpFromRtpReceiver(NULL, base::TimeDelta(), NULL, &stats_);
EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
RunTasks(33);
@@ -401,7 +347,7 @@ TEST_F(RtcpTest, Rtt) {
EXPECT_NEAR(2 * kAddedDelay, min_rtt.InMilliseconds(), 2);
EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 2);
- rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 2);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 2, 1, 1);
RunTasks(33);
EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
EXPECT_NEAR(2 * kAddedDelay, rtt.InMilliseconds(), 2);
@@ -411,7 +357,7 @@ TEST_F(RtcpTest, Rtt) {
receiver_to_sender_.set_short_delay();
sender_to_receiver_.set_short_delay();
- rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
+ rtcp_receiver.SendRtcpFromRtpReceiver(NULL, base::TimeDelta(), NULL, &stats_);
EXPECT_TRUE(rtcp_sender.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
EXPECT_NEAR(kAddedDelay + kAddedShortDelay, rtt.InMilliseconds(), 2);
EXPECT_NEAR(
@@ -419,7 +365,7 @@ TEST_F(RtcpTest, Rtt) {
EXPECT_NEAR(kAddedDelay + kAddedShortDelay, min_rtt.InMilliseconds(), 2);
EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 2);
- rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 3);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 3, 1, 1);
RunTasks(33);
EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
EXPECT_NEAR(2 * kAddedShortDelay, rtt.InMilliseconds(), 1);
@@ -429,13 +375,13 @@ TEST_F(RtcpTest, Rtt) {
EXPECT_NEAR(2 * kAddedShortDelay, min_rtt.InMilliseconds(), 2);
EXPECT_NEAR(2 * kAddedDelay, max_rtt.InMilliseconds(), 2);
- rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
+ rtcp_receiver.SendRtcpFromRtpReceiver(NULL, base::TimeDelta(), NULL, &stats_);
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);
+ rtcp_receiver.SendRtcpFromRtpReceiver(NULL, base::TimeDelta(), NULL, &stats_);
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);
@@ -444,36 +390,32 @@ TEST_F(RtcpTest, Rtt) {
TEST_F(RtcpTest, RttWithPacketLoss) {
// Media receiver.
- Rtcp rtcp_receiver(cast_environment_,
- &mock_sender_feedback_,
- NULL,
+ Rtcp rtcp_receiver(RtcpCastMessageCallback(),
+ RtcpRttCallback(),
+ RtcpLogMessageCallback(),
+ testing_clock_,
&receiver_to_sender_,
- NULL,
- kRtcpReducedSize,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
kReceiverSsrc,
kSenderSsrc,
- kCName,
- AUDIO_EVENT);
+ kCName);
// Media sender.
- Rtcp rtcp_sender(cast_environment_,
- &mock_sender_feedback_,
- transport_sender_.get(),
- NULL,
- NULL,
- kRtcpReducedSize,
- base::TimeDelta::FromMilliseconds(kRtcpIntervalMs),
+ Rtcp rtcp_sender(base::Bind(&MockFrameSender::OnReceivedCastFeedback,
+ base::Unretained(&mock_frame_sender_)),
+ base::Bind(&MockFrameSender::OnReceivedRtt,
+ base::Unretained(&mock_frame_sender_)),
+ RtcpLogMessageCallback(),
+ testing_clock_,
+ &sender_to_receiver_,
kSenderSsrc,
kReceiverSsrc,
- kCName,
- AUDIO_EVENT);
+ kCName);
receiver_to_sender_.set_rtcp_receiver(&rtcp_sender);
sender_to_receiver_.set_rtcp_receiver(&rtcp_receiver);
- rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
- rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 0);
+ rtcp_receiver.SendRtcpFromRtpReceiver(NULL, base::TimeDelta(), NULL, &stats_);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 0, 1, 1);
RunTasks(33);
base::TimeDelta rtt;
@@ -491,8 +433,8 @@ TEST_F(RtcpTest, RttWithPacketLoss) {
sender_to_receiver_.set_short_delay();
receiver_to_sender_.set_drop_packets(true);
- rtcp_receiver.SendRtcpFromRtpReceiver(NULL, NULL);
- rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 1);
+ rtcp_receiver.SendRtcpFromRtpReceiver(NULL, base::TimeDelta(), NULL, &stats_);
+ rtcp_sender.SendRtcpFromRtpSender(testing_clock_->NowTicks(), 1, 1, 1);
RunTasks(33);
EXPECT_TRUE(rtcp_receiver.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt));
diff --git a/media/cast/net/rtp/cast_message_builder.cc b/media/cast/net/rtp/cast_message_builder.cc
index bb36613..42d6b98 100644
--- a/media/cast/net/rtp/cast_message_builder.cc
+++ b/media/cast/net/rtp/cast_message_builder.cc
@@ -26,7 +26,7 @@ CastMessageBuilder::CastMessageBuilder(
slowing_down_ack_(false),
acked_last_frame_(true),
last_acked_frame_id_(kStartFrameId) {
- cast_msg_.ack_frame_id_ = kStartFrameId;
+ cast_msg_.ack_frame_id = kStartFrameId;
}
CastMessageBuilder::~CastMessageBuilder() {}
@@ -86,8 +86,8 @@ bool CastMessageBuilder::UpdateAckMessage(uint32 frame_id) {
}
acked_last_frame_ = true;
last_acked_frame_id_ = frame_id;
- cast_msg_.ack_frame_id_ = last_acked_frame_id_;
- cast_msg_.missing_frames_and_packets_.clear();
+ cast_msg_.ack_frame_id = last_acked_frame_id_;
+ cast_msg_.missing_frames_and_packets.clear();
last_update_time_ = clock_->NowTicks();
return true;
}
@@ -113,8 +113,8 @@ void CastMessageBuilder::UpdateCastMessage() {
}
void CastMessageBuilder::Reset() {
- cast_msg_.ack_frame_id_ = kStartFrameId;
- cast_msg_.missing_frames_and_packets_.clear();
+ cast_msg_.ack_frame_id = kStartFrameId;
+ cast_msg_.missing_frames_and_packets.clear();
time_last_nacked_map_.clear();
}
@@ -137,7 +137,7 @@ bool CastMessageBuilder::UpdateCastMessageInternal(RtcpCastMessage* message) {
// Needed to cover when a frame is skipped.
UpdateAckMessage(last_acked_frame_id_);
BuildPacketList();
- message->Copy(cast_msg_);
+ *message = cast_msg_;
return true;
}
@@ -145,14 +145,14 @@ void CastMessageBuilder::BuildPacketList() {
base::TimeTicks now = clock_->NowTicks();
// Clear message NACK list.
- cast_msg_.missing_frames_and_packets_.clear();
+ cast_msg_.missing_frames_and_packets.clear();
// Are we missing packets?
if (frame_id_map_->Empty())
return;
uint32 newest_frame_id = frame_id_map_->NewestFrameId();
- uint32 next_expected_frame_id = cast_msg_.ack_frame_id_ + 1;
+ uint32 next_expected_frame_id = cast_msg_.ack_frame_id + 1;
// Iterate over all frames.
for (; !IsNewerFrameId(next_expected_frame_id, newest_frame_id);
@@ -175,13 +175,13 @@ void CastMessageBuilder::BuildPacketList() {
next_expected_frame_id, last_frame, &missing);
if (!missing.empty()) {
time_last_nacked_map_[next_expected_frame_id] = now;
- cast_msg_.missing_frames_and_packets_.insert(
+ cast_msg_.missing_frames_and_packets.insert(
std::make_pair(next_expected_frame_id, missing));
}
} else {
time_last_nacked_map_[next_expected_frame_id] = now;
missing.insert(kRtcpCastAllPacketsLost);
- cast_msg_.missing_frames_and_packets_[next_expected_frame_id] = missing;
+ cast_msg_.missing_frames_and_packets[next_expected_frame_id] = missing;
}
}
}
diff --git a/media/cast/net/rtp/cast_message_builder_unittest.cc b/media/cast/net/rtp/cast_message_builder_unittest.cc
index b0e30c4..e8a9aef 100644
--- a/media/cast/net/rtp/cast_message_builder_unittest.cc
+++ b/media/cast/net/rtp/cast_message_builder_unittest.cc
@@ -28,16 +28,16 @@ class NackFeedbackVerification : public RtpPayloadFeedback {
: triggered_(false), missing_packets_(), last_frame_acked_(0) {}
virtual void CastFeedback(const RtcpCastMessage& cast_feedback) OVERRIDE {
- EXPECT_EQ(kSsrc, cast_feedback.media_ssrc_);
+ EXPECT_EQ(kSsrc, cast_feedback.media_ssrc);
- last_frame_acked_ = cast_feedback.ack_frame_id_;
+ last_frame_acked_ = cast_feedback.ack_frame_id;
MissingFramesAndPacketsMap::const_iterator frame_it =
- cast_feedback.missing_frames_and_packets_.begin();
+ cast_feedback.missing_frames_and_packets.begin();
// Keep track of the number of missing packets per frame.
missing_packets_.clear();
- while (frame_it != cast_feedback.missing_frames_and_packets_.end()) {
+ while (frame_it != cast_feedback.missing_frames_and_packets.end()) {
// Check for complete frame lost.
if ((frame_it->second.size() == 1) &&
(*frame_it->second.begin() == kRtcpCastAllPacketsLost)) {
diff --git a/media/cast/receiver/cast_receiver_impl.cc b/media/cast/receiver/cast_receiver_impl.cc
index 36669b9..91821bb 100644
--- a/media/cast/receiver/cast_receiver_impl.cc
+++ b/media/cast/receiver/cast_receiver_impl.cc
@@ -10,6 +10,7 @@
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "media/cast/net/rtcp/rtcp_receiver.h"
#include "media/cast/receiver/audio_decoder.h"
#include "media/cast/receiver/video_decoder.h"
@@ -51,8 +52,8 @@ void CastReceiverImpl::DispatchReceivedPacket(scoped_ptr<Packet> packet) {
const size_t length = packet->size();
uint32 ssrc_of_sender;
- if (Rtcp::IsRtcpPacket(data, length)) {
- ssrc_of_sender = Rtcp::GetSsrcOfSender(data, length);
+ if (RtcpReceiver::IsRtcpPacket(data, length)) {
+ ssrc_of_sender = RtcpReceiver::GetSsrcOfSender(data, length);
} else if (!FrameReceiver::ParseSenderSsrc(data, length, &ssrc_of_sender)) {
VLOG(1) << "Invalid RTP packet.";
return;
diff --git a/media/cast/receiver/frame_receiver.cc b/media/cast/receiver/frame_receiver.cc
index 951e958..31620cd 100644
--- a/media/cast/receiver/frame_receiver.cc
+++ b/media/cast/receiver/frame_receiver.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "media/cast/cast_environment.h"
+#include "media/cast/net/rtcp/rtcp_receiver.h"
namespace {
const int kMinSchedulingDelayMs = 1;
@@ -40,24 +41,21 @@ FrameReceiver::FrameReceiver(
config.incoming_ssrc,
true,
config.rtp_max_delay_ms * config.max_frame_rate / 1000),
- rtcp_(cast_environment_,
- NULL,
- NULL,
+ rtcp_(RtcpCastMessageCallback(),
+ RtcpRttCallback(),
+ RtcpLogMessageCallback(),
+ cast_environment_->Clock(),
packet_sender,
- &stats_,
- config.rtcp_mode,
- base::TimeDelta::FromMilliseconds(config.rtcp_interval),
config.feedback_ssrc,
config.incoming_ssrc,
- config.rtcp_c_name,
- event_media_type),
+ config.rtcp_c_name),
is_waiting_for_consecutive_frame_(false),
lip_sync_drift_(ClockDriftSmoother::GetDefaultTimeConstant()),
+ rtcp_interval_(base::TimeDelta::FromMilliseconds(config.rtcp_interval)),
weak_factory_(this) {
DCHECK_GT(config.rtp_max_delay_ms, 0);
DCHECK_GT(config.max_frame_rate, 0);
decryptor_.Initialize(config.aes_key, config.aes_iv_mask);
- rtcp_.SetTargetDelay(target_playout_delay_);
cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_);
memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_));
}
@@ -77,7 +75,7 @@ void FrameReceiver::RequestEncodedFrame(
bool FrameReceiver::ProcessPacket(scoped_ptr<Packet> packet) {
DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
- if (Rtcp::IsRtcpPacket(&packet->front(), packet->size())) {
+ if (RtcpReceiver::IsRtcpPacket(&packet->front(), packet->size())) {
rtcp_.IncomingRtcpPacket(&packet->front(), packet->size());
} else {
RtpCastHeader rtp_header;
@@ -176,14 +174,15 @@ void FrameReceiver::CastFeedback(const RtcpCastMessage& cast_message) {
base::TimeTicks now = cast_environment_->Clock()->NowTicks();
RtpTimestamp rtp_timestamp =
- frame_id_to_rtp_timestamp_[cast_message.ack_frame_id_ & 0xff];
+ frame_id_to_rtp_timestamp_[cast_message.ack_frame_id & 0xff];
cast_environment_->Logging()->InsertFrameEvent(
now, FRAME_ACK_SENT, event_media_type_,
- rtp_timestamp, cast_message.ack_frame_id_);
+ rtp_timestamp, cast_message.ack_frame_id);
ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events;
event_subscriber_.GetRtcpEventsAndReset(&rtcp_events);
- rtcp_.SendRtcpFromRtpReceiver(&cast_message, &rtcp_events);
+ rtcp_.SendRtcpFromRtpReceiver(&cast_message, target_playout_delay_,
+ &rtcp_events, NULL);
}
void FrameReceiver::EmitAvailableEncodedFrames() {
@@ -302,9 +301,7 @@ void FrameReceiver::SendNextCastMessage() {
void FrameReceiver::ScheduleNextRtcpReport() {
DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
- base::TimeDelta time_to_next = rtcp_.TimeToSendNextRtcpReport() -
- cast_environment_->Clock()->NowTicks();
-
+ base::TimeDelta time_to_next = rtcp_interval_;
time_to_next = std::max(
time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
@@ -318,7 +315,7 @@ void FrameReceiver::ScheduleNextRtcpReport() {
void FrameReceiver::SendNextRtcpReport() {
DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
- rtcp_.SendRtcpFromRtpReceiver(NULL, NULL);
+ rtcp_.SendRtcpFromRtpReceiver(NULL, base::TimeDelta(), NULL, &stats_);
ScheduleNextRtcpReport();
}
diff --git a/media/cast/receiver/frame_receiver.h b/media/cast/receiver/frame_receiver.h
index f8e4481..2ddeeb9 100644
--- a/media/cast/receiver/frame_receiver.h
+++ b/media/cast/receiver/frame_receiver.h
@@ -172,6 +172,9 @@ class FrameReceiver : public RtpPayloadFeedback,
base::TimeTicks lip_sync_reference_time_;
ClockDriftSmoother lip_sync_drift_;
+ // Time interval for sending a RTCP report.
+ const base::TimeDelta rtcp_interval_;
+
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<FrameReceiver> weak_factory_;
diff --git a/media/cast/sender/audio_sender.cc b/media/cast/sender/audio_sender.cc
index 7c7c696..ae9653f 100644
--- a/media/cast/sender/audio_sender.cc
+++ b/media/cast/sender/audio_sender.cc
@@ -9,7 +9,6 @@
#include "base/message_loop/message_loop.h"
#include "media/cast/cast_defines.h"
#include "media/cast/net/cast_transport_config.h"
-#include "media/cast/net/rtcp/rtcp_defines.h"
#include "media/cast/sender/audio_encoder.h"
namespace media {
@@ -39,23 +38,15 @@ int GetMaxUnackedFrames(base::TimeDelta target_delay) {
AudioSender::AudioSender(scoped_refptr<CastEnvironment> cast_environment,
const AudioSenderConfig& audio_config,
CastTransportSender* const transport_sender)
- : cast_environment_(cast_environment),
+ : FrameSender(
+ cast_environment,
+ transport_sender,
+ base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval),
+ audio_config.frequency,
+ audio_config.ssrc),
target_playout_delay_(audio_config.target_playout_delay),
- transport_sender_(transport_sender),
max_unacked_frames_(GetMaxUnackedFrames(target_playout_delay_)),
configured_encoder_bitrate_(audio_config.bitrate),
- rtcp_(cast_environment,
- this,
- transport_sender_,
- NULL, // paced sender.
- NULL,
- audio_config.rtcp_mode,
- base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval),
- audio_config.ssrc,
- audio_config.incoming_feedback_ssrc,
- audio_config.rtcp_c_name,
- AUDIO_EVENT),
- rtp_timestamp_helper_(audio_config.frequency),
num_aggressive_rtcp_reports_sent_(0),
last_sent_frame_id_(0),
latest_acked_frame_id_(0),
@@ -82,16 +73,20 @@ AudioSender::AudioSender(scoped_refptr<CastEnvironment> cast_environment,
media::cast::CastTransportRtpConfig transport_config;
transport_config.ssrc = audio_config.ssrc;
+ transport_config.feedback_ssrc = audio_config.incoming_feedback_ssrc;
+ transport_config.c_name = audio_config.rtcp_c_name;
transport_config.rtp_payload_type = audio_config.rtp_payload_type;
// TODO(miu): AudioSender needs to be like VideoSender in providing an upper
// limit on the number of in-flight frames.
transport_config.stored_frames = max_unacked_frames_;
transport_config.aes_key = audio_config.aes_key;
transport_config.aes_iv_mask = audio_config.aes_iv_mask;
- transport_sender_->InitializeAudio(transport_config);
-
- rtcp_.SetCastReceiverEventHistorySize(kReceiverRtcpEventHistorySize);
+ transport_sender->InitializeAudio(
+ transport_config,
+ base::Bind(&AudioSender::OnReceivedCastFeedback,
+ weak_factory_.GetWeakPtr()),
+ base::Bind(&AudioSender::OnReceivedRtt, weak_factory_.GetWeakPtr()));
memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_));
}
@@ -161,43 +156,6 @@ void AudioSender::SendEncodedAudioFrame(
transport_sender_->InsertCodedAudioFrame(*encoded_frame);
}
-void AudioSender::IncomingRtcpPacket(scoped_ptr<Packet> packet) {
- DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
- rtcp_.IncomingRtcpPacket(&packet->front(), packet->size());
-}
-
-void AudioSender::ScheduleNextRtcpReport() {
- DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
- base::TimeDelta time_to_next =
- rtcp_.TimeToSendNextRtcpReport() - cast_environment_->Clock()->NowTicks();
-
- time_to_next = std::max(
- time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
-
- cast_environment_->PostDelayedTask(
- CastEnvironment::MAIN,
- FROM_HERE,
- base::Bind(&AudioSender::SendRtcpReport,
- weak_factory_.GetWeakPtr(),
- true),
- time_to_next);
-}
-
-void AudioSender::SendRtcpReport(bool schedule_future_reports) {
- DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
- const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
- uint32 now_as_rtp_timestamp = 0;
- if (rtp_timestamp_helper_.GetCurrentTimeAsRtpTimestamp(
- now, &now_as_rtp_timestamp)) {
- rtcp_.SendRtcpFromRtpSender(now, now_as_rtp_timestamp);
- } else {
- // |rtp_timestamp_helper_| should have stored a mapping by this point.
- NOTREACHED();
- }
- if (schedule_future_reports)
- ScheduleNextRtcpReport();
-}
-
void AudioSender::ScheduleNextResendCheck() {
DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
DCHECK(!last_send_time_.is_null());
@@ -232,7 +190,7 @@ void AudioSender::ResendCheck() {
void AudioSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
- if (rtcp_.is_rtt_available()) {
+ if (is_rtt_available()) {
// Having the RTT values implies the receiver sent back a receiver report
// based on it having received a report from here. Therefore, ensure this
// sender stops aggressively sending reports.
@@ -247,9 +205,9 @@ void AudioSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
if (last_send_time_.is_null())
return; // Cannot get an ACK without having first sent a frame.
- if (cast_feedback.missing_frames_and_packets_.empty()) {
+ if (cast_feedback.missing_frames_and_packets.empty()) {
// We only count duplicate ACKs when we have sent newer frames.
- if (latest_acked_frame_id_ == cast_feedback.ack_frame_id_ &&
+ if (latest_acked_frame_id_ == cast_feedback.ack_frame_id &&
latest_acked_frame_id_ != last_sent_frame_id_) {
duplicate_ack_counter_++;
} else {
@@ -265,43 +223,37 @@ void AudioSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
// This is to avoid aggresive resend.
duplicate_ack_counter_ = 0;
- base::TimeDelta rtt;
- base::TimeDelta avg_rtt;
- base::TimeDelta min_rtt;
- base::TimeDelta max_rtt;
- rtcp_.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt);
-
// A NACK is also used to cancel pending re-transmissions.
transport_sender_->ResendPackets(
- true, cast_feedback.missing_frames_and_packets_, false, min_rtt);
+ true, cast_feedback.missing_frames_and_packets, false, min_rtt_);
}
const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
const RtpTimestamp rtp_timestamp =
- frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id_ & 0xff];
+ frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id & 0xff];
cast_environment_->Logging()->InsertFrameEvent(now,
FRAME_ACK_RECEIVED,
AUDIO_EVENT,
rtp_timestamp,
- cast_feedback.ack_frame_id_);
+ cast_feedback.ack_frame_id);
const bool is_acked_out_of_order =
- static_cast<int32>(cast_feedback.ack_frame_id_ -
+ static_cast<int32>(cast_feedback.ack_frame_id -
latest_acked_frame_id_) < 0;
VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "")
- << " for frame " << cast_feedback.ack_frame_id_;
+ << " for frame " << cast_feedback.ack_frame_id;
if (!is_acked_out_of_order) {
// Cancel resends of acked frames.
MissingFramesAndPacketsMap missing_frames_and_packets;
PacketIdSet missing;
- while (latest_acked_frame_id_ != cast_feedback.ack_frame_id_) {
+ while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) {
latest_acked_frame_id_++;
missing_frames_and_packets[latest_acked_frame_id_] = missing;
}
transport_sender_->ResendPackets(
true, missing_frames_and_packets, true, base::TimeDelta());
- latest_acked_frame_id_ = cast_feedback.ack_frame_id_;
+ latest_acked_frame_id_ = cast_feedback.ack_frame_id;
}
}
@@ -333,16 +285,10 @@ void AudioSender::ResendForKickstart() {
std::make_pair(last_sent_frame_id_, missing));
last_send_time_ = cast_environment_->Clock()->NowTicks();
- base::TimeDelta rtt;
- base::TimeDelta avg_rtt;
- base::TimeDelta min_rtt;
- base::TimeDelta max_rtt;
- rtcp_.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt);
-
// Sending this extra packet is to kick-start the session. There is
// no need to optimize re-transmission for this case.
transport_sender_->ResendPackets(
- true, missing_frames_and_packets, false, min_rtt);
+ true, missing_frames_and_packets, false, min_rtt_);
}
} // namespace cast
diff --git a/media/cast/sender/audio_sender.h b/media/cast/sender/audio_sender.h
index efaa2b3..02582ae 100644
--- a/media/cast/sender/audio_sender.h
+++ b/media/cast/sender/audio_sender.h
@@ -14,10 +14,7 @@
#include "base/time/time.h"
#include "media/base/audio_bus.h"
#include "media/cast/cast_config.h"
-#include "media/cast/cast_environment.h"
-#include "media/cast/logging/logging_defines.h"
-#include "media/cast/net/rtcp/rtcp.h"
-#include "media/cast/sender/rtp_timestamp_helper.h"
+#include "media/cast/sender/frame_sender.h"
namespace media {
namespace cast {
@@ -30,7 +27,7 @@ class AudioEncoder;
// RTCP packets.
// Additionally it posts a bunch of delayed tasks to the main thread for various
// timeouts.
-class AudioSender : public RtcpSenderFeedback,
+class AudioSender : public FrameSender,
public base::NonThreadSafe,
public base::SupportsWeakPtr<AudioSender> {
public:
@@ -53,19 +50,11 @@ class AudioSender : public RtcpSenderFeedback,
void InsertAudio(scoped_ptr<AudioBus> audio_bus,
const base::TimeTicks& recorded_time);
- // Only called from the main cast thread.
- void IncomingRtcpPacket(scoped_ptr<Packet> packet);
-
protected:
// Protected for testability.
- virtual void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback)
- OVERRIDE;
+ void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback);
private:
- // Schedule and execute periodic sending of RTCP report.
- void ScheduleNextRtcpReport();
- void SendRtcpReport(bool schedule_future_reports);
-
// Schedule and execute periodic checks for re-sending packets. If no
// acknowledgements have been received for "too long," AudioSender will
// speculatively re-send certain packets of an unacked frame to kick-start
@@ -84,8 +73,6 @@ class AudioSender : public RtcpSenderFeedback,
// Called by the |audio_encoder_| with the next EncodedFrame to send.
void SendEncodedAudioFrame(scoped_ptr<EncodedFrame> audio_frame);
- const scoped_refptr<CastEnvironment> cast_environment_;
-
// The total amount of time between a frame's capture/recording on the sender
// and its playback on the receiver (i.e., shown to a user). This is fixed as
// a value large enough to give the system sufficient time to encode,
@@ -94,13 +81,6 @@ class AudioSender : public RtcpSenderFeedback,
// etc.).
const base::TimeDelta target_playout_delay_;
- // Sends encoded frames over the configured transport (e.g., UDP). In
- // Chromium, this could be a proxy that first sends the frames from a renderer
- // process to the browser process over IPC, with the browser process being
- // responsible for "packetizing" the frames and pushing packets into the
- // network layer.
- CastTransportSender* const transport_sender_;
-
// Maximum number of outstanding frames before the encoding and sending of
// new frames shall halt.
const int max_unacked_frames_;
@@ -109,14 +89,6 @@ class AudioSender : public RtcpSenderFeedback,
scoped_ptr<AudioEncoder> audio_encoder_;
const int configured_encoder_bitrate_;
- // Manages sending/receiving of RTCP packets, including sender/receiver
- // reports.
- Rtcp rtcp_;
-
- // Records lip-sync (i.e., mapping of RTP <--> NTP timestamps), and
- // extrapolates this mapping to any other point in time.
- RtpTimestampHelper rtp_timestamp_helper_;
-
// Counts how many RTCP reports are being "aggressively" sent (i.e., one per
// frame) at the start of the session. Once a threshold is reached, RTCP
// reports are instead sent at the configured interval + random drift.
diff --git a/media/cast/sender/audio_sender_unittest.cc b/media/cast/sender/audio_sender_unittest.cc
index ab92381..287630d 100644
--- a/media/cast/sender/audio_sender_unittest.cc
+++ b/media/cast/sender/audio_sender_unittest.cc
@@ -13,7 +13,7 @@
#include "media/cast/cast_environment.h"
#include "media/cast/net/cast_transport_config.h"
#include "media/cast/net/cast_transport_sender_impl.h"
-#include "media/cast/net/rtcp/rtcp.h"
+#include "media/cast/net/rtcp/rtcp_receiver.h"
#include "media/cast/sender/audio_sender.h"
#include "media/cast/test/fake_single_thread_task_runner.h"
#include "media/cast/test/utility/audio_utility.h"
@@ -28,7 +28,7 @@ class TestPacketSender : public PacketSender {
virtual bool SendPacket(PacketRef packet,
const base::Closure& cb) OVERRIDE {
- if (Rtcp::IsRtcpPacket(&packet->data[0], packet->data.size())) {
+ if (RtcpReceiver::IsRtcpPacket(&packet->data[0], packet->data.size())) {
++number_of_rtcp_packets_;
} else {
// Check that at least one RTCP packet was sent before the first RTP
diff --git a/media/cast/sender/frame_sender.cc b/media/cast/sender/frame_sender.cc
new file mode 100644
index 0000000..e5bc95c
--- /dev/null
+++ b/media/cast/sender/frame_sender.cc
@@ -0,0 +1,72 @@
+// 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/sender/frame_sender.h"
+
+namespace media {
+namespace cast {
+namespace {
+const int kMinSchedulingDelayMs = 1;
+} // namespace
+
+FrameSender::FrameSender(scoped_refptr<CastEnvironment> cast_environment,
+ CastTransportSender* const transport_sender,
+ base::TimeDelta rtcp_interval,
+ int frequency,
+ uint32 ssrc)
+ : cast_environment_(cast_environment),
+ transport_sender_(transport_sender),
+ rtp_timestamp_helper_(frequency),
+ rtt_available_(false),
+ rtcp_interval_(rtcp_interval),
+ ssrc_(ssrc),
+ weak_factory_(this) {
+}
+
+FrameSender::~FrameSender() {
+}
+
+void FrameSender::ScheduleNextRtcpReport() {
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
+ base::TimeDelta time_to_next = rtcp_interval_;
+
+ time_to_next = std::max(
+ time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
+
+ cast_environment_->PostDelayedTask(
+ CastEnvironment::MAIN,
+ FROM_HERE,
+ base::Bind(&FrameSender::SendRtcpReport, weak_factory_.GetWeakPtr(),
+ true),
+ time_to_next);
+}
+
+void FrameSender::SendRtcpReport(bool schedule_future_reports) {
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
+ const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
+ uint32 now_as_rtp_timestamp = 0;
+ if (rtp_timestamp_helper_.GetCurrentTimeAsRtpTimestamp(
+ now, &now_as_rtp_timestamp)) {
+ transport_sender_->SendSenderReport(ssrc_, now, now_as_rtp_timestamp);
+ } else {
+ // |rtp_timestamp_helper_| should have stored a mapping by this point.
+ NOTREACHED();
+ }
+ if (schedule_future_reports)
+ ScheduleNextRtcpReport();
+}
+
+void FrameSender::OnReceivedRtt(base::TimeDelta rtt,
+ base::TimeDelta avg_rtt,
+ base::TimeDelta min_rtt,
+ base::TimeDelta max_rtt) {
+ rtt_available_ = true;
+ rtt_ = rtt;
+ avg_rtt_ = avg_rtt;
+ min_rtt_ = min_rtt;
+ max_rtt_ = max_rtt;
+}
+
+} // namespace cast
+} // namespace media
diff --git a/media/cast/sender/frame_sender.h b/media/cast/sender/frame_sender.h
new file mode 100644
index 0000000..70eccba
--- /dev/null
+++ b/media/cast/sender/frame_sender.h
@@ -0,0 +1,77 @@
+// 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.
+//
+// This is the base class for an object that send frames to a receiver.
+// TODO(hclam): Refactor such that there is no separate AudioSender vs.
+// VideoSender, and the functionality of both is rolled into this class.
+
+#ifndef MEDIA_CAST_SENDER_FRAME_SENDER_H_
+#define MEDIA_CAST_SENDER_FRAME_SENDER_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "media/cast/cast_environment.h"
+#include "media/cast/net/rtcp/rtcp.h"
+#include "media/cast/sender/rtp_timestamp_helper.h"
+
+namespace media {
+namespace cast {
+
+class FrameSender {
+ public:
+ FrameSender(scoped_refptr<CastEnvironment> cast_environment,
+ CastTransportSender* const transport_sender,
+ base::TimeDelta rtcp_interval,
+ int frequency,
+ uint32 ssrc);
+ virtual ~FrameSender();
+
+ protected:
+ // Schedule and execute periodic sending of RTCP report.
+ void ScheduleNextRtcpReport();
+ void SendRtcpReport(bool schedule_future_reports);
+
+ void OnReceivedRtt(base::TimeDelta rtt,
+ base::TimeDelta avg_rtt,
+ base::TimeDelta min_rtt,
+ base::TimeDelta max_rtt);
+
+ bool is_rtt_available() const { return rtt_available_; }
+
+ const scoped_refptr<CastEnvironment> cast_environment_;
+
+ // Sends encoded frames over the configured transport (e.g., UDP). In
+ // Chromium, this could be a proxy that first sends the frames from a renderer
+ // process to the browser process over IPC, with the browser process being
+ // responsible for "packetizing" the frames and pushing packets into the
+ // network layer.
+ CastTransportSender* const transport_sender_;
+
+ // Records lip-sync (i.e., mapping of RTP <--> NTP timestamps), and
+ // extrapolates this mapping to any other point in time.
+ RtpTimestampHelper rtp_timestamp_helper_;
+
+ // RTT information from RTCP.
+ bool rtt_available_;
+ base::TimeDelta rtt_;
+ base::TimeDelta avg_rtt_;
+ base::TimeDelta min_rtt_;
+ base::TimeDelta max_rtt_;
+
+ private:
+ const base::TimeDelta rtcp_interval_;
+ const uint32 ssrc_;
+
+ // NOTE: Weak pointers must be invalidated before all other member variables.
+ base::WeakPtrFactory<FrameSender> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameSender);
+};
+
+} // namespace cast
+} // namespace media
+
+#endif // MEDIA_CAST_SENDER_FRAME_SENDER_H_
diff --git a/media/cast/sender/video_sender.cc b/media/cast/sender/video_sender.cc
index 0d82690..aff09c1 100644
--- a/media/cast/sender/video_sender.cc
+++ b/media/cast/sender/video_sender.cc
@@ -13,7 +13,6 @@
#include "base/message_loop/message_loop.h"
#include "media/cast/cast_defines.h"
#include "media/cast/net/cast_transport_config.h"
-#include "media/cast/net/rtcp/rtcp_defines.h"
#include "media/cast/sender/external_video_encoder.h"
#include "media/cast/sender/video_encoder_impl.h"
@@ -29,26 +28,18 @@ VideoSender::VideoSender(
const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
CastTransportSender* const transport_sender)
- : cast_environment_(cast_environment),
+ : FrameSender(
+ cast_environment,
+ transport_sender,
+ base::TimeDelta::FromMilliseconds(video_config.rtcp_interval),
+ kVideoFrequency,
+ video_config.ssrc),
target_playout_delay_(video_config.target_playout_delay),
- transport_sender_(transport_sender),
max_unacked_frames_(
std::min(kMaxUnackedFrames,
1 + static_cast<int>(target_playout_delay_ *
video_config.max_frame_rate /
base::TimeDelta::FromSeconds(1)))),
- rtcp_(cast_environment_,
- this,
- transport_sender_,
- NULL, // paced sender.
- NULL,
- video_config.rtcp_mode,
- base::TimeDelta::FromMilliseconds(video_config.rtcp_interval),
- video_config.ssrc,
- video_config.incoming_feedback_ssrc,
- video_config.rtcp_c_name,
- VIDEO_EVENT),
- rtp_timestamp_helper_(kVideoFrequency),
num_aggressive_rtcp_reports_sent_(0),
frames_in_encoder_(0),
last_sent_frame_id_(0),
@@ -76,13 +67,18 @@ VideoSender::VideoSender(
media::cast::CastTransportRtpConfig transport_config;
transport_config.ssrc = video_config.ssrc;
+ transport_config.feedback_ssrc = video_config.incoming_feedback_ssrc;
+ transport_config.c_name = video_config.rtcp_c_name;
transport_config.rtp_payload_type = video_config.rtp_payload_type;
transport_config.stored_frames = max_unacked_frames_;
transport_config.aes_key = video_config.aes_key;
transport_config.aes_iv_mask = video_config.aes_iv_mask;
- transport_sender_->InitializeVideo(transport_config);
- rtcp_.SetCastReceiverEventHistorySize(kReceiverRtcpEventHistorySize);
+ transport_sender->InitializeVideo(
+ transport_config,
+ base::Bind(&VideoSender::OnReceivedCastFeedback,
+ weak_factory_.GetWeakPtr()),
+ base::Bind(&VideoSender::OnReceivedRtt, weak_factory_.GetWeakPtr()));
memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_));
}
@@ -202,41 +198,20 @@ void VideoSender::SendEncodedVideoFrame(
transport_sender_->InsertCodedVideoFrame(*encoded_frame);
}
-void VideoSender::IncomingRtcpPacket(scoped_ptr<Packet> packet) {
- DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
- rtcp_.IncomingRtcpPacket(&packet->front(), packet->size());
-}
-
-void VideoSender::ScheduleNextRtcpReport() {
- DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
- base::TimeDelta time_to_next = rtcp_.TimeToSendNextRtcpReport() -
- cast_environment_->Clock()->NowTicks();
-
- time_to_next = std::max(
- time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
-
- cast_environment_->PostDelayedTask(
- CastEnvironment::MAIN,
- FROM_HERE,
- base::Bind(&VideoSender::SendRtcpReport,
- weak_factory_.GetWeakPtr(),
- true),
- time_to_next);
-}
-
-void VideoSender::SendRtcpReport(bool schedule_future_reports) {
+void VideoSender::ResendCheck() {
DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
- const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
- uint32 now_as_rtp_timestamp = 0;
- if (rtp_timestamp_helper_.GetCurrentTimeAsRtpTimestamp(
- now, &now_as_rtp_timestamp)) {
- rtcp_.SendRtcpFromRtpSender(now, now_as_rtp_timestamp);
- } else {
- // |rtp_timestamp_helper_| should have stored a mapping by this point.
- NOTREACHED();
+ DCHECK(!last_send_time_.is_null());
+ const base::TimeDelta time_since_last_send =
+ cast_environment_->Clock()->NowTicks() - last_send_time_;
+ if (time_since_last_send > target_playout_delay_) {
+ if (latest_acked_frame_id_ == last_sent_frame_id_) {
+ // Last frame acked, no point in doing anything
+ } else {
+ VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_;
+ ResendForKickstart();
+ }
}
- if (schedule_future_reports)
- ScheduleNextRtcpReport();
+ ScheduleNextResendCheck();
}
void VideoSender::ScheduleNextResendCheck() {
@@ -254,22 +229,6 @@ void VideoSender::ScheduleNextResendCheck() {
time_to_next);
}
-void VideoSender::ResendCheck() {
- DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
- DCHECK(!last_send_time_.is_null());
- const base::TimeDelta time_since_last_send =
- cast_environment_->Clock()->NowTicks() - last_send_time_;
- if (time_since_last_send > target_playout_delay_) {
- if (latest_acked_frame_id_ == last_sent_frame_id_) {
- // Last frame acked, no point in doing anything
- } else {
- VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_;
- ResendForKickstart();
- }
- }
- ScheduleNextResendCheck();
-}
-
void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
@@ -277,7 +236,12 @@ void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
base::TimeDelta avg_rtt;
base::TimeDelta min_rtt;
base::TimeDelta max_rtt;
- if (rtcp_.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt)) {
+ if (is_rtt_available()) {
+ rtt = rtt_;
+ avg_rtt = avg_rtt_;
+ min_rtt = min_rtt_;
+ max_rtt = max_rtt_;
+
congestion_control_.UpdateRtt(rtt);
// Don't use a RTT lower than our average.
@@ -300,11 +264,11 @@ void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
if (last_send_time_.is_null())
return; // Cannot get an ACK without having first sent a frame.
- if (cast_feedback.missing_frames_and_packets_.empty()) {
- video_encoder_->LatestFrameIdToReference(cast_feedback.ack_frame_id_);
+ if (cast_feedback.missing_frames_and_packets.empty()) {
+ video_encoder_->LatestFrameIdToReference(cast_feedback.ack_frame_id);
// We only count duplicate ACKs when we have sent newer frames.
- if (latest_acked_frame_id_ == cast_feedback.ack_frame_id_ &&
+ if (latest_acked_frame_id_ == cast_feedback.ack_frame_id &&
latest_acked_frame_id_ != last_sent_frame_id_) {
duplicate_ack_counter_++;
} else {
@@ -322,36 +286,36 @@ void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
// A NACK is also used to cancel pending re-transmissions.
transport_sender_->ResendPackets(
- false, cast_feedback.missing_frames_and_packets_, true, rtt);
+ false, cast_feedback.missing_frames_and_packets, true, rtt);
}
base::TimeTicks now = cast_environment_->Clock()->NowTicks();
- congestion_control_.AckFrame(cast_feedback.ack_frame_id_, now);
+ congestion_control_.AckFrame(cast_feedback.ack_frame_id, now);
RtpTimestamp rtp_timestamp =
- frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id_ & 0xff];
+ frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id & 0xff];
cast_environment_->Logging()->InsertFrameEvent(now,
FRAME_ACK_RECEIVED,
VIDEO_EVENT,
rtp_timestamp,
- cast_feedback.ack_frame_id_);
+ cast_feedback.ack_frame_id);
const bool is_acked_out_of_order =
- static_cast<int32>(cast_feedback.ack_frame_id_ -
+ static_cast<int32>(cast_feedback.ack_frame_id -
latest_acked_frame_id_) < 0;
VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "")
- << " for frame " << cast_feedback.ack_frame_id_;
+ << " for frame " << cast_feedback.ack_frame_id;
if (!is_acked_out_of_order) {
// Cancel resends of acked frames.
MissingFramesAndPacketsMap missing_frames_and_packets;
PacketIdSet missing;
- while (latest_acked_frame_id_ != cast_feedback.ack_frame_id_) {
+ while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) {
latest_acked_frame_id_++;
missing_frames_and_packets[latest_acked_frame_id_] = missing;
}
transport_sender_->ResendPackets(
false, missing_frames_and_packets, true, rtt);
- latest_acked_frame_id_ = cast_feedback.ack_frame_id_;
+ latest_acked_frame_id_ = cast_feedback.ack_frame_id;
}
}
@@ -384,16 +348,10 @@ void VideoSender::ResendForKickstart() {
std::make_pair(last_sent_frame_id_, missing));
last_send_time_ = cast_environment_->Clock()->NowTicks();
- base::TimeDelta rtt;
- base::TimeDelta avg_rtt;
- base::TimeDelta min_rtt;
- base::TimeDelta max_rtt;
- rtcp_.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt);
-
// Sending this extra packet is to kick-start the session. There is
// no need to optimize re-transmission for this case.
transport_sender_->ResendPackets(false, missing_frames_and_packets,
- false, rtt);
+ false, rtt_);
}
} // namespace cast
diff --git a/media/cast/sender/video_sender.h b/media/cast/sender/video_sender.h
index 6587572..09fac8d 100644
--- a/media/cast/sender/video_sender.h
+++ b/media/cast/sender/video_sender.h
@@ -13,11 +13,8 @@
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "media/cast/cast_config.h"
-#include "media/cast/cast_environment.h"
-#include "media/cast/logging/logging_defines.h"
-#include "media/cast/net/rtcp/rtcp.h"
#include "media/cast/sender/congestion_control.h"
-#include "media/cast/sender/rtp_timestamp_helper.h"
+#include "media/cast/sender/frame_sender.h"
namespace media {
@@ -26,7 +23,6 @@ class VideoFrame;
namespace cast {
class CastTransportSender;
-class LocalVideoEncoderCallback;
class VideoEncoder;
// Not thread safe. Only called from the main cast thread.
@@ -35,7 +31,7 @@ class VideoEncoder;
// RTCP packets.
// Additionally it posts a bunch of delayed tasks to the main thread for various
// timeouts.
-class VideoSender : public RtcpSenderFeedback,
+class VideoSender : public FrameSender,
public base::NonThreadSafe,
public base::SupportsWeakPtr<VideoSender> {
public:
@@ -60,19 +56,11 @@ class VideoSender : public RtcpSenderFeedback,
void InsertRawVideoFrame(const scoped_refptr<media::VideoFrame>& video_frame,
const base::TimeTicks& capture_time);
- // Only called from the main cast thread.
- void IncomingRtcpPacket(scoped_ptr<Packet> packet);
-
protected:
// Protected for testability.
- virtual void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback)
- OVERRIDE;
+ void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback);
private:
- // Schedule and execute periodic sending of RTCP report.
- void ScheduleNextRtcpReport();
- void SendRtcpReport(bool schedule_future_reports);
-
// Schedule and execute periodic checks for re-sending packets. If no
// acknowledgements have been received for "too long," VideoSender will
// speculatively re-send certain packets of an unacked frame to kick-start
@@ -92,8 +80,6 @@ class VideoSender : public RtcpSenderFeedback,
void SendEncodedVideoFrame(int requested_bitrate_before_encode,
scoped_ptr<EncodedFrame> encoded_frame);
- const scoped_refptr<CastEnvironment> cast_environment_;
-
// The total amount of time between a frame's capture/recording on the sender
// and its playback on the receiver (i.e., shown to a user). This is fixed as
// a value large enough to give the system sufficient time to encode,
@@ -102,13 +88,6 @@ class VideoSender : public RtcpSenderFeedback,
// etc.).
const base::TimeDelta target_playout_delay_;
- // Sends encoded frames over the configured transport (e.g., UDP). In
- // Chromium, this could be a proxy that first sends the frames from a renderer
- // process to the browser process over IPC, with the browser process being
- // responsible for "packetizing" the frames and pushing packets into the
- // network layer.
- CastTransportSender* const transport_sender_;
-
// Maximum number of outstanding frames before the encoding and sending of
// new frames shall halt.
const int max_unacked_frames_;
@@ -118,14 +97,6 @@ class VideoSender : public RtcpSenderFeedback,
// a hardware-based encoder.
scoped_ptr<VideoEncoder> video_encoder_;
- // Manages sending/receiving of RTCP packets, including sender/receiver
- // reports.
- Rtcp rtcp_;
-
- // Records lip-sync (i.e., mapping of RTP <--> NTP timestamps), and
- // extrapolates this mapping to any other point in time.
- RtpTimestampHelper rtp_timestamp_helper_;
-
// Counts how many RTCP reports are being "aggressively" sent (i.e., one per
// frame) at the start of the session. Once a threshold is reached, RTCP
// reports are instead sent at the configured interval + random drift.
diff --git a/media/cast/sender/video_sender_unittest.cc b/media/cast/sender/video_sender_unittest.cc
index bccc248..8ae3ca3 100644
--- a/media/cast/sender/video_sender_unittest.cc
+++ b/media/cast/sender/video_sender_unittest.cc
@@ -15,6 +15,7 @@
#include "media/cast/net/cast_transport_config.h"
#include "media/cast/net/cast_transport_sender_impl.h"
#include "media/cast/net/pacing/paced_sender.h"
+#include "media/cast/net/rtcp/rtcp_receiver.h"
#include "media/cast/sender/video_sender.h"
#include "media/cast/test/fake_single_thread_task_runner.h"
#include "media/cast/test/fake_video_encode_accelerator.h"
@@ -66,7 +67,7 @@ class TestPacketSender : public PacketSender {
callback_ = cb;
return false;
}
- if (Rtcp::IsRtcpPacket(&packet->data[0], packet->data.size())) {
+ if (RtcpReceiver::IsRtcpPacket(&packet->data[0], packet->data.size())) {
++number_of_rtcp_packets_;
} else {
// Check that at least one RTCP packet was sent before the first RTP
@@ -272,8 +273,8 @@ TEST_F(VideoSenderTest, RtcpTimer) {
EXPECT_LE(1, transport_.number_of_rtcp_packets());
// Build Cast msg and expect RTCP packet.
RtcpCastMessage cast_feedback(1);
- cast_feedback.media_ssrc_ = 2;
- cast_feedback.ack_frame_id_ = 0;
+ cast_feedback.media_ssrc = 2;
+ cast_feedback.ack_frame_id = 0;
video_sender_->OnReceivedCastFeedback(cast_feedback);
RunTasks(max_rtcp_timeout.InMilliseconds());
EXPECT_LE(1, transport_.number_of_rtcp_packets());
@@ -289,8 +290,8 @@ TEST_F(VideoSenderTest, ResendTimer) {
// ACK the key frame.
RtcpCastMessage cast_feedback(1);
- cast_feedback.media_ssrc_ = 2;
- cast_feedback.ack_frame_id_ = 0;
+ cast_feedback.media_ssrc = 2;
+ cast_feedback.ack_frame_id = 0;
video_sender_->OnReceivedCastFeedback(cast_feedback);
video_frame = GetNewVideoFrame();
@@ -324,7 +325,7 @@ TEST_F(VideoSenderTest, LogAckReceivedEvent) {
task_runner_->RunTasks();
RtcpCastMessage cast_feedback(1);
- cast_feedback.ack_frame_id_ = num_frames - 1;
+ cast_feedback.ack_frame_id = num_frames - 1;
video_sender_->OnReceivedCastFeedback(cast_feedback);
@@ -370,8 +371,8 @@ TEST_F(VideoSenderTest, StopSendingInTheAbsenceOfAck) {
// Start acking and make sure we're back to steady-state.
RtcpCastMessage cast_feedback(1);
- cast_feedback.media_ssrc_ = 2;
- cast_feedback.ack_frame_id_ = 0;
+ cast_feedback.media_ssrc = 2;
+ cast_feedback.ack_frame_id = 0;
video_sender_->OnReceivedCastFeedback(cast_feedback);
EXPECT_LE(
4,
@@ -391,8 +392,8 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmit) {
video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
RunTasks(33);
RtcpCastMessage cast_feedback(1);
- cast_feedback.media_ssrc_ = 2;
- cast_feedback.ack_frame_id_ = 0;
+ cast_feedback.media_ssrc = 2;
+ cast_feedback.ack_frame_id = 0;
// Send 3 more frames but don't ACK.
for (int i = 0; i < 3; ++i) {
@@ -405,11 +406,11 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmit) {
// Send duplicated ACKs and mix some invalid NACKs.
for (int i = 0; i < 10; ++i) {
RtcpCastMessage ack_feedback(1);
- ack_feedback.media_ssrc_ = 2;
- ack_feedback.ack_frame_id_ = 0;
+ ack_feedback.media_ssrc = 2;
+ ack_feedback.ack_frame_id = 0;
RtcpCastMessage nack_feedback(1);
- nack_feedback.media_ssrc_ = 2;
- nack_feedback.missing_frames_and_packets_[255] = PacketIdSet();
+ nack_feedback.media_ssrc = 2;
+ nack_feedback.missing_frames_and_packets[255] = PacketIdSet();
video_sender_->OnReceivedCastFeedback(ack_feedback);
video_sender_->OnReceivedCastFeedback(nack_feedback);
}
@@ -418,8 +419,8 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmit) {
// Re-transmit one packet because of duplicated ACKs.
for (int i = 0; i < 3; ++i) {
RtcpCastMessage ack_feedback(1);
- ack_feedback.media_ssrc_ = 2;
- ack_feedback.ack_frame_id_ = 0;
+ ack_feedback.media_ssrc = 2;
+ ack_feedback.ack_frame_id = 0;
video_sender_->OnReceivedCastFeedback(ack_feedback);
}
EXPECT_EQ(number_of_packets_sent + 1, transport_.number_of_rtp_packets());
@@ -431,8 +432,8 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) {
video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
RunTasks(33);
RtcpCastMessage cast_feedback(1);
- cast_feedback.media_ssrc_ = 2;
- cast_feedback.ack_frame_id_ = 0;
+ cast_feedback.media_ssrc = 2;
+ cast_feedback.ack_frame_id = 0;
// Send 2 more frames but don't ACK.
for (int i = 0; i < 2; ++i) {
@@ -453,11 +454,11 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) {
// Send duplicated ACKs and mix some invalid NACKs.
for (int i = 0; i < 10; ++i) {
RtcpCastMessage ack_feedback(1);
- ack_feedback.media_ssrc_ = 2;
- ack_feedback.ack_frame_id_ = 0;
+ ack_feedback.media_ssrc = 2;
+ ack_feedback.ack_frame_id = 0;
RtcpCastMessage nack_feedback(1);
- nack_feedback.media_ssrc_ = 2;
- nack_feedback.missing_frames_and_packets_[255] = PacketIdSet();
+ nack_feedback.media_ssrc = 2;
+ nack_feedback.missing_frames_and_packets[255] = PacketIdSet();
video_sender_->OnReceivedCastFeedback(ack_feedback);
video_sender_->OnReceivedCastFeedback(nack_feedback);
}
@@ -466,8 +467,8 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) {
// Re-transmit one packet because of duplicated ACKs.
for (int i = 0; i < 3; ++i) {
RtcpCastMessage ack_feedback(1);
- ack_feedback.media_ssrc_ = 2;
- ack_feedback.ack_frame_id_ = 0;
+ ack_feedback.media_ssrc = 2;
+ ack_feedback.ack_frame_id = 0;
video_sender_->OnReceivedCastFeedback(ack_feedback);
}
@@ -485,8 +486,8 @@ TEST_F(VideoSenderTest, AcksCancelRetransmits) {
// Frame should be in buffer, waiting. Now let's ack it.
RtcpCastMessage cast_feedback(1);
- cast_feedback.media_ssrc_ = 2;
- cast_feedback.ack_frame_id_ = 0;
+ cast_feedback.media_ssrc = 2;
+ cast_feedback.ack_frame_id = 0;
video_sender_->OnReceivedCastFeedback(cast_feedback);
transport_.SetPause(false);
@@ -508,11 +509,11 @@ TEST_F(VideoSenderTest, NAcksCancelRetransmits) {
// Frames should be in buffer, waiting. Now let's ack the first one and nack
// one packet in the second one.
RtcpCastMessage cast_feedback(1);
- cast_feedback.media_ssrc_ = 2;
- cast_feedback.ack_frame_id_ = 0;
+ cast_feedback.media_ssrc = 2;
+ cast_feedback.ack_frame_id = 0;
PacketIdSet missing_packets;
missing_packets.insert(0);
- cast_feedback.missing_frames_and_packets_[1] = missing_packets;
+ cast_feedback.missing_frames_and_packets[1] = missing_packets;
video_sender_->OnReceivedCastFeedback(cast_feedback);
transport_.SetPause(false);
diff --git a/media/cast/test/cast_benchmarks.cc b/media/cast/test/cast_benchmarks.cc
index a2483fa..57806b3 100644
--- a/media/cast/test/cast_benchmarks.cc
+++ b/media/cast/test/cast_benchmarks.cc
@@ -89,7 +89,8 @@ void VideoInitializationStatus(CastInitializationStatus status) {
EXPECT_EQ(STATUS_VIDEO_INITIALIZED, status);
}
-void IgnoreRawEvents(const std::vector<PacketEvent>& packet_events) {
+void IgnoreRawEvents(const std::vector<PacketEvent>& packet_events,
+ const std::vector<FrameEvent>& frame_events) {
}
} // namespace
@@ -108,18 +109,17 @@ class CastTransportSenderWrapper : public CastTransportSender {
}
virtual void InitializeAudio(
- const CastTransportRtpConfig& config) OVERRIDE {
- transport_->InitializeAudio(config);
+ const CastTransportRtpConfig& config,
+ const RtcpCastMessageCallback& cast_message_cb,
+ const RtcpRttCallback& rtt_cb) OVERRIDE {
+ transport_->InitializeAudio(config, cast_message_cb, rtt_cb);
}
virtual void InitializeVideo(
- const CastTransportRtpConfig& config) OVERRIDE {
- transport_->InitializeVideo(config);
- }
-
- virtual void SetPacketReceiver(
- const PacketReceiverCallback& packet_receiver) OVERRIDE {
- transport_->SetPacketReceiver(packet_receiver);
+ const CastTransportRtpConfig& config,
+ const RtcpCastMessageCallback& cast_message_cb,
+ const RtcpRttCallback& rtt_cb) OVERRIDE {
+ transport_->InitializeVideo(config, cast_message_cb, rtt_cb);
}
virtual void InsertCodedAudioFrame(
@@ -134,20 +134,13 @@ class CastTransportSenderWrapper : public CastTransportSender {
transport_->InsertCodedVideoFrame(video_frame);
}
- virtual void SendRtcpFromRtpSender(uint32 packet_type_flags,
- uint32 ntp_seconds,
- uint32 ntp_fraction,
- uint32 rtp_timestamp,
- const RtcpDlrrReportBlock& dlrr,
- uint32 sending_ssrc,
- const std::string& c_name) OVERRIDE {
- transport_->SendRtcpFromRtpSender(packet_type_flags,
- ntp_seconds,
- ntp_fraction,
- rtp_timestamp,
- dlrr,
- sending_ssrc,
- c_name);
+ virtual void SendSenderReport(
+ uint32 ssrc,
+ base::TimeTicks current_time,
+ uint32 current_time_as_rtp_timestamp) OVERRIDE {
+ transport_->SendSenderReport(ssrc,
+ current_time,
+ current_time_as_rtp_timestamp);
}
// Retransmission request.
@@ -160,6 +153,10 @@ class CastTransportSenderWrapper : public CastTransportSender {
is_audio, missing_packets, cancel_rtx_if_not_in_list, dedupe_window);
}
+ virtual PacketReceiverCallback PacketReceiverForTesting() OVERRIDE {
+ return transport_->PacketReceiverForTesting();
+ }
+
private:
scoped_ptr<CastTransportSender> transport_;
uint64* encoded_video_bytes_;
@@ -298,17 +295,18 @@ class RunOneBenchmark {
video_receiver_config_,
&receiver_to_sender_);
net::IPEndPoint dummy_endpoint;
- transport_sender_.Init(new CastTransportSenderImpl(
- NULL,
- testing_clock_sender_,
- dummy_endpoint,
- base::Bind(&UpdateCastTransportStatus),
- base::Bind(&IgnoreRawEvents),
- base::TimeDelta::FromSeconds(1),
- task_runner_sender_,
- &sender_to_receiver_),
- &video_bytes_encoded_,
- &audio_bytes_encoded_);
+ transport_sender_.Init(
+ new CastTransportSenderImpl(
+ NULL,
+ testing_clock_sender_,
+ dummy_endpoint,
+ base::Bind(&UpdateCastTransportStatus),
+ base::Bind(&IgnoreRawEvents),
+ base::TimeDelta::FromSeconds(1),
+ task_runner_sender_,
+ &sender_to_receiver_),
+ &video_bytes_encoded_,
+ &audio_bytes_encoded_);
cast_sender_ =
CastSender::Create(cast_environment_sender_, &transport_sender_);
@@ -322,7 +320,8 @@ class RunOneBenchmark {
CreateDefaultVideoEncodeMemoryCallback());
receiver_to_sender_.Initialize(
- CreateSimplePipe(p).Pass(), cast_sender_->packet_receiver(),
+ CreateSimplePipe(p).Pass(),
+ transport_sender_.PacketReceiverForTesting(),
task_runner_, &testing_clock_);
sender_to_receiver_.Initialize(
CreateSimplePipe(p).Pass(), cast_receiver_->packet_receiver(),
diff --git a/media/cast/test/end2end_unittest.cc b/media/cast/test/end2end_unittest.cc
index a1d4a3a..bfd9fab 100644
--- a/media/cast/test/end2end_unittest.cc
+++ b/media/cast/test/end2end_unittest.cc
@@ -588,7 +588,7 @@ class End2EndTest : public ::testing::Test {
dummy_endpoint,
base::Bind(&UpdateCastTransportStatus),
base::Bind(&End2EndTest::LogRawEvents, base::Unretained(this)),
- base::TimeDelta::FromSeconds(1),
+ base::TimeDelta::FromMilliseconds(1),
task_runner_sender_,
&sender_to_receiver_));
@@ -603,9 +603,10 @@ class End2EndTest : public ::testing::Test {
CreateDefaultVideoEncodeAcceleratorCallback(),
CreateDefaultVideoEncodeMemoryCallback());
- receiver_to_sender_.SetPacketReceiver(cast_sender_->packet_receiver(),
- task_runner_,
- &testing_clock_);
+ receiver_to_sender_.SetPacketReceiver(
+ transport_sender_->PacketReceiverForTesting(),
+ task_runner_,
+ &testing_clock_);
sender_to_receiver_.SetPacketReceiver(cast_receiver_->packet_receiver(),
task_runner_,
&testing_clock_);
@@ -715,8 +716,8 @@ class End2EndTest : public ::testing::Test {
base::Unretained(this)));
}
- void LogRawEvents(const std::vector<PacketEvent>& packet_events) {
- EXPECT_FALSE(packet_events.empty());
+ void LogRawEvents(const std::vector<PacketEvent>& packet_events,
+ const std::vector<FrameEvent>& frame_events) {
for (std::vector<media::cast::PacketEvent>::const_iterator it =
packet_events.begin();
it != packet_events.end();
@@ -730,6 +731,16 @@ class End2EndTest : public ::testing::Test {
it->max_packet_id,
it->size);
}
+ for (std::vector<media::cast::FrameEvent>::const_iterator it =
+ frame_events.begin();
+ it != frame_events.end();
+ ++it) {
+ cast_environment_sender_->Logging()->InsertFrameEvent(it->timestamp,
+ it->type,
+ it->media_type,
+ it->rtp_timestamp,
+ it->frame_id);
+ }
}
FrameReceiverConfig audio_receiver_config_;
@@ -1254,14 +1265,14 @@ TEST_F(End2EndTest, VideoLogging) {
total_event_count_for_packet += map_it->second.counter[i];
}
- int expected_event_count_for_packet = 0;
EXPECT_GT(map_it->second.counter[PACKET_RECEIVED], 0);
- expected_event_count_for_packet +=
- map_it->second.counter[PACKET_RECEIVED];
+ int packets_received = map_it->second.counter[PACKET_RECEIVED];
+ int packets_sent = map_it->second.counter[PACKET_SENT_TO_NETWORK];
+ EXPECT_EQ(packets_sent, packets_received);
// Verify that there were no other events logged with respect to this
- // packet. (i.e. Total event count = expected event count)
- EXPECT_EQ(total_event_count_for_packet, expected_event_count_for_packet);
+ // packet. (i.e. Total event count = packets sent + packets received)
+ EXPECT_EQ(packets_received + packets_sent, total_event_count_for_packet);
}
}
diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc
index 6f9074f..0ce23c8 100644
--- a/media/cast/test/sender.cc
+++ b/media/cast/test/sender.cc
@@ -123,7 +123,8 @@ void UpdateCastTransportStatus(
void LogRawEvents(
const scoped_refptr<media::cast::CastEnvironment>& cast_environment,
- const std::vector<media::cast::PacketEvent>& packet_events) {
+ const std::vector<media::cast::PacketEvent>& packet_events,
+ const std::vector<media::cast::FrameEvent>& frame_events) {
VLOG(1) << "Got packet events from transport, size: " << packet_events.size();
for (std::vector<media::cast::PacketEvent>::const_iterator it =
packet_events.begin();
@@ -138,6 +139,17 @@ void LogRawEvents(
it->max_packet_id,
it->size);
}
+ VLOG(1) << "Got frame events from transport, size: " << frame_events.size();
+ for (std::vector<media::cast::FrameEvent>::const_iterator it =
+ frame_events.begin();
+ it != frame_events.end();
+ ++it) {
+ cast_environment->Logging()->InsertFrameEvent(it->timestamp,
+ it->type,
+ it->media_type,
+ it->rtp_timestamp,
+ it->frame_id);
+ }
}
void InitializationResult(media::cast::CastInitializationStatus result) {
@@ -327,7 +339,6 @@ int main(int argc, char** argv) {
media::cast::CreateDefaultVideoEncodeAcceleratorCallback(),
media::cast::CreateDefaultVideoEncodeMemoryCallback());
cast_sender->InitializeAudio(audio_config, base::Bind(&InitializationResult));
- transport_sender->SetPacketReceiver(cast_sender->packet_receiver());
// Set up event subscribers.
scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber;
diff --git a/media/cast/test/simulator.cc b/media/cast/test/simulator.cc
index 43b3a02..27812c3 100644
--- a/media/cast/test/simulator.cc
+++ b/media/cast/test/simulator.cc
@@ -85,7 +85,8 @@ void VideoInitializationStatus(CastInitializationStatus status) {
}
void LogTransportEvents(const scoped_refptr<CastEnvironment>& env,
- const std::vector<PacketEvent>& packet_events) {
+ const std::vector<PacketEvent>& packet_events,
+ const std::vector<FrameEvent>& frame_events) {
for (std::vector<media::cast::PacketEvent>::const_iterator it =
packet_events.begin();
it != packet_events.end();
@@ -99,6 +100,16 @@ void LogTransportEvents(const scoped_refptr<CastEnvironment>& env,
it->max_packet_id,
it->size);
}
+ for (std::vector<media::cast::FrameEvent>::const_iterator it =
+ frame_events.begin();
+ it != frame_events.end();
+ ++it) {
+ env->Logging()->InsertFrameEvent(it->timestamp,
+ it->type,
+ it->media_type,
+ it->rtp_timestamp,
+ it->frame_id);
+ }
}
void GotVideoFrame(
@@ -265,8 +276,8 @@ void RunSimulation(const base::FilePath& source_path,
// Connect sender to receiver. This initializes the pipe.
receiver_to_sender.Initialize(
- ipp.NewBuffer(128 * 1024), cast_sender->packet_receiver(), task_runner,
- &testing_clock);
+ ipp.NewBuffer(128 * 1024), transport_sender->PacketReceiverForTesting(),
+ task_runner, &testing_clock);
sender_to_receiver.Initialize(
ipp.NewBuffer(128 * 1024), cast_receiver->packet_receiver(), task_runner,
&testing_clock);