diff options
author | hubbe@chromium.org <hubbe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-15 19:45:17 +0000 |
---|---|---|
committer | hubbe@chromium.org <hubbe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-15 19:45:17 +0000 |
commit | 1ea4c493152c8b225d397ade32ef1023870293c3 (patch) | |
tree | 2a501aa3b654e498925b34f4e95dc75840491334 | |
parent | f53f76329e5a7c2c435a28d28bbadff1078f7e72 (diff) | |
download | chromium_src-1ea4c493152c8b225d397ade32ef1023870293c3.zip chromium_src-1ea4c493152c8b225d397ade32ef1023870293c3.tar.gz chromium_src-1ea4c493152c8b225d397ade32ef1023870293c3.tar.bz2 |
IPC glue between cast library transport and encoders.
This CL lets the cast library run the packetizing and encryption in the browser and the video and audio encoding in the renderer. The encoded data is sent over IPC to the browser.
BUG=301920
Review URL: https://codereview.chromium.org/138753004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251592 0039d316-1c4b-4281-b951-d872f2087c98
40 files changed, 1126 insertions, 136 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index e89e889..428cff0 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -46,6 +46,7 @@ #include "chrome/browser/guestview/guestview_constants.h" #include "chrome/browser/guestview/webview/webview_guest.h" #include "chrome/browser/local_discovery/storage/privet_filesystem_backend.h" +#include "chrome/browser/media/cast_transport_host_filter.h" #include "chrome/browser/media/media_capture_devices_dispatcher.h" #include "chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.h" #include "chrome/browser/nacl_host/nacl_browser_delegate_impl.h" @@ -912,6 +913,7 @@ void ChromeContentBrowserClient::RenderProcessWillLaunch( #if defined(ENABLE_PLUGINS) host->AddFilter(new PluginInfoMessageFilter(id, profile)); #endif + host->AddFilter(new cast::CastTransportHostFilter); #if defined(ENABLE_PRINTING) host->AddFilter(new PrintingMessageFilter(id, profile)); #endif diff --git a/chrome/browser/media/DEPS b/chrome/browser/media/DEPS index c9dd508..87894e2 100644 --- a/chrome/browser/media/DEPS +++ b/chrome/browser/media/DEPS @@ -1,6 +1,7 @@ include_rules = [ "+media/audio", "+media/base", + "+media/cast", "+third_party/libyuv", "+third_party/webrtc", "+third_party/zlib" diff --git a/chrome/browser/media/cast_transport_host_filter.cc b/chrome/browser/media/cast_transport_host_filter.cc new file mode 100644 index 0000000..fe5ccac --- /dev/null +++ b/chrome/browser/media/cast_transport_host_filter.cc @@ -0,0 +1,172 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/media/cast_transport_host_filter.h" +#include "media/cast/transport/cast_transport_sender.h" + +namespace cast { + +CastTransportHostFilter::CastTransportHostFilter() { +} + +CastTransportHostFilter::~CastTransportHostFilter() { +} + +bool CastTransportHostFilter::OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP_EX(CastTransportHostFilter, message, *message_was_ok) + IPC_MESSAGE_HANDLER(CastHostMsg_New, OnNew) + IPC_MESSAGE_HANDLER(CastHostMsg_Delete, OnDelete) + IPC_MESSAGE_HANDLER(CastHostMsg_InsertCodedAudioFrame, + OnInsertCodedAudioFrame) + IPC_MESSAGE_HANDLER(CastHostMsg_InsertCodedVideoFrame, + OnInsertCodedVideoFrame) + IPC_MESSAGE_HANDLER(CastHostMsg_SendRtcpFromRtpSender, + OnSendRtcpFromRtpSender); + IPC_MESSAGE_HANDLER(CastHostMsg_ResendPackets, + OnResendPackets) + IPC_MESSAGE_UNHANDLED(handled = false); + IPC_END_MESSAGE_MAP_EX(); + return handled; +} + +void CastTransportHostFilter::NotifyStatusChange( + int32 channel_id, + media::cast::transport::CastTransportStatus status) { + Send(new CastMsg_NotifyStatusChange(channel_id, status)); +} + +void CastTransportHostFilter::ReceivedPacket( + int32 channel_id, + scoped_ptr<media::cast::transport::Packet> packet) { + Send(new CastMsg_ReceivedPacket(channel_id, *packet)); +} + +void CastTransportHostFilter::ReceivedRtpStatistics( + int32 channel_id, + bool audio, + const media::cast::transport::RtcpSenderInfo& sender_info, + base::TimeTicks time_sent, + uint32 rtp_timestamp) { + Send(new CastMsg_RtpStatistics(channel_id, + audio, + sender_info, + time_sent, + rtp_timestamp)); +} + +void CastTransportHostFilter::OnNew( + int32 channel_id, + const media::cast::transport::CastTransportConfig& config) { + media::cast::transport::CastTransportSender* sender = + id_map_.Lookup(channel_id); + if (sender) { + id_map_.Remove(channel_id); + } + + sender = media::cast::transport::CastTransportSender:: + CreateCastTransportSender( + &clock_, + config, + base::Bind(&CastTransportHostFilter::NotifyStatusChange, + base::Unretained(this), + channel_id), + base::MessageLoopProxy::current()); + sender->SetPacketReceiver( + base::Bind(&CastTransportHostFilter::ReceivedPacket, + base::Unretained(this), + channel_id)); + sender->SubscribeAudioRtpStatsCallback( + base::Bind(&CastTransportHostFilter::ReceivedRtpStatistics, + base::Unretained(this), + channel_id, + true /* audio */)); + sender->SubscribeVideoRtpStatsCallback( + base::Bind(&CastTransportHostFilter::ReceivedRtpStatistics, + base::Unretained(this), + channel_id, + false /* not audio */)); + + id_map_.AddWithID(sender, channel_id); +} + +void CastTransportHostFilter::OnDelete(int32 channel_id) { + media::cast::transport::CastTransportSender* sender = + id_map_.Lookup(channel_id); + if (sender) { + id_map_.Remove(channel_id); + } else { + DVLOG(1) << "CastTransportHostFilter::Delete called " + << "on non-existing channel"; + } +} + +void CastTransportHostFilter::OnInsertCodedAudioFrame( + int32 channel_id, + const media::cast::transport::EncodedAudioFrame& audio_frame, + base::TimeTicks recorded_time) { + media::cast::transport::CastTransportSender* sender = + id_map_.Lookup(channel_id); + if (sender) { + sender->InsertCodedAudioFrame(&audio_frame, recorded_time); + } else { + DVLOG(1) + << "CastTransportHostFilter::OnInsertCodedAudioFrame " + << "on non-existing channel"; + } +} + +void CastTransportHostFilter::OnInsertCodedVideoFrame( + int32 channel_id, + const media::cast::transport::EncodedVideoFrame& video_frame, + base::TimeTicks capture_time) { + media::cast::transport::CastTransportSender* sender = + id_map_.Lookup(channel_id); + if (sender) { + sender->InsertCodedVideoFrame(&video_frame, capture_time); + } else { + DVLOG(1) + << "CastTransportHostFilter::OnInsertCodedVideoFrame " + << "on non-existing channel"; + } +} + +void CastTransportHostFilter::OnSendRtcpFromRtpSender( + int32 channel_id, + const media::cast::transport::SendRtcpFromRtpSenderData& data, + const media::cast::transport::RtcpSenderInfo& sender_info, + const media::cast::transport::RtcpDlrrReportBlock& dlrr, + const media::cast::transport::RtcpSenderLogMessage& sender_log) { + media::cast::transport::CastTransportSender* sender = + id_map_.Lookup(channel_id); + if (sender) { + sender->SendRtcpFromRtpSender(data.packet_type_flags, + sender_info, + dlrr, + sender_log, + data.sending_ssrc, + data.c_name); + } else { + DVLOG(1) + << "CastTransportHostFilter::OnSendRtcpFromRtpSender " + << "on non-existing channel"; + } +} + +void CastTransportHostFilter::OnResendPackets( + int32 channel_id, + bool is_audio, + const media::cast::MissingFramesAndPacketsMap& missing_packets) { + media::cast::transport::CastTransportSender* sender = + id_map_.Lookup(channel_id); + if (sender) { + sender->ResendPackets(is_audio, missing_packets); + } else { + DVLOG(1) + << "CastTransportHostFilter::OnResendPackets on non-existing channel"; + } +} + +} // namespace cast diff --git a/chrome/browser/media/cast_transport_host_filter.h b/chrome/browser/media/cast_transport_host_filter.h new file mode 100644 index 0000000..a839c03 --- /dev/null +++ b/chrome/browser/media/cast_transport_host_filter.h @@ -0,0 +1,73 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_MEDIA_CAST_TRANSPORT_HOST_FILTER_H_ +#define CHROME_BROWSER_MEDIA_CAST_TRANSPORT_HOST_FILTER_H_ + +#include "base/id_map.h" +#include "base/time/default_tick_clock.h" +#include "chrome/common/cast_messages.h" +#include "content/public/browser/browser_message_filter.h" +#include "media/cast/cast_sender.h" +#include "media/cast/transport/cast_transport_sender.h" + +namespace cast { + +class CastTransportHostFilter : public content::BrowserMessageFilter { + public: + CastTransportHostFilter(); + private: + virtual ~CastTransportHostFilter(); + + void NotifyStatusChange( + int32 channel_id, + media::cast::transport::CastTransportStatus result); + void ReceivedPacket( + int32 channel_id, + scoped_ptr<media::cast::transport::Packet> result); + void ReceivedRtpStatistics( + int32 channel_id, + bool audio, + const media::cast::transport::RtcpSenderInfo& sender_info, + base::TimeTicks time_sent, + uint32 rtp_timestamp); + + // BrowserMessageFilter implementation. + virtual bool OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) OVERRIDE; + + // Forwarding functions. + void OnInsertCodedAudioFrame( + int32 channel_id, + const media::cast::transport::EncodedAudioFrame& audio_frame, + base::TimeTicks recorded_time); + void OnInsertCodedVideoFrame( + int32 channel_id, + const media::cast::transport::EncodedVideoFrame& video_frame, + base::TimeTicks capture_time); + void OnSendRtcpFromRtpSender( + int32 channel_id, + const media::cast::transport::SendRtcpFromRtpSenderData& data, + const media::cast::transport::RtcpSenderInfo& sender_info, + const media::cast::transport::RtcpDlrrReportBlock& dlrr, + const media::cast::transport::RtcpSenderLogMessage& sender_log); + void OnResendPackets( + int32 channel_id, + bool is_audio, + const media::cast::MissingFramesAndPacketsMap& missing_packets); + void OnNew( + int32 channel_id, + const media::cast::transport::CastTransportConfig& config); + void OnDelete(int32 channel_id); + + IDMap<media::cast::transport::CastTransportSender, IDMapOwnPointer> id_map_; + + // Clock used by Cast transport. + base::DefaultTickClock clock_; + DISALLOW_COPY_AND_ASSIGN(CastTransportHostFilter); +}; + +} // namespace cast + +#endif // CHROME_BROWSER_MEDIA_CAST_TRANSPORT_HOST_FILTER_H_ diff --git a/chrome/browser/media/cast_transport_host_filter_unittest.cc b/chrome/browser/media/cast_transport_host_filter_unittest.cc new file mode 100644 index 0000000..0332dd4 --- /dev/null +++ b/chrome/browser/media/cast_transport_host_filter_unittest.cc @@ -0,0 +1,161 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/callback.h" +#include "base/message_loop/message_loop.h" +#include "base/time/default_tick_clock.h" +#include "chrome/browser/media/cast_transport_host_filter.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class CastTransportHostFilterTest : public testing::Test { + public: + CastTransportHostFilterTest() + : browser_thread_bundle_( + content::TestBrowserThreadBundle::IO_MAINLOOP) { + } + protected: + virtual void SetUp() OVERRIDE { + filter_ = new cast::CastTransportHostFilter(); + } + + void FakeSend(const IPC::Message& message) { + bool message_was_ok; + EXPECT_TRUE(filter_->OnMessageReceived(message, &message_was_ok)); + EXPECT_TRUE(message_was_ok); + } + + net::IPEndPoint GetLocalEndPoint() { + return net::IPEndPoint(net::IPAddressNumber(4, 0), 0); + } + + net::IPEndPoint GetRemoteEndPoint() { + // 127.0.0.1:7 is the local echo service port, which + // is probably not going to respond, but that's ok. + // TODO(hubbe): Open up an UDP port and make sure + // we can send and receive packets. + net::IPAddressNumber receiver_address(4, 0); + receiver_address[0] = 127; + receiver_address[3] = 1; + return net::IPEndPoint(receiver_address, 7); + } + + content::TestBrowserThreadBundle browser_thread_bundle_; + scoped_refptr<content::BrowserMessageFilter> filter_; + net::IPAddressNumber receiver_address_; +}; + +TEST_F(CastTransportHostFilterTest, NewDelete) { + media::cast::transport::CastTransportConfig config; + config.local_endpoint = GetLocalEndPoint(); + config.receiver_endpoint = GetRemoteEndPoint(); + const int kChannelId = 17; + CastHostMsg_New new_msg(kChannelId, config); + CastHostMsg_Delete delete_msg(kChannelId); + + // New, then delete, as expected. + FakeSend(new_msg); + FakeSend(delete_msg); + FakeSend(new_msg); + FakeSend(delete_msg); + FakeSend(new_msg); + FakeSend(delete_msg); + + // Now create/delete transport senders in the wrong order to make sure + // this doesn't crash. + FakeSend(new_msg); + FakeSend(new_msg); + FakeSend(new_msg); + FakeSend(delete_msg); + FakeSend(delete_msg); + FakeSend(delete_msg); +} + +TEST_F(CastTransportHostFilterTest, NewMany) { + media::cast::transport::CastTransportConfig config; + config.local_endpoint = GetLocalEndPoint(); + config.receiver_endpoint = GetRemoteEndPoint(); + + for (int i = 0; i < 100; i++) { + CastHostMsg_New new_msg(i, config); + FakeSend(new_msg); + } + + for (int i = 0; i < 60; i++) { + CastHostMsg_Delete delete_msg(i); + FakeSend(delete_msg); + } + + // Leave some open, see what happens. +} + +TEST_F(CastTransportHostFilterTest, SimpleMessages) { + // Create a cast transport sender. + media::cast::transport::CastTransportConfig config; + config.local_endpoint = GetLocalEndPoint(); + config.receiver_endpoint = GetRemoteEndPoint(); + const int32 kChannelId = 42; + CastHostMsg_New new_msg(kChannelId, config); + FakeSend(new_msg); + + media::cast::transport::EncodedAudioFrame audio_frame; + audio_frame.codec = media::cast::transport::kPcm16; + audio_frame.frame_id = 1; + audio_frame.rtp_timestamp = 47; + const int kSamples = 47; + const int kBytesPerSample = 2; + const int kChannels = 2; + audio_frame.data = std::string(kSamples * kBytesPerSample * kChannels, 'q'); + CastHostMsg_InsertCodedAudioFrame insert_coded_audio_frame( + kChannelId, audio_frame, base::TimeTicks::Now()); + FakeSend(new_msg); + + media::cast::transport::EncodedVideoFrame video_frame; + video_frame.codec = media::cast::transport::kVp8; + video_frame.key_frame = true; + video_frame.frame_id = 1; + video_frame.last_referenced_frame_id = 0; + // Let's make sure we try a few kb so multiple packets + // are generated. + const int kVideoDataSize = 4711; + video_frame.data = std::string(kVideoDataSize, 'p'); + CastHostMsg_InsertCodedVideoFrame insert_coded_video_frame( + kChannelId, video_frame, base::TimeTicks::Now()); + FakeSend(new_msg); + + media::cast::transport::SendRtcpFromRtpSenderData rtcp_data; + rtcp_data.packet_type_flags = 0; + rtcp_data.sending_ssrc = 0; + rtcp_data.c_name = "FNRD"; + media::cast::transport::RtcpSenderInfo sender_info; + sender_info.ntp_seconds = 1; + sender_info.ntp_fraction = 2; + sender_info.rtp_timestamp = 3; + sender_info.send_packet_count = 4; + sender_info.send_octet_count = 5; + media::cast::transport::RtcpDlrrReportBlock dlrr; + dlrr.last_rr = 7; + dlrr.delay_since_last_rr = 8; + media::cast::transport::RtcpSenderLogMessage sender_log(1); + sender_log[0].frame_status = + media::cast::transport::kRtcpSenderFrameStatusSentToNetwork; + sender_log[0].rtp_timestamp = 9; + CastHostMsg_SendRtcpFromRtpSender rtcp_msg( + kChannelId, rtcp_data, sender_info, dlrr, sender_log); + FakeSend(rtcp_msg); + + media::cast::MissingFramesAndPacketsMap missing_packets; + missing_packets[1].insert(4); + missing_packets[3].insert(7); + CastHostMsg_ResendPackets resend_msg( + kChannelId, false, missing_packets); + FakeSend(resend_msg); + + CastHostMsg_Delete delete_msg(kChannelId); + FakeSend(delete_msg); +} + +} // namespace diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index a2e050d..e646d75 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -50,9 +50,10 @@ '../content/content.gyp:content_browser', '../content/content.gyp:content_common', '../crypto/crypto.gyp:crypto', - '../google_apis/google_apis.gyp:google_apis', '../google_apis/gcm/gcm.gyp:gcm', + '../google_apis/google_apis.gyp:google_apis', '../jingle/jingle.gyp:notifier', + '../media/cast/transport/cast_transport.gyp:cast_transport', '../skia/skia.gyp:skia', '../sql/sql.gyp:sql', '../sync/sync.gyp:sync', @@ -1113,6 +1114,8 @@ 'browser/managed_mode/supervised_user_pref_store.h', 'browser/media/audio_stream_indicator.cc', 'browser/media/audio_stream_indicator.h', + 'browser/media/cast_transport_host_filter.cc', + 'browser/media/cast_transport_host_filter.h', 'browser/media/chrome_midi_permission_context.cc', 'browser/media/chrome_midi_permission_context.h', 'browser/media/chrome_midi_permission_context_factory.cc', diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index c1444cc..ffb1c82 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi @@ -23,6 +23,7 @@ '../content/content.gyp:content_renderer', '../media/cast/cast.gyp:cast_config', '../media/cast/cast_sender.gyp:cast_sender', + '../media/cast/transport/cast_transport.gyp:cast_transport', '../net/net.gyp:net', '../skia/skia.gyp:skia', '../third_party/WebKit/public/blink.gyp:blink', @@ -160,10 +161,14 @@ 'renderer/loadtimes_extension_bindings.h', 'renderer/media/cast_rtp_stream.cc', 'renderer/media/cast_rtp_stream.h', + 'renderer/media/cast_ipc_dispatcher.cc', + 'renderer/media/cast_ipc_dispatcher.h', 'renderer/media/cast_session.cc', 'renderer/media/cast_session.h', 'renderer/media/cast_session_delegate.cc', 'renderer/media/cast_session_delegate.h', + 'renderer/media/cast_transport_sender_ipc.cc', + 'renderer/media/cast_transport_sender_ipc.h', 'renderer/media/cast_udp_transport.cc', 'renderer/media/cast_udp_transport.h', 'renderer/media/chrome_key_systems.cc', diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 69bfdde..256af0d 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -1041,6 +1041,7 @@ 'browser/managed_mode/managed_user_shared_settings_update_unittest.cc', 'browser/managed_mode/supervised_user_pref_mapping_service_unittest.cc', 'browser/managed_mode/supervised_user_pref_store_unittest.cc', + 'browser/media/cast_transport_host_filter_unittest.cc', 'browser/media/desktop_media_list_ash_unittest.cc', 'browser/media/native_desktop_media_list_unittest.cc', 'browser/media/webrtc_log_uploader_unittest.cc', diff --git a/chrome/common/DEPS b/chrome/common/DEPS index d019c5d..2c0d962 100644 --- a/chrome/common/DEPS +++ b/chrome/common/DEPS @@ -10,6 +10,7 @@ include_rules = [ "+components/translate/core/common", "+extensions/common", "+grit", # For generated headers + "+media", "+ppapi/shared_impl", "+remoting/client/plugin", "+webkit/common/user_agent", diff --git a/chrome/common/cast_messages.h b/chrome/common/cast_messages.h new file mode 100644 index 0000000..022d9ad --- /dev/null +++ b/chrome/common/cast_messages.h @@ -0,0 +1,140 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// IPC messages for the Cast transport API. +// Multiply-included message file, hence no include guard. + +#include "ipc/ipc_message_macros.h" +#include "media/cast/cast_sender.h" +#include "media/cast/rtcp/rtcp_defines.h" +#include "media/cast/transport/cast_transport_sender.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_util.h" + +#undef IPC_MESSAGE_EXPORT +#define IPC_MESSAGE_EXPORT +#define IPC_MESSAGE_START CastMsgStart + +IPC_ENUM_TRAITS(media::cast::transport::AudioCodec) +IPC_ENUM_TRAITS(media::cast::transport::VideoCodec) +IPC_ENUM_TRAITS(media::cast::transport::RtcpSenderFrameStatus) +IPC_ENUM_TRAITS(media::cast::transport::CastTransportStatus) + +IPC_STRUCT_TRAITS_BEGIN(media::cast::transport::EncodedAudioFrame) + IPC_STRUCT_TRAITS_MEMBER(codec) + IPC_STRUCT_TRAITS_MEMBER(frame_id) + IPC_STRUCT_TRAITS_MEMBER(rtp_timestamp) + IPC_STRUCT_TRAITS_MEMBER(data) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(media::cast::transport::EncodedVideoFrame) + IPC_STRUCT_TRAITS_MEMBER(codec) + IPC_STRUCT_TRAITS_MEMBER(key_frame) + IPC_STRUCT_TRAITS_MEMBER(frame_id) + IPC_STRUCT_TRAITS_MEMBER(last_referenced_frame_id) + IPC_STRUCT_TRAITS_MEMBER(data) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(media::cast::transport::RtcpSenderInfo) + IPC_STRUCT_TRAITS_MEMBER(ntp_seconds) + IPC_STRUCT_TRAITS_MEMBER(ntp_fraction) + IPC_STRUCT_TRAITS_MEMBER(rtp_timestamp) + IPC_STRUCT_TRAITS_MEMBER(send_packet_count) + IPC_STRUCT_TRAITS_MEMBER(send_octet_count) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(media::cast::transport::RtcpDlrrReportBlock) + IPC_STRUCT_TRAITS_MEMBER(last_rr) + IPC_STRUCT_TRAITS_MEMBER(delay_since_last_rr) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(media::cast::transport::RtcpSenderFrameLogMessage) + IPC_STRUCT_TRAITS_MEMBER(frame_status) + IPC_STRUCT_TRAITS_MEMBER(rtp_timestamp) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(media::cast::transport::RtpConfig) + IPC_STRUCT_TRAITS_MEMBER(history_ms) + IPC_STRUCT_TRAITS_MEMBER(max_delay_ms) + IPC_STRUCT_TRAITS_MEMBER(payload_type) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(media::cast::transport::CastTransportConfig) + IPC_STRUCT_TRAITS_MEMBER(receiver_endpoint) + IPC_STRUCT_TRAITS_MEMBER(local_endpoint) + IPC_STRUCT_TRAITS_MEMBER(audio_ssrc) + IPC_STRUCT_TRAITS_MEMBER(video_ssrc) + IPC_STRUCT_TRAITS_MEMBER(video_codec) + IPC_STRUCT_TRAITS_MEMBER(audio_codec) + IPC_STRUCT_TRAITS_MEMBER(audio_frequency) + IPC_STRUCT_TRAITS_MEMBER(audio_channels) + IPC_STRUCT_TRAITS_MEMBER(audio_rtp_config) + IPC_STRUCT_TRAITS_MEMBER(video_rtp_config) + IPC_STRUCT_TRAITS_MEMBER(aes_key) + IPC_STRUCT_TRAITS_MEMBER(aes_iv_mask) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(media::cast::transport::SendRtcpFromRtpSenderData) + IPC_STRUCT_TRAITS_MEMBER(packet_type_flags) + IPC_STRUCT_TRAITS_MEMBER(sending_ssrc) + IPC_STRUCT_TRAITS_MEMBER(c_name) +IPC_STRUCT_TRAITS_END() + + +// Cast messages sent from the browser to the renderer. + +IPC_MESSAGE_CONTROL2(CastMsg_ReceivedPacket, + int32 /* channel_id */, + media::cast::Packet /* packet */); + +IPC_MESSAGE_CONTROL2( + CastMsg_NotifyStatusChange, + int32 /* channel_id */, + media::cast::transport::CastTransportStatus /* status */); + +IPC_MESSAGE_CONTROL5( + CastMsg_RtpStatistics, + int32 /* channel_id */, + bool /* audio */, + media::cast::transport::RtcpSenderInfo /* sender_info */, + base::TimeTicks /* time_sent */, + uint32 /* rtp_timestamp */); + + +// Cast messages sent from the renderer to the browser. + +IPC_MESSAGE_CONTROL3( + CastHostMsg_InsertCodedAudioFrame, + int32 /* channel_id */, + media::cast::transport::EncodedAudioFrame /* audio_frame */, + base::TimeTicks /* recorded_time */) + +IPC_MESSAGE_CONTROL3( + CastHostMsg_InsertCodedVideoFrame, + int32 /* channel_id */, + media::cast::transport::EncodedVideoFrame /* video_frame */, + base::TimeTicks /* recorded_time */) + +IPC_MESSAGE_CONTROL5( + CastHostMsg_SendRtcpFromRtpSender, + int32 /* channel_id */, + media::cast::transport::SendRtcpFromRtpSenderData /* flags, ssrc, name */, + media::cast::transport::RtcpSenderInfo /* sender_info */, + media::cast::transport::RtcpDlrrReportBlock /* dlrr */, + media::cast::transport::RtcpSenderLogMessage /* sender_log */) + +IPC_MESSAGE_CONTROL3( + CastHostMsg_ResendPackets, + int32 /* channel_id */, + bool /* is_audio */, + media::cast::MissingFramesAndPacketsMap /* missing_packets */) + +IPC_MESSAGE_CONTROL2( + CastHostMsg_New, + int32 /* channel_id */, + media::cast::transport::CastTransportConfig /* config */); + +IPC_MESSAGE_CONTROL1( + CastHostMsg_Delete, + int32 /* channel_id */); diff --git a/chrome/common/common_message_generator.h b/chrome/common/common_message_generator.h index 15ca139..8de637d 100644 --- a/chrome/common/common_message_generator.h +++ b/chrome/common/common_message_generator.h @@ -6,6 +6,7 @@ #include "apps/app_shim/app_shim_messages.h" #include "chrome/common/benchmarking_messages.h" +#include "chrome/common/cast_messages.h" #include "chrome/common/chrome_utility_messages.h" #include "chrome/common/extensions/extension_messages.h" #include "chrome/common/prerender_messages.h" diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 45a5afe..858990b 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -41,6 +41,7 @@ #include "chrome/renderer/extensions/resource_request_policy.h" #include "chrome/renderer/external_extension.h" #include "chrome/renderer/loadtimes_extension_bindings.h" +#include "chrome/renderer/media/cast_ipc_dispatcher.h" #include "chrome/renderer/media/chrome_key_systems.h" #include "chrome/renderer/net/net_error_helper.h" #include "chrome/renderer/net/prescient_networking_dispatcher.h" @@ -274,6 +275,8 @@ void ChromeContentRendererClient::RenderThreadStarted() { #if defined(ENABLE_WEBRTC) thread->AddFilter(webrtc_logging_message_filter_.get()); #endif + thread->AddFilter(new CastIPCDispatcher( + content::RenderThread::Get()->GetIOMessageLoopProxy())); thread->RegisterExtension(extensions_v8::ExternalExtension::Get()); thread->RegisterExtension(extensions_v8::LoadTimesExtension::Get()); diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index d31e1c3..64ad7ca 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h @@ -13,6 +13,7 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" #include "content/public/renderer/content_renderer_client.h" +#include "ipc/ipc_channel_proxy.h" class ChromeRenderProcessObserver; class PrescientNetworkingDispatcher; diff --git a/chrome/renderer/chrome_content_renderer_client_browsertest.cc b/chrome/renderer/chrome_content_renderer_client_browsertest.cc index 38a71d7..77b8db4 100644 --- a/chrome/renderer/chrome_content_renderer_client_browsertest.cc +++ b/chrome/renderer/chrome_content_renderer_client_browsertest.cc @@ -28,6 +28,8 @@ TEST_F(InstantProcessNavigationTest, ForkForNavigationsFromInstantProcess) { // to potentially Instant URLs get bounced back to the browser to be rebucketed // into an Instant renderer if necessary. TEST_F(InstantProcessNavigationTest, ForkForNavigationsToSearchURLs) { + chrome_render_thread_->set_io_message_loop_proxy( + base::MessageLoopProxy::current()); chrome_content_renderer_client_.RenderThreadStarted(); std::vector<GURL> search_urls; search_urls.push_back(GURL("http://example.com/search")); diff --git a/chrome/renderer/media/cast_ipc_dispatcher.cc b/chrome/renderer/media/cast_ipc_dispatcher.cc new file mode 100644 index 0000000..3d71e92 --- /dev/null +++ b/chrome/renderer/media/cast_ipc_dispatcher.cc @@ -0,0 +1,117 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/media/cast_ipc_dispatcher.h" + +#include "chrome/common/cast_messages.h" +#include "chrome/renderer/media/cast_transport_sender_ipc.h" +#include "ipc/ipc_message_macros.h" + +CastIPCDispatcher* CastIPCDispatcher::global_instance_ = NULL; + +CastIPCDispatcher::CastIPCDispatcher( + const scoped_refptr<base::MessageLoopProxy>& io_message_loop) + : channel_(NULL), + io_message_loop_(io_message_loop) { + DCHECK(io_message_loop_); + DCHECK(!global_instance_); +} + +CastIPCDispatcher::~CastIPCDispatcher() { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + // Unfortunately, you do not always get a OnFilterRemoved call. + global_instance_ = NULL; +} + +CastIPCDispatcher* CastIPCDispatcher::Get() { + return global_instance_; +} + +void CastIPCDispatcher::Send(IPC::Message* message) { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + if (channel_) { + channel_->Send(message); + } else { + delete message; + } +} + +int32 CastIPCDispatcher::AddSender(CastTransportSenderIPC* sender) { + return id_map_.Add(sender); +} + +void CastIPCDispatcher::RemoveSender(int32 channel_id) { + return id_map_.Remove(channel_id); +} + +bool CastIPCDispatcher::OnMessageReceived(const IPC::Message& message) { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(CastIPCDispatcher, message) + IPC_MESSAGE_HANDLER(CastMsg_ReceivedPacket, OnReceivedPacket) + IPC_MESSAGE_HANDLER(CastMsg_NotifyStatusChange, OnNotifyStatusChange) + IPC_MESSAGE_HANDLER(CastMsg_RtpStatistics, OnRtpStatistics) + IPC_MESSAGE_UNHANDLED(handled = false); + IPC_END_MESSAGE_MAP(); + return handled; +} + +void CastIPCDispatcher::OnFilterAdded(IPC::Channel* channel) { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + DCHECK(!global_instance_); + global_instance_ = this; + channel_ = channel; +} + +void CastIPCDispatcher::OnFilterRemoved() { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + DCHECK_EQ(this, global_instance_); + global_instance_ = NULL; + channel_ = NULL; +} + +void CastIPCDispatcher::OnChannelClosing() { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + DCHECK_EQ(this, global_instance_); + channel_ = NULL; +} + +void CastIPCDispatcher::OnReceivedPacket( + int32 channel_id, + const media::cast::transport::Packet& packet) { + CastTransportSenderIPC* sender = id_map_.Lookup(channel_id); + if (sender) { + sender->OnReceivedPacket(packet); + } else { + LOG(ERROR) << "CastIPCDispatcher::OnReceivedPacket " + << "on non-existing channel."; + } +} + +void CastIPCDispatcher::OnNotifyStatusChange( + int32 channel_id, + media::cast::transport::CastTransportStatus status) { + CastTransportSenderIPC* sender = id_map_.Lookup(channel_id); + if (sender) { + sender->OnNotifyStatusChange(status); + } else { + LOG(ERROR) + << "CastIPCDispatcher::OnNotifystatusChange on non-existing channel."; + } +} + +void CastIPCDispatcher::OnRtpStatistics( + int32 channel_id, + bool audio, + const media::cast::transport::RtcpSenderInfo& sender_info, + base::TimeTicks time_sent, + uint32 rtp_timestamp) { + CastTransportSenderIPC* sender = id_map_.Lookup(channel_id); + if (sender) { + sender->OnRtpStatistics(audio, sender_info, time_sent, rtp_timestamp); + } else { + LOG(ERROR) + << "CastIPCDispatcher::OnNotifystatusChange on non-existing channel."; + } +} diff --git a/chrome/renderer/media/cast_ipc_dispatcher.h b/chrome/renderer/media/cast_ipc_dispatcher.h new file mode 100644 index 0000000..7464f4d --- /dev/null +++ b/chrome/renderer/media/cast_ipc_dispatcher.h @@ -0,0 +1,63 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_MEDIA_CAST_IPC_DISPATCHER_H_ +#define CHROME_RENDERER_MEDIA_CAST_IPC_DISPATCHER_H_ + +#include "base/callback.h" +#include "base/id_map.h" +#include "ipc/ipc_channel_proxy.h" +#include "media/cast/cast_sender.h" +#include "media/cast/transport/cast_transport_sender.h" + +class CastTransportSenderIPC; + +// This dispatcher listens to incoming IPC messages and sends +// the call to the correct CastTransportSenderIPC instance. +class CastIPCDispatcher : public IPC::ChannelProxy::MessageFilter { + public: + explicit CastIPCDispatcher( + const scoped_refptr<base::MessageLoopProxy>& io_message_loop); + + static CastIPCDispatcher* Get(); + void Send(IPC::Message* message); + int32 AddSender(CastTransportSenderIPC* sender); + void RemoveSender(int32 channel_id); + + // IPC::ChannelProxy::MessageFilter implementation + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE; + virtual void OnFilterRemoved() OVERRIDE; + virtual void OnChannelClosing() OVERRIDE; + + protected: + virtual ~CastIPCDispatcher(); + + private: + void OnReceivedPacket(int32 channel_id, const media::cast::Packet& packet); + void OnNotifyStatusChange( + int32 channel_id, + media::cast::transport::CastTransportStatus status); + void OnRtpStatistics( + int32 channel_id, + bool audio, + const media::cast::transport::RtcpSenderInfo& sender_info, + base::TimeTicks time_sent, + uint32 rtp_timestamp); + + static CastIPCDispatcher* global_instance_; + + // IPC channel for Send(); must only be accesed on |io_message_loop_|. + IPC::Channel* channel_; + + // Message loop on which IPC calls are driven. + const scoped_refptr<base::MessageLoopProxy> io_message_loop_; + + // A map of stream ids to delegates; must only be accessed on + // |io_message_loop_|. + IDMap<CastTransportSenderIPC> id_map_; + DISALLOW_COPY_AND_ASSIGN(CastIPCDispatcher); +}; + +#endif // CHROME_RENDERER_MEDIA_CAST_IPC_DISPATCHER_H_ diff --git a/chrome/renderer/media/cast_session.cc b/chrome/renderer/media/cast_session.cc index 5163125..bab95ff 100644 --- a/chrome/renderer/media/cast_session.cc +++ b/chrome/renderer/media/cast_session.cc @@ -51,3 +51,14 @@ void CastSession::StartVideo(const media::cast::VideoSenderConfig& config, config, media::BindToCurrentLoop(callback))); } + +void CastSession::StartUDP(const net::IPEndPoint& local_endpoint, + const net::IPEndPoint& remote_endpoint) { + io_message_loop_proxy_->PostTask( + FROM_HERE, + base::Bind( + &CastSessionDelegate::StartUDP, + base::Unretained(delegate_.get()), + local_endpoint, + remote_endpoint)); +} diff --git a/chrome/renderer/media/cast_session.h b/chrome/renderer/media/cast_session.h index aa2da78..63278b5 100644 --- a/chrome/renderer/media/cast_session.h +++ b/chrome/renderer/media/cast_session.h @@ -26,7 +26,7 @@ struct VideoSenderConfig; } // namespace cast } // namespace media -namespace content{ +namespace content { class P2PSocketClient; } // namespace content @@ -53,6 +53,8 @@ class CastSession : public base::RefCounted<CastSession> { const FrameInputAvailableCallback& callback); void StartVideo(const media::cast::VideoSenderConfig& config, const FrameInputAvailableCallback& callback); + void StartUDP(const net::IPEndPoint& local_endpoint, + const net::IPEndPoint& remote_endpoint); private: friend class base::RefCounted<CastSession>; diff --git a/chrome/renderer/media/cast_session_browsertest.cc b/chrome/renderer/media/cast_session_browsertest.cc index 3fe21e8..fb55553 100644 --- a/chrome/renderer/media/cast_session_browsertest.cc +++ b/chrome/renderer/media/cast_session_browsertest.cc @@ -15,9 +15,9 @@ typedef ChromeRenderViewTest CastSessionBrowserTest; // Tests that CastSession is created and destroyed properly inside // chrome renderer. TEST_F(CastSessionBrowserTest, CreateAndDestroy) { - chrome_content_renderer_client_.RenderThreadStarted(); chrome_render_thread_->set_io_message_loop_proxy( base::MessageLoopProxy::current()); + chrome_content_renderer_client_.RenderThreadStarted(); scoped_refptr<CastSession> session(new CastSession()); diff --git a/chrome/renderer/media/cast_session_delegate.cc b/chrome/renderer/media/cast_session_delegate.cc index 5da3443..d5133b6 100644 --- a/chrome/renderer/media/cast_session_delegate.cc +++ b/chrome/renderer/media/cast_session_delegate.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/message_loop/message_loop_proxy.h" +#include "chrome/renderer/media/cast_transport_sender_ipc.h" #include "content/public/renderer/p2p_socket_client.h" #include "content/public/renderer/render_thread.h" #include "media/cast/cast_config.h" @@ -20,56 +21,13 @@ using media::cast::CastEnvironment; using media::cast::CastSender; using media::cast::VideoSenderConfig; -namespace { - -// This is a dummy class that does nothing. This is needed temporarily -// to enable tests for cast.streaming extension APIs. -// The real implementation of CastTransportSender is to use IPC to send -// data to the browser process. -// See crbug.com/327482 for more details. -class DummyTransport : public media::cast::transport::CastTransportSender { - public: - DummyTransport() {} - virtual ~DummyTransport() {} - - // CastTransportSender implementations. - virtual void SetPacketReceiver( - const media::cast::transport::PacketReceiverCallback& packet_receiver) - OVERRIDE {} - virtual void InsertCodedAudioFrame( - const media::cast::transport::EncodedAudioFrame* audio_frame, - const base::TimeTicks& recorded_time) OVERRIDE {} - virtual void InsertCodedVideoFrame( - const media::cast::transport::EncodedVideoFrame* video_frame, - const base::TimeTicks& capture_time) OVERRIDE {} - virtual void SendRtcpFromRtpSender( - uint32 packet_type_flags, - const media::cast::transport::RtcpSenderInfo& sender_info, - const media::cast::transport::RtcpDlrrReportBlock& dlrr, - const media::cast::transport::RtcpSenderLogMessage& sender_log, - uint32 sending_ssrc, - const std::string& c_name) OVERRIDE {} - virtual void ResendPackets( - bool is_audio, - const media::cast::transport::MissingFramesAndPacketsMap& missing_packets) - OVERRIDE {} - virtual void SubscribeAudioRtpStatsCallback( - const media::cast::transport::CastTransportRtpStatistics& callback) - OVERRIDE {} - virtual void SubscribeVideoRtpStatsCallback( - const media::cast::transport::CastTransportRtpStatistics& callback) - OVERRIDE {} - - private: - DISALLOW_COPY_AND_ASSIGN(DummyTransport); -}; -} // namespace - CastSessionDelegate::CastSessionDelegate() : audio_encode_thread_("CastAudioEncodeThread"), video_encode_thread_("CastVideoEncodeThread"), + transport_configured_(false), io_message_loop_proxy_( content::RenderThread::Get()->GetIOMessageLoopProxy()) { + DCHECK(io_message_loop_proxy_); } CastSessionDelegate::~CastSessionDelegate() { @@ -80,7 +38,6 @@ void CastSessionDelegate::Initialize() { if (cast_environment_) return; // Already initialized. - cast_transport_.reset(new DummyTransport()); audio_encode_thread_.Start(); video_encode_thread_.Start(); @@ -105,32 +62,71 @@ void CastSessionDelegate::StartAudio( DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); audio_config_.reset(new AudioSenderConfig(config)); - StartSendingInternal(callback, true); + video_frame_input_available_callback_ = callback; + StartSendingInternal(); } void CastSessionDelegate::StartVideo( const VideoSenderConfig& config, const FrameInputAvailableCallback& callback) { DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); + audio_frame_input_available_callback_ = callback; video_config_.reset(new VideoSenderConfig(config)); - StartSendingInternal(callback, false); + StartSendingInternal(); +} + +void CastSessionDelegate::StartUDP( + const net::IPEndPoint& local_endpoint, + const net::IPEndPoint& remote_endpoint) { + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); + transport_configured_ = true; + local_endpoint_ = local_endpoint; + remote_endpoint_ = remote_endpoint; + StartSendingInternal(); } -void CastSessionDelegate::StartSendingInternal( - const FrameInputAvailableCallback& callback, - bool is_audio) { +void CastSessionDelegate::StatusNotificationCB( + media::cast::transport::CastTransportStatus unused_status) { DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); + // TODO(hubbe): Call javascript UDPTransport error function. +} + +void CastSessionDelegate::StartSendingInternal() { + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); + + // No transport, wait. + if (!transport_configured_) + return; + + // No audio or video, wait. + if (!audio_config_ && !video_config_) + return; Initialize(); - if (is_audio) { - audio_frame_input_available_callback_.reset( - new FrameInputAvailableCallback(callback)); - } else { - video_frame_input_available_callback_.reset( - new FrameInputAvailableCallback(callback)); + media::cast::transport::CastTransportConfig config; + + // TODO(hubbe): set config.aes_key and config.aes_iv_mask. + config.local_endpoint = local_endpoint_; + config.receiver_endpoint = remote_endpoint_; + if (audio_config_) { + config.audio_ssrc = audio_config_->sender_ssrc; + config.audio_codec = audio_config_->codec; + config.audio_rtp_config = audio_config_->rtp_config; + config.audio_frequency = audio_config_->frequency; + config.audio_channels = audio_config_->channels; } + if (video_config_) { + config.video_ssrc = video_config_->sender_ssrc; + config.video_codec = video_config_->codec; + config.video_rtp_config = video_config_->rtp_config; + } + + cast_transport_.reset(new CastTransportSenderIPC( + config, + base::Bind(&CastSessionDelegate::StatusNotificationCB, + base::Unretained(this)))); cast_sender_.reset(CastSender::CreateCastSender( cast_environment_, @@ -140,6 +136,7 @@ void CastSessionDelegate::StartSendingInternal( base::Bind(&CastSessionDelegate::InitializationResult, base::Unretained(this)), cast_transport_.get())); + cast_transport_->SetPacketReceiver(cast_sender_->packet_receiver()); } void CastSessionDelegate::InitializationResult( @@ -148,11 +145,11 @@ void CastSessionDelegate::InitializationResult( // TODO(pwestin): handle the error codes. if (result == media::cast::STATUS_INITIALIZED) { - if (audio_frame_input_available_callback_) { - audio_frame_input_available_callback_->Run(cast_sender_->frame_input()); + if (!audio_frame_input_available_callback_.is_null()) { + audio_frame_input_available_callback_.Run(cast_sender_->frame_input()); } - if (video_frame_input_available_callback_) { - video_frame_input_available_callback_->Run(cast_sender_->frame_input()); + if (!video_frame_input_available_callback_.is_null()) { + video_frame_input_available_callback_.Run(cast_sender_->frame_input()); } } } diff --git a/chrome/renderer/media/cast_session_delegate.h b/chrome/renderer/media/cast_session_delegate.h index d382287..1dc6e96 100644 --- a/chrome/renderer/media/cast_session_delegate.h +++ b/chrome/renderer/media/cast_session_delegate.h @@ -53,6 +53,8 @@ class CastSessionDelegate { const FrameInputAvailableCallback& callback); void StartVideo(const media::cast::VideoSenderConfig& config, const FrameInputAvailableCallback& callback); + void StartUDP(const net::IPEndPoint& local_endpoint, + const net::IPEndPoint& remote_endpoint); protected: // Callback with the result of the initialization. @@ -66,8 +68,10 @@ class CastSessionDelegate { // Configure CastSender. It is ready to accept audio / video frames after // receiving a successful call to InitializationResult. - void StartSendingInternal(const FrameInputAvailableCallback& callback, - bool is_audio); + void StartSendingInternal(); + + void StatusNotificationCB( + media::cast::transport::CastTransportStatus status); base::ThreadChecker thread_checker_; scoped_refptr<media::cast::CastEnvironment> cast_environment_; @@ -85,8 +89,12 @@ class CastSessionDelegate { scoped_ptr<media::cast::AudioSenderConfig> audio_config_; scoped_ptr<media::cast::VideoSenderConfig> video_config_; - scoped_ptr<FrameInputAvailableCallback> audio_frame_input_available_callback_; - scoped_ptr<FrameInputAvailableCallback> video_frame_input_available_callback_; + FrameInputAvailableCallback audio_frame_input_available_callback_; + FrameInputAvailableCallback video_frame_input_available_callback_; + + net::IPEndPoint local_endpoint_; + net::IPEndPoint remote_endpoint_; + bool transport_configured_; // Proxy to the IO message loop. scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; diff --git a/chrome/renderer/media/cast_transport_sender_ipc.cc b/chrome/renderer/media/cast_transport_sender_ipc.cc new file mode 100644 index 0000000..b3f4bbd --- /dev/null +++ b/chrome/renderer/media/cast_transport_sender_ipc.cc @@ -0,0 +1,125 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/media/cast_transport_sender_ipc.h" + +#include "base/callback.h" +#include "base/id_map.h" +#include "chrome/common/cast_messages.h" +#include "chrome/renderer/media/cast_ipc_dispatcher.h" +#include "ipc/ipc_channel_proxy.h" +#include "media/cast/cast_sender.h" +#include "media/cast/transport/cast_transport_sender.h" + +CastTransportSenderIPC::CastTransportSenderIPC( + const media::cast::transport::CastTransportConfig& config, + const media::cast::transport::CastTransportStatusCallback& status_cb) + : status_callback_(status_cb) { + if (CastIPCDispatcher::Get()) { + channel_id_ = CastIPCDispatcher::Get()->AddSender(this); + } + Send(new CastHostMsg_New(channel_id_, config)); +} + +CastTransportSenderIPC::~CastTransportSenderIPC() { + Send(new CastHostMsg_Delete(channel_id_)); + if (CastIPCDispatcher::Get()) { + CastIPCDispatcher::Get()->RemoveSender(channel_id_); + } +} + +void CastTransportSenderIPC::SetPacketReceiver( + const media::cast::transport::PacketReceiverCallback& packet_callback) { + packet_callback_ = packet_callback; +} + +void CastTransportSenderIPC::InsertCodedAudioFrame( + const media::cast::transport::EncodedAudioFrame* audio_frame, + const base::TimeTicks& recorded_time) { + Send(new CastHostMsg_InsertCodedAudioFrame(channel_id_, + *audio_frame, + recorded_time)); +} + +void CastTransportSenderIPC::InsertCodedVideoFrame( + const media::cast::transport::EncodedVideoFrame* video_frame, + const base::TimeTicks& capture_time) { + Send(new CastHostMsg_InsertCodedVideoFrame(channel_id_, + *video_frame, + capture_time)); +} + +void CastTransportSenderIPC::SendRtcpFromRtpSender( + uint32 packet_type_flags, + const media::cast::transport::RtcpSenderInfo& sender_info, + const media::cast::transport::RtcpDlrrReportBlock& dlrr, + const media::cast::transport::RtcpSenderLogMessage& sender_log, + uint32 sending_ssrc, + const std::string& c_name) { + struct media::cast::transport::SendRtcpFromRtpSenderData data; + data.packet_type_flags = packet_type_flags; + data.sending_ssrc = sending_ssrc; + data.c_name = c_name; + Send(new CastHostMsg_SendRtcpFromRtpSender( + channel_id_, + data, + sender_info, + dlrr, + sender_log)); +} + +void CastTransportSenderIPC::ResendPackets( + bool is_audio, + const media::cast::MissingFramesAndPacketsMap& missing_packets) { + Send(new CastHostMsg_ResendPackets(channel_id_, + is_audio, + missing_packets)); +} + +void CastTransportSenderIPC::SubscribeAudioRtpStatsCallback( + const media::cast::transport::CastTransportRtpStatistics& callback) { + audio_rtp_callback_ = callback; +} + +void CastTransportSenderIPC::SubscribeVideoRtpStatsCallback( + const media::cast::transport::CastTransportRtpStatistics& callback) { + video_rtp_callback_ = callback; +} + + +void CastTransportSenderIPC::OnReceivedPacket( + const media::cast::Packet& packet) { + if (!packet_callback_.is_null()) { + // TODO(hubbe): Perhaps an non-ownership-transferring cb here? + scoped_ptr<media::cast::transport::Packet> packet_copy( + new media::cast::transport::Packet(packet)); + packet_callback_.Run(packet_copy.Pass()); + } else { + LOG(ERROR) << "CastIPCDispatcher::OnReceivedPacket " + << "no packet callback yet."; + } +} + +void CastTransportSenderIPC::OnNotifyStatusChange( + media::cast::transport::CastTransportStatus status) { + status_callback_.Run(status); +} + +void CastTransportSenderIPC::OnRtpStatistics( + bool audio, + const media::cast::transport::RtcpSenderInfo& sender_info, + base::TimeTicks time_sent, + uint32 rtp_timestamp) { + const media::cast::transport::CastTransportRtpStatistics& callback = + audio ? audio_rtp_callback_ : video_rtp_callback_; + callback.Run(sender_info, time_sent, rtp_timestamp); +} + +void CastTransportSenderIPC::Send(IPC::Message* message) { + if (CastIPCDispatcher::Get()) { + CastIPCDispatcher::Get()->Send(message); + } else { + delete message; + } +} diff --git a/chrome/renderer/media/cast_transport_sender_ipc.h b/chrome/renderer/media/cast_transport_sender_ipc.h new file mode 100644 index 0000000..b86f6c9 --- /dev/null +++ b/chrome/renderer/media/cast_transport_sender_ipc.h @@ -0,0 +1,74 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_MEDIA_CAST_TRANSPORT_SENDER_IPC_H_ +#define CHROME_RENDERER_MEDIA_CAST_TRANSPORT_SENDER_IPC_H_ + +#include "base/message_loop/message_loop_proxy.h" +#include "ipc/ipc_channel_proxy.h" +#include "media/cast/transport/cast_transport_sender.h" + +// This implementation of the CastTransportSender interface +// communicates with the browser process over IPC and relays +// all calls to/from the transport sender to the browser process. +// The primary reason for this arrangement is to give the +// renderer less direct control over the UDP sockets. +class CastTransportSenderIPC + : public media::cast::transport::CastTransportSender { + public: + CastTransportSenderIPC( + const media::cast::transport::CastTransportConfig& config, + const media::cast::transport::CastTransportStatusCallback& status_cb); + + virtual ~CastTransportSenderIPC(); + + // media::cast::transport::CastTransportSender implementation. + virtual void SetPacketReceiver( + const media::cast::transport::PacketReceiverCallback& packet_callback) + OVERRIDE; + virtual void InsertCodedAudioFrame( + const media::cast::transport::EncodedAudioFrame* audio_frame, + const base::TimeTicks& recorded_time) OVERRIDE; + virtual void InsertCodedVideoFrame( + const media::cast::transport::EncodedVideoFrame* video_frame, + const base::TimeTicks& capture_time) OVERRIDE; + virtual void SendRtcpFromRtpSender( + uint32 packet_type_flags, + const media::cast::transport::RtcpSenderInfo& sender_info, + const media::cast::transport::RtcpDlrrReportBlock& dlrr, + const media::cast::transport::RtcpSenderLogMessage& sender_log, + uint32 sending_ssrc, + const std::string& c_name) OVERRIDE; + virtual void ResendPackets( + bool is_audio, + const media::cast::transport::MissingFramesAndPacketsMap& missing_packets) + OVERRIDE; + virtual void SubscribeAudioRtpStatsCallback( + const media::cast::transport::CastTransportRtpStatistics& callback) + OVERRIDE; + virtual void SubscribeVideoRtpStatsCallback( + const media::cast::transport::CastTransportRtpStatistics& callback) + OVERRIDE; + + void OnReceivedPacket(const media::cast::transport::Packet& packet); + void OnNotifyStatusChange( + media::cast::transport::CastTransportStatus status); + void OnRtpStatistics( + bool audio, + const media::cast::transport::RtcpSenderInfo& sender_info, + base::TimeTicks time_sent, + uint32 rtp_timestamp); + + private: + void Send(IPC::Message* message); + + int32 channel_id_; + media::cast::transport::PacketReceiverCallback packet_callback_; + media::cast::transport::CastTransportStatusCallback status_callback_; + media::cast::transport::CastTransportRtpStatistics audio_rtp_callback_; + media::cast::transport::CastTransportRtpStatistics video_rtp_callback_; + DISALLOW_COPY_AND_ASSIGN(CastTransportSenderIPC); +}; + +#endif // CHROME_RENDERER_MEDIA_CAST_TRANSPORT_SENDER_IPC_H_ diff --git a/chrome/renderer/media/cast_udp_transport.cc b/chrome/renderer/media/cast_udp_transport.cc index 11fe751..2bd5e6d 100644 --- a/chrome/renderer/media/cast_udp_transport.cc +++ b/chrome/renderer/media/cast_udp_transport.cc @@ -16,4 +16,6 @@ CastUdpTransport::~CastUdpTransport() { void CastUdpTransport::SetDestination(const net::IPEndPoint& remote_address) { remote_address_ = remote_address; + cast_session_->StartUDP(net::IPEndPoint(net::IPAddressNumber(4, 0), 0), + remote_address); } diff --git a/content/common/content_param_traits.cc b/content/common/content_param_traits.cc index 3b0ab98..7a1e2aa 100644 --- a/content/common/content_param_traits.cc +++ b/content/common/content_param_traits.cc @@ -11,25 +11,6 @@ namespace IPC { -void ParamTraits<net::IPEndPoint>::Write(Message* m, const param_type& p) { - WriteParam(m, p.address()); - WriteParam(m, p.port()); -} - -bool ParamTraits<net::IPEndPoint>::Read(const Message* m, PickleIterator* iter, - param_type* p) { - net::IPAddressNumber address; - int port; - if (!ReadParam(m, iter, &address) || !ReadParam(m, iter, &port)) - return false; - *p = net::IPEndPoint(address, port); - return true; -} - -void ParamTraits<net::IPEndPoint>::Log(const param_type& p, std::string* l) { - LogParam("IPEndPoint:" + p.ToString(), l); -} - void ParamTraits<gfx::Range>::Write(Message* m, const gfx::Range& r) { m->WriteUInt64(r.start()); m->WriteUInt64(r.end()); diff --git a/content/common/content_param_traits.h b/content/common/content_param_traits.h index d4bc359..239fe5c 100644 --- a/content/common/content_param_traits.h +++ b/content/common/content_param_traits.h @@ -29,14 +29,6 @@ class IPEndPoint; namespace IPC { template <> -struct ParamTraits<net::IPEndPoint> { - typedef net::IPEndPoint param_type; - static void Write(Message* m, const param_type& p); - static bool Read(const Message* m, PickleIterator* iter, param_type* p); - static void Log(const param_type& p, std::string* l); -}; - -template <> struct ParamTraits<gfx::Range> { typedef gfx::Range param_type; static void Write(Message* m, const param_type& p); diff --git a/content/public/common/common_param_traits.cc b/content/public/common/common_param_traits.cc index e3eec02..7c47ab5 100644 --- a/content/public/common/common_param_traits.cc +++ b/content/public/common/common_param_traits.cc @@ -9,6 +9,7 @@ #include "content/public/common/referrer.h" #include "content/public/common/url_utils.h" #include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/rect.h" #include "ui/gfx/rect_f.h" @@ -108,6 +109,25 @@ void ParamTraits<net::HostPortPair>::Log(const param_type& p, std::string* l) { l->append(p.ToString()); } +void ParamTraits<net::IPEndPoint>::Write(Message* m, const param_type& p) { + WriteParam(m, p.address()); + WriteParam(m, p.port()); +} + +bool ParamTraits<net::IPEndPoint>::Read(const Message* m, PickleIterator* iter, + param_type* p) { + net::IPAddressNumber address; + int port; + if (!ReadParam(m, iter, &address) || !ReadParam(m, iter, &port)) + return false; + *p = net::IPEndPoint(address, port); + return true; +} + +void ParamTraits<net::IPEndPoint>::Log(const param_type& p, std::string* l) { + LogParam("IPEndPoint:" + p.ToString(), l); +} + void ParamTraits<content::PageState>::Write( Message* m, const param_type& p) { WriteParam(m, p.ToEncodedData()); diff --git a/content/public/common/common_param_traits.h b/content/public/common/common_param_traits.h index 70c8dfa..18a0ee0 100644 --- a/content/public/common/common_param_traits.h +++ b/content/public/common/common_param_traits.h @@ -38,6 +38,7 @@ class Vector2d; namespace net { class HostPortPair; +class IPEndPoint; } namespace IPC { @@ -59,6 +60,14 @@ struct CONTENT_EXPORT ParamTraits<net::HostPortPair> { }; template <> +struct CONTENT_EXPORT ParamTraits<net::IPEndPoint> { + typedef net::IPEndPoint param_type; + static void Write(Message* m, const param_type& p); + static bool Read(const Message* m, PickleIterator* iter, param_type* p); + static void Log(const param_type& p, std::string* l); +}; + +template <> struct CONTENT_EXPORT ParamTraits<content::PageState> { typedef content::PageState param_type; static void Write(Message* m, const param_type& p); diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h index 2ebc24f..5b9c9d7 100644 --- a/ipc/ipc_message_start.h +++ b/ipc/ipc_message_start.h @@ -94,6 +94,7 @@ enum IPCMessageStart { MessagePortMsgStart, EmbeddedWorkerMsgStart, EmbeddedWorkerContextMsgStart, + CastMsgStart, LastIPCMsgStart // Must come last. }; diff --git a/media/cast/audio_sender/audio_sender.cc b/media/cast/audio_sender/audio_sender.cc index 66027e4..8da20cb 100644 --- a/media/cast/audio_sender/audio_sender.cc +++ b/media/cast/audio_sender/audio_sender.cc @@ -69,7 +69,7 @@ class LocalRtpSenderStatistics : public RtpSenderStatistics { sender_info->send_octet_count = sender_info_.send_octet_count; } - void StoreStatistics(transport::RtcpSenderInfo& sender_info, + void StoreStatistics(const transport::RtcpSenderInfo& sender_info, base::TimeTicks time_sent, uint32 rtp_timestamp) { sender_info_ = sender_info; diff --git a/media/cast/rtcp/rtcp_defines.h b/media/cast/rtcp/rtcp_defines.h index 40f4a0d..a8f91d7 100644 --- a/media/cast/rtcp/rtcp_defines.h +++ b/media/cast/rtcp/rtcp_defines.h @@ -5,7 +5,6 @@ #ifndef MEDIA_CAST_RTCP_RTCP_DEFINES_H_ #define MEDIA_CAST_RTCP_RTCP_DEFINES_H_ -#include <list> #include <map> #include <set> diff --git a/media/cast/transport/cast_transport_config.cc b/media/cast/transport/cast_transport_config.cc index 99aca57..1ec6be5 100644 --- a/media/cast/transport/cast_transport_config.cc +++ b/media/cast/transport/cast_transport_config.cc @@ -69,6 +69,11 @@ RtcpDlrrReportBlock::RtcpDlrrReportBlock() : last_rr(0), delay_since_last_rr(0) {} RtcpDlrrReportBlock::~RtcpDlrrReportBlock() {} +SendRtcpFromRtpSenderData::SendRtcpFromRtpSenderData() + : packet_type_flags(0), + sending_ssrc(0) {} +SendRtcpFromRtpSenderData::~SendRtcpFromRtpSenderData() {} + } // namespace transport } // namespace cast } // namespace media diff --git a/media/cast/transport/cast_transport_config.h b/media/cast/transport/cast_transport_config.h index c59bf1c..d8474f4 100644 --- a/media/cast/transport/cast_transport_config.h +++ b/media/cast/transport/cast_transport_config.h @@ -113,7 +113,7 @@ struct RtcpSenderFrameLogMessage { uint32 rtp_timestamp; }; -typedef std::list<RtcpSenderFrameLogMessage> RtcpSenderLogMessage; +typedef std::vector<RtcpSenderFrameLogMessage> RtcpSenderLogMessage; struct RtcpSenderInfo { RtcpSenderInfo(); @@ -147,6 +147,16 @@ struct RtcpDlrrReportBlock { uint32 delay_since_last_rr; }; +// This is only needed because IPC messages don't support more than +// 5 arguments. +struct SendRtcpFromRtpSenderData { + SendRtcpFromRtpSenderData(); + ~SendRtcpFromRtpSenderData(); + uint32 packet_type_flags; + uint32 sending_ssrc; + std::string c_name; +}; + inline bool operator==(RtcpSenderInfo lhs, RtcpSenderInfo rhs) { return lhs.ntp_seconds == rhs.ntp_seconds && lhs.ntp_fraction == rhs.ntp_fraction && diff --git a/media/cast/transport/cast_transport_defines.h b/media/cast/transport/cast_transport_defines.h index eff33b5..75e8d62 100644 --- a/media/cast/transport/cast_transport_defines.h +++ b/media/cast/transport/cast_transport_defines.h @@ -5,7 +5,6 @@ #ifndef MEDIA_CAST_TRANSPORT_CAST_TRANSPORT_DEFINES_H_ #define MEDIA_CAST_TRANSPORT_CAST_TRANSPORT_DEFINES_H_ -#include <list> #include <map> #include <set> #include <string> diff --git a/media/cast/transport/cast_transport_sender.h b/media/cast/transport/cast_transport_sender.h index 24bfedb..2e214bf 100644 --- a/media/cast/transport/cast_transport_sender.h +++ b/media/cast/transport/cast_transport_sender.h @@ -38,7 +38,7 @@ namespace transport { typedef base::Callback<void(CastTransportStatus status)> CastTransportStatusCallback; -typedef base::Callback<void(RtcpSenderInfo& sender_info, +typedef base::Callback<void(const RtcpSenderInfo& sender_info, base::TimeTicks time_sent, uint32 rtp_timestamp)> CastTransportRtpStatistics; diff --git a/media/cast/transport/rtcp/rtcp_builder.cc b/media/cast/transport/rtcp/rtcp_builder.cc index e891023..6ab8c8b 100644 --- a/media/cast/transport/rtcp/rtcp_builder.cc +++ b/media/cast/transport/rtcp/rtcp_builder.cc @@ -55,17 +55,17 @@ void RtcpBuilder::SendRtcpFromRtpSender( Packet packet; packet.reserve(kMaxIpPacketSize); if (packet_type_flags & kRtcpSr) { - BuildSR(sender_info, &packet); - BuildSdec(&packet); + if (!BuildSR(sender_info, &packet)) return; + if (!BuildSdec(&packet)) return; } if (packet_type_flags & kRtcpBye) { - BuildBye(&packet); + if (!BuildBye(&packet)) return; } if (packet_type_flags & kRtcpDlrr) { - BuildDlrrRb(dlrr, &packet); + if (!BuildDlrrRb(dlrr, &packet)) return; } if (packet_type_flags & kRtcpSenderLog) { - BuildSenderLog(sender_log, &packet); + if (!BuildSenderLog(sender_log, &packet)) return; } if (packet.empty()) return; // Sanity - don't send empty packets. @@ -73,12 +73,14 @@ void RtcpBuilder::SendRtcpFromRtpSender( transport_->SendRtcpPacket(packet); } -void RtcpBuilder::BuildSR(const RtcpSenderInfo& sender_info, +bool RtcpBuilder::BuildSR(const RtcpSenderInfo& sender_info, Packet* packet) const { // Sender report. size_t start_size = packet->size(); - DCHECK_LT(start_size + 52, kMaxIpPacketSize) << "Not enough buffer space"; - if (start_size + 52 > kMaxIpPacketSize) return; + if (start_size + 52 > kMaxIpPacketSize) { + DLOG(FATAL) << "Not enough buffer space"; + return false; + } uint16 number_of_rows = 6; packet->resize(start_size + 28); @@ -93,13 +95,15 @@ void RtcpBuilder::BuildSR(const RtcpSenderInfo& sender_info, big_endian_writer.WriteU32(sender_info.rtp_timestamp); big_endian_writer.WriteU32(sender_info.send_packet_count); big_endian_writer.WriteU32(static_cast<uint32>(sender_info.send_octet_count)); + return true; } -void RtcpBuilder::BuildSdec(Packet* packet) const { +bool RtcpBuilder::BuildSdec(Packet* packet) const { size_t start_size = packet->size(); - DCHECK_LT(start_size + 12 + c_name_.length(), kMaxIpPacketSize) - << "Not enough buffer space"; - if (start_size + 12 > kMaxIpPacketSize) return; + if (start_size + 12 + c_name_.length() > kMaxIpPacketSize) { + DLOG(FATAL) << "Not enough buffer space"; + return false; + } // SDES Source Description. packet->resize(start_size + 10); @@ -136,12 +140,15 @@ void RtcpBuilder::BuildSdec(Packet* packet) const { // In 32-bit words minus one and we don't count the header. uint8 buffer_length = static_cast<uint8>((sdes_length / 4) - 1); (*packet)[sdes_length_position] = buffer_length; + return true; } -void RtcpBuilder::BuildBye(Packet* packet) const { +bool RtcpBuilder::BuildBye(Packet* packet) const { size_t start_size = packet->size(); - DCHECK_LT(start_size + 8, kMaxIpPacketSize) << "Not enough buffer space"; - if (start_size + 8 > kMaxIpPacketSize) return; + if (start_size + 8 > kMaxIpPacketSize) { + DLOG(FATAL) << "Not enough buffer space"; + return false; + } packet->resize(start_size + 8); @@ -150,6 +157,7 @@ void RtcpBuilder::BuildBye(Packet* packet) const { big_endian_writer.WriteU8(kPacketTypeBye); big_endian_writer.WriteU16(1); // Length. big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. + return true; } /* @@ -169,11 +177,13 @@ void RtcpBuilder::BuildBye(Packet* packet) const { | delay since last RR (DLRR) | +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ */ -void RtcpBuilder::BuildDlrrRb(const RtcpDlrrReportBlock& dlrr, +bool RtcpBuilder::BuildDlrrRb(const RtcpDlrrReportBlock& dlrr, Packet* packet) const { size_t start_size = packet->size(); - DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space"; - if (start_size + 24 > kMaxIpPacketSize) return; + if (start_size + 24 > kMaxIpPacketSize) { + DLOG(FATAL) << "Not enough buffer space"; + return false; + } packet->resize(start_size + 24); @@ -188,17 +198,18 @@ void RtcpBuilder::BuildDlrrRb(const RtcpDlrrReportBlock& dlrr, big_endian_writer.WriteU32(ssrc_); // Add the media (received RTP) SSRC. big_endian_writer.WriteU32(dlrr.last_rr); big_endian_writer.WriteU32(dlrr.delay_since_last_rr); + return true; } -void RtcpBuilder::BuildSenderLog(const RtcpSenderLogMessage& sender_log_message, +bool RtcpBuilder::BuildSenderLog(const RtcpSenderLogMessage& sender_log_message, Packet* packet) const { DCHECK(packet); size_t start_size = packet->size(); size_t remaining_space = kMaxIpPacketSize - start_size; - DCHECK_GE(remaining_space, kRtcpCastLogHeaderSize + kRtcpSenderFrameLogSize) - << "Not enough buffer space"; - if (remaining_space < kRtcpCastLogHeaderSize + kRtcpSenderFrameLogSize) - return; + if (remaining_space < kRtcpCastLogHeaderSize + kRtcpSenderFrameLogSize) { + DLOG(FATAL) << "Not enough buffer space"; + return false; + } size_t space_for_x_messages = (remaining_space - kRtcpCastLogHeaderSize) / kRtcpSenderFrameLogSize; @@ -216,7 +227,7 @@ void RtcpBuilder::BuildSenderLog(const RtcpSenderLogMessage& sender_log_message, big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. big_endian_writer.WriteU32(kCast); - std::list<RtcpSenderFrameLogMessage>::const_iterator it = + std::vector<RtcpSenderFrameLogMessage>::const_iterator it = sender_log_message.begin(); for (; number_of_messages > 0; --number_of_messages) { DCHECK(!sender_log_message.empty()); @@ -228,6 +239,7 @@ void RtcpBuilder::BuildSenderLog(const RtcpSenderLogMessage& sender_log_message, big_endian_writer.WriteU8(static_cast<uint8>(message.rtp_timestamp)); ++it; } + return true; } } // namespace transport diff --git a/media/cast/transport/rtcp/rtcp_builder.h b/media/cast/transport/rtcp/rtcp_builder.h index bcc45df..c56ee61 100644 --- a/media/cast/transport/rtcp/rtcp_builder.h +++ b/media/cast/transport/rtcp/rtcp_builder.h @@ -47,16 +47,12 @@ class RtcpBuilder { }; private: - void BuildSR(const RtcpSenderInfo& sender_info, - Packet* packet) const; - - void BuildSdec(Packet* packet) const; - - void BuildBye(Packet* packet) const; - - void BuildDlrrRb(const RtcpDlrrReportBlock& dlrr, + bool BuildSR(const RtcpSenderInfo& sender_info, Packet* packet) const; + bool BuildSdec(Packet* packet) const; + bool BuildBye(Packet* packet) const; + bool BuildDlrrRb(const RtcpDlrrReportBlock& dlrr, Packet* packet) const; - void BuildSenderLog(const RtcpSenderLogMessage& sender_log_message, + bool BuildSenderLog(const RtcpSenderLogMessage& sender_log_message, Packet* packet) const; PacedSender* const transport_; // Not owned by this class. diff --git a/media/cast/transport/rtp_sender/rtp_sender.cc b/media/cast/transport/rtp_sender/rtp_sender.cc index 92ad67c..7bcfbca 100644 --- a/media/cast/transport/rtp_sender/rtp_sender.cc +++ b/media/cast/transport/rtp_sender/rtp_sender.cc @@ -134,7 +134,7 @@ void RtpSender::SubscribeRtpStatsCallback( void RtpSender::ScheduleNextStatsReport() { transport_task_runner_->PostDelayedTask( FROM_HERE, - base::Bind(&RtpSender::RtpStatistics, base::Unretained(this)), + base::Bind(&RtpSender::RtpStatistics, base::AsWeakPtr(this)), 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 54961de..4fc4957 100644 --- a/media/cast/transport/rtp_sender/rtp_sender.h +++ b/media/cast/transport/rtp_sender/rtp_sender.h @@ -13,6 +13,7 @@ #include "base/memory/scoped_ptr.h" #include "base/time/tick_clock.h" #include "base/time/time.h" +#include "base/memory/weak_ptr.h" #include "media/cast/cast_config.h" #include "media/cast/cast_environment.h" #include "media/cast/transport/cast_transport_defines.h" @@ -29,7 +30,7 @@ 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 { +class RtpSender : public base::SupportsWeakPtr<RtpSender>{ public: RtpSender(base::TickClock* clock, const CastTransportConfig& config, diff --git a/media/cast/video_sender/video_sender.cc b/media/cast/video_sender/video_sender.cc index 7a3d55b..f9057c5 100644 --- a/media/cast/video_sender/video_sender.cc +++ b/media/cast/video_sender/video_sender.cc @@ -73,7 +73,7 @@ class LocalRtpVideoSenderStatistics : public RtpSenderStatistics { sender_info->send_octet_count = sender_info_.send_octet_count; } - void StoreStatistics(transport::RtcpSenderInfo& sender_info, + void StoreStatistics(const transport::RtcpSenderInfo& sender_info, base::TimeTicks time_sent, uint32 rtp_timestamp) { sender_info_ = sender_info; |