summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/media/cast_transport_host_filter.cc27
-rw-r--r--chrome/browser/media/cast_transport_host_filter.h6
-rw-r--r--chrome/browser/media/cast_transport_host_filter_unittest.cc15
-rw-r--r--chrome/chrome_browser.gypi1
-rw-r--r--chrome/chrome_renderer.gypi2
-rw-r--r--chrome/common/cast_messages.h26
-rw-r--r--chrome/renderer/media/cast_ipc_dispatcher.cc21
-rw-r--r--chrome/renderer/media/cast_ipc_dispatcher.h3
-rw-r--r--chrome/renderer/media/cast_session_delegate.cc31
-rw-r--r--chrome/renderer/media/cast_session_delegate.h6
-rw-r--r--chrome/renderer/media/cast_transport_sender_ipc.cc17
-rw-r--r--chrome/renderer/media/cast_transport_sender_ipc.h8
-rw-r--r--media/cast/audio_sender/audio_sender_unittest.cc6
-rw-r--r--media/cast/cast.gyp73
-rw-r--r--media/cast/logging/logging.gyp87
-rw-r--r--media/cast/logging/logging_defines.cc6
-rw-r--r--media/cast/logging/logging_defines.h2
-rw-r--r--media/cast/logging/proto/proto_utils.cc3
-rw-r--r--media/cast/rtcp/rtcp_unittest.cc7
-rw-r--r--media/cast/test/end2end_unittest.cc28
-rw-r--r--media/cast/test/sender.cc51
-rw-r--r--media/cast/transport/cast_transport.gyp1
-rw-r--r--media/cast/transport/cast_transport_sender.h7
-rw-r--r--media/cast/transport/cast_transport_sender_impl.cc37
-rw-r--r--media/cast/transport/cast_transport_sender_impl.h25
-rw-r--r--media/cast/transport/cast_transport_sender_impl_unittest.cc114
-rw-r--r--media/cast/video_sender/video_sender_unittest.cc7
27 files changed, 492 insertions, 125 deletions
diff --git a/chrome/browser/media/cast_transport_host_filter.cc b/chrome/browser/media/cast_transport_host_filter.cc
index 807d0e1..7e2e87b 100644
--- a/chrome/browser/media/cast_transport_host_filter.cc
+++ b/chrome/browser/media/cast_transport_host_filter.cc
@@ -8,6 +8,13 @@
#include "chrome/browser/net/chrome_net_log.h"
#include "media/cast/transport/cast_transport_sender.h"
+namespace {
+
+// How often to send raw events.
+const int kSendRawEventsIntervalSecs = 1;
+
+}
+
namespace cast {
CastTransportHostFilter::CastTransportHostFilter()
@@ -58,9 +65,18 @@ void CastTransportHostFilter::ReceivedRtpStatistics(
channel_id, audio, sender_info, time_sent, rtp_timestamp));
}
-void CastTransportHostFilter::OnNew(int32 channel_id,
- const net::IPEndPoint& local_end_point,
- const net::IPEndPoint& remote_end_point) {
+void CastTransportHostFilter::RawEvents(
+ int32 channel_id,
+ const std::vector<media::cast::PacketEvent>& packet_events) {
+ if (!packet_events.empty())
+ Send(new CastMsg_RawEvents(channel_id, packet_events));
+}
+
+void CastTransportHostFilter::OnNew(
+ int32 channel_id,
+ const net::IPEndPoint& local_end_point,
+ const net::IPEndPoint& remote_end_point,
+ const media::cast::CastLoggingConfig& logging_config) {
if (id_map_.Lookup(channel_id)) {
id_map_.Remove(channel_id);
}
@@ -71,9 +87,14 @@ void CastTransportHostFilter::OnNew(int32 channel_id,
&clock_,
local_end_point,
remote_end_point,
+ logging_config,
base::Bind(&CastTransportHostFilter::NotifyStatusChange,
base::Unretained(this),
channel_id),
+ base::Bind(&CastTransportHostFilter::RawEvents,
+ base::Unretained(this),
+ channel_id),
+ base::TimeDelta::FromSeconds(kSendRawEventsIntervalSecs),
base::MessageLoopProxy::current());
sender->SetPacketReceiver(base::Bind(&CastTransportHostFilter::ReceivedPacket,
diff --git a/chrome/browser/media/cast_transport_host_filter.h b/chrome/browser/media/cast_transport_host_filter.h
index 2c53ab8..c644a54 100644
--- a/chrome/browser/media/cast_transport_host_filter.h
+++ b/chrome/browser/media/cast_transport_host_filter.h
@@ -10,6 +10,7 @@
#include "chrome/common/cast_messages.h"
#include "content/public/browser/browser_message_filter.h"
#include "media/cast/cast_sender.h"
+#include "media/cast/logging/logging_defines.h"
#include "media/cast/transport/cast_transport_sender.h"
namespace cast {
@@ -32,6 +33,8 @@ class CastTransportHostFilter : public content::BrowserMessageFilter {
const media::cast::transport::RtcpSenderInfo& sender_info,
base::TimeTicks time_sent,
uint32 rtp_timestamp);
+ void RawEvents(int32 channel_id,
+ const std::vector<media::cast::PacketEvent>& packet_events);
// BrowserMessageFilter implementation.
virtual bool OnMessageReceived(const IPC::Message& message,
@@ -65,7 +68,8 @@ class CastTransportHostFilter : public content::BrowserMessageFilter {
void OnNew(
int32 channel_id,
const net::IPEndPoint& local_end_point,
- const net::IPEndPoint& remote_end_point);
+ const net::IPEndPoint& remote_end_point,
+ const media::cast::CastLoggingConfig& logging_config);
void OnDelete(int32 channel_id);
IDMap<media::cast::transport::CastTransportSender, IDMapOwnPointer> id_map_;
diff --git a/chrome/browser/media/cast_transport_host_filter_unittest.cc b/chrome/browser/media/cast_transport_host_filter_unittest.cc
index c7139a4..81f4c61 100644
--- a/chrome/browser/media/cast_transport_host_filter_unittest.cc
+++ b/chrome/browser/media/cast_transport_host_filter_unittest.cc
@@ -7,6 +7,7 @@
#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 "media/cast/logging/logging_defines.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -15,7 +16,9 @@ class CastTransportHostFilterTest : public testing::Test {
public:
CastTransportHostFilterTest()
: browser_thread_bundle_(
- content::TestBrowserThreadBundle::IO_MAINLOOP) {
+ content::TestBrowserThreadBundle::IO_MAINLOOP),
+ logging_config_(
+ media::cast::GetLoggingConfigWithRawEventsAndStatsEnabled()) {
filter_ = new cast::CastTransportHostFilter();
local_endpoint_ = net::IPEndPoint(net::IPAddressNumber(4, 0), 0);
// 127.0.0.1:7 is the local echo service port, which
@@ -40,11 +43,13 @@ class CastTransportHostFilterTest : public testing::Test {
net::IPAddressNumber receiver_address_;
net::IPEndPoint local_endpoint_;
net::IPEndPoint receive_endpoint_;
+ media::cast::CastLoggingConfig logging_config_;
};
TEST_F(CastTransportHostFilterTest, NewDelete) {
const int kChannelId = 17;
- CastHostMsg_New new_msg(kChannelId, local_endpoint_, receive_endpoint_);
+ CastHostMsg_New new_msg(kChannelId, local_endpoint_, receive_endpoint_,
+ logging_config_);
CastHostMsg_Delete delete_msg(kChannelId);
// New, then delete, as expected.
@@ -67,7 +72,8 @@ TEST_F(CastTransportHostFilterTest, NewDelete) {
TEST_F(CastTransportHostFilterTest, NewMany) {
for (int i = 0; i < 100; i++) {
- CastHostMsg_New new_msg(i, local_endpoint_, receive_endpoint_);
+ CastHostMsg_New new_msg(i, local_endpoint_, receive_endpoint_,
+ logging_config_);
FakeSend(new_msg);
}
@@ -82,7 +88,8 @@ TEST_F(CastTransportHostFilterTest, NewMany) {
TEST_F(CastTransportHostFilterTest, SimpleMessages) {
// Create a cast transport sender.
const int32 kChannelId = 42;
- CastHostMsg_New new_msg(kChannelId, local_endpoint_, receive_endpoint_);
+ CastHostMsg_New new_msg(kChannelId, local_endpoint_, receive_endpoint_,
+ logging_config_);
FakeSend(new_msg);
media::cast::transport::CastTransportAudioConfig audio_config;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index ccc9de1..62cb6d7 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -62,6 +62,7 @@
'../google_apis/gcm/gcm.gyp:gcm',
'../google_apis/google_apis.gyp:google_apis',
'../jingle/jingle.gyp:notifier',
+ '../media/cast/logging/logging.gyp:cast_common_logging',
'../media/cast/transport/cast_transport.gyp:cast_transport',
'../skia/skia.gyp:skia',
'../sql/sql.gyp:sql',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 8ef45c8..b57fc7f 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -22,8 +22,8 @@
'../components/components.gyp:visitedlink_renderer',
'../content/content.gyp:content_renderer',
'../media/cast/cast.gyp:cast_config',
- '../media/cast/cast.gyp:sender_logging',
'../media/cast/cast_sender.gyp:cast_sender',
+ '../media/cast/logging/logging.gyp:sender_logging',
'../media/cast/transport/cast_transport.gyp:cast_transport',
'../net/net.gyp:net',
'../skia/skia.gyp:skia',
diff --git a/chrome/common/cast_messages.h b/chrome/common/cast_messages.h
index 404a26f..51f4e54 100644
--- a/chrome/common/cast_messages.h
+++ b/chrome/common/cast_messages.h
@@ -7,6 +7,7 @@
#include "ipc/ipc_message_macros.h"
#include "media/cast/cast_sender.h"
+#include "media/cast/logging/logging_defines.h"
#include "media/cast/rtcp/rtcp_defines.h"
#include "media/cast/transport/cast_transport_sender.h"
#include "net/base/ip_endpoint.h"
@@ -24,6 +25,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(media::cast::transport::RtcpSenderFrameStatus,
media::cast::transport::kRtcpSenderFrameStatusLast)
IPC_ENUM_TRAITS_MAX_VALUE(media::cast::transport::CastTransportStatus,
media::cast::transport::CAST_TRANSPORT_STATUS_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(media::cast::CastLoggingEvent,
+ media::cast::kNumOfLoggingEvents)
IPC_STRUCT_TRAITS_BEGIN(media::cast::transport::EncodedAudioFrame)
IPC_STRUCT_TRAITS_MEMBER(codec)
@@ -90,6 +93,21 @@ IPC_STRUCT_TRAITS_BEGIN(media::cast::transport::SendRtcpFromRtpSenderData)
IPC_STRUCT_TRAITS_MEMBER(c_name)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(media::cast::PacketEvent)
+ IPC_STRUCT_TRAITS_MEMBER(rtp_timestamp)
+ IPC_STRUCT_TRAITS_MEMBER(frame_id)
+ IPC_STRUCT_TRAITS_MEMBER(max_packet_id)
+ IPC_STRUCT_TRAITS_MEMBER(packet_id)
+ IPC_STRUCT_TRAITS_MEMBER(size)
+ IPC_STRUCT_TRAITS_MEMBER(timestamp)
+ IPC_STRUCT_TRAITS_MEMBER(type)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(media::cast::CastLoggingConfig)
+ IPC_STRUCT_TRAITS_MEMBER(enable_raw_data_collection)
+ IPC_STRUCT_TRAITS_MEMBER(enable_stats_data_collection)
+ IPC_STRUCT_TRAITS_MEMBER(enable_tracing)
+IPC_STRUCT_TRAITS_END()
// Cast messages sent from the browser to the renderer.
@@ -110,6 +128,9 @@ IPC_MESSAGE_CONTROL5(
base::TimeTicks /* time_sent */,
uint32 /* rtp_timestamp */);
+IPC_MESSAGE_CONTROL2(CastMsg_RawEvents,
+ int32 /* channel_id */,
+ std::vector<media::cast::PacketEvent> /* packet_events */);
// Cast messages sent from the renderer to the browser.
@@ -149,11 +170,12 @@ IPC_MESSAGE_CONTROL3(
bool /* is_audio */,
media::cast::MissingFramesAndPacketsMap /* missing_packets */)
-IPC_MESSAGE_CONTROL3(
+IPC_MESSAGE_CONTROL4(
CastHostMsg_New,
int32 /* channel_id */,
net::IPEndPoint /*local_end_point*/,
- net::IPEndPoint /*remote_end_point*/);
+ net::IPEndPoint /*remote_end_point*/,
+ media::cast::CastLoggingConfig /* logging_config */);
IPC_MESSAGE_CONTROL1(
CastHostMsg_Delete,
diff --git a/chrome/renderer/media/cast_ipc_dispatcher.cc b/chrome/renderer/media/cast_ipc_dispatcher.cc
index feff41d..022d7ec 100644
--- a/chrome/renderer/media/cast_ipc_dispatcher.cc
+++ b/chrome/renderer/media/cast_ipc_dispatcher.cc
@@ -51,6 +51,7 @@ bool CastIPCDispatcher::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(CastMsg_ReceivedPacket, OnReceivedPacket)
IPC_MESSAGE_HANDLER(CastMsg_NotifyStatusChange, OnNotifyStatusChange)
IPC_MESSAGE_HANDLER(CastMsg_RtpStatistics, OnRtpStatistics)
+ IPC_MESSAGE_HANDLER(CastMsg_RawEvents, OnRawEvents)
IPC_MESSAGE_UNHANDLED(handled = false);
IPC_END_MESSAGE_MAP();
return handled;
@@ -82,8 +83,8 @@ void CastIPCDispatcher::OnReceivedPacket(
if (sender) {
sender->OnReceivedPacket(packet);
} else {
- LOG(ERROR) << "CastIPCDispatcher::OnReceivedPacket "
- << "on non-existing channel.";
+ DVLOG(1) << "CastIPCDispatcher::OnReceivedPacket "
+ << "on non-existing channel.";
}
}
@@ -94,7 +95,7 @@ void CastIPCDispatcher::OnNotifyStatusChange(
if (sender) {
sender->OnNotifyStatusChange(status);
} else {
- LOG(ERROR)
+ DVLOG(1)
<< "CastIPCDispatcher::OnNotifystatusChange on non-existing channel.";
}
}
@@ -109,7 +110,17 @@ void CastIPCDispatcher::OnRtpStatistics(
if (sender) {
sender->OnRtpStatistics(audio, sender_info, time_sent, rtp_timestamp);
} else {
- LOG(ERROR)
- << "CastIPCDispatcher::OnNotifystatusChange on non-existing channel.";
+ DVLOG(1) << "CastIPCDispatcher::OnRtpStatistics on non-existing channel.";
+ }
+}
+
+void CastIPCDispatcher::OnRawEvents(
+ int32 channel_id,
+ const std::vector<media::cast::PacketEvent>& packet_events) {
+ CastTransportSenderIPC* sender = id_map_.Lookup(channel_id);
+ if (sender) {
+ sender->OnRawEvents(packet_events);
+ } else {
+ DVLOG(1) << "CastIPCDispatcher::OnRawEvents on non-existing channel.";
}
}
diff --git a/chrome/renderer/media/cast_ipc_dispatcher.h b/chrome/renderer/media/cast_ipc_dispatcher.h
index 7464f4d..4e87f2e 100644
--- a/chrome/renderer/media/cast_ipc_dispatcher.h
+++ b/chrome/renderer/media/cast_ipc_dispatcher.h
@@ -9,6 +9,7 @@
#include "base/id_map.h"
#include "ipc/ipc_channel_proxy.h"
#include "media/cast/cast_sender.h"
+#include "media/cast/logging/logging_defines.h"
#include "media/cast/transport/cast_transport_sender.h"
class CastTransportSenderIPC;
@@ -45,6 +46,8 @@ class CastIPCDispatcher : public IPC::ChannelProxy::MessageFilter {
const media::cast::transport::RtcpSenderInfo& sender_info,
base::TimeTicks time_sent,
uint32 rtp_timestamp);
+ void OnRawEvents(int32 channel_id,
+ const std::vector<media::cast::PacketEvent>& packet_events);
static CastIPCDispatcher* global_instance_;
diff --git a/chrome/renderer/media/cast_session_delegate.cc b/chrome/renderer/media/cast_session_delegate.cc
index f72c682..4340ab7 100644
--- a/chrome/renderer/media/cast_session_delegate.cc
+++ b/chrome/renderer/media/cast_session_delegate.cc
@@ -63,14 +63,14 @@ CastSessionDelegate::~CastSessionDelegate() {
}
}
-void CastSessionDelegate::Initialize() {
+void CastSessionDelegate::Initialize(
+ const media::cast::CastLoggingConfig& logging_config) {
if (cast_environment_)
return; // Already initialized.
// CastSender uses the renderer's IO thread as the main thread. This reduces
// thread hopping for incoming video frames and outgoing network packets.
// There's no need to decode so no thread assigned for decoding.
- // Logging: enable raw events and stats collection.
cast_environment_ = new CastEnvironment(
scoped_ptr<base::TickClock>(new base::DefaultTickClock()).Pass(),
base::MessageLoopProxy::current(),
@@ -79,7 +79,7 @@ void CastSessionDelegate::Initialize() {
g_cast_threads.Get().GetVideoEncodeMessageLoopProxy(),
NULL,
base::MessageLoopProxy::current(),
- media::cast::GetLoggingConfigWithRawEventsAndStatsEnabled());
+ logging_config);
}
void CastSessionDelegate::StartAudio(
@@ -198,7 +198,10 @@ void CastSessionDelegate::StartSendingInternal() {
if (!audio_config_ || !video_config_)
return;
- Initialize();
+ // Logging: enable raw events and stats collection.
+ media::cast::CastLoggingConfig logging_config =
+ media::cast::GetLoggingConfigWithRawEventsAndStatsEnabled();
+ Initialize(logging_config);
// Rationale for using unretained: The callback cannot be called after the
// destruction of CastTransportSenderIPC, and they both share the same thread.
@@ -206,6 +209,9 @@ void CastSessionDelegate::StartSendingInternal() {
local_endpoint_,
remote_endpoint_,
base::Bind(&CastSessionDelegate::StatusNotificationCB,
+ base::Unretained(this)),
+ logging_config,
+ base::Bind(&CastSessionDelegate::LogRawEvents,
base::Unretained(this))));
// TODO(hubbe): set config.aes_key and config.aes_iv_mask.
@@ -252,3 +258,20 @@ void CastSessionDelegate::InitializationResult(
}
}
+void CastSessionDelegate::LogRawEvents(
+ const std::vector<media::cast::PacketEvent>& packet_events) {
+ DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
+
+ for (std::vector<media::cast::PacketEvent>::const_iterator it =
+ packet_events.begin();
+ it != packet_events.end();
+ ++it) {
+ cast_environment_->Logging()->InsertPacketEvent(it->timestamp,
+ it->type,
+ it->rtp_timestamp,
+ it->frame_id,
+ it->packet_id,
+ it->max_packet_id,
+ it->size);
+ }
+}
diff --git a/chrome/renderer/media/cast_session_delegate.h b/chrome/renderer/media/cast_session_delegate.h
index 05d1366..9c9767a 100644
--- a/chrome/renderer/media/cast_session_delegate.h
+++ b/chrome/renderer/media/cast_session_delegate.h
@@ -17,6 +17,7 @@
#include "base/time/default_tick_clock.h"
#include "media/cast/cast_config.h"
#include "media/cast/cast_sender.h"
+#include "media/cast/logging/logging_defines.h"
namespace base {
class MessageLoopProxy;
@@ -72,7 +73,7 @@ class CastSessionDelegate {
private:
// Start encoding threads and initialize the CastEnvironment.
- void Initialize();
+ void Initialize(const media::cast::CastLoggingConfig& logging_config);
// Configure CastSender. It is ready to accept audio / video frames after
// receiving a successful call to InitializationResult.
@@ -81,6 +82,9 @@ class CastSessionDelegate {
void StatusNotificationCB(
media::cast::transport::CastTransportStatus status);
+ // Adds logs collected from transport on browser side.
+ void LogRawEvents(const std::vector<media::cast::PacketEvent>& packet_events);
+
base::ThreadChecker thread_checker_;
scoped_refptr<media::cast::CastEnvironment> cast_environment_;
scoped_ptr<media::cast::CastSender> cast_sender_;
diff --git a/chrome/renderer/media/cast_transport_sender_ipc.cc b/chrome/renderer/media/cast_transport_sender_ipc.cc
index 7b59693..c4ccd44 100644
--- a/chrome/renderer/media/cast_transport_sender_ipc.cc
+++ b/chrome/renderer/media/cast_transport_sender_ipc.cc
@@ -15,12 +15,15 @@
CastTransportSenderIPC::CastTransportSenderIPC(
const net::IPEndPoint& local_end_point,
const net::IPEndPoint& remote_end_point,
- const media::cast::transport::CastTransportStatusCallback& status_cb)
- : status_callback_(status_cb) {
+ const media::cast::transport::CastTransportStatusCallback& status_cb,
+ const media::cast::CastLoggingConfig& logging_config,
+ const media::cast::transport::BulkRawEventsCallback& raw_events_cb)
+ : status_callback_(status_cb), raw_events_callback_(raw_events_cb) {
if (CastIPCDispatcher::Get()) {
channel_id_ = CastIPCDispatcher::Get()->AddSender(this);
}
- Send(new CastHostMsg_New(channel_id_, local_end_point, remote_end_point));
+ Send(new CastHostMsg_New(channel_id_, local_end_point, remote_end_point,
+ logging_config));
}
CastTransportSenderIPC::~CastTransportSenderIPC() {
@@ -107,8 +110,7 @@ void CastTransportSenderIPC::OnReceivedPacket(
new media::cast::transport::Packet(packet));
packet_callback_.Run(packet_copy.Pass());
} else {
- LOG(ERROR) << "CastIPCDispatcher::OnReceivedPacket "
- << "no packet callback yet.";
+ DVLOG(1) << "CastIPCDispatcher::OnReceivedPacket no packet callback yet.";
}
}
@@ -127,6 +129,11 @@ void CastTransportSenderIPC::OnRtpStatistics(
callback.Run(sender_info, time_sent, rtp_timestamp);
}
+void CastTransportSenderIPC::OnRawEvents(
+ const std::vector<media::cast::PacketEvent>& packet_events) {
+ raw_events_callback_.Run(packet_events);
+}
+
void CastTransportSenderIPC::Send(IPC::Message* message) {
if (CastIPCDispatcher::Get()) {
CastIPCDispatcher::Get()->Send(message);
diff --git a/chrome/renderer/media/cast_transport_sender_ipc.h b/chrome/renderer/media/cast_transport_sender_ipc.h
index ba7a3d3..089f1fa 100644
--- a/chrome/renderer/media/cast_transport_sender_ipc.h
+++ b/chrome/renderer/media/cast_transport_sender_ipc.h
@@ -7,6 +7,7 @@
#include "base/message_loop/message_loop_proxy.h"
#include "ipc/ipc_channel_proxy.h"
+#include "media/cast/logging/logging_defines.h"
#include "media/cast/transport/cast_transport_sender.h"
// This implementation of the CastTransportSender interface
@@ -20,7 +21,9 @@ class CastTransportSenderIPC
CastTransportSenderIPC(
const net::IPEndPoint& local_end_point,
const net::IPEndPoint& remote_end_point,
- const media::cast::transport::CastTransportStatusCallback& status_cb);
+ const media::cast::transport::CastTransportStatusCallback& status_cb,
+ const media::cast::CastLoggingConfig& logging_config,
+ const media::cast::transport::BulkRawEventsCallback& raw_events_cb);
virtual ~CastTransportSenderIPC();
@@ -64,6 +67,7 @@ class CastTransportSenderIPC
const media::cast::transport::RtcpSenderInfo& sender_info,
base::TimeTicks time_sent,
uint32 rtp_timestamp);
+ void OnRawEvents(const std::vector<media::cast::PacketEvent>& packet_events);
private:
void Send(IPC::Message* message);
@@ -73,6 +77,8 @@ class CastTransportSenderIPC
media::cast::transport::CastTransportStatusCallback status_callback_;
media::cast::transport::CastTransportRtpStatistics audio_rtp_callback_;
media::cast::transport::CastTransportRtpStatistics video_rtp_callback_;
+ media::cast::transport::BulkRawEventsCallback raw_events_callback_;
+
DISALLOW_COPY_AND_ASSIGN(CastTransportSenderIPC);
};
diff --git a/media/cast/audio_sender/audio_sender_unittest.cc b/media/cast/audio_sender/audio_sender_unittest.cc
index 8db06cb..c7ce707 100644
--- a/media/cast/audio_sender/audio_sender_unittest.cc
+++ b/media/cast/audio_sender/audio_sender_unittest.cc
@@ -61,6 +61,7 @@ class AudioSenderTest : public ::testing::Test {
testing_clock_->Advance(
base::TimeDelta::FromMilliseconds(kStartMillisecond));
task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
+ CastLoggingConfig logging_config = GetDefaultCastSenderLoggingConfig();
cast_environment_ =
new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
task_runner_,
@@ -69,7 +70,7 @@ class AudioSenderTest : public ::testing::Test {
task_runner_,
task_runner_,
task_runner_,
- GetDefaultCastSenderLoggingConfig());
+ logging_config);
audio_config_.codec = transport::kOpus;
audio_config_.use_external_encoder = false;
audio_config_.frequency = kDefaultAudioSamplingRate;
@@ -87,7 +88,10 @@ class AudioSenderTest : public ::testing::Test {
testing_clock_,
dummy_endpoint,
dummy_endpoint,
+ logging_config,
base::Bind(&UpdateCastTransportStatus),
+ transport::BulkRawEventsCallback(),
+ base::TimeDelta(),
task_runner_,
&transport_));
transport_sender_->InitializeAudio(transport_config);
diff --git a/media/cast/cast.gyp b/media/cast/cast.gyp
index 33ac3f4..e0d0c69 100644
--- a/media/cast/cast.gyp
+++ b/media/cast/cast.gyp
@@ -23,70 +23,6 @@
'cast_defines.h',
'cast_environment.cc',
'cast_environment.h',
- 'logging/logging_defines.cc',
- 'logging/logging_defines.h',
- 'logging/logging_impl.cc',
- 'logging/logging_impl.h',
- 'logging/logging_raw.cc',
- 'logging/logging_raw.h',
- 'logging/logging_stats.cc',
- 'logging/logging_stats.h',
- 'logging/raw_event_subscriber.h',
- 'logging/simple_event_subscriber.cc',
- 'logging/simple_event_subscriber.h',
- ], # source
- },
- {
- 'target_name': 'cast_logging_proto_lib',
- 'type': 'static_library',
- 'sources': [
- 'logging/proto/proto_utils.cc',
- 'logging/proto/raw_events.proto',
- ],
- 'variables': {
- 'proto_in_dir': 'logging/proto',
- 'proto_out_dir': 'media/cast/logging/proto',
- },
- 'includes': ['../../build/protoc.gypi'],
- },
- {
- 'target_name': 'sender_logging',
- 'type': 'static_library',
- 'include_dirs': [
- '<(DEPTH)/',
- ],
- 'dependencies': [
- 'cast_config',
- 'cast_logging_proto_lib',
- '<(DEPTH)/base/base.gyp:base',
- ],
- 'export_dependent_settings': [
- 'cast_logging_proto_lib',
- ],
- 'sources': [
- 'logging/encoding_event_subscriber.cc',
- 'logging/encoding_event_subscriber.h',
- 'logging/log_serializer.cc',
- 'logging/log_serializer.h',
- ], # source
- },
- {
- 'target_name': 'cast_log_analysis',
- 'type': 'static_library',
- 'include_dirs': [
- '<(DEPTH)/',
- ],
- 'dependencies': [
- 'cast_config',
- 'cast_logging_proto_lib',
- '<(DEPTH)/base/base.gyp:base',
- ],
- 'export_dependent_settings': [
- 'cast_logging_proto_lib',
- ],
- 'sources': [
- 'logging/log_deserializer.cc',
- 'logging/log_deserializer.h',
], # source
},
], # targets,
@@ -98,11 +34,11 @@
'type': '<(gtest_target_type)',
'dependencies': [
'cast_config',
- 'cast_log_analysis',
- 'cast_logging_proto_lib',
'cast_receiver.gyp:cast_receiver',
'cast_sender.gyp:cast_sender',
- 'sender_logging',
+ 'logging/logging.gyp:cast_log_analysis',
+ 'logging/logging.gyp:cast_logging_proto_lib',
+ 'logging/logging.gyp:sender_logging',
'test/utility/utility.gyp:cast_test_utility',
'transport/cast_transport.gyp:cast_transport',
'<(DEPTH)/base/base.gyp:test_support_base',
@@ -153,6 +89,7 @@
'test/fake_single_thread_task_runner.h',
'test/fake_video_encode_accelerator.cc',
'test/fake_video_encode_accelerator.h',
+ 'transport/cast_transport_sender_impl_unittest.cc',
'transport/pacing/mock_paced_packet_sender.cc',
'transport/pacing/mock_paced_packet_sender.h',
'transport/pacing/paced_sender_unittest.cc',
@@ -176,7 +113,7 @@
],
'dependencies': [
'cast_config',
- 'sender_logging',
+ 'logging/logging.gyp:sender_logging',
'<(DEPTH)/ui/gfx/gfx.gyp:gfx',
'<(DEPTH)/net/net.gyp:net_test_support',
'<(DEPTH)/media/cast/cast_sender.gyp:*',
diff --git a/media/cast/logging/logging.gyp b/media/cast/logging/logging.gyp
new file mode 100644
index 0000000..ba2c2dc
--- /dev/null
+++ b/media/cast/logging/logging.gyp
@@ -0,0 +1,87 @@
+# 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.
+{
+ 'targets': [
+ {
+ 'target_name': 'cast_common_logging',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '<(DEPTH)/',
+ ],
+ 'dependencies': [
+ 'cast_logging_proto_lib',
+ '<(DEPTH)/base/base.gyp:base',
+ ],
+ 'export_dependent_settings': [
+ 'cast_logging_proto_lib',
+ ],
+ 'sources': [
+ 'logging_defines.cc',
+ 'logging_defines.h',
+ 'logging_impl.cc',
+ 'logging_impl.h',
+ 'logging_raw.cc',
+ 'logging_raw.h',
+ 'logging_stats.cc',
+ 'logging_stats.h',
+ 'raw_event_subscriber.h',
+ 'simple_event_subscriber.cc',
+ 'simple_event_subscriber.h',
+ ], # source
+ },
+ {
+ 'target_name': 'sender_logging',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '<(DEPTH)/',
+ ],
+ 'dependencies': [
+ 'cast_common_logging',
+ 'cast_logging_proto_lib',
+ '<(DEPTH)/base/base.gyp:base',
+ ],
+ 'export_dependent_settings': [
+ 'cast_logging_proto_lib',
+ ],
+ 'sources': [
+ 'encoding_event_subscriber.cc',
+ 'encoding_event_subscriber.h',
+ 'log_serializer.cc',
+ 'log_serializer.h',
+ ], # source
+ },
+ {
+ 'target_name': 'cast_logging_proto_lib',
+ 'type': 'static_library',
+ 'sources': [
+ 'proto/proto_utils.cc',
+ 'proto/raw_events.proto',
+ ],
+ 'variables': {
+ 'proto_in_dir': 'proto',
+ 'proto_out_dir': 'media/cast/logging/proto',
+ },
+ 'includes': ['../../../build/protoc.gypi'],
+ },
+ {
+ 'target_name': 'cast_log_analysis',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '<(DEPTH)/',
+ ],
+ 'dependencies': [
+ 'cast_logging_proto_lib',
+ 'sender_logging',
+ '<(DEPTH)/base/base.gyp:base',
+ ],
+ 'export_dependent_settings': [
+ 'cast_logging_proto_lib',
+ ],
+ 'sources': [
+ 'log_deserializer.cc',
+ 'log_deserializer.h',
+ ], # source
+ },
+ ],
+}
diff --git a/media/cast/logging/logging_defines.cc b/media/cast/logging/logging_defines.cc
index 5adb574..b82072a 100644
--- a/media/cast/logging/logging_defines.cc
+++ b/media/cast/logging/logging_defines.cc
@@ -65,9 +65,6 @@ std::string CastLoggingToString(CastLoggingEvent event) {
ENUM_TO_STRING(VideoPacketReceived);
ENUM_TO_STRING(DuplicateAudioPacketReceived);
ENUM_TO_STRING(DuplicateVideoPacketReceived);
- case kNumOfLoggingEvents:
- NOTREACHED();
- return "";
}
NOTREACHED();
return "";
@@ -105,9 +102,6 @@ EventMediaType GetEventMediaType(CastLoggingEvent event) {
case kVideoPacketReceived:
case kDuplicateVideoPacketReceived:
return VIDEO_EVENT;
- case kNumOfLoggingEvents:
- NOTREACHED();
- return OTHER_EVENT;
}
NOTREACHED();
return OTHER_EVENT;
diff --git a/media/cast/logging/logging_defines.h b/media/cast/logging/logging_defines.h
index 10529a2..675f751 100644
--- a/media/cast/logging/logging_defines.h
+++ b/media/cast/logging/logging_defines.h
@@ -71,7 +71,7 @@ enum CastLoggingEvent {
kVideoPacketReceived,
kDuplicateAudioPacketReceived,
kDuplicateVideoPacketReceived,
- kNumOfLoggingEvents,
+ kNumOfLoggingEvents = kDuplicateVideoPacketReceived
};
std::string CastLoggingToString(CastLoggingEvent event);
diff --git a/media/cast/logging/proto/proto_utils.cc b/media/cast/logging/proto/proto_utils.cc
index 5805ddc..4b97295 100644
--- a/media/cast/logging/proto/proto_utils.cc
+++ b/media/cast/logging/proto/proto_utils.cc
@@ -43,9 +43,6 @@ media::cast::proto::EventType ToProtoEventType(CastLoggingEvent event) {
DUPLICATE_AUDIO_PACKET_RECEIVED);
TO_PROTO_ENUM(kDuplicateVideoPacketReceived,
DUPLICATE_VIDEO_PACKET_RECEIVED);
- case kNumOfLoggingEvents:
- NOTREACHED();
- return media::cast::proto::UNKNOWN;
}
NOTREACHED();
return media::cast::proto::UNKNOWN;
diff --git a/media/cast/rtcp/rtcp_unittest.cc b/media/cast/rtcp/rtcp_unittest.cc
index 9ee0523..ac7144c 100644
--- a/media/cast/rtcp/rtcp_unittest.cc
+++ b/media/cast/rtcp/rtcp_unittest.cc
@@ -145,6 +145,7 @@ class RtcpTest : public ::testing::Test {
RtcpTest()
: testing_clock_(new base::SimpleTestTickClock()),
task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
+ logging_config_(GetDefaultCastSenderLoggingConfig()),
cast_environment_(new CastEnvironment(
scoped_ptr<base::TickClock>(testing_clock_).Pass(),
task_runner_,
@@ -153,7 +154,7 @@ class RtcpTest : public ::testing::Test {
task_runner_,
task_runner_,
task_runner_,
- GetDefaultCastSenderLoggingConfig())),
+ logging_config_)),
sender_to_receiver_(testing_clock_),
receiver_to_sender_(cast_environment_, testing_clock_) {
testing_clock_->Advance(
@@ -164,7 +165,10 @@ class RtcpTest : public ::testing::Test {
testing_clock_,
dummy_endpoint,
dummy_endpoint,
+ logging_config_,
base::Bind(&UpdateCastTransportStatus),
+ transport::BulkRawEventsCallback(),
+ base::TimeDelta(),
task_runner_,
&sender_to_receiver_));
EXPECT_CALL(mock_sender_feedback_, OnReceivedCastFeedback(_)).Times(0);
@@ -188,6 +192,7 @@ class RtcpTest : public ::testing::Test {
base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
+ CastLoggingConfig logging_config_;
scoped_refptr<CastEnvironment> cast_environment_;
RtcpTestPacketSender sender_to_receiver_;
scoped_ptr<transport::CastTransportSenderImpl> transport_sender_;
diff --git a/media/cast/test/end2end_unittest.cc b/media/cast/test/end2end_unittest.cc
index 70f7c46..1524c8f 100644
--- a/media/cast/test/end2end_unittest.cc
+++ b/media/cast/test/end2end_unittest.cc
@@ -398,6 +398,7 @@ class End2EndTest : public ::testing::Test {
testing_clock_receiver_(new base::SimpleTestTickClock()),
task_runner_(new test::FakeSingleThreadTaskRunner(
testing_clock_sender_)),
+ logging_config_(GetLoggingConfigWithRawEventsAndStatsEnabled()),
cast_environment_sender_(new CastEnvironment(
scoped_ptr<base::TickClock>(testing_clock_sender_).Pass(),
task_runner_,
@@ -406,7 +407,7 @@ class End2EndTest : public ::testing::Test {
task_runner_,
task_runner_,
task_runner_,
- GetLoggingConfigWithRawEventsAndStatsEnabled())),
+ logging_config_)),
cast_environment_receiver_(new CastEnvironment(
scoped_ptr<base::TickClock>(testing_clock_receiver_).Pass(),
task_runner_,
@@ -415,7 +416,7 @@ class End2EndTest : public ::testing::Test {
task_runner_,
task_runner_,
task_runner_,
- GetLoggingConfigWithRawEventsAndStatsEnabled())),
+ logging_config_)),
receiver_to_sender_(cast_environment_receiver_),
sender_to_receiver_(cast_environment_sender_),
test_receiver_audio_callback_(new TestReceiverAudioCallback()),
@@ -502,7 +503,10 @@ class End2EndTest : public ::testing::Test {
testing_clock_sender_,
dummy_endpoint,
dummy_endpoint,
+ logging_config_,
base::Bind(&UpdateCastTransportStatus),
+ base::Bind(&End2EndTest::LogRawEvents, base::Unretained(this)),
+ base::TimeDelta::FromSeconds(1),
task_runner_,
&sender_to_receiver_));
transport_sender_->InitializeAudio(transport_audio_config_);
@@ -567,6 +571,22 @@ class End2EndTest : public ::testing::Test {
EXPECT_EQ(result, STATUS_INITIALIZED);
}
+ void LogRawEvents(const std::vector<PacketEvent>& packet_events) {
+ EXPECT_FALSE(packet_events.empty());
+ for (std::vector<media::cast::PacketEvent>::const_iterator it =
+ packet_events.begin();
+ it != packet_events.end();
+ ++it) {
+ cast_environment_sender_->Logging()->InsertPacketEvent(it->timestamp,
+ it->type,
+ it->rtp_timestamp,
+ it->frame_id,
+ it->packet_id,
+ it->max_packet_id,
+ it->size);
+ }
+ }
+
AudioReceiverConfig audio_receiver_config_;
VideoReceiverConfig video_receiver_config_;
AudioSenderConfig audio_sender_config_;
@@ -578,6 +598,7 @@ class End2EndTest : public ::testing::Test {
base::SimpleTestTickClock* testing_clock_sender_;
base::SimpleTestTickClock* testing_clock_receiver_;
scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
+ CastLoggingConfig logging_config_;
scoped_refptr<CastEnvironment> cast_environment_sender_;
scoped_refptr<CastEnvironment> cast_environment_receiver_;
@@ -599,6 +620,9 @@ class End2EndTest : public ::testing::Test {
std::vector<FrameEvent> frame_events_;
std::vector<PacketEvent> packet_events_;
std::vector<GenericEvent> generic_events_;
+
+ // |transport_sender_| has a RepeatingTimer which needs a MessageLoop.
+ base::MessageLoop message_loop_;
};
TEST_F(End2EndTest, LoopNoLossPcm16) {
diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc
index af369eb..7a0ff7e 100644
--- a/media/cast/test/sender.cc
+++ b/media/cast/test/sender.cc
@@ -317,6 +317,24 @@ namespace {
void UpdateCastTransportStatus(
media::cast::transport::CastTransportStatus status) {}
+void LogRawEvents(
+ const scoped_refptr<media::cast::CastEnvironment>& cast_environment,
+ const std::vector<media::cast::PacketEvent>& packet_events) {
+ VLOG(1) << "Got packet events from transport, size: " << packet_events.size();
+ for (std::vector<media::cast::PacketEvent>::const_iterator it =
+ packet_events.begin();
+ it != packet_events.end();
+ ++it) {
+ cast_environment->Logging()->InsertPacketEvent(it->timestamp,
+ it->type,
+ it->rtp_timestamp,
+ it->frame_id,
+ it->packet_id,
+ it->max_packet_id,
+ it->size);
+ }
+}
+
void InitializationResult(media::cast::CastInitializationStatus result) {
CHECK_EQ(result, media::cast::STATUS_INITIALIZED);
VLOG(1) << "Cast Sender initialized";
@@ -410,6 +428,11 @@ int main(int argc, char** argv) {
media::cast::VideoSenderConfig video_config =
media::cast::GetVideoSenderConfig();
+ // Enable main and send side threads only. Enable raw event logging.
+ // Running transport on the main thread.
+ media::cast::CastLoggingConfig logging_config;
+ logging_config.enable_raw_data_collection = true;
+
// Setting up transport config.
media::cast::transport::CastTransportAudioConfig transport_audio_config;
media::cast::transport::CastTransportVideoConfig transport_video_config;
@@ -421,18 +444,6 @@ int main(int argc, char** argv) {
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(),
- local_endpoint,
- remote_endpoint,
- base::Bind(&UpdateCastTransportStatus),
- 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.
scoped_refptr<media::cast::CastEnvironment> cast_environment(
@@ -446,6 +457,21 @@ int main(int argc, char** argv) {
io_message_loop.message_loop_proxy(),
media::cast::GetLoggingConfigWithRawEventsAndStatsEnabled()));
+ scoped_ptr<media::cast::transport::CastTransportSender> transport_sender =
+ media::cast::transport::CastTransportSender::Create(
+ NULL, // net log.
+ clock.get(),
+ local_endpoint,
+ remote_endpoint,
+ logging_config,
+ base::Bind(&UpdateCastTransportStatus),
+ base::Bind(&LogRawEvents, cast_environment),
+ base::TimeDelta::FromSeconds(1),
+ io_message_loop.message_loop_proxy());
+
+ transport_sender->InitializeAudio(transport_audio_config);
+ transport_sender->InitializeVideo(transport_video_config);
+
scoped_ptr<media::cast::CastSender> cast_sender(
media::cast::CastSender::CreateCastSender(
cast_environment,
@@ -465,7 +491,6 @@ int main(int argc, char** argv) {
frame_input));
// Set up event subscribers.
- // TODO(imcheng): Set up separate subscribers for audio / video / other.
int logging_duration = media::cast::GetLoggingDuration();
scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber;
scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber;
diff --git a/media/cast/transport/cast_transport.gyp b/media/cast/transport/cast_transport.gyp
index 8a69356..9809db3 100644
--- a/media/cast/transport/cast_transport.gyp
+++ b/media/cast/transport/cast_transport.gyp
@@ -16,6 +16,7 @@
],
'dependencies': [
'<(DEPTH)/base/base.gyp:base',
+ '<(DEPTH)/media/cast/logging/logging.gyp:cast_common_logging',
'<(DEPTH)/net/net.gyp:net',
'utility/utility.gypi:transport_utility',
],
diff --git a/media/cast/transport/cast_transport_sender.h b/media/cast/transport/cast_transport_sender.h
index 5bfa00e..4f4863b 100644
--- a/media/cast/transport/cast_transport_sender.h
+++ b/media/cast/transport/cast_transport_sender.h
@@ -29,6 +29,7 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/non_thread_safe.h"
#include "base/time/tick_clock.h"
+#include "media/cast/logging/logging_defines.h"
#include "media/cast/transport/cast_transport_config.h"
#include "media/cast/transport/cast_transport_defines.h"
@@ -49,6 +50,9 @@ typedef base::Callback<void(const RtcpSenderInfo& sender_info,
base::TimeTicks time_sent,
uint32 rtp_timestamp)> CastTransportRtpStatistics;
+typedef base::Callback<void(const std::vector<PacketEvent>&)>
+ BulkRawEventsCallback;
+
// The application should only trigger this class from the transport thread.
class CastTransportSender : public base::NonThreadSafe {
public:
@@ -57,7 +61,10 @@ class CastTransportSender : public base::NonThreadSafe {
base::TickClock* clock,
const net::IPEndPoint& local_end_point,
const net::IPEndPoint& remote_end_point,
+ const CastLoggingConfig& logging_config,
const CastTransportStatusCallback& status_callback,
+ const BulkRawEventsCallback& raw_events_callback,
+ base::TimeDelta raw_events_callback_interval,
const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner);
virtual ~CastTransportSender() {}
diff --git a/media/cast/transport/cast_transport_sender_impl.cc b/media/cast/transport/cast_transport_sender_impl.cc
index 9975e3a..38f10f8 100644
--- a/media/cast/transport/cast_transport_sender_impl.cc
+++ b/media/cast/transport/cast_transport_sender_impl.cc
@@ -17,14 +17,20 @@ scoped_ptr<CastTransportSender> CastTransportSender::Create(
base::TickClock* clock,
const net::IPEndPoint& local_end_point,
const net::IPEndPoint& remote_end_point,
+ const CastLoggingConfig& logging_config,
const CastTransportStatusCallback& status_callback,
+ const BulkRawEventsCallback& raw_events_callback,
+ base::TimeDelta raw_events_callback_interval,
const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) {
return scoped_ptr<CastTransportSender>(
new CastTransportSenderImpl(net_log,
clock,
local_end_point,
remote_end_point,
+ logging_config,
status_callback,
+ raw_events_callback,
+ raw_events_callback_interval,
transport_task_runner.get(),
NULL));
}
@@ -34,7 +40,10 @@ CastTransportSenderImpl::CastTransportSenderImpl(
base::TickClock* clock,
const net::IPEndPoint& local_end_point,
const net::IPEndPoint& remote_end_point,
+ const CastLoggingConfig& logging_config,
const CastTransportStatusCallback& status_callback,
+ const BulkRawEventsCallback& raw_events_callback,
+ base::TimeDelta raw_events_callback_interval,
const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner,
PacketSender* external_transport)
: clock_(clock),
@@ -49,9 +58,25 @@ CastTransportSenderImpl::CastTransportSenderImpl(
pacer_(clock,
external_transport ? external_transport : transport_.get(),
transport_task_runner),
- rtcp_builder_(&pacer_) {}
+ rtcp_builder_(&pacer_),
+ logging_(transport_task_runner, logging_config),
+ raw_events_callback_(raw_events_callback) {
+ if (!raw_events_callback_.is_null()) {
+ DCHECK(logging_config.enable_raw_data_collection);
+ DCHECK(raw_events_callback_interval > base::TimeDelta());
+ event_subscriber_.reset(new SimpleEventSubscriber);
+ logging_.AddRawEventSubscriber(event_subscriber_.get());
+ raw_events_timer_.Start(FROM_HERE,
+ raw_events_callback_interval,
+ this,
+ &CastTransportSenderImpl::SendRawEvents);
+ }
+}
-CastTransportSenderImpl::~CastTransportSenderImpl() {}
+CastTransportSenderImpl::~CastTransportSenderImpl() {
+ if (event_subscriber_.get())
+ logging_.RemoveRawEventSubscriber(event_subscriber_.get());
+}
void CastTransportSenderImpl::InitializeAudio(
const CastTransportAudioConfig& config) {
@@ -127,6 +152,14 @@ void CastTransportSenderImpl::SubscribeVideoRtpStatsCallback(
video_sender_->SubscribeVideoRtpStatsCallback(callback);
}
+void CastTransportSenderImpl::SendRawEvents() {
+ DCHECK(event_subscriber_.get());
+ DCHECK(!raw_events_callback_.is_null());
+ std::vector<PacketEvent> packet_events;
+ event_subscriber_->GetPacketEventsAndReset(&packet_events);
+ raw_events_callback_.Run(packet_events);
+}
+
} // namespace transport
} // namespace cast
} // namespace media
diff --git a/media/cast/transport/cast_transport_sender_impl.h b/media/cast/transport/cast_transport_sender_impl.h
index b7ee50a..92a665b 100644
--- a/media/cast/transport/cast_transport_sender_impl.h
+++ b/media/cast/transport/cast_transport_sender_impl.h
@@ -10,6 +10,9 @@
#include "base/memory/scoped_ptr.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "media/cast/logging/logging_defines.h"
+#include "media/cast/logging/simple_event_subscriber.h"
#include "media/cast/transport/cast_transport_config.h"
#include "media/cast/transport/cast_transport_sender.h"
#include "media/cast/transport/pacing/paced_sender.h"
@@ -26,12 +29,20 @@ class CastTransportSenderImpl : public CastTransportSender {
// external_transport is only used for testing.
// Note that SetPacketReceiver does not work if an external
// transport is provided.
+ // |raw_events_callback|: Raw events will be returned on this callback
+ // which will be invoked every |raw_events_callback_interval|.
+ // This can be a null callback, i.e. if user is not interested in raw events.
+ // |raw_events_callback_interval|: This can be |base::TimeDelta()| if
+ // |raw_events_callback| is a null callback.
CastTransportSenderImpl(
net::NetLog* net_log,
base::TickClock* clock,
const net::IPEndPoint& local_end_point,
const net::IPEndPoint& remote_end_point,
+ const CastLoggingConfig& logging_config,
const CastTransportStatusCallback& status_callback,
+ const BulkRawEventsCallback& raw_events_callback,
+ base::TimeDelta raw_events_callback_interval,
const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner,
PacketSender* external_transport);
@@ -71,15 +82,29 @@ class CastTransportSenderImpl : public CastTransportSender {
const CastTransportRtpStatistics& callback) OVERRIDE;
private:
+ // If raw events logging is enabled, this is called periodically.
+ // Calls |raw_events_callback_| with events collected by |event_subscriber_|
+ // since last call.
+ void SendRawEvents();
+
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_;
scoped_ptr<TransportAudioSender> audio_sender_;
scoped_ptr<TransportVideoSender> video_sender_;
+ LoggingImpl logging_;
+
+ // This is non-null iff raw events logging is enabled.
+ scoped_ptr<SimpleEventSubscriber> event_subscriber_;
+ base::RepeatingTimer<CastTransportSenderImpl> raw_events_timer_;
+
+ BulkRawEventsCallback raw_events_callback_;
+
DISALLOW_COPY_AND_ASSIGN(CastTransportSenderImpl);
};
diff --git a/media/cast/transport/cast_transport_sender_impl_unittest.cc b/media/cast/transport/cast_transport_sender_impl_unittest.cc
new file mode 100644
index 0000000..ea6f41c
--- /dev/null
+++ b/media/cast/transport/cast_transport_sender_impl_unittest.cc
@@ -0,0 +1,114 @@
+// 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 <gtest/gtest.h>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "media/cast/cast_config.h"
+#include "media/cast/rtcp/rtcp.h"
+#include "media/cast/test/fake_single_thread_task_runner.h"
+#include "media/cast/transport/cast_transport_config.h"
+#include "media/cast/transport/cast_transport_sender_impl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+namespace cast {
+namespace transport {
+
+static const int64 kStartMillisecond = GG_INT64_C(12345678900000);
+
+class FakePacketSender : public transport::PacketSender {
+ public:
+ FakePacketSender() {}
+
+ virtual bool SendPacket(const Packet& packet) OVERRIDE { return true; }
+};
+
+class CastTransportSenderImplTest : public ::testing::Test {
+ protected:
+ CastTransportSenderImplTest()
+ : num_times_callback_called_(0) {
+ testing_clock_.Advance(
+ base::TimeDelta::FromMilliseconds(kStartMillisecond));
+ task_runner_ = new test::FakeSingleThreadTaskRunner(&testing_clock_);
+ }
+
+ virtual ~CastTransportSenderImplTest() {}
+
+ void InitWithoutLogging() {
+ transport_sender_.reset(
+ new CastTransportSenderImpl(NULL,
+ &testing_clock_,
+ net::IPEndPoint(),
+ net::IPEndPoint(),
+ GetDefaultCastSenderLoggingConfig(),
+ base::Bind(&UpdateCastTransportStatus),
+ BulkRawEventsCallback(),
+ base::TimeDelta(),
+ task_runner_,
+ &transport_));
+ task_runner_->RunTasks();
+ }
+
+ void InitWithLogging() {
+ transport_sender_.reset(new CastTransportSenderImpl(
+ NULL,
+ &testing_clock_,
+ net::IPEndPoint(),
+ net::IPEndPoint(),
+ GetLoggingConfigWithRawEventsAndStatsEnabled(),
+ base::Bind(&UpdateCastTransportStatus),
+ base::Bind(&CastTransportSenderImplTest::LogRawEvents,
+ base::Unretained(this)),
+ base::TimeDelta::FromMilliseconds(10),
+ task_runner_,
+ &transport_));
+ task_runner_->RunTasks();
+ }
+
+ void LogRawEvents(const std::vector<PacketEvent>& packet_events) {
+ num_times_callback_called_++;
+ if (num_times_callback_called_ == 3) {
+ run_loop_.Quit();
+ }
+ }
+
+ static void UpdateCastTransportStatus(transport::CastTransportStatus status) {
+ }
+
+ base::SimpleTestTickClock testing_clock_;
+ scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
+ scoped_ptr<CastTransportSenderImpl> transport_sender_;
+ FakePacketSender transport_;
+ base::MessageLoopForIO message_loop_;
+ base::RunLoop run_loop_;
+ int num_times_callback_called_;
+};
+
+TEST_F(CastTransportSenderImplTest, InitWithoutLogging) {
+ InitWithoutLogging();
+ message_loop_.PostDelayedTask(FROM_HERE,
+ run_loop_.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(50));
+ run_loop_.Run();
+ EXPECT_EQ(0, num_times_callback_called_);
+}
+
+TEST_F(CastTransportSenderImplTest, InitWithLogging) {
+ InitWithLogging();
+ message_loop_.PostDelayedTask(FROM_HERE,
+ run_loop_.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(50));
+ run_loop_.Run();
+ EXPECT_GT(num_times_callback_called_, 1);
+}
+
+} // namespace transport
+} // namespace cast
+} // namespace media
diff --git a/media/cast/video_sender/video_sender_unittest.cc b/media/cast/video_sender/video_sender_unittest.cc
index 130dac9..982f7de 100644
--- a/media/cast/video_sender/video_sender_unittest.cc
+++ b/media/cast/video_sender/video_sender_unittest.cc
@@ -81,6 +81,8 @@ class VideoSenderTest : public ::testing::Test {
testing_clock_->Advance(
base::TimeDelta::FromMilliseconds(kStartMillisecond));
task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
+ CastLoggingConfig logging_config =
+ GetLoggingConfigWithRawEventsAndStatsEnabled();
cast_environment_ =
new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
task_runner_,
@@ -89,7 +91,7 @@ class VideoSenderTest : public ::testing::Test {
task_runner_,
task_runner_,
task_runner_,
- GetLoggingConfigWithRawEventsAndStatsEnabled());
+ logging_config);
transport::CastTransportVideoConfig transport_config;
net::IPEndPoint dummy_endpoint;
transport_sender_.reset(new transport::CastTransportSenderImpl(
@@ -97,7 +99,10 @@ class VideoSenderTest : public ::testing::Test {
testing_clock_,
dummy_endpoint,
dummy_endpoint,
+ logging_config,
base::Bind(&UpdateCastTransportStatus),
+ transport::BulkRawEventsCallback(),
+ base::TimeDelta(),
task_runner_,
&transport_));
transport_sender_->InitializeVideo(transport_config);