diff options
author | xjz <xjz@chromium.org> | 2016-02-23 16:20:17 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-24 00:21:33 +0000 |
commit | 74f752173cf8084d9f96073eaa88236f0ac54b79 (patch) | |
tree | 2efcdd1178f748b40113e09505195cb5a8cca68b | |
parent | bb910a25c0cdb25494d2b7c1ad62cdb0dc3fe018 (diff) | |
download | chromium_src-74f752173cf8084d9f96073eaa88236f0ac54b79.zip chromium_src-74f752173cf8084d9f96073eaa88236f0ac54b79.tar.gz chromium_src-74f752173cf8084d9f96073eaa88236f0ac54b79.tar.bz2 |
Simplify interface for media/cast: CastTransportSenderImpl
Defined an interface to reduce the 11-arg constructor down to 4 args.
BUG=557477
Review URL: https://codereview.chromium.org/1515023002
Cr-Commit-Position: refs/heads/master@{#377148}
24 files changed, 782 insertions, 606 deletions
diff --git a/chrome/browser/media/cast_transport_host_filter.cc b/chrome/browser/media/cast_transport_host_filter.cc index ee31f41..acdcd05 100644 --- a/chrome/browser/media/cast_transport_host_filter.cc +++ b/chrome/browser/media/cast_transport_host_filter.cc @@ -16,8 +16,47 @@ namespace { // How often to send raw events. const int kSendRawEventsIntervalSecs = 1; +class TransportClient : public media::cast::CastTransportSender::Client { + public: + TransportClient(int32_t channel_id, + cast::CastTransportHostFilter* cast_transport_host_filter) + : channel_id_(channel_id), + cast_transport_host_filter_(cast_transport_host_filter) {} + + void OnStatusChanged(media::cast::CastTransportStatus status) final; + void OnLoggingEventsReceived( + scoped_ptr<std::vector<media::cast::FrameEvent>> frame_events, + scoped_ptr<std::vector<media::cast::PacketEvent>> packet_events) final; + void ProcessRtpPacket(scoped_ptr<media::cast::Packet> packet) final; + + private: + const int32_t channel_id_; + cast::CastTransportHostFilter* const cast_transport_host_filter_; + + DISALLOW_COPY_AND_ASSIGN(TransportClient); +}; + +void TransportClient::OnStatusChanged(media::cast::CastTransportStatus status) { + cast_transport_host_filter_->Send( + new CastMsg_NotifyStatusChange(channel_id_, status)); } +void TransportClient::OnLoggingEventsReceived( + scoped_ptr<std::vector<media::cast::FrameEvent>> frame_events, + scoped_ptr<std::vector<media::cast::PacketEvent>> packet_events) { + if (frame_events->empty() && packet_events->empty()) + return; + cast_transport_host_filter_->Send( + new CastMsg_RawEvents(channel_id_, *packet_events, *frame_events)); +} + +void TransportClient::ProcessRtpPacket(scoped_ptr<media::cast::Packet> packet) { + cast_transport_host_filter_->Send( + new CastMsg_ReceivedPacket(channel_id_, *packet)); +} + +} // namespace + namespace cast { CastTransportHostFilter::CastTransportHostFilter() @@ -26,6 +65,12 @@ CastTransportHostFilter::CastTransportHostFilter() CastTransportHostFilter::~CastTransportHostFilter() {} +void CastTransportHostFilter::OnStatusChanged( + int32_t channel_id, + media::cast::CastTransportStatus status) { + Send(new CastMsg_NotifyStatusChange(channel_id, status)); +} + bool CastTransportHostFilter::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(CastTransportHostFilter, message) @@ -49,27 +94,6 @@ bool CastTransportHostFilter::OnMessageReceived(const IPC::Message& message) { return handled; } -void CastTransportHostFilter::ReceivedPacket( - int32_t channel_id, - scoped_ptr<media::cast::Packet> packet) { - Send(new CastMsg_ReceivedPacket(channel_id, *packet)); -} - -void CastTransportHostFilter::NotifyStatusChange( - int32_t channel_id, - media::cast::CastTransportStatus status) { - Send(new CastMsg_NotifyStatusChange(channel_id, status)); -} - -void CastTransportHostFilter::SendRawEvents( - int32_t channel_id, - scoped_ptr<std::vector<media::cast::FrameEvent>> frame_events, - scoped_ptr<std::vector<media::cast::PacketEvent>> packet_events) { - if (frame_events->empty() && packet_events->empty()) - return; - Send(new CastMsg_RawEvents(channel_id, *packet_events, *frame_events)); -} - void CastTransportHostFilter::SendRtt(int32_t channel_id, uint32_t ssrc, base::TimeDelta rtt) { @@ -100,24 +124,19 @@ void CastTransportHostFilter::OnNew(int32_t channel_id, id_map_.Remove(channel_id); } + scoped_ptr<media::cast::UdpTransport> udp_transport( + new media::cast::UdpTransport( + g_browser_process->net_log(), base::ThreadTaskRunnerHandle::Get(), + local_end_point, remote_end_point, + base::Bind(&CastTransportHostFilter::OnStatusChanged, + weak_factory_.GetWeakPtr(), channel_id))); + udp_transport->SetUdpOptions(options); scoped_ptr<media::cast::CastTransportSender> sender = media::cast::CastTransportSender::Create( - g_browser_process->net_log(), - &clock_, - local_end_point, - remote_end_point, - make_scoped_ptr(options.DeepCopy()), - base::Bind(&CastTransportHostFilter::NotifyStatusChange, - weak_factory_.GetWeakPtr(), - channel_id), - base::Bind(&CastTransportHostFilter::SendRawEvents, - weak_factory_.GetWeakPtr(), - channel_id), - base::TimeDelta::FromSeconds(kSendRawEventsIntervalSecs), - base::Bind(&CastTransportHostFilter::ReceivedPacket, - weak_factory_.GetWeakPtr(), - channel_id), - base::ThreadTaskRunnerHandle::Get()); + &clock_, base::TimeDelta::FromSeconds(kSendRawEventsIntervalSecs), + make_scoped_ptr(new TransportClient(channel_id, this)), + std::move(udp_transport), base::ThreadTaskRunnerHandle::Get()); + sender->SetOptions(options); id_map_.AddWithID(sender.release(), channel_id); } @@ -264,5 +283,4 @@ void CastTransportHostFilter::OnSendRtcpFromRtpReceiver( } } - } // namespace cast diff --git a/chrome/browser/media/cast_transport_host_filter.h b/chrome/browser/media/cast_transport_host_filter.h index 127e7d1..2331e97 100644 --- a/chrome/browser/media/cast_transport_host_filter.h +++ b/chrome/browser/media/cast_transport_host_filter.h @@ -16,6 +16,7 @@ #include "media/cast/cast_sender.h" #include "media/cast/logging/logging_defines.h" #include "media/cast/net/cast_transport_sender.h" +#include "media/cast/net/udp_transport.h" namespace content { class PowerSaveBlocker; @@ -30,18 +31,13 @@ class CastTransportHostFilter : public content::BrowserMessageFilter { private: ~CastTransportHostFilter() override; - void NotifyStatusChange(int32_t channel_id, - media::cast::CastTransportStatus result); - void SendRawEvents( - int32_t channel_id, - scoped_ptr<std::vector<media::cast::FrameEvent>> frame_events, - scoped_ptr<std::vector<media::cast::PacketEvent>> packet_events); + // Status callback to create UdpTransport. + void OnStatusChanged(int32_t channel_id, + media::cast::CastTransportStatus status); void SendRtt(int32_t channel_id, uint32_t ssrc, base::TimeDelta rtt); void SendCastMessage(int32_t channel_id, uint32_t ssrc, const media::cast::RtcpCastMessage& cast_message); - void ReceivedPacket(int32_t channel_id, - scoped_ptr<media::cast::Packet> packet); // BrowserMessageFilter implementation. bool OnMessageReceived(const IPC::Message& message) override; diff --git a/chrome/renderer/media/cast_transport_sender_ipc.h b/chrome/renderer/media/cast_transport_sender_ipc.h index af66c03..2903d31 100644 --- a/chrome/renderer/media/cast_transport_sender_ipc.h +++ b/chrome/renderer/media/cast_transport_sender_ipc.h @@ -62,6 +62,8 @@ class CastTransportSenderIPC const media::cast::RtpReceiverStatistics* rtp_receiver_statistics) override; + void SetOptions(const base::DictionaryValue& options) final {} + void OnNotifyStatusChange( media::cast::CastTransportStatus status); void OnRawEvents(const std::vector<media::cast::PacketEvent>& packet_events, diff --git a/media/cast/net/cast_transport_config.h b/media/cast/net/cast_transport_config.h index 82823ad..dc63bee 100644 --- a/media/cast/net/cast_transport_config.h +++ b/media/cast/net/cast_transport_config.h @@ -126,6 +126,8 @@ typedef base::Callback<void(scoped_ptr<Packet> packet)> PacketReceiverCallback; typedef base::Callback<bool(scoped_ptr<Packet> packet)> PacketReceiverCallbackWithStatus; +// TODO(xjz): Rename PacketSender as it also deals with receiving packets. +// http://crbug.com/589157. class PacketSender { public: // Send a packet to the network. Returns false if the network is blocked @@ -138,6 +140,13 @@ class PacketSender { // Returns the number of bytes ever sent. virtual int64_t GetBytesSent() = 0; + // Start receiving packets. Pakets are submitted to |packet_receiver|. + virtual void StartReceiving( + const PacketReceiverCallbackWithStatus& packet_receiver) = 0; + + // Stop receiving packets. + virtual void StopReceiving() = 0; + virtual ~PacketSender() {} }; diff --git a/media/cast/net/cast_transport_sender.h b/media/cast/net/cast_transport_sender.h index 0ff76e1..3272f74 100644 --- a/media/cast/net/cast_transport_sender.h +++ b/media/cast/net/cast_transport_sender.h @@ -25,6 +25,7 @@ #include "base/single_thread_task_runner.h" #include "base/threading/non_thread_safe.h" #include "base/time/tick_clock.h" +#include "base/values.h" #include "media/cast/logging/logging_defines.h" #include "media/cast/net/cast_transport_config.h" #include "media/cast/net/cast_transport_defines.h" @@ -42,6 +43,7 @@ class NetLog; namespace media { namespace cast { + struct RtpReceiverStatistics; struct RtcpTimeData; @@ -54,19 +56,36 @@ typedef base::Callback<void(scoped_ptr<std::vector<FrameEvent>>, scoped_ptr<std::vector<PacketEvent>>)> BulkRawEventsCallback; +// TODO(xjz): Rename CastTransportSender as it also deals with receiving +// packets. http://crbug.com/589157. // The application should only trigger this class from the transport thread. class CastTransportSender : public base::NonThreadSafe { public: + // Interface used for receiving status updates, raw events, and RTP packets + // from CastTransportSender. + class Client { + public: + virtual ~Client(){}; + + // Audio and Video transport status change is reported on this callback. + virtual void OnStatusChanged(CastTransportStatus status) = 0; + + // Raw events will be invoked on this callback periodically, according to + // the configured logging flush interval passed to + // CastTransportSender::Create(). + virtual void OnLoggingEventsReceived( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) = 0; + + // Called to pass RTP packets to the Client. + virtual void ProcessRtpPacket(scoped_ptr<Packet> packet) = 0; + }; + static scoped_ptr<CastTransportSender> Create( - net::NetLog* net_log, - base::TickClock* clock, - const net::IPEndPoint& local_end_point, - const net::IPEndPoint& remote_end_point, - scoped_ptr<base::DictionaryValue> options, - const CastTransportStatusCallback& status_callback, - const BulkRawEventsCallback& raw_events_callback, - base::TimeDelta raw_events_callback_interval, - const PacketReceiverCallback& packet_callback, + base::TickClock* clock, // Owned by the caller. + base::TimeDelta logging_flush_interval, + scoped_ptr<Client> client, + scoped_ptr<PacketSender> transport, const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner); virtual ~CastTransportSender() {} @@ -122,6 +141,9 @@ class CastTransportSender : public base::NonThreadSafe { base::TimeDelta target_delay, const ReceiverRtcpEventSubscriber::RtcpEvents* rtcp_events, const RtpReceiverStatistics* rtp_receiver_statistics) = 0; + + // Set options for the PacedSender and Wifi. + virtual void SetOptions(const base::DictionaryValue& options) = 0; }; } // namespace cast diff --git a/media/cast/net/cast_transport_sender_impl.cc b/media/cast/net/cast_transport_sender_impl.cc index c1b700df..2962967 100644 --- a/media/cast/net/cast_transport_sender_impl.cc +++ b/media/cast/net/cast_transport_sender_impl.cc @@ -10,28 +10,22 @@ #include <utility> #include "base/single_thread_task_runner.h" -#include "base/values.h" #include "build/build_config.h" #include "media/cast/net/cast_transport_defines.h" #include "media/cast/net/rtcp/receiver_rtcp_session.h" #include "media/cast/net/rtcp/sender_rtcp_session.h" -#include "media/cast/net/udp_transport.h" #include "net/base/net_errors.h" -#include "net/base/network_interfaces.h" namespace media { namespace cast { namespace { -// See header file for what these mean. -const char kOptionDscp[] = "DSCP"; -#if defined(OS_WIN) -const char kOptionDisableNonBlockingIO[] = "disable_non_blocking_io"; -#endif -const char kOptionPacerTargetBurstSize[] = "pacer_target_burst_size"; +// Options for PaceSender. const char kOptionPacerMaxBurstSize[] = "pacer_max_burst_size"; -const char kOptionSendBufferMinSize[] = "send_buffer_min_size"; +const char kOptionPacerTargetBurstSize[] = "pacer_target_burst_size"; + +// Wifi options. const char kOptionWifiDisableScan[] = "disable_wifi_scan"; const char kOptionWifiMediaStreamingMode[] = "media_streaming_mode"; @@ -46,35 +40,17 @@ int LookupOptionWithDefault(const base::DictionaryValue& options, } } -int32_t GetTransportSendBufferSize(const base::DictionaryValue& options) { - // Socket send buffer size needs to be at least greater than one burst - // size. - int32_t max_burst_size = - LookupOptionWithDefault(options, kOptionPacerMaxBurstSize, - kMaxBurstSize) * - kMaxIpPacketSize; - int32_t min_send_buffer_size = - LookupOptionWithDefault(options, kOptionSendBufferMinSize, 0); - return std::max(max_burst_size, min_send_buffer_size); -} - } // namespace scoped_ptr<CastTransportSender> CastTransportSender::Create( - net::NetLog* net_log, - base::TickClock* clock, - const net::IPEndPoint& local_end_point, - const net::IPEndPoint& remote_end_point, - scoped_ptr<base::DictionaryValue> options, - const CastTransportStatusCallback& status_callback, - const BulkRawEventsCallback& raw_events_callback, - base::TimeDelta raw_events_callback_interval, - const PacketReceiverCallback& packet_callback, + base::TickClock* clock, // Owned by the caller. + base::TimeDelta logging_flush_interval, + scoped_ptr<Client> client, + scoped_ptr<PacketSender> transport, const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) { return scoped_ptr<CastTransportSender>(new CastTransportSenderImpl( - net_log, clock, local_end_point, remote_end_point, std::move(options), - status_callback, raw_events_callback, raw_events_callback_interval, - transport_task_runner.get(), packet_callback, NULL)); + clock, logging_flush_interval, std::move(client), std::move(transport), + transport_task_runner.get())); } PacketReceiverCallback CastTransportSender::PacketReceiverForTesting() { @@ -82,83 +58,41 @@ PacketReceiverCallback CastTransportSender::PacketReceiverForTesting() { } CastTransportSenderImpl::CastTransportSenderImpl( - net::NetLog* net_log, base::TickClock* clock, - const net::IPEndPoint& local_end_point, - const net::IPEndPoint& remote_end_point, - scoped_ptr<base::DictionaryValue> options, - const CastTransportStatusCallback& status_callback, - const BulkRawEventsCallback& raw_events_callback, - base::TimeDelta raw_events_callback_interval, - const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, - const PacketReceiverCallback& packet_callback, - PacketSender* external_transport) + base::TimeDelta logging_flush_interval, + scoped_ptr<Client> client, + scoped_ptr<PacketSender> transport, + const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) : clock_(clock), - status_callback_(status_callback), + logging_flush_interval_(logging_flush_interval), + transport_client_(std::move(client)), + transport_(std::move(transport)), transport_task_runner_(transport_task_runner), - transport_(external_transport - ? nullptr - : new UdpTransport(net_log, - transport_task_runner, - local_end_point, - remote_end_point, - GetTransportSendBufferSize(*options), - status_callback)), - pacer_(LookupOptionWithDefault(*options, - kOptionPacerTargetBurstSize, - kTargetBurstSize), - LookupOptionWithDefault(*options, - kOptionPacerMaxBurstSize, - kMaxBurstSize), + pacer_(kTargetBurstSize, + kMaxBurstSize, clock, - raw_events_callback.is_null() ? nullptr : &recent_packet_events_, - external_transport ? external_transport : transport_.get(), + logging_flush_interval > base::TimeDelta() ? &recent_packet_events_ + : nullptr, + transport_.get(), transport_task_runner), - raw_events_callback_(raw_events_callback), - raw_events_callback_interval_(raw_events_callback_interval), last_byte_acked_for_audio_(0), - packet_callback_(packet_callback), weak_factory_(this) { - DCHECK(clock_); - if (!raw_events_callback_.is_null()) { - DCHECK(raw_events_callback_interval > base::TimeDelta()); - transport_task_runner->PostDelayedTask( - FROM_HERE, - base::Bind(&CastTransportSenderImpl::SendRawEvents, - weak_factory_.GetWeakPtr()), - raw_events_callback_interval); - } - if (transport_) { - if (options->HasKey(kOptionDscp)) { - // The default DSCP value for cast is AF41. Which gives it a higher - // priority over other traffic. - transport_->SetDscp(net::DSCP_AF41); - } -#if defined(OS_WIN) - if (!options->HasKey(kOptionDisableNonBlockingIO)) { - transport_->UseNonBlockingIO(); - } -#endif - transport_->StartReceiving( - base::Bind(&CastTransportSenderImpl::OnReceivedPacket, - base::Unretained(this))); - int wifi_options = 0; - if (options->HasKey(kOptionWifiDisableScan)) { - wifi_options |= net::WIFI_OPTIONS_DISABLE_SCAN; - } - if (options->HasKey(kOptionWifiMediaStreamingMode)) { - wifi_options |= net::WIFI_OPTIONS_MEDIA_STREAMING_MODE; - } - if (wifi_options) { - wifi_options_autoreset_ = net::SetWifiOptions(wifi_options); - } + DCHECK(clock); + DCHECK(transport_client_); + DCHECK(transport_); + DCHECK(transport_task_runner_); + if (logging_flush_interval_ > base::TimeDelta()) { + transport_task_runner_->PostDelayedTask( + FROM_HERE, base::Bind(&CastTransportSenderImpl::SendRawEvents, + weak_factory_.GetWeakPtr()), + logging_flush_interval_); } + transport_->StartReceiving(base::Bind( + &CastTransportSenderImpl::OnReceivedPacket, base::Unretained(this))); } CastTransportSenderImpl::~CastTransportSenderImpl() { - if (transport_) { - transport_->StopReceiving(); - } + transport_->StopReceiving(); } void CastTransportSenderImpl::InitializeAudio( @@ -168,7 +102,7 @@ void CastTransportSenderImpl::InitializeAudio( 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); + transport_client_->OnStatusChanged(TRANSPORT_AUDIO_UNINITIALIZED); return; } @@ -177,10 +111,10 @@ void CastTransportSenderImpl::InitializeAudio( // Audio packets have a higher priority. pacer_.RegisterAudioSsrc(config.ssrc); pacer_.RegisterPrioritySsrc(config.ssrc); - status_callback_.Run(TRANSPORT_AUDIO_INITIALIZED); + transport_client_->OnStatusChanged(TRANSPORT_AUDIO_INITIALIZED); } else { audio_sender_.reset(); - status_callback_.Run(TRANSPORT_AUDIO_UNINITIALIZED); + transport_client_->OnStatusChanged(TRANSPORT_AUDIO_UNINITIALIZED); return; } @@ -192,7 +126,7 @@ void CastTransportSenderImpl::InitializeAudio( clock_, &pacer_, config.ssrc, config.feedback_ssrc)); pacer_.RegisterAudioSsrc(config.ssrc); AddValidSsrc(config.feedback_ssrc); - status_callback_.Run(TRANSPORT_AUDIO_INITIALIZED); + transport_client_->OnStatusChanged(TRANSPORT_AUDIO_INITIALIZED); } void CastTransportSenderImpl::InitializeVideo( @@ -202,14 +136,14 @@ void CastTransportSenderImpl::InitializeVideo( 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); + transport_client_->OnStatusChanged(TRANSPORT_VIDEO_UNINITIALIZED); return; } video_sender_.reset(new RtpSender(transport_task_runner_, &pacer_)); if (!video_sender_->Initialize(config)) { video_sender_.reset(); - status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED); + transport_client_->OnStatusChanged(TRANSPORT_VIDEO_UNINITIALIZED); return; } @@ -221,7 +155,7 @@ void CastTransportSenderImpl::InitializeVideo( clock_, &pacer_, config.ssrc, config.feedback_ssrc)); pacer_.RegisterVideoSsrc(config.ssrc); AddValidSsrc(config.feedback_ssrc); - status_callback_.Run(TRANSPORT_VIDEO_INITIALIZED); + transport_client_->OnStatusChanged(TRANSPORT_VIDEO_INITIALIZED); } namespace { @@ -327,7 +261,7 @@ PacketReceiverCallback CastTransportSenderImpl::PacketReceiverForTesting() { } void CastTransportSenderImpl::SendRawEvents() { - DCHECK(!raw_events_callback_.is_null()); + DCHECK(logging_flush_interval_ > base::TimeDelta()); if (!recent_frame_events_.empty() || !recent_packet_events_.empty()) { scoped_ptr<std::vector<FrameEvent>> frame_events( @@ -336,14 +270,14 @@ void CastTransportSenderImpl::SendRawEvents() { scoped_ptr<std::vector<PacketEvent>> packet_events( new std::vector<PacketEvent>()); packet_events->swap(recent_packet_events_); - raw_events_callback_.Run(std::move(frame_events), std::move(packet_events)); + transport_client_->OnLoggingEventsReceived(std::move(frame_events), + std::move(packet_events)); } transport_task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&CastTransportSenderImpl::SendRawEvents, - weak_factory_.GetWeakPtr()), - raw_events_callback_interval_); + FROM_HERE, base::Bind(&CastTransportSenderImpl::SendRawEvents, + weak_factory_.GetWeakPtr()), + logging_flush_interval_); } bool CastTransportSenderImpl::OnReceivedPacket(scoped_ptr<Packet> packet) { @@ -369,18 +303,14 @@ bool CastTransportSenderImpl::OnReceivedPacket(scoped_ptr<Packet> packet) { video_rtcp_session_->IncomingRtcpPacket(data, length)) { return true; } - if (packet_callback_.is_null()) { - VLOG(1) << "Stale packet received."; - return false; - } - packet_callback_.Run(std::move(packet)); + transport_client_->ProcessRtpPacket(std::move(packet)); return true; } void CastTransportSenderImpl::OnReceivedLogMessage( EventMediaType media_type, const RtcpReceiverLogMessage& log) { - if (raw_events_callback_.is_null()) + if (logging_flush_interval_ <= base::TimeDelta()) return; // Add received log messages into our log system. @@ -460,6 +390,29 @@ void CastTransportSenderImpl::AddValidSsrc(uint32_t ssrc) { valid_ssrcs_.insert(ssrc); } +void CastTransportSenderImpl::SetOptions(const base::DictionaryValue& options) { + // Set PacedSender options. + int burst_size = LookupOptionWithDefault(options, kOptionPacerTargetBurstSize, + media::cast::kTargetBurstSize); + if (burst_size != media::cast::kTargetBurstSize) + pacer_.SetTargetBurstSize(burst_size); + burst_size = LookupOptionWithDefault(options, kOptionPacerMaxBurstSize, + media::cast::kMaxBurstSize); + if (burst_size != media::cast::kMaxBurstSize) + pacer_.SetMaxBurstSize(burst_size); + + // Set Wifi options. + int wifi_options = 0; + if (options.HasKey(kOptionWifiDisableScan)) { + wifi_options |= net::WIFI_OPTIONS_DISABLE_SCAN; + } + if (options.HasKey(kOptionWifiMediaStreamingMode)) { + wifi_options |= net::WIFI_OPTIONS_MEDIA_STREAMING_MODE; + } + if (wifi_options) + wifi_options_autoreset_ = net::SetWifiOptions(wifi_options); +} + // TODO(isheriff): This interface needs clean up. // https://crbug.com/569259 void CastTransportSenderImpl::SendRtcpFromRtpReceiver( diff --git a/media/cast/net/cast_transport_sender_impl.h b/media/cast/net/cast_transport_sender_impl.h index 53f8694..18b2db1 100644 --- a/media/cast/net/cast_transport_sender_impl.h +++ b/media/cast/net/cast_transport_sender_impl.h @@ -54,44 +54,12 @@ class UdpTransport; class CastTransportSenderImpl : public CastTransportSender { public: - // |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. - // |raw_events_callback_interval|: This can be |base::TimeDelta()| if - // |raw_events_callback| is a null callback. - // |options| contains optional settings for the transport, possible - // keys are: - // "DSCP" (value ignored) - // - Turns DSCP on (higher IP Precedence and Type of Service). - // "disable_non_blocking_io" (value ignored) - // - Windows only. Turns off non-blocking IO for the socket. - // Note: Non-blocking IO is, by default, enabled on all platforms. - // "pacer_target_burst_size": int - // - Specifies how many packets to send per 10 ms ideally. - // "pacer_max_burst_size": int - // - Specifies how many pakcets to send per 10 ms, maximum. - // "send_buffer_min_size": int - // - Specifies the minimum socket send buffer size. - // "disable_wifi_scan" (value ignored) - // - Disable wifi scans while streaming. - // "media_streaming_mode" (value ignored) - // - Turn media streaming mode on. - // Note, these options may be ignored on some platforms. - // TODO(hubbe): Too many callbacks, replace with an interface. - // http://crbug.com/557477 CastTransportSenderImpl( - net::NetLog* net_log, - base::TickClock* clock, - const net::IPEndPoint& local_end_point, - const net::IPEndPoint& remote_end_point, - scoped_ptr<base::DictionaryValue> options, - const CastTransportStatusCallback& status_callback, - const BulkRawEventsCallback& raw_events_callback, - base::TimeDelta raw_events_callback_interval, - const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, - const PacketReceiverCallback& packet_callback, - PacketSender* external_transport); + base::TickClock* clock, // Owned by the caller. + base::TimeDelta logging_flush_interval, + scoped_ptr<Client> client, + scoped_ptr<PacketSender> transport, + const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner); ~CastTransportSenderImpl() final; @@ -115,6 +83,20 @@ class CastTransportSenderImpl : public CastTransportSender { PacketReceiverCallback PacketReceiverForTesting() final; + // Possible keys of |options| handled here are: + // "pacer_target_burst_size": int + // - Specifies how many packets to send per 10 ms ideally. + // "pacer_max_burst_size": int + // - Specifies how many pakcets to send per 10 ms, maximum. + // "send_buffer_min_size": int + // - Specifies the minimum socket send buffer size. + // "disable_wifi_scan" (value ignored) + // - Disable wifi scans while streaming. + // "media_streaming_mode" (value ignored) + // - Turn media streaming mode on. + // Note, these options may be ignored on some platforms. + void SetOptions(const base::DictionaryValue& options) final; + // CastTransportReceiver implementation. void AddValidSsrc(uint32_t ssrc) final; @@ -143,8 +125,8 @@ class CastTransportSenderImpl : public CastTransportSender { bool cancel_rtx_if_not_in_list, const DedupInfo& dedup_info); - // If |raw_events_callback_| is non-null, calls it with events collected - // in |recent_frame_events_| and |recent_packet_events_| since last call. + // If |logging_flush_interval| is set, this is called at approximate periodic + // intervals. void SendRawEvents(); // Called when a packet is received. @@ -159,18 +141,18 @@ class CastTransportSenderImpl : public CastTransportSender { const RtcpCastMessageCallback& cast_message_cb, const RtcpCastMessage& cast_message); - base::TickClock* clock_; // Not owned by this class. - CastTransportStatusCallback status_callback_; - scoped_refptr<base::SingleThreadTaskRunner> transport_task_runner_; + base::TickClock* const clock_; // Not owned by this class. + const base::TimeDelta logging_flush_interval_; + const scoped_ptr<Client> transport_client_; + const scoped_ptr<PacketSender> transport_; + const scoped_refptr<base::SingleThreadTaskRunner> transport_task_runner_; - // FrameEvents and PacketEvents pending delivery via |raw_events_callback_|. - // Do not add elements to these when |raw_events_callback_.is_null()|. + // FrameEvents and PacketEvents pending delivery via raw events callback. + // Do not add elements to these when |logging_flush_interval| is + // |base::TimeDelta()|. std::vector<FrameEvent> recent_frame_events_; std::vector<PacketEvent> recent_packet_events_; - // Interface to a UDP socket. - scoped_ptr<UdpTransport> transport_; - // Packet sender that performs pacing. PacedSender pacer_; @@ -189,9 +171,6 @@ class CastTransportSenderImpl : public CastTransportSender { TransportEncryptionHandler audio_encryptor_; TransportEncryptionHandler video_encryptor_; - BulkRawEventsCallback raw_events_callback_; - base::TimeDelta raw_events_callback_interval_; - // Right after a frame is sent we record the number of bytes sent to the // socket. We record the corresponding bytes sent for the most recent ACKed // audio packet. @@ -200,10 +179,9 @@ class CastTransportSenderImpl : public CastTransportSender { // Packets that don't match these ssrcs are ignored. std::set<uint32_t> valid_ssrcs_; - // Called with incoming packets. (Unless they match the - // channels created by Initialize{Audio,Video}. - PacketReceiverCallback packet_callback_; - + // While non-null, global WiFi behavior modifications are in effect. This is + // used, for example, to turn off WiFi scanning that tends to interfere with + // the reliability of UDP packet transmission. scoped_ptr<net::ScopedWifiOptions> wifi_options_autoreset_; base::WeakPtrFactory<CastTransportSenderImpl> weak_factory_; diff --git a/media/cast/net/cast_transport_sender_impl_unittest.cc b/media/cast/net/cast_transport_sender_impl_unittest.cc index db6c5df..f2e9d5c 100644 --- a/media/cast/net/cast_transport_sender_impl_unittest.cc +++ b/media/cast/net/cast_transport_sender_impl_unittest.cc @@ -23,9 +23,11 @@ namespace media { namespace cast { namespace { + const int64_t kStartMillisecond = INT64_C(12345678900000); const uint32_t kVideoSsrc = 1; const uint32_t kAudioSsrc = 2; + } // namespace class FakePacketSender : public PacketSender { @@ -46,6 +48,11 @@ class FakePacketSender : public PacketSender { int64_t GetBytesSent() final { return bytes_sent_; } + void StartReceiving( + const PacketReceiverCallbackWithStatus& packet_receiver) final {} + + void StopReceiving() final {} + void SetPaused(bool paused) { paused_ = paused; if (!paused && stored_packet_.get()) { @@ -67,6 +74,9 @@ class FakePacketSender : public PacketSender { }; class CastTransportSenderImplTest : public ::testing::Test { + public: + void ReceivedLoggingEvents() { num_times_logging_callback_called_++; } + protected: CastTransportSenderImplTest() : num_times_logging_callback_called_(0) { testing_clock_.Advance( @@ -76,62 +86,16 @@ class CastTransportSenderImplTest : public ::testing::Test { ~CastTransportSenderImplTest() override {} - void InitWithoutLogging() { - transport_sender_.reset( - new CastTransportSenderImpl(NULL, - &testing_clock_, - net::IPEndPoint(), - net::IPEndPoint(), - make_scoped_ptr(new base::DictionaryValue), - base::Bind(&UpdateCastTransportStatus), - BulkRawEventsCallback(), - base::TimeDelta(), - task_runner_, - PacketReceiverCallback(), - &transport_)); - task_runner_->RunTasks(); - } - - void InitWithOptions() { - scoped_ptr<base::DictionaryValue> options( - new base::DictionaryValue); - options->SetBoolean("DHCP", true); - options->SetBoolean("disable_wifi_scan", true); - options->SetBoolean("media_streaming_mode", true); - options->SetInteger("pacer_target_burst_size", 20); - options->SetInteger("pacer_max_burst_size", 100); - transport_sender_.reset(new CastTransportSenderImpl( - NULL, &testing_clock_, net::IPEndPoint(), net::IPEndPoint(), - std::move(options), base::Bind(&UpdateCastTransportStatus), - BulkRawEventsCallback(), base::TimeDelta(), task_runner_, - PacketReceiverCallback(), &transport_)); - task_runner_->RunTasks(); - } - - void InitWithLogging() { - transport_sender_.reset(new CastTransportSenderImpl( - NULL, - &testing_clock_, - net::IPEndPoint(), - net::IPEndPoint(), - make_scoped_ptr(new base::DictionaryValue), - base::Bind(&UpdateCastTransportStatus), - base::Bind(&CastTransportSenderImplTest::LogRawEvents, - base::Unretained(this)), - base::TimeDelta::FromMilliseconds(10), - task_runner_, - PacketReceiverCallback(), - &transport_)); - task_runner_->RunTasks(); - } + void InitWithoutLogging(); + void InitWithOptions(); + void InitWithLogging(); void InitializeVideo() { CastTransportRtpConfig rtp_config; rtp_config.ssrc = kVideoSsrc; rtp_config.feedback_ssrc = 2; rtp_config.rtp_payload_type = 3; - transport_sender_->InitializeVideo(rtp_config, - RtcpCastMessageCallback(), + transport_sender_->InitializeVideo(rtp_config, RtcpCastMessageCallback(), RtcpRttCallback()); } @@ -140,26 +104,75 @@ class CastTransportSenderImplTest : public ::testing::Test { rtp_config.ssrc = kAudioSsrc; rtp_config.feedback_ssrc = 3; rtp_config.rtp_payload_type = 4; - transport_sender_->InitializeAudio(rtp_config, - RtcpCastMessageCallback(), + transport_sender_->InitializeAudio(rtp_config, RtcpCastMessageCallback(), RtcpRttCallback()); } - void LogRawEvents(scoped_ptr<std::vector<FrameEvent>> frame_events, - scoped_ptr<std::vector<PacketEvent>> packet_events) { - num_times_logging_callback_called_++; - } - - static void UpdateCastTransportStatus(CastTransportStatus status) { - } - base::SimpleTestTickClock testing_clock_; scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; scoped_ptr<CastTransportSenderImpl> transport_sender_; - FakePacketSender transport_; + FakePacketSender* transport_; // Owned by CastTransportSender. int num_times_logging_callback_called_; }; +namespace { + +class TransportClient : public CastTransportSender::Client { + public: + explicit TransportClient( + CastTransportSenderImplTest* cast_transport_sender_impl_test) + : cast_transport_sender_impl_test_(cast_transport_sender_impl_test) {} + + void OnStatusChanged(CastTransportStatus status) final{}; + void OnLoggingEventsReceived( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) final { + CHECK(cast_transport_sender_impl_test_); + cast_transport_sender_impl_test_->ReceivedLoggingEvents(); + }; + void ProcessRtpPacket(scoped_ptr<Packet> packet) final{}; + + private: + CastTransportSenderImplTest* const cast_transport_sender_impl_test_; + + DISALLOW_COPY_AND_ASSIGN(TransportClient); +}; + +} // namespace + +void CastTransportSenderImplTest::InitWithoutLogging() { + transport_ = new FakePacketSender(); + transport_sender_.reset( + new CastTransportSenderImpl(&testing_clock_, base::TimeDelta(), + make_scoped_ptr(new TransportClient(nullptr)), + make_scoped_ptr(transport_), task_runner_)); + task_runner_->RunTasks(); +} + +void CastTransportSenderImplTest::InitWithOptions() { + scoped_ptr<base::DictionaryValue> options(new base::DictionaryValue); + options->SetBoolean("disable_wifi_scan", true); + options->SetBoolean("media_streaming_mode", true); + options->SetInteger("pacer_target_burst_size", 20); + options->SetInteger("pacer_max_burst_size", 100); + transport_ = new FakePacketSender(); + transport_sender_.reset( + new CastTransportSenderImpl(&testing_clock_, base::TimeDelta(), + make_scoped_ptr(new TransportClient(nullptr)), + make_scoped_ptr(transport_), task_runner_)); + transport_sender_->SetOptions(*options); + task_runner_->RunTasks(); +} + +void CastTransportSenderImplTest::InitWithLogging() { + transport_ = new FakePacketSender(); + transport_sender_.reset(new CastTransportSenderImpl( + &testing_clock_, base::TimeDelta::FromMilliseconds(10), + make_scoped_ptr(new TransportClient(this)), make_scoped_ptr(transport_), + task_runner_)); + task_runner_->RunTasks(); +} + TEST_F(CastTransportSenderImplTest, InitWithoutLogging) { InitWithoutLogging(); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(50)); @@ -187,7 +200,7 @@ TEST_F(CastTransportSenderImplTest, NacksCancelRetransmits) { transport_sender_->InsertFrame(kVideoSsrc, fake_frame); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); - EXPECT_EQ(4, transport_.packets_sent()); + EXPECT_EQ(4, transport_->packets_sent()); EXPECT_EQ(1, num_times_logging_callback_called_); // Resend packet 0. @@ -196,7 +209,7 @@ TEST_F(CastTransportSenderImplTest, NacksCancelRetransmits) { missing_packets[1].insert(1); missing_packets[1].insert(2); - transport_.SetPaused(true); + transport_->SetPaused(true); DedupInfo dedup_info; dedup_info.resend_interval = base::TimeDelta::FromMilliseconds(10); transport_sender_->ResendPackets( @@ -212,13 +225,13 @@ TEST_F(CastTransportSenderImplTest, NacksCancelRetransmits) { transport_sender_->OnReceivedCastMessage(kVideoSsrc, RtcpCastMessageCallback(), cast_message); - transport_.SetPaused(false); + transport_->SetPaused(false); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); EXPECT_EQ(3, num_times_logging_callback_called_); // Resend one packet in the socket when unpaused. // Resend one more packet from NACK. - EXPECT_EQ(6, transport_.packets_sent()); + EXPECT_EQ(6, transport_->packets_sent()); } TEST_F(CastTransportSenderImplTest, CancelRetransmits) { @@ -236,14 +249,14 @@ TEST_F(CastTransportSenderImplTest, CancelRetransmits) { transport_sender_->InsertFrame(kVideoSsrc, fake_frame); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); - EXPECT_EQ(4, transport_.packets_sent()); + EXPECT_EQ(4, transport_->packets_sent()); EXPECT_EQ(1, num_times_logging_callback_called_); // Resend all packets for frame 1. MissingFramesAndPacketsMap missing_packets; missing_packets[1].insert(kRtcpCastAllPacketsLost); - transport_.SetPaused(true); + transport_->SetPaused(true); DedupInfo dedup_info; dedup_info.resend_interval = base::TimeDelta::FromMilliseconds(10); transport_sender_->ResendPackets( @@ -256,12 +269,12 @@ TEST_F(CastTransportSenderImplTest, CancelRetransmits) { cancel_sending_frames.push_back(1); transport_sender_->CancelSendingFrames(kVideoSsrc, cancel_sending_frames); - transport_.SetPaused(false); + transport_->SetPaused(false); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); EXPECT_EQ(2, num_times_logging_callback_called_); // Resend one packet in the socket when unpaused. - EXPECT_EQ(5, transport_.packets_sent()); + EXPECT_EQ(5, transport_->packets_sent()); } TEST_F(CastTransportSenderImplTest, Kickstart) { @@ -277,12 +290,12 @@ TEST_F(CastTransportSenderImplTest, Kickstart) { fake_frame.dependency = EncodedFrame::KEY; fake_frame.data.resize(5000, ' '); - transport_.SetPaused(true); + transport_->SetPaused(true); transport_sender_->InsertFrame(kVideoSsrc, fake_frame); transport_sender_->ResendFrameForKickstart(kVideoSsrc, 1); - transport_.SetPaused(false); + transport_->SetPaused(false); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); - EXPECT_EQ(4, transport_.packets_sent()); + EXPECT_EQ(4, transport_->packets_sent()); EXPECT_EQ(1, num_times_logging_callback_called_); // Resend 2 packets for frame 1. @@ -290,19 +303,19 @@ TEST_F(CastTransportSenderImplTest, Kickstart) { missing_packets[1].insert(0); missing_packets[1].insert(1); - transport_.SetPaused(true); + transport_->SetPaused(true); DedupInfo dedup_info; dedup_info.resend_interval = base::TimeDelta::FromMilliseconds(10); transport_sender_->ResendPackets( kVideoSsrc, missing_packets, true, dedup_info); transport_sender_->ResendFrameForKickstart(kVideoSsrc, 1); - transport_.SetPaused(false); + transport_->SetPaused(false); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(10)); EXPECT_EQ(2, num_times_logging_callback_called_); // Resend one packet in the socket when unpaused. // Two more retransmission packets sent. - EXPECT_EQ(7, transport_.packets_sent()); + EXPECT_EQ(7, transport_->packets_sent()); } TEST_F(CastTransportSenderImplTest, DedupRetransmissionWithAudio) { @@ -324,7 +337,7 @@ TEST_F(CastTransportSenderImplTest, DedupRetransmissionWithAudio) { fake_audio.reference_time = testing_clock_.NowTicks(); transport_sender_->InsertFrame(kAudioSsrc, fake_audio); task_runner_->Sleep(base::TimeDelta::FromMilliseconds(2)); - EXPECT_EQ(2, transport_.packets_sent()); + EXPECT_EQ(2, transport_->packets_sent()); // Ack the first audio frame. RtcpCastMessage cast_message; @@ -334,7 +347,7 @@ TEST_F(CastTransportSenderImplTest, DedupRetransmissionWithAudio) { RtcpCastMessageCallback(), cast_message); task_runner_->RunTasks(); - EXPECT_EQ(2, transport_.packets_sent()); + EXPECT_EQ(2, transport_->packets_sent()); EXPECT_EQ(0, num_times_logging_callback_called_); // Only 4 ms since last. // Send a fake video frame that will be decomposed into 4 packets. @@ -344,7 +357,7 @@ TEST_F(CastTransportSenderImplTest, DedupRetransmissionWithAudio) { fake_video.data.resize(5000, ' '); transport_sender_->InsertFrame(kVideoSsrc, fake_video); task_runner_->RunTasks(); - EXPECT_EQ(6, transport_.packets_sent()); + EXPECT_EQ(6, transport_->packets_sent()); EXPECT_EQ(0, num_times_logging_callback_called_); // Only 4 ms since last. // Retransmission is reject because audio is not acked yet. @@ -356,7 +369,7 @@ TEST_F(CastTransportSenderImplTest, DedupRetransmissionWithAudio) { RtcpCastMessageCallback(), cast_message); task_runner_->RunTasks(); - EXPECT_EQ(6, transport_.packets_sent()); + EXPECT_EQ(6, transport_->packets_sent()); EXPECT_EQ(1, num_times_logging_callback_called_); // Ack the second audio frame. @@ -368,7 +381,7 @@ TEST_F(CastTransportSenderImplTest, DedupRetransmissionWithAudio) { RtcpCastMessageCallback(), cast_message); task_runner_->RunTasks(); - EXPECT_EQ(6, transport_.packets_sent()); + EXPECT_EQ(6, transport_->packets_sent()); EXPECT_EQ(1, num_times_logging_callback_called_); // Only 6 ms since last. // Retransmission of video packet now accepted. @@ -380,7 +393,7 @@ TEST_F(CastTransportSenderImplTest, DedupRetransmissionWithAudio) { RtcpCastMessageCallback(), cast_message); task_runner_->RunTasks(); - EXPECT_EQ(7, transport_.packets_sent()); + EXPECT_EQ(7, transport_->packets_sent()); EXPECT_EQ(1, num_times_logging_callback_called_); // Only 8 ms since last. task_runner_->Sleep(base::TimeDelta::FromMilliseconds(2)); diff --git a/media/cast/net/mock_cast_transport_sender.h b/media/cast/net/mock_cast_transport_sender.h index 371b419..bf1dfc0 100644 --- a/media/cast/net/mock_cast_transport_sender.h +++ b/media/cast/net/mock_cast_transport_sender.h @@ -45,6 +45,7 @@ class MockCastTransportSender : public CastTransportSender { base::TimeDelta target_delay, const ReceiverRtcpEventSubscriber::RtcpEvents* rtcp_events, const RtpReceiverStatistics* rtp_receiver_statistics)); + MOCK_METHOD1(SetOptions, void(const base::DictionaryValue& options)); }; } // namespace cast diff --git a/media/cast/net/pacing/paced_sender.h b/media/cast/net/pacing/paced_sender.h index 714fe9d..8d45cc4 100644 --- a/media/cast/net/pacing/paced_sender.h +++ b/media/cast/net/pacing/paced_sender.h @@ -131,6 +131,13 @@ class PacedSender : public PacedPacketSender, bool SendRtcpPacket(uint32_t ssrc, PacketRef packet) final; void CancelSendingPacket(const PacketKey& packet_key) final; + void SetTargetBurstSize(int burst_size) { + target_burst_size_ = current_max_burst_size_ = next_max_burst_size_ = + next_next_max_burst_size_ = burst_size; + } + + void SetMaxBurstSize(int burst_size) { max_burst_size_ = burst_size; } + private: // Actually sends the packets to the transport. void SendStoredPackets(); diff --git a/media/cast/net/pacing/paced_sender_unittest.cc b/media/cast/net/pacing/paced_sender_unittest.cc index fec5c5f..89c341f 100644 --- a/media/cast/net/pacing/paced_sender_unittest.cc +++ b/media/cast/net/pacing/paced_sender_unittest.cc @@ -47,6 +47,11 @@ class TestPacketSender : public PacketSender { int64_t GetBytesSent() final { return bytes_sent_; } + void StartReceiving( + const PacketReceiverCallbackWithStatus& packet_receiver) final {} + + void StopReceiving() final {} + void AddExpectedSize(int expected_packet_size, int repeat_count) { for (int i = 0; i < repeat_count; ++i) { expected_packet_size_.push_back(expected_packet_size); diff --git a/media/cast/net/rtp/rtp_packetizer_unittest.cc b/media/cast/net/rtp/rtp_packetizer_unittest.cc index 5c58125..76aa232 100644 --- a/media/cast/net/rtp/rtp_packetizer_unittest.cc +++ b/media/cast/net/rtp/rtp_packetizer_unittest.cc @@ -80,6 +80,11 @@ class TestRtpPacketTransport : public PacketSender { int64_t GetBytesSent() final { return 0; } + void StartReceiving( + const PacketReceiverCallbackWithStatus& packet_receiver) final {} + + void StopReceiving() final {} + size_t number_of_packets_received() const { return packets_sent_; } void set_expected_number_of_packets(size_t expected_number_of_packets) { diff --git a/media/cast/net/udp_transport.cc b/media/cast/net/udp_transport.cc index 2560b45..bf126bc 100644 --- a/media/cast/net/udp_transport.cc +++ b/media/cast/net/udp_transport.cc @@ -21,7 +21,13 @@ namespace media { namespace cast { namespace { -const int kMaxPacketSize = 1500; + +const char kOptionDscp[] = "DSCP"; +#if defined(OS_WIN) +const char kOptionDisableNonBlockingIO[] = "disable_non_blocking_io"; +#endif +const char kOptionSendBufferMinSize[] = "send_buffer_min_size"; +const char kOptionPacerMaxBurstSize[] = "pacer_max_burst_size"; bool IsEmpty(const net::IPEndPoint& addr) { net::IPAddressNumber empty_addr(addr.address().size()); @@ -30,6 +36,29 @@ bool IsEmpty(const net::IPEndPoint& addr) { !addr.port(); } +int LookupOptionWithDefault(const base::DictionaryValue& options, + const std::string& path, + int default_value) { + int ret; + if (options.GetInteger(path, &ret)) { + return ret; + } else { + return default_value; + } +} + +int32_t GetTransportSendBufferSize(const base::DictionaryValue& options) { + // Socket send buffer size needs to be at least greater than one burst + // size. + int32_t max_burst_size = + LookupOptionWithDefault(options, kOptionPacerMaxBurstSize, + media::cast::kMaxBurstSize) * + media::cast::kMaxIpPacketSize; + int32_t min_send_buffer_size = + LookupOptionWithDefault(options, kOptionSendBufferMinSize, 0); + return std::max(max_burst_size, min_send_buffer_size); +} + } // namespace UdpTransport::UdpTransport( @@ -37,7 +66,6 @@ UdpTransport::UdpTransport( const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_proxy, const net::IPEndPoint& local_end_point, const net::IPEndPoint& remote_end_point, - int32_t send_buffer_size, const CastTransportStatusCallback& status_callback) : io_thread_proxy_(io_thread_proxy), local_addr_(local_end_point), @@ -50,7 +78,8 @@ UdpTransport::UdpTransport( receive_pending_(false), client_connected_(false), next_dscp_value_(net::DSCP_NO_CHANGE), - send_buffer_size_(send_buffer_size), + send_buffer_size_(media::cast::kMaxBurstSize * + media::cast::kMaxIpPacketSize), status_callback_(status_callback), bytes_sent_(0), weak_factory_(this) { @@ -145,15 +174,13 @@ void UdpTransport::ReceiveNextPacket(int length_or_status) { // the future when a packet is ready. while (true) { if (length_or_status == net::ERR_IO_PENDING) { - next_packet_.reset(new Packet(kMaxPacketSize)); + next_packet_.reset(new Packet(media::cast::kMaxIpPacketSize)); recv_buf_ = new net::WrappedIOBuffer( reinterpret_cast<char*>(&next_packet_->front())); - length_or_status = - udp_socket_->RecvFrom(recv_buf_.get(), - kMaxPacketSize, - &recv_addr_, - base::Bind(&UdpTransport::ReceiveNextPacket, - weak_factory_.GetWeakPtr())); + length_or_status = udp_socket_->RecvFrom( + recv_buf_.get(), media::cast::kMaxIpPacketSize, &recv_addr_, + base::Bind(&UdpTransport::ReceiveNextPacket, + weak_factory_.GetWeakPtr())); if (length_or_status == net::ERR_IO_PENDING) { receive_pending_ = true; return; @@ -275,5 +302,23 @@ void UdpTransport::OnSent(const scoped_refptr<net::IOBuffer>& buf, } } +void UdpTransport::SetUdpOptions(const base::DictionaryValue& options) { + SetSendBufferSize(GetTransportSendBufferSize(options)); + if (options.HasKey(kOptionDscp)) { + // The default DSCP value for cast is AF41. Which gives it a higher + // priority over other traffic. + SetDscp(net::DSCP_AF41); + } +#if defined(OS_WIN) + if (!options.HasKey(kOptionDisableNonBlockingIO)) { + UseNonBlockingIO(); + } +#endif +} + +void UdpTransport::SetSendBufferSize(int32_t send_buffer_size) { + send_buffer_size_ = send_buffer_size; +} + } // namespace cast } // namespace media diff --git a/media/cast/net/udp_transport.h b/media/cast/net/udp_transport.h index 6da6ae3..c098a58 100644 --- a/media/cast/net/udp_transport.h +++ b/media/cast/net/udp_transport.h @@ -11,10 +11,12 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/values.h" #include "build/build_config.h" #include "media/cast/cast_environment.h" #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 "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/udp/diff_serv_code_point.h" @@ -44,18 +46,35 @@ class UdpTransport : public PacketSender { const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_proxy, const net::IPEndPoint& local_end_point, const net::IPEndPoint& remote_end_point, - int32_t send_buffer_size, const CastTransportStatusCallback& status_callback); ~UdpTransport() final; // Start receiving packets. Packets are submitted to |packet_receiver|. - void StartReceiving(const PacketReceiverCallbackWithStatus& packet_receiver); - void StopReceiving(); + void StartReceiving( + const PacketReceiverCallbackWithStatus& packet_receiver) final; + void StopReceiving() final; // Set a new DSCP value to the socket. The value will be set right before // the next send. void SetDscp(net::DiffServCodePoint dscp); + // Set UdpTransport options. + // Possible keys are: + // "pacer_max_burst_size": int + // - Specifies how many pakcets to send per 10 ms, maximum. + // "send_buffer_min_size": int + // - Specifies the minimum socket send buffer size. + // "DSCP" (value ignored) + // - Turns DSCP on (higher IP Precedence and Type of Service). + // "disable_non_blocking_io" (value ignored) + // - Windows only. Turns off non-blocking IO for the socket. + // Note: Non-blocking IO is, by default, enabled on all platforms. + void SetUdpOptions(const base::DictionaryValue& options); + + // This has to be called before |StartReceiving()| to change the + // |send_buffer_size_|. Calling |SetUdpOptions()| will automatically call it. + void SetSendBufferSize(int32_t send_buffer_size); + #if defined(OS_WIN) // Switch to use non-blocking IO. Must be called before StartReceiving(). void UseNonBlockingIO(); diff --git a/media/cast/net/udp_transport_unittest.cc b/media/cast/net/udp_transport_unittest.cc index 1e7729b..b73c683 100644 --- a/media/cast/net/udp_transport_unittest.cc +++ b/media/cast/net/udp_transport_unittest.cc @@ -66,14 +66,14 @@ TEST(UdpTransport, SendAndReceive) { message_loop.task_runner(), free_local_port1, free_local_port2, - 65536, base::Bind(&UpdateCastTransportStatus)); + send_transport.SetSendBufferSize(65536); UdpTransport recv_transport(NULL, message_loop.task_runner(), free_local_port2, net::IPEndPoint(empty_addr_number, 0), - 65536, base::Bind(&UpdateCastTransportStatus)); + recv_transport.SetSendBufferSize(65536); Packet packet; packet.push_back('t'); diff --git a/media/cast/sender/audio_sender_unittest.cc b/media/cast/sender/audio_sender_unittest.cc index af6b9c4..bfe2383 100644 --- a/media/cast/sender/audio_sender_unittest.cc +++ b/media/cast/sender/audio_sender_unittest.cc @@ -35,6 +35,21 @@ void SaveOperationalStatus(OperationalStatus* out_status, *out_status = in_status; } +class TransportClient : public CastTransportSender::Client { + public: + TransportClient() {} + + void OnStatusChanged(CastTransportStatus status) final { + EXPECT_EQ(TRANSPORT_AUDIO_INITIALIZED, status); + }; + void OnLoggingEventsReceived( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) final{}; + void ProcessRtpPacket(scoped_ptr<Packet> packet) final{}; + + DISALLOW_COPY_AND_ASSIGN(TransportClient); +}; + } // namespace class TestPacketSender : public PacketSender { @@ -58,6 +73,11 @@ class TestPacketSender : public PacketSender { int64_t GetBytesSent() final { return 0; } + void StartReceiving( + const PacketReceiverCallbackWithStatus& packet_receiver) final {} + + void StopReceiving() final {} + int number_of_rtp_packets() const { return number_of_rtp_packets_; } int number_of_rtcp_packets() const { return number_of_rtcp_packets_; } @@ -86,20 +106,11 @@ class AudioSenderTest : public ::testing::Test { audio_config_.bitrate = kDefaultAudioEncoderBitrate; audio_config_.rtp_payload_type = 127; - net::IPEndPoint dummy_endpoint; - - transport_sender_.reset(new CastTransportSenderImpl( - NULL, - testing_clock_, - net::IPEndPoint(), - dummy_endpoint, - make_scoped_ptr(new base::DictionaryValue), - base::Bind(&UpdateCastTransportStatus), - BulkRawEventsCallback(), - base::TimeDelta(), - task_runner_, - PacketReceiverCallback(), - &transport_)); + transport_ = new TestPacketSender(); + transport_sender_.reset( + new CastTransportSenderImpl(testing_clock_, base::TimeDelta(), + make_scoped_ptr(new TransportClient()), + make_scoped_ptr(transport_), task_runner_)); OperationalStatus operational_status = STATUS_UNINITIALIZED; audio_sender_.reset(new AudioSender( cast_environment_, @@ -112,12 +123,8 @@ class AudioSenderTest : public ::testing::Test { ~AudioSenderTest() override {} - static void UpdateCastTransportStatus(CastTransportStatus status) { - EXPECT_EQ(TRANSPORT_AUDIO_INITIALIZED, status); - } - base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. - TestPacketSender transport_; + TestPacketSender* transport_; // Owned by CastTransportSender. scoped_ptr<CastTransportSenderImpl> transport_sender_; scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; scoped_ptr<AudioSender> audio_sender_; @@ -135,8 +142,8 @@ TEST_F(AudioSenderTest, Encode20ms) { audio_sender_->InsertAudio(std::move(bus), testing_clock_->NowTicks()); task_runner_->RunTasks(); - EXPECT_LE(1, transport_.number_of_rtp_packets()); - EXPECT_LE(1, transport_.number_of_rtcp_packets()); + EXPECT_LE(1, transport_->number_of_rtp_packets()); + EXPECT_LE(1, transport_->number_of_rtcp_packets()); } TEST_F(AudioSenderTest, RtcpTimer) { @@ -155,8 +162,8 @@ TEST_F(AudioSenderTest, RtcpTimer) { base::TimeDelta::FromMilliseconds(1 + kRtcpReportIntervalMs * 3 / 2); testing_clock_->Advance(max_rtcp_timeout); task_runner_->RunTasks(); - EXPECT_LE(1, transport_.number_of_rtp_packets()); - EXPECT_LE(1, transport_.number_of_rtcp_packets()); + EXPECT_LE(1, transport_->number_of_rtp_packets()); + EXPECT_LE(1, transport_->number_of_rtcp_packets()); } } // namespace cast diff --git a/media/cast/sender/video_sender_unittest.cc b/media/cast/sender/video_sender_unittest.cc index 9c5d9c4..3d315ea 100644 --- a/media/cast/sender/video_sender_unittest.cc +++ b/media/cast/sender/video_sender_unittest.cc @@ -77,6 +77,11 @@ class TestPacketSender : public PacketSender { int64_t GetBytesSent() final { return 0; } + void StartReceiving( + const PacketReceiverCallbackWithStatus& packet_receiver) final {} + + void StopReceiving() final {} + int number_of_rtp_packets() const { return number_of_rtp_packets_; } int number_of_rtcp_packets() const { return number_of_rtcp_packets_; } @@ -121,6 +126,21 @@ class PeerVideoSender : public VideoSender { using VideoSender::OnReceivedCastFeedback; }; +class TransportClient : public CastTransportSender::Client { + public: + TransportClient() {} + + void OnStatusChanged(CastTransportStatus status) final { + EXPECT_EQ(TRANSPORT_VIDEO_INITIALIZED, status); + }; + void OnLoggingEventsReceived( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) final{}; + void ProcessRtpPacket(scoped_ptr<Packet> packet) final{}; + + DISALLOW_COPY_AND_ASSIGN(TransportClient); +}; + } // namespace class VideoSenderTest : public ::testing::Test { @@ -138,19 +158,11 @@ class VideoSenderTest : public ::testing::Test { testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks()); vea_factory_.SetAutoRespond(true); last_pixel_value_ = kPixelValue; - net::IPEndPoint dummy_endpoint; - transport_sender_.reset(new CastTransportSenderImpl( - NULL, - testing_clock_, - dummy_endpoint, - dummy_endpoint, - make_scoped_ptr(new base::DictionaryValue), - base::Bind(&UpdateCastTransportStatus), - BulkRawEventsCallback(), - base::TimeDelta(), - task_runner_, - PacketReceiverCallback(), - &transport_)); + transport_ = new TestPacketSender(); + transport_sender_.reset( + new CastTransportSenderImpl(testing_clock_, base::TimeDelta(), + make_scoped_ptr(new TransportClient()), + make_scoped_ptr(transport_), task_runner_)); } ~VideoSenderTest() override {} @@ -160,10 +172,6 @@ class VideoSenderTest : public ::testing::Test { task_runner_->RunTasks(); } - static void UpdateCastTransportStatus(CastTransportStatus status) { - EXPECT_EQ(TRANSPORT_VIDEO_INITIALIZED, status); - } - // If |external| is true then external video encoder (VEA) is used. // |expect_init_success| is true if initialization is expected to succeed. void InitEncoder(bool external, bool expect_init_success) { @@ -229,7 +237,7 @@ class VideoSenderTest : public ::testing::Test { const scoped_refptr<CastEnvironment> cast_environment_; OperationalStatus operational_status_; FakeVideoEncodeAcceleratorFactory vea_factory_; - TestPacketSender transport_; + TestPacketSender* transport_; // Owned by CastTransportSender. scoped_ptr<CastTransportSenderImpl> transport_sender_; scoped_ptr<PeerVideoSender> video_sender_; int last_pixel_value_; @@ -249,8 +257,8 @@ TEST_F(VideoSenderTest, BuiltInEncoder) { video_sender_->InsertRawVideoFrame(video_frame, reference_time); task_runner_->RunTasks(); - EXPECT_LE(1, transport_.number_of_rtp_packets()); - EXPECT_LE(1, transport_.number_of_rtcp_packets()); + EXPECT_LE(1, transport_->number_of_rtp_packets()); + EXPECT_LE(1, transport_->number_of_rtcp_packets()); } TEST_F(VideoSenderTest, ExternalEncoder) { @@ -324,15 +332,15 @@ TEST_F(VideoSenderTest, RtcpTimer) { base::TimeDelta::FromMilliseconds(1 + kRtcpReportIntervalMs * 3 / 2); RunTasks(max_rtcp_timeout.InMilliseconds()); - EXPECT_LE(1, transport_.number_of_rtp_packets()); - EXPECT_LE(1, transport_.number_of_rtcp_packets()); + EXPECT_LE(1, transport_->number_of_rtp_packets()); + 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; video_sender_->OnReceivedCastFeedback(cast_feedback); RunTasks(max_rtcp_timeout.InMilliseconds()); - EXPECT_LE(1, transport_.number_of_rtcp_packets()); + EXPECT_LE(1, transport_->number_of_rtcp_packets()); } TEST_F(VideoSenderTest, ResendTimer) { @@ -359,9 +367,8 @@ TEST_F(VideoSenderTest, ResendTimer) { // Make sure that we do a re-send. RunTasks(max_resend_timeout.InMilliseconds()); // Should have sent at least 3 packets. - EXPECT_LE( - 3, - transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets()); + EXPECT_LE(3, transport_->number_of_rtp_packets() + + transport_->number_of_rtcp_packets()); } TEST_F(VideoSenderTest, LogAckReceivedEvent) { @@ -414,7 +421,7 @@ TEST_F(VideoSenderTest, StopSendingInTheAbsenceOfAck) { video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks()); RunTasks(33); } - const int number_of_packets_sent = transport_.number_of_rtp_packets(); + const int number_of_packets_sent = transport_->number_of_rtp_packets(); // Send 3 more frames - they should not be encoded, as we have not received // any acks. @@ -426,24 +433,21 @@ TEST_F(VideoSenderTest, StopSendingInTheAbsenceOfAck) { // We expect a frame to be retransmitted because of duplicated ACKs. // Only one packet of the frame is re-transmitted. - EXPECT_EQ(number_of_packets_sent + 1, - transport_.number_of_rtp_packets()); + EXPECT_EQ(number_of_packets_sent + 1, transport_->number_of_rtp_packets()); // 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; video_sender_->OnReceivedCastFeedback(cast_feedback); - EXPECT_LE( - 4, - transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets()); + EXPECT_LE(4, transport_->number_of_rtp_packets() + + transport_->number_of_rtcp_packets()); // Empty the pipeline. RunTasks(100); // Should have sent at least 7 packets. - EXPECT_LE( - 7, - transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets()); + EXPECT_LE(7, transport_->number_of_rtp_packets() + + transport_->number_of_rtcp_packets()); } TEST_F(VideoSenderTest, DuplicateAckRetransmit) { @@ -463,7 +467,7 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmit) { video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks()); RunTasks(33); } - const int number_of_packets_sent = transport_.number_of_rtp_packets(); + const int number_of_packets_sent = transport_->number_of_rtp_packets(); // Send duplicated ACKs and mix some invalid NACKs. for (int i = 0; i < 10; ++i) { @@ -476,7 +480,7 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmit) { video_sender_->OnReceivedCastFeedback(ack_feedback); video_sender_->OnReceivedCastFeedback(nack_feedback); } - EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets()); + EXPECT_EQ(number_of_packets_sent, transport_->number_of_rtp_packets()); // Re-transmit one packet because of duplicated ACKs. for (int i = 0; i < 3; ++i) { @@ -485,7 +489,7 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmit) { ack_feedback.ack_frame_id = 0; video_sender_->OnReceivedCastFeedback(ack_feedback); } - EXPECT_EQ(number_of_packets_sent + 1, transport_.number_of_rtp_packets()); + EXPECT_EQ(number_of_packets_sent + 1, transport_->number_of_rtp_packets()); } TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) { @@ -506,14 +510,14 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) { RunTasks(33); } // Pause the transport - transport_.SetPause(true); + transport_->SetPause(true); // Insert one more video frame. video_frame = GetLargeNewVideoFrame(); video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks()); RunTasks(33); - const int number_of_packets_sent = transport_.number_of_rtp_packets(); + const int number_of_packets_sent = transport_->number_of_rtp_packets(); // Send duplicated ACKs and mix some invalid NACKs. for (int i = 0; i < 10; ++i) { @@ -526,7 +530,7 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) { video_sender_->OnReceivedCastFeedback(ack_feedback); video_sender_->OnReceivedCastFeedback(nack_feedback); } - EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets()); + EXPECT_EQ(number_of_packets_sent, transport_->number_of_rtp_packets()); // Re-transmit one packet because of duplicated ACKs. for (int i = 0; i < 3; ++i) { @@ -536,16 +540,16 @@ TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) { video_sender_->OnReceivedCastFeedback(ack_feedback); } - transport_.SetPause(false); + transport_->SetPause(false); RunTasks(100); - EXPECT_LT(number_of_packets_sent + 1, transport_.number_of_rtp_packets()); + EXPECT_LT(number_of_packets_sent + 1, transport_->number_of_rtp_packets()); } TEST_F(VideoSenderTest, AcksCancelRetransmits) { InitEncoder(false, true); ASSERT_EQ(STATUS_INITIALIZED, operational_status_); - transport_.SetPause(true); + transport_->SetPause(true); scoped_refptr<media::VideoFrame> video_frame = GetLargeNewVideoFrame(); video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks()); RunTasks(33); @@ -556,9 +560,9 @@ TEST_F(VideoSenderTest, AcksCancelRetransmits) { cast_feedback.ack_frame_id = 0; video_sender_->OnReceivedCastFeedback(cast_feedback); - transport_.SetPause(false); + transport_->SetPause(false); RunTasks(33); - EXPECT_EQ(0, transport_.number_of_rtp_packets()); + EXPECT_EQ(0, transport_->number_of_rtp_packets()); } TEST_F(VideoSenderTest, CheckVideoFrameFactoryIsNull) { diff --git a/media/cast/test/cast_benchmarks.cc b/media/cast/test/cast_benchmarks.cc index 29e2d41..3d3950e 100644 --- a/media/cast/test/cast_benchmarks.cc +++ b/media/cast/test/cast_benchmarks.cc @@ -71,12 +71,6 @@ namespace { static const int64_t kStartMillisecond = INT64_C(1245); static const int kTargetPlayoutDelayMs = 400; -void UpdateCastTransportStatus(CastTransportStatus status) { - bool result = (status == TRANSPORT_AUDIO_INITIALIZED || - status == TRANSPORT_VIDEO_INITIALIZED); - EXPECT_TRUE(result); -} - void ExpectVideoSuccess(OperationalStatus status) { EXPECT_EQ(STATUS_INITIALIZED, status); } @@ -85,9 +79,6 @@ void ExpectAudioSuccess(OperationalStatus status) { EXPECT_EQ(STATUS_INITIALIZED, status); } -void IgnoreRawEvents(scoped_ptr<std::vector<FrameEvent>> frame_events, - scoped_ptr<std::vector<PacketEvent>> packet_events) {} - } // namespace // Wraps a CastTransportSender and records some statistics about @@ -168,6 +159,8 @@ class CastTransportSenderWrapper : public CastTransportSender { rtp_receiver_statistics); } + void SetOptions(const base::DictionaryValue& options) final {} + private: scoped_ptr<CastTransportSender> transport_; uint32_t audio_ssrc_, video_ssrc_; @@ -220,8 +213,6 @@ class RunOneBenchmark { task_runner_receiver_, task_runner_receiver_, task_runner_receiver_)), - receiver_to_sender_(cast_environment_receiver_), - sender_to_receiver_(cast_environment_sender_), video_bytes_encoded_(0), audio_bytes_encoded_(0), frames_sent_(0) { @@ -269,64 +260,7 @@ class RunOneBenchmark { task_runner_receiver_->SetSkew(1.0 / skew); } - void Create(const MeasuringPoint& p) { - net::IPEndPoint dummy_endpoint; - transport_sender_.Init( - new CastTransportSenderImpl( - NULL, - testing_clock_sender_, - dummy_endpoint, - dummy_endpoint, - make_scoped_ptr(new base::DictionaryValue), - base::Bind(&UpdateCastTransportStatus), - base::Bind(&IgnoreRawEvents), - base::TimeDelta::FromSeconds(1), - task_runner_sender_, - PacketReceiverCallback(), - &sender_to_receiver_), - &video_bytes_encoded_, - &audio_bytes_encoded_); - - transport_receiver_.reset( - new CastTransportSenderImpl( - NULL, - testing_clock_receiver_, - dummy_endpoint, - dummy_endpoint, - make_scoped_ptr(new base::DictionaryValue), - base::Bind(&UpdateCastTransportStatus), - base::Bind(&IgnoreRawEvents), - base::TimeDelta::FromSeconds(1), - task_runner_receiver_, - base::Bind(&RunOneBenchmark::ReceivePacket, base::Unretained(this)), - &receiver_to_sender_)); - - cast_receiver_ = CastReceiver::Create(cast_environment_receiver_, - audio_receiver_config_, - video_receiver_config_, - transport_receiver_.get()); - - cast_sender_ = - CastSender::Create(cast_environment_sender_, &transport_sender_); - - cast_sender_->InitializeAudio( - audio_sender_config_, - base::Bind(&ExpectAudioSuccess)); - cast_sender_->InitializeVideo( - video_sender_config_, - base::Bind(&ExpectVideoSuccess), - CreateDefaultVideoEncodeAcceleratorCallback(), - CreateDefaultVideoEncodeMemoryCallback()); - - receiver_to_sender_.Initialize(CreateSimplePipe(p), - transport_sender_.PacketReceiverForTesting(), - task_runner_, &testing_clock_); - sender_to_receiver_.Initialize( - CreateSimplePipe(p), transport_receiver_->PacketReceiverForTesting(), - task_runner_, &testing_clock_); - - task_runner_->RunTasks(); - } + void Create(const MeasuringPoint& p); void ReceivePacket(scoped_ptr<Packet> packet) { cast_receiver_->ReceivePacket(std::move(packet)); @@ -484,8 +418,8 @@ class RunOneBenchmark { scoped_refptr<CastEnvironment> cast_environment_sender_; scoped_refptr<CastEnvironment> cast_environment_receiver_; - LoopBackTransport receiver_to_sender_; - LoopBackTransport sender_to_receiver_; + LoopBackTransport* receiver_to_sender_; // Owned by CastTransportSenderImpl. + LoopBackTransport* sender_to_receiver_; // Owned by CastTransportSenderImpl. CastTransportSenderWrapper transport_sender_; scoped_ptr<CastTransportSender> transport_receiver_; uint64_t video_bytes_encoded_; @@ -501,6 +435,73 @@ class RunOneBenchmark { std::vector<std::pair<base::TimeTicks, base::TimeTicks> > video_ticks_; }; +namespace { + +class TransportClient : public CastTransportSender::Client { + public: + explicit TransportClient(RunOneBenchmark* run_one_benchmark) + : run_one_benchmark_(run_one_benchmark) {} + + void OnStatusChanged(CastTransportStatus status) final { + bool result = (status == TRANSPORT_AUDIO_INITIALIZED || + status == TRANSPORT_VIDEO_INITIALIZED); + EXPECT_TRUE(result); + }; + void OnLoggingEventsReceived( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) final{}; + void ProcessRtpPacket(scoped_ptr<Packet> packet) final { + if (run_one_benchmark_) + run_one_benchmark_->ReceivePacket(std::move(packet)); + }; + + private: + RunOneBenchmark* const run_one_benchmark_; + + DISALLOW_COPY_AND_ASSIGN(TransportClient); +}; + +} // namepspace + +void RunOneBenchmark::Create(const MeasuringPoint& p) { + sender_to_receiver_ = new LoopBackTransport(cast_environment_sender_); + transport_sender_.Init( + new CastTransportSenderImpl( + testing_clock_sender_, base::TimeDelta::FromSeconds(1), + make_scoped_ptr(new TransportClient(nullptr)), + make_scoped_ptr(sender_to_receiver_), task_runner_sender_), + &video_bytes_encoded_, &audio_bytes_encoded_); + + receiver_to_sender_ = new LoopBackTransport(cast_environment_receiver_); + transport_receiver_.reset(new CastTransportSenderImpl( + testing_clock_receiver_, base::TimeDelta::FromSeconds(1), + make_scoped_ptr(new TransportClient(this)), + make_scoped_ptr(receiver_to_sender_), task_runner_receiver_)); + + cast_receiver_ = + CastReceiver::Create(cast_environment_receiver_, audio_receiver_config_, + video_receiver_config_, transport_receiver_.get()); + + cast_sender_ = + CastSender::Create(cast_environment_sender_, &transport_sender_); + + cast_sender_->InitializeAudio(audio_sender_config_, + base::Bind(&ExpectAudioSuccess)); + cast_sender_->InitializeVideo(video_sender_config_, + base::Bind(&ExpectVideoSuccess), + CreateDefaultVideoEncodeAcceleratorCallback(), + CreateDefaultVideoEncodeMemoryCallback()); + + receiver_to_sender_->Initialize(CreateSimplePipe(p), + transport_sender_.PacketReceiverForTesting(), + task_runner_, &testing_clock_); + sender_to_receiver_->Initialize( + CreateSimplePipe(p), transport_receiver_->PacketReceiverForTesting(), + task_runner_, &testing_clock_); + + task_runner_->RunTasks(); +} + enum CacheResult { FOUND_TRUE, FOUND_FALSE, NOT_FOUND }; template <class T> diff --git a/media/cast/test/end2end_unittest.cc b/media/cast/test/end2end_unittest.cc index 2dd2f93..7145ba3 100644 --- a/media/cast/test/end2end_unittest.cc +++ b/media/cast/test/end2end_unittest.cc @@ -94,12 +94,6 @@ std::string ConvertFromBase16String(const std::string& base_16) { return compressed; } -void UpdateCastTransportStatus(CastTransportStatus status) { - bool result = (status == TRANSPORT_AUDIO_INITIALIZED || - status == TRANSPORT_VIDEO_INITIALIZED); - EXPECT_TRUE(result); -} - void ExpectSuccessOperationalStatus(OperationalStatus status) { EXPECT_EQ(STATUS_INITIALIZED, status); } @@ -213,6 +207,11 @@ class LoopBackTransport : public PacketSender { int64_t GetBytesSent() final { return bytes_sent_; } + void StartReceiving( + const PacketReceiverCallbackWithStatus& packet_receiver) final {} + + void StopReceiving() final {} + void SetSendPackets(bool send_packets) { send_packets_ = send_packets; } void DropAllPacketsBelongingToOddFrames() { @@ -397,6 +396,11 @@ class TestReceiverVideoCallback // The actual test class, generate synthetic data for both audio and video and // send those through the sender and receiver and analyzes the result. class End2EndTest : public ::testing::Test { + public: + void ReceivePacket(scoped_ptr<media::cast::Packet> packet) { + cast_receiver_->ReceivePacket(std::move(packet)); + }; + protected: End2EndTest() : start_time_(), @@ -417,8 +421,8 @@ class End2EndTest : public ::testing::Test { task_runner_receiver_, task_runner_receiver_, task_runner_receiver_)), - receiver_to_sender_(cast_environment_receiver_), - sender_to_receiver_(cast_environment_sender_), + receiver_to_sender_(new LoopBackTransport(cast_environment_receiver_)), + sender_to_receiver_(new LoopBackTransport(cast_environment_sender_)), test_receiver_audio_callback_(new TestReceiverAudioCallback()), test_receiver_video_callback_(new TestReceiverVideoCallback()) { testing_clock_.Advance( @@ -549,68 +553,7 @@ class End2EndTest : public ::testing::Test { } } - void ReceivePacket(scoped_ptr<Packet> packet) { - cast_receiver_->ReceivePacket(std::move(packet)); - } - - void Create() { - net::IPEndPoint dummy_endpoint; - transport_sender_.reset(new CastTransportSenderImpl( - nullptr, testing_clock_sender_, dummy_endpoint, dummy_endpoint, - make_scoped_ptr(new base::DictionaryValue), - base::Bind(&UpdateCastTransportStatus), - base::Bind(&LogEventDispatcher::DispatchBatchOfEvents, - base::Unretained(cast_environment_sender_->logger())), - base::TimeDelta::FromMilliseconds(1), task_runner_sender_, - PacketReceiverCallback(), &sender_to_receiver_)); - - transport_receiver_.reset(new CastTransportSenderImpl( - nullptr, testing_clock_sender_, dummy_endpoint, dummy_endpoint, - make_scoped_ptr(new base::DictionaryValue), - base::Bind(&UpdateCastTransportStatus), - base::Bind(&LogEventDispatcher::DispatchBatchOfEvents, - base::Unretained(cast_environment_receiver_->logger())), - base::TimeDelta::FromMilliseconds(1), task_runner_sender_, - base::Bind(&End2EndTest::ReceivePacket, base::Unretained(this)), - &receiver_to_sender_)); - - cast_receiver_ = CastReceiver::Create(cast_environment_receiver_, - audio_receiver_config_, - video_receiver_config_, - transport_receiver_.get()); - - cast_sender_ = - CastSender::Create(cast_environment_sender_, transport_sender_.get()); - - // Initializing audio and video senders. - cast_sender_->InitializeAudio( - audio_sender_config_, - base::Bind(&ExpectSuccessOperationalStatus)); - cast_sender_->InitializeVideo( - video_sender_config_, - base::Bind(&ExpectSuccessOperationalStatus), - CreateDefaultVideoEncodeAcceleratorCallback(), - CreateDefaultVideoEncodeMemoryCallback()); - task_runner_->RunTasks(); - - receiver_to_sender_.SetPacketReceiver( - transport_sender_->PacketReceiverForTesting(), - task_runner_, - &testing_clock_); - sender_to_receiver_.SetPacketReceiver( - transport_receiver_->PacketReceiverForTesting(), - task_runner_, - &testing_clock_); - - audio_frame_input_ = cast_sender_->audio_frame_input(); - video_frame_input_ = cast_sender_->video_frame_input(); - - audio_bus_factory_.reset( - new TestAudioBusFactory(audio_sender_config_.channels, - audio_sender_config_.frequency, - kSoundFrequency, - kSoundVolume)); - } + void Create(); ~End2EndTest() override { cast_environment_sender_->logger()->Unsubscribe(&event_subscriber_sender_); @@ -916,8 +859,9 @@ class End2EndTest : public ::testing::Test { scoped_refptr<CastEnvironment> cast_environment_sender_; scoped_refptr<CastEnvironment> cast_environment_receiver_; - LoopBackTransport receiver_to_sender_; - LoopBackTransport sender_to_receiver_; + LoopBackTransport* receiver_to_sender_; // Owned by CastTransportSender. + LoopBackTransport* sender_to_receiver_; // Owned by CastTransportSender. + scoped_ptr<CastTransportSenderImpl> transport_sender_; scoped_ptr<CastTransportSenderImpl> transport_receiver_; @@ -940,6 +884,83 @@ class End2EndTest : public ::testing::Test { base::MessageLoop message_loop_; }; +namespace { + +class TransportClient : public CastTransportSender::Client { + public: + TransportClient(LogEventDispatcher* log_event_dispatcher, + End2EndTest* e2e_test) + : log_event_dispatcher_(log_event_dispatcher), e2e_test_(e2e_test) {} + + void OnStatusChanged(media::cast::CastTransportStatus status) final { + bool result = (status == TRANSPORT_AUDIO_INITIALIZED || + status == TRANSPORT_VIDEO_INITIALIZED); + EXPECT_TRUE(result); + }; + void OnLoggingEventsReceived( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) final { + log_event_dispatcher_->DispatchBatchOfEvents(std::move(frame_events), + std::move(packet_events)); + }; + void ProcessRtpPacket(scoped_ptr<Packet> packet) final { + if (e2e_test_) + e2e_test_->ReceivePacket(std::move(packet)); + }; + + private: + LogEventDispatcher* const log_event_dispatcher_; // Not owned by this class. + End2EndTest* const e2e_test_; // Not owned by this class. + + DISALLOW_COPY_AND_ASSIGN(TransportClient); +}; + +} // namespace + +void End2EndTest::Create() { + transport_sender_.reset(new CastTransportSenderImpl( + testing_clock_sender_, base::TimeDelta::FromMilliseconds(1), + make_scoped_ptr( + new TransportClient(cast_environment_sender_->logger(), nullptr)), + make_scoped_ptr(sender_to_receiver_), task_runner_sender_)); + + transport_receiver_.reset(new CastTransportSenderImpl( + testing_clock_sender_, base::TimeDelta::FromMilliseconds(1), + make_scoped_ptr( + new TransportClient(cast_environment_receiver_->logger(), this)), + make_scoped_ptr(receiver_to_sender_), task_runner_sender_)); + + cast_receiver_ = + CastReceiver::Create(cast_environment_receiver_, audio_receiver_config_, + video_receiver_config_, transport_receiver_.get()); + + cast_sender_ = + CastSender::Create(cast_environment_sender_, transport_sender_.get()); + + // Initializing audio and video senders. + cast_sender_->InitializeAudio(audio_sender_config_, + base::Bind(&ExpectSuccessOperationalStatus)); + cast_sender_->InitializeVideo(video_sender_config_, + base::Bind(&ExpectSuccessOperationalStatus), + CreateDefaultVideoEncodeAcceleratorCallback(), + CreateDefaultVideoEncodeMemoryCallback()); + task_runner_->RunTasks(); + + receiver_to_sender_->SetPacketReceiver( + transport_sender_->PacketReceiverForTesting(), task_runner_, + &testing_clock_); + sender_to_receiver_->SetPacketReceiver( + transport_receiver_->PacketReceiverForTesting(), task_runner_, + &testing_clock_); + + audio_frame_input_ = cast_sender_->audio_frame_input(); + video_frame_input_ = cast_sender_->video_frame_input(); + + audio_bus_factory_.reset(new TestAudioBusFactory( + audio_sender_config_.channels, audio_sender_config_.frequency, + kSoundFrequency, kSoundVolume)); +} + TEST_F(End2EndTest, LoopWithLosslessEncoding) { Configure(CODEC_VIDEO_FAKE, CODEC_AUDIO_PCM16); Create(); @@ -980,7 +1001,7 @@ TEST_F(End2EndTest, DISABLED_StartSenderBeforeReceiver) { int frame_number = 0; int audio_diff = kFrameTimerMs; - sender_to_receiver_.SetSendPackets(false); + sender_to_receiver_->SetSendPackets(false); const int test_delay_ms = 100; @@ -1015,7 +1036,7 @@ TEST_F(End2EndTest, DISABLED_StartSenderBeforeReceiver) { } RunTasks(test_delay_ms); - sender_to_receiver_.SetSendPackets(true); + sender_to_receiver_->SetSendPackets(true); int num_audio_frames_requested = 0; for (int j = 0; j < 10; ++j) { @@ -1142,8 +1163,8 @@ TEST_F(End2EndTest, SmoothPlayoutWithFivePercentClockRateSkew) { TEST_F(End2EndTest, EvilNetwork) { Configure(CODEC_VIDEO_FAKE, CODEC_AUDIO_PCM16); - receiver_to_sender_.SetPacketPipe(test::EvilNetwork()); - sender_to_receiver_.SetPacketPipe(test::EvilNetwork()); + receiver_to_sender_->SetPacketPipe(test::EvilNetwork()); + sender_to_receiver_->SetPacketPipe(test::EvilNetwork()); Create(); StartBasicPlayer(); @@ -1164,8 +1185,8 @@ TEST_F(End2EndTest, EvilNetwork) { // at a much higher frame rate. TEST_F(End2EndTest, ShoveHighFrameRateDownYerThroat) { Configure(CODEC_VIDEO_FAKE, CODEC_AUDIO_PCM16); - receiver_to_sender_.SetPacketPipe(test::EvilNetwork()); - sender_to_receiver_.SetPacketPipe(test::EvilNetwork()); + receiver_to_sender_->SetPacketPipe(test::EvilNetwork()); + sender_to_receiver_->SetPacketPipe(test::EvilNetwork()); Create(); StartBasicPlayer(); @@ -1185,7 +1206,7 @@ TEST_F(End2EndTest, ShoveHighFrameRateDownYerThroat) { TEST_F(End2EndTest, OldPacketNetwork) { Configure(CODEC_VIDEO_FAKE, CODEC_AUDIO_PCM16); - sender_to_receiver_.SetPacketPipe(test::NewRandomDrop(0.01)); + sender_to_receiver_->SetPacketPipe(test::NewRandomDrop(0.01)); scoped_ptr<test::PacketPipe> echo_chamber( test::NewDuplicateAndDelay(1, 10 * kFrameTimerMs)); echo_chamber->AppendToPipe( @@ -1197,7 +1218,7 @@ TEST_F(End2EndTest, OldPacketNetwork) { echo_chamber->AppendToPipe( test::NewDuplicateAndDelay(1, 160 * kFrameTimerMs)); - receiver_to_sender_.SetPacketPipe(std::move(echo_chamber)); + receiver_to_sender_->SetPacketPipe(std::move(echo_chamber)); Create(); StartBasicPlayer(); diff --git a/media/cast/test/loopback_transport.h b/media/cast/test/loopback_transport.h index e61ae4d..7f32c6f 100644 --- a/media/cast/test/loopback_transport.h +++ b/media/cast/test/loopback_transport.h @@ -36,6 +36,11 @@ class LoopBackTransport : public PacketSender { int64_t GetBytesSent() final; + void StartReceiving( + const PacketReceiverCallbackWithStatus& packet_receiver) final {} + + void StopReceiving() final {} + // Initiailize this loopback transport. // Establish a flow of packets from |pipe| to |packet_receiver|. // diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc index 206bfb5..fa508dc 100644 --- a/media/cast/test/sender.cc +++ b/media/cast/test/sender.cc @@ -160,6 +160,31 @@ void WriteStatsAndDestroySubscribers( VLOG(0) << "Audio stats: " << json; } +class TransportClient : public media::cast::CastTransportSender::Client { + public: + explicit TransportClient( + media::cast::LogEventDispatcher* log_event_dispatcher) + : log_event_dispatcher_(log_event_dispatcher) {} + + void OnStatusChanged(media::cast::CastTransportStatus status) final { + VLOG(1) << "Transport status: " << status; + }; + void OnLoggingEventsReceived( + scoped_ptr<std::vector<media::cast::FrameEvent>> frame_events, + scoped_ptr<std::vector<media::cast::PacketEvent>> packet_events) final { + DCHECK(log_event_dispatcher_); + log_event_dispatcher_->DispatchBatchOfEvents(std::move(frame_events), + std::move(packet_events)); + }; + void ProcessRtpPacket(scoped_ptr<media::cast::Packet> packet) final {} + + private: + media::cast::LogEventDispatcher* const + log_event_dispatcher_; // Not owned by this class. + + DISALLOW_COPY_AND_ASSIGN(TransportClient); +}; + } // namespace int main(int argc, char** argv) { @@ -235,14 +260,12 @@ int main(int argc, char** argv) { // CastTransportSender initialization. scoped_ptr<media::cast::CastTransportSender> transport_sender = media::cast::CastTransportSender::Create( - nullptr, // net log. - cast_environment->Clock(), net::IPEndPoint(), remote_endpoint, - make_scoped_ptr(new base::DictionaryValue), // options - base::Bind(&UpdateCastTransportStatus), - base::Bind(&media::cast::LogEventDispatcher::DispatchBatchOfEvents, - base::Unretained(cast_environment->logger())), - base::TimeDelta::FromSeconds(1), - media::cast::PacketReceiverCallback(), io_message_loop.task_runner()); + cast_environment->Clock(), base::TimeDelta::FromSeconds(1), + make_scoped_ptr(new TransportClient(cast_environment->logger())), + make_scoped_ptr(new media::cast::UdpTransport( + nullptr, io_message_loop.task_runner(), net::IPEndPoint(), + remote_endpoint, base::Bind(&UpdateCastTransportStatus))), + io_message_loop.task_runner()); // 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 a2aa6e4..78c1ccf 100644 --- a/media/cast/test/simulator.cc +++ b/media/cast/test/simulator.cc @@ -114,10 +114,6 @@ int GetIntegerSwitchValue(const char* switch_name, int default_value) { return as_int; } -void UpdateCastTransportStatus(CastTransportStatus status) { - LOG(INFO) << "Cast transport status: " << status; -} - void LogAudioOperationalStatus(OperationalStatus status) { LOG(INFO) << "Audio status: " << status; } @@ -126,6 +122,44 @@ void LogVideoOperationalStatus(OperationalStatus status) { LOG(INFO) << "Video status: " << status; } +struct PacketProxy { + PacketProxy() : receiver(NULL) {} + void ReceivePacket(scoped_ptr<Packet> packet) { + if (receiver) + receiver->ReceivePacket(std::move(packet)); + } + CastReceiver* receiver; +}; + +class TransportClient : public CastTransportSender::Client { + public: + TransportClient(LogEventDispatcher* log_event_dispatcher, + PacketProxy* packet_proxy) + : log_event_dispatcher_(log_event_dispatcher), + packet_proxy_(packet_proxy) {} + + void OnStatusChanged(CastTransportStatus status) final { + LOG(INFO) << "Cast transport status: " << status; + }; + void OnLoggingEventsReceived( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) final { + DCHECK(log_event_dispatcher_); + log_event_dispatcher_->DispatchBatchOfEvents(std::move(frame_events), + std::move(packet_events)); + }; + void ProcessRtpPacket(scoped_ptr<Packet> packet) final { + if (packet_proxy_) + packet_proxy_->ReceivePacket(std::move(packet)); + }; + + private: + LogEventDispatcher* const log_event_dispatcher_; // Not owned by this class. + PacketProxy* const packet_proxy_; // Not owned by this class. + + DISALLOW_COPY_AND_ASSIGN(TransportClient); +}; + // Maintains a queue of encoded video frames. // This works by tracking FRAME_CAPTURE_END and FRAME_ENCODED events. // If a video frame is detected to be encoded it transfers a frame @@ -345,33 +379,19 @@ void RunSimulation(const base::FilePath& source_path, video_receiver_config.rtp_max_delay_ms = video_sender_config.max_playout_delay.InMilliseconds(); - // Loopback transport. - LoopBackTransport receiver_to_sender(receiver_env); - LoopBackTransport sender_to_receiver(sender_env); - - struct PacketProxy { - PacketProxy() : receiver(NULL) {} - void ReceivePacket(scoped_ptr<Packet> packet) { - if (receiver) - receiver->ReceivePacket(std::move(packet)); - } - CastReceiver* receiver; - }; + // Loopback transport. Owned by CastTransportSender. + LoopBackTransport* receiver_to_sender = new LoopBackTransport(receiver_env); + LoopBackTransport* sender_to_receiver = new LoopBackTransport(sender_env); PacketProxy packet_proxy; // Cast receiver. scoped_ptr<CastTransportSender> transport_receiver( new CastTransportSenderImpl( - nullptr, &testing_clock, net::IPEndPoint(), net::IPEndPoint(), - make_scoped_ptr(new base::DictionaryValue), - base::Bind(&UpdateCastTransportStatus), - base::Bind(&LogEventDispatcher::DispatchBatchOfEvents, - base::Unretained(receiver_env->logger())), - base::TimeDelta::FromSeconds(1), task_runner, - base::Bind(&PacketProxy::ReceivePacket, - base::Unretained(&packet_proxy)), - &receiver_to_sender)); + &testing_clock, base::TimeDelta::FromSeconds(1), + make_scoped_ptr( + new TransportClient(receiver_env->logger(), &packet_proxy)), + make_scoped_ptr(receiver_to_sender), task_runner)); scoped_ptr<CastReceiver> cast_receiver( CastReceiver::Create(receiver_env, audio_receiver_config, @@ -382,13 +402,9 @@ void RunSimulation(const base::FilePath& source_path, // Cast sender and transport sender. scoped_ptr<CastTransportSender> transport_sender(new CastTransportSenderImpl( - nullptr, &testing_clock, net::IPEndPoint(), net::IPEndPoint(), - make_scoped_ptr(new base::DictionaryValue), - base::Bind(&UpdateCastTransportStatus), - base::Bind(&LogEventDispatcher::DispatchBatchOfEvents, - base::Unretained(sender_env->logger())), - base::TimeDelta::FromSeconds(1), task_runner, PacketReceiverCallback(), - &sender_to_receiver)); + &testing_clock, base::TimeDelta::FromSeconds(1), + make_scoped_ptr(new TransportClient(sender_env->logger(), nullptr)), + make_scoped_ptr(sender_to_receiver), task_runner)); scoped_ptr<CastSender> cast_sender( CastSender::Create(sender_env, transport_sender.get())); @@ -406,20 +422,19 @@ void RunSimulation(const base::FilePath& source_path, ipp.reset(new test::InterruptedPoissonProcess( average_rates, ipp_model.coef_burstiness(), ipp_model.coef_variance(), 0)); - receiver_to_sender.Initialize(ipp->NewBuffer(128 * 1024), - transport_sender->PacketReceiverForTesting(), - task_runner, &testing_clock); - sender_to_receiver.Initialize( + receiver_to_sender->Initialize(ipp->NewBuffer(128 * 1024), + transport_sender->PacketReceiverForTesting(), + task_runner, &testing_clock); + sender_to_receiver->Initialize( ipp->NewBuffer(128 * 1024), transport_receiver->PacketReceiverForTesting(), task_runner, &testing_clock); } else { LOG(INFO) << "No network simulation."; - receiver_to_sender.Initialize( - scoped_ptr<test::PacketPipe>(), - transport_sender->PacketReceiverForTesting(), - task_runner, &testing_clock); - sender_to_receiver.Initialize( + receiver_to_sender->Initialize(scoped_ptr<test::PacketPipe>(), + transport_sender->PacketReceiverForTesting(), + task_runner, &testing_clock); + sender_to_receiver->Initialize( scoped_ptr<test::PacketPipe>(), transport_receiver->PacketReceiverForTesting(), task_runner, &testing_clock); diff --git a/media/cast/test/utility/in_process_receiver.cc b/media/cast/test/utility/in_process_receiver.cc index 1e97c9a..b4da3a8 100644 --- a/media/cast/test/utility/in_process_receiver.cc +++ b/media/cast/test/utility/in_process_receiver.cc @@ -23,6 +23,19 @@ using media::cast::UdpTransport; namespace media { namespace cast { +void InProcessReceiver::TransportClient::OnStatusChanged( + CastTransportStatus status) { + LOG_IF(ERROR, status == media::cast::TRANSPORT_SOCKET_ERROR) + << "Transport socket error occurred. InProcessReceiver is likely " + "dead."; + VLOG(1) << "CastTransportStatus is now " << status; +} + +void InProcessReceiver::TransportClient::ProcessRtpPacket( + scoped_ptr<Packet> packet) { + in_process_receiver_->ReceivePacket(std::move(packet)); +} + InProcessReceiver::InProcessReceiver( const scoped_refptr<CastEnvironment>& cast_environment, const net::IPEndPoint& local_end_point, @@ -63,8 +76,8 @@ void InProcessReceiver::Stop() { void InProcessReceiver::StopOnMainThread(base::WaitableEvent* event) { DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); - cast_receiver_.reset(NULL); - transport_.reset(NULL); + cast_receiver_.reset(nullptr); + transport_.reset(nullptr); weak_factory_.InvalidateWeakPtrs(); event->Signal(); } @@ -81,17 +94,13 @@ void InProcessReceiver::StartOnMainThread() { DCHECK(!transport_ && !cast_receiver_); transport_ = CastTransportSender::Create( - NULL, - cast_environment_->Clock(), - local_end_point_, - remote_end_point_, - scoped_ptr<base::DictionaryValue>(new base::DictionaryValue), - base::Bind(&InProcessReceiver::UpdateCastTransportStatus, - base::Unretained(this)), - BulkRawEventsCallback(), - base::TimeDelta(), - base::Bind(&InProcessReceiver::ReceivePacket, - base::Unretained(this)), + cast_environment_->Clock(), base::TimeDelta(), + make_scoped_ptr(new InProcessReceiver::TransportClient(this)), + make_scoped_ptr(new UdpTransport( + nullptr, cast_environment_->GetTaskRunner(CastEnvironment::MAIN), + local_end_point_, remote_end_point_, + base::Bind(&InProcessReceiver::UpdateCastTransportStatus, + base::Unretained(this)))), cast_environment_->GetTaskRunner(CastEnvironment::MAIN)); cast_receiver_ = CastReceiver::Create( diff --git a/media/cast/test/utility/in_process_receiver.h b/media/cast/test/utility/in_process_receiver.h index cd957d4..8248ceb 100644 --- a/media/cast/test/utility/in_process_receiver.h +++ b/media/cast/test/utility/in_process_receiver.h @@ -33,6 +33,7 @@ namespace cast { class CastEnvironment; class CastReceiver; class UdpTransport; +class InProcessReceiver; // Common base functionality for an in-process Cast receiver. This is meant to // be subclassed with the OnAudioFrame() and OnVideoFrame() methods implemented, @@ -40,6 +41,23 @@ class UdpTransport; // rather than on the boilerplate "glue" code. class InProcessReceiver { public: + class TransportClient : public CastTransportSender::Client { + public: + explicit TransportClient(InProcessReceiver* in_process_receiver) + : in_process_receiver_(in_process_receiver) {} + + void OnStatusChanged(CastTransportStatus status) final; + void OnLoggingEventsReceived( + scoped_ptr<std::vector<FrameEvent>> frame_events, + scoped_ptr<std::vector<PacketEvent>> packet_events) final {} + void ProcessRtpPacket(scoped_ptr<Packet> packet) final; + + private: + InProcessReceiver* in_process_receiver_; + + DISALLOW_COPY_AND_ASSIGN(TransportClient); + }; + // Construct a receiver with the given configuration. |remote_end_point| can // be left empty, if the transport should automatically mate with the first // remote sender it encounters. |