Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / renderer / media / cast_session_delegate.cc
blob7393254ee20b74974fa6d5b478a46ff57765e93f
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/renderer/media/cast_session_delegate.h"
7 #include "base/lazy_instance.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "chrome/renderer/media/cast_threads.h"
11 #include "chrome/renderer/media/cast_transport_sender_ipc.h"
12 #include "content/public/renderer/render_thread.h"
13 #include "media/cast/cast_config.h"
14 #include "media/cast/cast_environment.h"
15 #include "media/cast/cast_sender.h"
16 #include "media/cast/logging/log_serializer.h"
17 #include "media/cast/logging/logging_defines.h"
18 #include "media/cast/logging/raw_event_subscriber_bundle.h"
19 #include "media/cast/transport/cast_transport_config.h"
20 #include "media/cast/transport/cast_transport_sender.h"
22 using media::cast::AudioSenderConfig;
23 using media::cast::CastEnvironment;
24 using media::cast::CastSender;
25 using media::cast::VideoSenderConfig;
27 static base::LazyInstance<CastThreads> g_cast_threads =
28 LAZY_INSTANCE_INITIALIZER;
30 CastSessionDelegate::CastSessionDelegate()
31 : io_message_loop_proxy_(
32 content::RenderThread::Get()->GetIOMessageLoopProxy()),
33 weak_factory_(this) {
34 DCHECK(io_message_loop_proxy_);
37 CastSessionDelegate::~CastSessionDelegate() {
38 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
41 void CastSessionDelegate::StartAudio(
42 const AudioSenderConfig& config,
43 const AudioFrameInputAvailableCallback& callback,
44 const ErrorCallback& error_callback) {
45 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
47 if (!cast_transport_ || !cast_sender_) {
48 error_callback.Run("Destination not set.");
49 return;
52 audio_frame_input_available_callback_ = callback;
53 cast_sender_->InitializeAudio(
54 config,
55 base::Bind(&CastSessionDelegate::InitializationResultCB,
56 weak_factory_.GetWeakPtr()));
59 void CastSessionDelegate::StartVideo(
60 const VideoSenderConfig& config,
61 const VideoFrameInputAvailableCallback& callback,
62 const ErrorCallback& error_callback,
63 const media::cast::CreateVideoEncodeAcceleratorCallback& create_vea_cb,
64 const media::cast::CreateVideoEncodeMemoryCallback&
65 create_video_encode_mem_cb) {
66 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
68 if (!cast_transport_ || !cast_sender_) {
69 error_callback.Run("Destination not set.");
70 return;
73 video_frame_input_available_callback_ = callback;
75 cast_sender_->InitializeVideo(
76 config,
77 base::Bind(&CastSessionDelegate::InitializationResultCB,
78 weak_factory_.GetWeakPtr()),
79 create_vea_cb,
80 create_video_encode_mem_cb);
83 void CastSessionDelegate::StartUDP(const net::IPEndPoint& remote_endpoint) {
84 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
86 // CastSender uses the renderer's IO thread as the main thread. This reduces
87 // thread hopping for incoming video frames and outgoing network packets.
88 cast_environment_ = new CastEnvironment(
89 scoped_ptr<base::TickClock>(new base::DefaultTickClock()).Pass(),
90 base::MessageLoopProxy::current(),
91 g_cast_threads.Get().GetAudioEncodeMessageLoopProxy(),
92 g_cast_threads.Get().GetVideoEncodeMessageLoopProxy());
94 event_subscribers_.reset(
95 new media::cast::RawEventSubscriberBundle(cast_environment_));
97 // Rationale for using unretained: The callback cannot be called after the
98 // destruction of CastTransportSenderIPC, and they both share the same thread.
99 cast_transport_.reset(new CastTransportSenderIPC(
100 remote_endpoint,
101 base::Bind(&CastSessionDelegate::StatusNotificationCB,
102 base::Unretained(this)),
103 base::Bind(&CastSessionDelegate::LogRawEvents, base::Unretained(this))));
105 cast_sender_ = CastSender::Create(cast_environment_, cast_transport_.get());
106 cast_transport_->SetPacketReceiver(cast_sender_->packet_receiver());
109 void CastSessionDelegate::ToggleLogging(bool is_audio, bool enable) {
110 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
111 if (!event_subscribers_.get())
112 return;
114 if (enable)
115 event_subscribers_->AddEventSubscribers(is_audio);
116 else
117 event_subscribers_->RemoveEventSubscribers(is_audio);
120 void CastSessionDelegate::GetEventLogsAndReset(
121 bool is_audio,
122 const EventLogsCallback& callback) {
123 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
125 if (!event_subscribers_.get()) {
126 callback.Run(make_scoped_ptr(new base::BinaryValue).Pass());
127 return;
130 media::cast::EncodingEventSubscriber* subscriber =
131 event_subscribers_->GetEncodingEventSubscriber(is_audio);
132 if (!subscriber) {
133 callback.Run(make_scoped_ptr(new base::BinaryValue).Pass());
134 return;
137 media::cast::proto::LogMetadata metadata;
138 media::cast::FrameEventList frame_events;
139 media::cast::PacketEventList packet_events;
141 subscriber->GetEventsAndReset(&metadata, &frame_events, &packet_events);
143 scoped_ptr<char[]> serialized_log(new char[media::cast::kMaxSerializedBytes]);
144 int output_bytes;
145 bool success = media::cast::SerializeEvents(metadata,
146 frame_events,
147 packet_events,
148 true,
149 media::cast::kMaxSerializedBytes,
150 serialized_log.get(),
151 &output_bytes);
153 if (!success) {
154 VLOG(2) << "Failed to serialize event log.";
155 callback.Run(make_scoped_ptr(new base::BinaryValue).Pass());
156 return;
159 DVLOG(2) << "Serialized log length: " << output_bytes;
161 scoped_ptr<base::BinaryValue> blob(
162 new base::BinaryValue(serialized_log.Pass(), output_bytes));
163 callback.Run(blob.Pass());
166 void CastSessionDelegate::GetStatsAndReset(bool is_audio,
167 const StatsCallback& callback) {
168 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
170 if (!event_subscribers_.get()) {
171 callback.Run(make_scoped_ptr(new base::DictionaryValue).Pass());
172 return;
175 media::cast::StatsEventSubscriber* subscriber =
176 event_subscribers_->GetStatsEventSubscriber(is_audio);
177 if (!subscriber) {
178 callback.Run(make_scoped_ptr(new base::DictionaryValue).Pass());
179 return;
182 scoped_ptr<base::DictionaryValue> stats = subscriber->GetStats();
183 subscriber->Reset();
185 callback.Run(stats.Pass());
188 void CastSessionDelegate::StatusNotificationCB(
189 media::cast::transport::CastTransportStatus unused_status) {
190 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
191 // TODO(hubbe): Call javascript UDPTransport error function.
194 void CastSessionDelegate::InitializationResultCB(
195 media::cast::CastInitializationStatus result) const {
196 DCHECK(cast_sender_);
198 // TODO(pwestin): handle the error codes.
199 if (result == media::cast::STATUS_AUDIO_INITIALIZED) {
200 audio_frame_input_available_callback_.Run(
201 cast_sender_->audio_frame_input());
202 } else if (result == media::cast::STATUS_VIDEO_INITIALIZED) {
203 video_frame_input_available_callback_.Run(
204 cast_sender_->video_frame_input());
208 void CastSessionDelegate::LogRawEvents(
209 const std::vector<media::cast::PacketEvent>& packet_events) {
210 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
212 for (std::vector<media::cast::PacketEvent>::const_iterator it =
213 packet_events.begin();
214 it != packet_events.end();
215 ++it) {
216 cast_environment_->Logging()->InsertPacketEvent(it->timestamp,
217 it->type,
218 it->rtp_timestamp,
219 it->frame_id,
220 it->packet_id,
221 it->max_packet_id,
222 it->size);