diff options
author | mikhal@chromium.org <mikhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-04 00:26:10 +0000 |
---|---|---|
committer | mikhal@chromium.org <mikhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-04 00:26:10 +0000 |
commit | 0bec2d88ede93585840b6775be337e5d6ce035d5 (patch) | |
tree | 2bb8cc56d6c60a6cb5b92ca77a002f0b1298fe57 /media/cast | |
parent | 4be5aac332f8cd47b660f8b7b5d8e275d9388d78 (diff) | |
download | chromium_src-0bec2d88ede93585840b6775be337e5d6ce035d5.zip chromium_src-0bec2d88ede93585840b6775be337e5d6ce035d5.tar.gz chromium_src-0bec2d88ede93585840b6775be337e5d6ce035d5.tar.bz2 |
Cast:Transport: Dividing A/V Initialization pipeline
This cl is part of the effort to split the A/V initialization pipeline,
which started in https://chromiumcodereview.appspot.com/163553006/.
Main changes in this cl:
1. Adding initialization functions to audio and video.
2. Changing the Create API to return a scoped ptr.
3. Using weak pointers in lieu of Unretained (part of BUG=344621)
BUG=346822
This cl must be committed prior to issue 163553006
Review URL: https://codereview.chromium.org/174183003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@254615 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/cast')
19 files changed, 257 insertions, 172 deletions
diff --git a/media/cast/audio_sender/audio_sender.cc b/media/cast/audio_sender/audio_sender.cc index bdf6b29..4ca58ea 100644 --- a/media/cast/audio_sender/audio_sender.cc +++ b/media/cast/audio_sender/audio_sender.cc @@ -43,9 +43,11 @@ class LocalRtpSenderStatistics : public RtpSenderStatistics { : transport_sender_(transport_sender), frequency_(0), sender_info_(), - rtp_timestamp_(0) { - transport_sender_->SubscribeAudioRtpStatsCallback(base::Bind( - &LocalRtpSenderStatistics::StoreStatistics, base::Unretained(this))); + rtp_timestamp_(0), + weak_factory_(this) { + transport_sender_->SubscribeAudioRtpStatsCallback( + base::Bind(&LocalRtpSenderStatistics::StoreStatistics, + weak_factory_.GetWeakPtr())); } virtual void GetStatistics(const base::TimeTicks& now, @@ -84,6 +86,8 @@ class LocalRtpSenderStatistics : public RtpSenderStatistics { base::TimeTicks time_sent_; uint32 rtp_timestamp_; + base::WeakPtrFactory<LocalRtpSenderStatistics> weak_factory_; + DISALLOW_IMPLICIT_CONSTRUCTORS(LocalRtpSenderStatistics); }; diff --git a/media/cast/audio_sender/audio_sender_unittest.cc b/media/cast/audio_sender/audio_sender_unittest.cc index 1546996..8db06cb 100644 --- a/media/cast/audio_sender/audio_sender_unittest.cc +++ b/media/cast/audio_sender/audio_sender_unittest.cc @@ -77,16 +77,20 @@ class AudioSenderTest : public ::testing::Test { audio_config_.bitrate = kDefaultAudioEncoderBitrate; audio_config_.rtp_config.payload_type = 127; - transport::CastTransportConfig transport_config; - transport_config.audio_rtp_config.payload_type = 127; - transport_config.audio_channels = 2; + transport::CastTransportAudioConfig transport_config; + transport_config.base.rtp_config.payload_type = 127; + transport_config.channels = 2; + net::IPEndPoint dummy_endpoint; + transport_sender_.reset(new transport::CastTransportSenderImpl( NULL, testing_clock_, - transport_config, + dummy_endpoint, + dummy_endpoint, base::Bind(&UpdateCastTransportStatus), task_runner_, &transport_)); + transport_sender_->InitializeAudio(transport_config); audio_sender_.reset(new AudioSender( cast_environment_, audio_config_, transport_sender_.get())); task_runner_->RunTasks(); @@ -95,7 +99,7 @@ class AudioSenderTest : public ::testing::Test { virtual ~AudioSenderTest() {} static void UpdateCastTransportStatus(transport::CastTransportStatus status) { - EXPECT_EQ(status, transport::TRANSPORT_INITIALIZED); + EXPECT_EQ(status, transport::TRANSPORT_AUDIO_INITIALIZED); } base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. diff --git a/media/cast/rtcp/rtcp_unittest.cc b/media/cast/rtcp/rtcp_unittest.cc index 99e4a32..9ee0523 100644 --- a/media/cast/rtcp/rtcp_unittest.cc +++ b/media/cast/rtcp/rtcp_unittest.cc @@ -158,11 +158,12 @@ class RtcpTest : public ::testing::Test { receiver_to_sender_(cast_environment_, testing_clock_) { testing_clock_->Advance( base::TimeDelta::FromMilliseconds(kStartMillisecond)); - transport::CastTransportConfig transport_config; + net::IPEndPoint dummy_endpoint; transport_sender_.reset(new transport::CastTransportSenderImpl( NULL, testing_clock_, - transport_config, + dummy_endpoint, + dummy_endpoint, base::Bind(&UpdateCastTransportStatus), task_runner_, &sender_to_receiver_)); @@ -172,7 +173,9 @@ class RtcpTest : public ::testing::Test { virtual ~RtcpTest() {} static void UpdateCastTransportStatus(transport::CastTransportStatus status) { - EXPECT_EQ(status, transport::TRANSPORT_INITIALIZED); + bool result = (status == transport::TRANSPORT_AUDIO_INITIALIZED || + status == transport::TRANSPORT_VIDEO_INITIALIZED); + EXPECT_TRUE(result); } void RunTasks(int during_ms) { diff --git a/media/cast/test/end2end_unittest.cc b/media/cast/test/end2end_unittest.cc index 9c4562a..70f7c46 100644 --- a/media/cast/test/end2end_unittest.cc +++ b/media/cast/test/end2end_unittest.cc @@ -90,7 +90,9 @@ std::string ConvertFromBase16String(const std::string base_16) { void OwnThatAudioBus(scoped_ptr<AudioBus> audio_bus) {} void UpdateCastTransportStatus(transport::CastTransportStatus status) { - EXPECT_EQ(status, transport::TRANSPORT_INITIALIZED); + bool result = (status == transport::TRANSPORT_AUDIO_INITIALIZED || + status == transport::TRANSPORT_VIDEO_INITIALIZED); + EXPECT_TRUE(result); } // This is wrapped in a struct because it needs to be put into a std::map. @@ -478,14 +480,14 @@ class End2EndTest : public ::testing::Test { video_receiver_config_.use_external_decoder = false; video_receiver_config_.codec = video_sender_config_.codec; - transport_config_.audio_ssrc = audio_sender_config_.sender_ssrc; - transport_config_.video_ssrc = video_sender_config_.sender_ssrc; - transport_config_.video_codec = video_sender_config_.codec; - transport_config_.audio_codec = audio_sender_config_.codec; - transport_config_.video_rtp_config = video_sender_config_.rtp_config; - transport_config_.audio_rtp_config = audio_sender_config_.rtp_config; - transport_config_.audio_frequency = audio_sender_config_.frequency; - transport_config_.audio_channels = audio_sender_config_.channels; + transport_audio_config_.base.ssrc = audio_sender_config_.sender_ssrc; + transport_audio_config_.codec = audio_sender_config_.codec; + transport_audio_config_.base.rtp_config = audio_sender_config_.rtp_config; + transport_audio_config_.frequency = audio_sender_config_.frequency; + transport_audio_config_.channels = audio_sender_config_.channels; + transport_video_config_.base.ssrc = video_sender_config_.sender_ssrc; + transport_video_config_.codec = video_sender_config_.codec; + transport_video_config_.base.rtp_config = video_sender_config_.rtp_config; } void Create() { @@ -494,13 +496,17 @@ class End2EndTest : public ::testing::Test { audio_receiver_config_, video_receiver_config_, &receiver_to_sender_)); + net::IPEndPoint dummy_endpoint; transport_sender_.reset(new transport::CastTransportSenderImpl( NULL, testing_clock_sender_, - transport_config_, + dummy_endpoint, + dummy_endpoint, base::Bind(&UpdateCastTransportStatus), task_runner_, &sender_to_receiver_)); + transport_sender_->InitializeAudio(transport_audio_config_); + transport_sender_->InitializeVideo(transport_video_config_); cast_sender_.reset(CastSender::CreateCastSender( cast_environment_sender_, @@ -565,7 +571,8 @@ class End2EndTest : public ::testing::Test { VideoReceiverConfig video_receiver_config_; AudioSenderConfig audio_sender_config_; VideoSenderConfig video_sender_config_; - transport::CastTransportConfig transport_config_; + transport::CastTransportAudioConfig transport_audio_config_; + transport::CastTransportVideoConfig transport_video_config_; base::TimeTicks start_time_; base::SimpleTestTickClock* testing_clock_sender_; @@ -974,13 +981,13 @@ TEST_F(End2EndTest, ResetReferenceFrameId) { TEST_F(End2EndTest, CryptoVideo) { SetupConfig(transport::kPcm16, 32000, false, 1); - transport_config_.aes_iv_mask = + transport_video_config_.base.aes_iv_mask = ConvertFromBase16String("1234567890abcdeffedcba0987654321"); - transport_config_.aes_key = + transport_video_config_.base.aes_key = ConvertFromBase16String("deadbeefcafeb0b0b0b0cafedeadbeef"); - video_receiver_config_.aes_iv_mask = transport_config_.aes_iv_mask; - video_receiver_config_.aes_key = transport_config_.aes_key; + video_receiver_config_.aes_iv_mask = transport_video_config_.base.aes_iv_mask; + video_receiver_config_.aes_key = transport_video_config_.base.aes_key; Create(); @@ -1011,13 +1018,13 @@ TEST_F(End2EndTest, CryptoVideo) { TEST_F(End2EndTest, CryptoAudio) { SetupConfig(transport::kPcm16, 32000, false, 1); - transport_config_.aes_iv_mask = + transport_audio_config_.base.aes_iv_mask = ConvertFromBase16String("abcdeffedcba12345678900987654321"); - transport_config_.aes_key = + transport_audio_config_.base.aes_key = ConvertFromBase16String("deadbeefcafecafedeadbeefb0b0b0b0"); - audio_receiver_config_.aes_iv_mask = transport_config_.aes_iv_mask; - audio_receiver_config_.aes_key = transport_config_.aes_key; + audio_receiver_config_.aes_iv_mask = transport_audio_config_.base.aes_iv_mask; + audio_receiver_config_.aes_key = transport_audio_config_.base.aes_key; Create(); diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc index 16f55dc..af369eb 100644 --- a/media/cast/test/sender.cc +++ b/media/cast/test/sender.cc @@ -411,21 +411,27 @@ int main(int argc, char** argv) { media::cast::GetVideoSenderConfig(); // Setting up transport config. - media::cast::transport::CastTransportConfig config; - config.receiver_endpoint = CreateUDPAddress(remote_ip_address, remote_port); - config.local_endpoint = CreateUDPAddress("0.0.0.0", 0); - config.audio_ssrc = audio_config.sender_ssrc; - config.video_ssrc = video_config.sender_ssrc; - config.audio_rtp_config = audio_config.rtp_config; - config.video_rtp_config = video_config.rtp_config; - - scoped_ptr<media::cast::transport::CastTransportSender> transport_sender( - media::cast::transport::CastTransportSender::CreateCastTransportSender( - NULL, + media::cast::transport::CastTransportAudioConfig transport_audio_config; + media::cast::transport::CastTransportVideoConfig transport_video_config; + net::IPEndPoint remote_endpoint = + CreateUDPAddress(remote_ip_address, remote_port); + net::IPEndPoint local_endpoint = CreateUDPAddress("0.0.0.0", 0); + transport_audio_config.base.ssrc = audio_config.sender_ssrc; + transport_audio_config.base.rtp_config = audio_config.rtp_config; + transport_video_config.base.ssrc = video_config.sender_ssrc; + transport_video_config.base.rtp_config = video_config.rtp_config; + + scoped_ptr<media::cast::transport::CastTransportSender> transport_sender = + media::cast::transport::CastTransportSender::Create( + NULL, // net log. clock.get(), - config, + local_endpoint, + remote_endpoint, base::Bind(&UpdateCastTransportStatus), - io_message_loop.message_loop_proxy())); + io_message_loop.message_loop_proxy()); + + transport_sender->InitializeAudio(transport_audio_config); + transport_sender->InitializeVideo(transport_video_config); // Enable main and send side threads only. Enable raw event and stats logging. // Running transport on the main thread. diff --git a/media/cast/transport/cast_transport_config.cc b/media/cast/transport/cast_transport_config.cc index 1ec6be5..cdff2fc 100644 --- a/media/cast/transport/cast_transport_config.cc +++ b/media/cast/transport/cast_transport_config.cc @@ -18,17 +18,19 @@ RtpConfig::RtpConfig() max_delay_ms(kDefaultRtpMaxDelayMs), payload_type(0) {} -CastTransportConfig::CastTransportConfig() - : audio_ssrc(0), - video_ssrc(0), - video_codec(kVp8), - audio_codec(kOpus), - audio_frequency(0), - audio_channels(0), - aes_key(""), - aes_iv_mask("") {} - -CastTransportConfig::~CastTransportConfig() {} +CastTransportBaseConfig::CastTransportBaseConfig() + : ssrc(0) {} + +CastTransportBaseConfig::~CastTransportBaseConfig() {} + +CastTransportAudioConfig::CastTransportAudioConfig() + : codec(kOpus), frequency(0), channels(0) {} + +CastTransportAudioConfig::~CastTransportAudioConfig() {} + +CastTransportVideoConfig::CastTransportVideoConfig() : codec(kVp8) {} + +CastTransportVideoConfig::~CastTransportVideoConfig() {} EncodedVideoFrame::EncodedVideoFrame() : codec(kVp8), @@ -70,8 +72,7 @@ RtcpDlrrReportBlock::RtcpDlrrReportBlock() RtcpDlrrReportBlock::~RtcpDlrrReportBlock() {} SendRtcpFromRtpSenderData::SendRtcpFromRtpSenderData() - : packet_type_flags(0), - sending_ssrc(0) {} + : packet_type_flags(0), sending_ssrc(0) {} SendRtcpFromRtpSenderData::~SendRtcpFromRtpSenderData() {} } // namespace transport diff --git a/media/cast/transport/cast_transport_config.h b/media/cast/transport/cast_transport_config.h index 90d039c..9191606 100644 --- a/media/cast/transport/cast_transport_config.h +++ b/media/cast/transport/cast_transport_config.h @@ -43,29 +43,33 @@ struct RtpConfig { int payload_type; }; -struct CastTransportConfig { - CastTransportConfig(); - ~CastTransportConfig(); +// TODO(mikhal): Consider combining this with the cast_sender config. +struct CastTransportBaseConfig { + CastTransportBaseConfig(); + ~CastTransportBaseConfig(); - // Transport: Local receiver. - net::IPEndPoint receiver_endpoint; - net::IPEndPoint local_endpoint; - - uint32 audio_ssrc; - uint32 video_ssrc; + uint32 ssrc; + RtpConfig rtp_config; + std::string aes_key; // Binary string of size kAesKeySize. + std::string aes_iv_mask; // Binary string of size kAesBlockSize. +}; - VideoCodec video_codec; - AudioCodec audio_codec; +struct CastTransportAudioConfig { + CastTransportAudioConfig(); + ~CastTransportAudioConfig(); - // RTP. - RtpConfig audio_rtp_config; - RtpConfig video_rtp_config; + CastTransportBaseConfig base; + AudioCodec codec; + int frequency; + int channels; +}; - int audio_frequency; - int audio_channels; +struct CastTransportVideoConfig { + CastTransportVideoConfig(); + ~CastTransportVideoConfig(); - std::string aes_key; // Binary string of size kAesKeySize. - std::string aes_iv_mask; // Binary string of size kAesBlockSize. + CastTransportBaseConfig base; + VideoCodec codec; }; struct EncodedVideoFrame { diff --git a/media/cast/transport/cast_transport_defines.h b/media/cast/transport/cast_transport_defines.h index 7d8f766..72089fc 100644 --- a/media/cast/transport/cast_transport_defines.h +++ b/media/cast/transport/cast_transport_defines.h @@ -18,8 +18,10 @@ namespace transport { // TODO(mikhal): Implement and add more types. enum CastTransportStatus { - TRANSPORT_UNINITIALIZED = 0, - TRANSPORT_INITIALIZED, + TRANSPORT_AUDIO_UNINITIALIZED = 0, + TRANSPORT_VIDEO_UNINITIALIZED, + TRANSPORT_AUDIO_INITIALIZED, + TRANSPORT_VIDEO_INITIALIZED, TRANSPORT_INVALID_CRYPTO_CONFIG, TRANSPORT_SOCKET_ERROR, CAST_TRANSPORT_STATUS_LAST = TRANSPORT_SOCKET_ERROR diff --git a/media/cast/transport/cast_transport_sender.h b/media/cast/transport/cast_transport_sender.h index 63f6312..5bfa00e 100644 --- a/media/cast/transport/cast_transport_sender.h +++ b/media/cast/transport/cast_transport_sender.h @@ -5,7 +5,6 @@ // This is the main interface for the cast transport sender. The cast sender // handles the cast pipeline from encoded frames (both audio and video), to // encryption, packetization and transport. -// All configurations are done at creation. // Construction of the Cast Sender and the Cast Transport Sender should be done // in the following order: @@ -13,6 +12,8 @@ // 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. +// 4. Initialize audio and/or video. +// Steps 3 & 4 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 @@ -39,6 +40,8 @@ namespace media { namespace cast { namespace transport { +// Following the initialization of either audio or video an initialization +// status will be sent via this callback. typedef base::Callback<void(CastTransportStatus status)> CastTransportStatusCallback; @@ -49,15 +52,23 @@ typedef base::Callback<void(const RtcpSenderInfo& sender_info, // The application should only trigger this class from the transport thread. class CastTransportSender : public base::NonThreadSafe { public: - static CastTransportSender* CreateCastTransportSender( + static scoped_ptr<CastTransportSender> Create( net::NetLog* net_log, base::TickClock* clock, - const CastTransportConfig& config, + const net::IPEndPoint& local_end_point, + const net::IPEndPoint& remote_end_point, const CastTransportStatusCallback& status_callback, const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner); virtual ~CastTransportSender() {} + // Audio/Video initialization. + // Encoded frames cannot be transmitted until the relevant initialize method + // is called. + virtual void InitializeAudio(const CastTransportAudioConfig& config) = 0; + + virtual void InitializeVideo(const CastTransportVideoConfig& 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( @@ -85,9 +96,9 @@ class CastTransportSender : public base::NonThreadSafe { bool is_audio, const MissingFramesAndPacketsMap& missing_packets) = 0; - // Audio/Video RTP statistics. // RTP statistics will be returned on a regular interval on the designated // callback. + // Must be called after initialization of the corresponding A/V pipeline. virtual void SubscribeAudioRtpStatsCallback( const CastTransportRtpStatistics& callback) = 0; diff --git a/media/cast/transport/cast_transport_sender_impl.cc b/media/cast/transport/cast_transport_sender_impl.cc index d8f0de2..9975e3a 100644 --- a/media/cast/transport/cast_transport_sender_impl.cc +++ b/media/cast/transport/cast_transport_sender_impl.cc @@ -12,48 +12,67 @@ namespace media { namespace cast { namespace transport { -CastTransportSender* CastTransportSender::CreateCastTransportSender( +scoped_ptr<CastTransportSender> CastTransportSender::Create( net::NetLog* net_log, base::TickClock* clock, - const CastTransportConfig& config, + const net::IPEndPoint& local_end_point, + const net::IPEndPoint& remote_end_point, const CastTransportStatusCallback& status_callback, const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) { - return new CastTransportSenderImpl(net_log, - clock, - config, - status_callback, - transport_task_runner.get(), - NULL); + return scoped_ptr<CastTransportSender>( + new CastTransportSenderImpl(net_log, + clock, + local_end_point, + remote_end_point, + status_callback, + transport_task_runner.get(), + NULL)); } CastTransportSenderImpl::CastTransportSenderImpl( net::NetLog* net_log, base::TickClock* clock, - const CastTransportConfig& config, + const net::IPEndPoint& local_end_point, + const net::IPEndPoint& remote_end_point, const CastTransportStatusCallback& status_callback, const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, PacketSender* external_transport) - : transport_(external_transport ? NULL + : clock_(clock), + status_callback_(status_callback), + transport_task_runner_(transport_task_runner), + transport_(external_transport ? NULL : new UdpTransport(net_log, transport_task_runner, - config.local_endpoint, - config.receiver_endpoint, + local_end_point, + remote_end_point, status_callback)), pacer_(clock, external_transport ? external_transport : transport_.get(), transport_task_runner), - rtcp_builder_(&pacer_), - audio_sender_(config, clock, transport_task_runner, &pacer_), - video_sender_(config, clock, transport_task_runner, &pacer_) { - if (audio_sender_.initialized() && video_sender_.initialized()) { - status_callback.Run(TRANSPORT_INITIALIZED); - } else { - status_callback.Run(TRANSPORT_UNINITIALIZED); - } -} + rtcp_builder_(&pacer_) {} CastTransportSenderImpl::~CastTransportSenderImpl() {} +void CastTransportSenderImpl::InitializeAudio( + const CastTransportAudioConfig& config) { + audio_sender_.reset(new TransportAudioSender( + config, clock_, transport_task_runner_, &pacer_)); + if (audio_sender_->initialized()) + status_callback_.Run(TRANSPORT_AUDIO_INITIALIZED); + else + status_callback_.Run(TRANSPORT_AUDIO_UNINITIALIZED); +} + +void CastTransportSenderImpl::InitializeVideo( + const CastTransportVideoConfig& config) { + video_sender_.reset(new TransportVideoSender( + config, clock_, transport_task_runner_, &pacer_)); + if (video_sender_->initialized()) + status_callback_.Run(TRANSPORT_VIDEO_INITIALIZED); + else + status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED); +} + void CastTransportSenderImpl::SetPacketReceiver( const PacketReceiverCallback& packet_receiver) { transport_->StartReceiving(packet_receiver); @@ -62,13 +81,15 @@ void CastTransportSenderImpl::SetPacketReceiver( void CastTransportSenderImpl::InsertCodedAudioFrame( const EncodedAudioFrame* audio_frame, const base::TimeTicks& recorded_time) { - audio_sender_.InsertCodedAudioFrame(audio_frame, recorded_time); + DCHECK(audio_sender_) << "Audio sender uninitialized"; + audio_sender_->InsertCodedAudioFrame(audio_frame, recorded_time); } void CastTransportSenderImpl::InsertCodedVideoFrame( const EncodedVideoFrame* video_frame, const base::TimeTicks& capture_time) { - video_sender_.InsertCodedVideoFrame(video_frame, capture_time); + DCHECK(video_sender_) << "Video sender uninitialized"; + video_sender_->InsertCodedVideoFrame(video_frame, capture_time); } void CastTransportSenderImpl::SendRtcpFromRtpSender( @@ -86,20 +107,24 @@ void CastTransportSenderImpl::ResendPackets( bool is_audio, const MissingFramesAndPacketsMap& missing_packets) { if (is_audio) { - audio_sender_.ResendPackets(missing_packets); + DCHECK(audio_sender_) << "Audio sender uninitialized"; + audio_sender_->ResendPackets(missing_packets); } else { - video_sender_.ResendPackets(missing_packets); + DCHECK(video_sender_) << "Video sender uninitialized"; + video_sender_->ResendPackets(missing_packets); } } void CastTransportSenderImpl::SubscribeAudioRtpStatsCallback( const CastTransportRtpStatistics& callback) { - audio_sender_.SubscribeAudioRtpStatsCallback(callback); + DCHECK(audio_sender_) << "Audio sender uninitialized"; + audio_sender_->SubscribeAudioRtpStatsCallback(callback); } void CastTransportSenderImpl::SubscribeVideoRtpStatsCallback( const CastTransportRtpStatistics& callback) { - video_sender_.SubscribeVideoRtpStatsCallback(callback); + DCHECK(video_sender_) << "Audio sender uninitialized"; + video_sender_->SubscribeVideoRtpStatsCallback(callback); } } // namespace transport diff --git a/media/cast/transport/cast_transport_sender_impl.h b/media/cast/transport/cast_transport_sender_impl.h index d1f7d9a..b7ee50a 100644 --- a/media/cast/transport/cast_transport_sender_impl.h +++ b/media/cast/transport/cast_transport_sender_impl.h @@ -29,13 +29,18 @@ class CastTransportSenderImpl : public CastTransportSender { CastTransportSenderImpl( net::NetLog* net_log, base::TickClock* clock, - const CastTransportConfig& config, + const net::IPEndPoint& local_end_point, + const net::IPEndPoint& remote_end_point, const CastTransportStatusCallback& status_callback, const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, PacketSender* external_transport); virtual ~CastTransportSenderImpl(); + virtual void InitializeAudio(const CastTransportAudioConfig& config) OVERRIDE; + + virtual void InitializeVideo(const CastTransportVideoConfig& config) OVERRIDE; + // CastTransportSender implementation. virtual void SetPacketReceiver(const PacketReceiverCallback& packet_receiver) OVERRIDE; @@ -66,11 +71,14 @@ class CastTransportSenderImpl : public CastTransportSender { const CastTransportRtpStatistics& callback) OVERRIDE; private: + base::TickClock* clock_; // Not owned by this class. + CastTransportStatusCallback status_callback_; + scoped_refptr<base::SingleThreadTaskRunner> transport_task_runner_; scoped_ptr<UdpTransport> transport_; PacedSender pacer_; RtcpBuilder rtcp_builder_; - TransportAudioSender audio_sender_; - TransportVideoSender video_sender_; + scoped_ptr<TransportAudioSender> audio_sender_; + scoped_ptr<TransportVideoSender> video_sender_; DISALLOW_COPY_AND_ASSIGN(CastTransportSenderImpl); }; diff --git a/media/cast/transport/pacing/paced_sender.h b/media/cast/transport/pacing/paced_sender.h index 80e2b3f..69a6079 100644 --- a/media/cast/transport/pacing/paced_sender.h +++ b/media/cast/transport/pacing/paced_sender.h @@ -76,7 +76,7 @@ class PacedSender : public PacedPacketSender, // Not owned by this class. base::TickClock* const clock_; PacketSender* transport_; // Not owned by this class. - scoped_refptr<base::TaskRunner> transport_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> transport_task_runner_; size_t burst_size_; size_t packets_sent_in_burst_; base::TimeTicks time_last_process_; diff --git a/media/cast/transport/rtp_sender/rtp_sender.cc b/media/cast/transport/rtp_sender/rtp_sender.cc index 91122de..b08c541 100644 --- a/media/cast/transport/rtp_sender/rtp_sender.cc +++ b/media/cast/transport/rtp_sender/rtp_sender.cc @@ -20,53 +20,55 @@ static const int kStatsCallbackIntervalMs = 33; RtpSender::RtpSender( base::TickClock* clock, - const CastTransportConfig& config, - bool is_audio, - const scoped_refptr<base::TaskRunner>& transport_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, PacedSender* const transport) - : config_(), + : clock_(clock), transport_(transport), stats_callback_(), - transport_task_runner_(transport_task_runner) { - // Store generic cast config and create packetizer config. - if (is_audio) { - storage_.reset( - new PacketStorage(clock, config.audio_rtp_config.history_ms)); - config_.audio = true; - config_.ssrc = config.audio_ssrc; - config_.payload_type = config.audio_rtp_config.payload_type; - config_.frequency = config.audio_frequency; - config_.audio_codec = config.audio_codec; - } else { - storage_.reset( - new PacketStorage(clock, config.audio_rtp_config.history_ms)); - config_.audio = false; - config_.ssrc = config.video_ssrc; - config_.payload_type = config.video_rtp_config.payload_type; - config_.frequency = kVideoFrequency; - config_.video_codec = config.video_codec; - } - // Randomly set start values. + transport_task_runner_(transport_task_runner), + weak_factory_(this) { + // Randomly set sequence number start value. config_.sequence_number = base::RandInt(0, 65535); - packetizer_.reset( - new RtpPacketizer(transport, storage_.get(), config_)); } RtpSender::~RtpSender() {} +void RtpSender::InitializeAudio(const CastTransportAudioConfig& config) { + storage_.reset(new PacketStorage(clock_, config.base.rtp_config.history_ms)); + config_.audio = true; + config_.ssrc = config.base.ssrc; + config_.payload_type = config.base.rtp_config.payload_type; + config_.frequency = config.frequency; + config_.audio_codec = config.codec; + packetizer_.reset(new RtpPacketizer(transport_, storage_.get(), config_)); +} + +void RtpSender::InitializeVideo(const CastTransportVideoConfig& config) { + storage_.reset(new PacketStorage(clock_, config.base.rtp_config.history_ms)); + config_.audio = false; + config_.ssrc = config.base.ssrc; + config_.payload_type = config.base.rtp_config.payload_type; + config_.frequency = kVideoFrequency; + config_.video_codec = config.codec; + packetizer_.reset(new RtpPacketizer(transport_, storage_.get(), config_)); +} + void RtpSender::IncomingEncodedVideoFrame(const EncodedVideoFrame* video_frame, const base::TimeTicks& capture_time) { + DCHECK(packetizer_); packetizer_->IncomingEncodedVideoFrame(video_frame, capture_time); } void RtpSender::IncomingEncodedAudioFrame( const EncodedAudioFrame* audio_frame, const base::TimeTicks& recorded_time) { + DCHECK(packetizer_); packetizer_->IncomingEncodedAudioFrame(audio_frame, recorded_time); } void RtpSender::ResendPackets( const MissingFramesAndPacketsMap& missing_frames_and_packets) { + DCHECK(storage_); // Iterate over all frames in the list. for (MissingFramesAndPacketsMap::const_iterator it = missing_frames_and_packets.begin(); @@ -133,7 +135,7 @@ void RtpSender::SubscribeRtpStatsCallback( void RtpSender::ScheduleNextStatsReport() { transport_task_runner_->PostDelayedTask( FROM_HERE, - base::Bind(&RtpSender::RtpStatistics, base::AsWeakPtr(this)), + base::Bind(&RtpSender::RtpStatistics, weak_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(kStatsCallbackIntervalMs)); } diff --git a/media/cast/transport/rtp_sender/rtp_sender.h b/media/cast/transport/rtp_sender/rtp_sender.h index 4fc4957..eea95d3 100644 --- a/media/cast/transport/rtp_sender/rtp_sender.h +++ b/media/cast/transport/rtp_sender/rtp_sender.h @@ -30,16 +30,23 @@ namespace transport { // This class handles splitting encoded audio and video frames into packets and // add an RTP header to each packet. The sent packets are stored until they are // acknowledged by the remote peer or timed out. -class RtpSender : public base::SupportsWeakPtr<RtpSender>{ +class RtpSender { public: - RtpSender(base::TickClock* clock, - const CastTransportConfig& config, - bool is_audio, - const scoped_refptr<base::TaskRunner>& transport_task_runner, - PacedSender* const transport); + RtpSender( + base::TickClock* clock, + const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, + PacedSender* const transport); ~RtpSender(); + // Initialize audio stack. Audio must be initialized prior to sending encoded + // audio frames. + void InitializeAudio(const CastTransportAudioConfig& config); + + // Initialize video stack. Video must be initialized prior to sending encoded + // video frames. + void InitializeVideo(const CastTransportVideoConfig& config); + // The video_frame objects ownership is handled by the main cast thread. void IncomingEncodedVideoFrame(const EncodedVideoFrame* video_frame, const base::TimeTicks& capture_time); @@ -60,12 +67,15 @@ class RtpSender : public base::SupportsWeakPtr<RtpSender>{ void RtpStatistics(); void UpdateSequenceNumber(Packet* packet); + base::TickClock* clock_; // Not owned by this class. RtpPacketizerConfig config_; scoped_ptr<RtpPacketizer> packetizer_; scoped_ptr<PacketStorage> storage_; PacedSender* const transport_; CastTransportRtpStatistics stats_callback_; - scoped_refptr<base::TaskRunner> transport_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> transport_task_runner_; + + base::WeakPtrFactory<RtpSender> weak_factory_; DISALLOW_COPY_AND_ASSIGN(RtpSender); }; diff --git a/media/cast/transport/transport_audio_sender.cc b/media/cast/transport/transport_audio_sender.cc index 818f9b1..b704e23 100644 --- a/media/cast/transport/transport_audio_sender.cc +++ b/media/cast/transport/transport_audio_sender.cc @@ -14,17 +14,15 @@ namespace cast { namespace transport { TransportAudioSender::TransportAudioSender( - const CastTransportConfig& config, + const CastTransportAudioConfig& config, base::TickClock* clock, - const scoped_refptr<base::TaskRunner>& transport_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, PacedSender* const paced_packet_sender) - : rtp_sender_(clock, - config, - true, - transport_task_runner, - paced_packet_sender), + : rtp_sender_(clock, transport_task_runner, paced_packet_sender), encryptor_() { - initialized_ = encryptor_.Initialize(config.aes_key, config.aes_iv_mask); + rtp_sender_.InitializeAudio(config); + initialized_ = + encryptor_.Initialize(config.base.aes_key, config.base.aes_iv_mask); } TransportAudioSender::~TransportAudioSender() {} @@ -47,7 +45,7 @@ bool TransportAudioSender::EncryptAudioFrame( const EncodedAudioFrame& audio_frame, EncodedAudioFrame* encrypted_frame) { if (!encryptor_.Encrypt( - audio_frame.frame_id, audio_frame.data, &encrypted_frame->data)) + audio_frame.frame_id, audio_frame.data, &encrypted_frame->data)) return false; encrypted_frame->codec = audio_frame.codec; diff --git a/media/cast/transport/transport_audio_sender.h b/media/cast/transport/transport_audio_sender.h index c988714..4be74a9 100644 --- a/media/cast/transport/transport_audio_sender.h +++ b/media/cast/transport/transport_audio_sender.h @@ -22,9 +22,9 @@ class PacedSender; class TransportAudioSender : public base::NonThreadSafe { public: TransportAudioSender( - const CastTransportConfig& config, + const CastTransportAudioConfig& config, base::TickClock* clock, - const scoped_refptr<base::TaskRunner>& transport_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, PacedSender* const paced_packet_sender); virtual ~TransportAudioSender(); diff --git a/media/cast/transport/transport_video_sender.cc b/media/cast/transport/transport_video_sender.cc index 060184f..1862458 100644 --- a/media/cast/transport/transport_video_sender.cc +++ b/media/cast/transport/transport_video_sender.cc @@ -17,19 +17,17 @@ namespace cast { namespace transport { TransportVideoSender::TransportVideoSender( - const CastTransportConfig& config, + const CastTransportVideoConfig& config, base::TickClock* clock, - const scoped_refptr<base::TaskRunner>& transport_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, PacedSender* const paced_packet_sender) : rtp_max_delay_(base::TimeDelta::FromMilliseconds( - config.video_rtp_config.max_delay_ms)), + config.base.rtp_config.max_delay_ms)), encryptor_(), - rtp_sender_(clock, - config, - false, - transport_task_runner, - paced_packet_sender) { - initialized_ = encryptor_.Initialize(config.aes_key, config.aes_iv_mask); + rtp_sender_(clock, transport_task_runner, paced_packet_sender) { + rtp_sender_.InitializeVideo(config); + initialized_ = + encryptor_.Initialize(config.base.aes_key, config.base.aes_iv_mask); } TransportVideoSender::~TransportVideoSender() {} @@ -57,7 +55,7 @@ bool TransportVideoSender::EncryptVideoFrame( const EncodedVideoFrame& video_frame, EncodedVideoFrame* encrypted_frame) { if (!encryptor_.Encrypt( - video_frame.frame_id, video_frame.data, &(encrypted_frame->data))) + video_frame.frame_id, video_frame.data, &(encrypted_frame->data))) return false; encrypted_frame->codec = video_frame.codec; diff --git a/media/cast/transport/transport_video_sender.h b/media/cast/transport/transport_video_sender.h index 2de67f1..3ed293a 100644 --- a/media/cast/transport/transport_video_sender.h +++ b/media/cast/transport/transport_video_sender.h @@ -19,7 +19,6 @@ class VideoFrame; namespace cast { namespace transport { - class PacedSender; // Not thread safe. Only called from the main cast transport thread. @@ -28,9 +27,9 @@ class PacedSender; class TransportVideoSender : public base::NonThreadSafe { public: TransportVideoSender( - const CastTransportConfig& config, + const CastTransportVideoConfig& config, base::TickClock* clock, - const scoped_refptr<base::TaskRunner>& transport_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, PacedSender* const paced_packet_sender); virtual ~TransportVideoSender(); diff --git a/media/cast/video_sender/video_sender_unittest.cc b/media/cast/video_sender/video_sender_unittest.cc index 2f5c06e..130dac9 100644 --- a/media/cast/video_sender/video_sender_unittest.cc +++ b/media/cast/video_sender/video_sender_unittest.cc @@ -90,14 +90,17 @@ class VideoSenderTest : public ::testing::Test { task_runner_, task_runner_, GetLoggingConfigWithRawEventsAndStatsEnabled()); - transport::CastTransportConfig transport_config; + transport::CastTransportVideoConfig transport_config; + net::IPEndPoint dummy_endpoint; transport_sender_.reset(new transport::CastTransportSenderImpl( NULL, testing_clock_, - transport_config, + dummy_endpoint, + dummy_endpoint, base::Bind(&UpdateCastTransportStatus), task_runner_, &transport_)); + transport_sender_->InitializeVideo(transport_config); } virtual ~VideoSenderTest() {} @@ -108,7 +111,7 @@ class VideoSenderTest : public ::testing::Test { } static void UpdateCastTransportStatus(transport::CastTransportStatus status) { - EXPECT_EQ(status, transport::TRANSPORT_INITIALIZED); + EXPECT_EQ(status, transport::TRANSPORT_VIDEO_INITIALIZED); } void InitEncoder(bool external) { |