Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(245)

Side by Side Diff: chrome/renderer/media/cast_session_delegate.cc

Issue 236123003: Cast: Provide more meaningful stats. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: minor fix Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/media/cast_session_delegate.h" 5 #include "chrome/renderer/media/cast_session_delegate.h"
6 6
7 #include "base/lazy_instance.h" 7 #include "base/lazy_instance.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop/message_loop_proxy.h" 9 #include "base/message_loop/message_loop_proxy.h"
10 #include "chrome/renderer/media/cast_threads.h" 10 #include "chrome/renderer/media/cast_threads.h"
11 #include "chrome/renderer/media/cast_transport_sender_ipc.h" 11 #include "chrome/renderer/media/cast_transport_sender_ipc.h"
12 #include "content/public/renderer/render_thread.h" 12 #include "content/public/renderer/render_thread.h"
13 #include "media/cast/cast_config.h" 13 #include "media/cast/cast_config.h"
14 #include "media/cast/cast_environment.h" 14 #include "media/cast/cast_environment.h"
15 #include "media/cast/cast_sender.h" 15 #include "media/cast/cast_sender.h"
16 #include "media/cast/logging/encoding_event_subscriber.h"
17 #include "media/cast/logging/log_serializer.h" 16 #include "media/cast/logging/log_serializer.h"
18 #include "media/cast/logging/logging_defines.h" 17 #include "media/cast/logging/logging_defines.h"
19 #include "media/cast/logging/stats_event_subscriber.h" 18 #include "media/cast/logging/receiver_time_offset_estimator_impl.h"
20 #include "media/cast/logging/stats_util.h"
21 #include "media/cast/transport/cast_transport_config.h" 19 #include "media/cast/transport/cast_transport_config.h"
22 #include "media/cast/transport/cast_transport_sender.h" 20 #include "media/cast/transport/cast_transport_sender.h"
23 21
24 using media::cast::AudioSenderConfig; 22 using media::cast::AudioSenderConfig;
25 using media::cast::CastEnvironment; 23 using media::cast::CastEnvironment;
26 using media::cast::CastSender; 24 using media::cast::CastSender;
27 using media::cast::VideoSenderConfig; 25 using media::cast::VideoSenderConfig;
28 26
29 static base::LazyInstance<CastThreads> g_cast_threads = 27 static base::LazyInstance<CastThreads> g_cast_threads =
30 LAZY_INSTANCE_INITIALIZER; 28 LAZY_INSTANCE_INITIALIZER;
(...skipping 13 matching lines...) Expand all
44 42
45 CastSessionDelegate::CastSessionDelegate() 43 CastSessionDelegate::CastSessionDelegate()
46 : io_message_loop_proxy_( 44 : io_message_loop_proxy_(
47 content::RenderThread::Get()->GetIOMessageLoopProxy()), 45 content::RenderThread::Get()->GetIOMessageLoopProxy()),
48 weak_factory_(this) { 46 weak_factory_(this) {
49 DCHECK(io_message_loop_proxy_); 47 DCHECK(io_message_loop_proxy_);
50 } 48 }
51 49
52 CastSessionDelegate::~CastSessionDelegate() { 50 CastSessionDelegate::~CastSessionDelegate() {
53 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 51 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
54
55 if (cast_environment_.get()) {
56 if (audio_event_subscriber_.get()) {
57 cast_environment_->Logging()->RemoveRawEventSubscriber(
58 audio_event_subscriber_.get());
59 }
60 if (video_event_subscriber_.get()) {
61 cast_environment_->Logging()->RemoveRawEventSubscriber(
62 video_event_subscriber_.get());
63 }
64 }
65 } 52 }
66 53
67 void CastSessionDelegate::StartAudio( 54 void CastSessionDelegate::StartAudio(
68 const AudioSenderConfig& config, 55 const AudioSenderConfig& config,
69 const AudioFrameInputAvailableCallback& callback, 56 const AudioFrameInputAvailableCallback& callback,
70 const ErrorCallback& error_callback) { 57 const ErrorCallback& error_callback) {
71 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 58 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
72 59
73 if (!cast_transport_ || !cast_sender_) { 60 if (!cast_transport_ || !cast_sender_) {
74 error_callback.Run("Destination not set."); 61 error_callback.Run("Destination not set.");
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 109 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
123 110
124 // CastSender uses the renderer's IO thread as the main thread. This reduces 111 // CastSender uses the renderer's IO thread as the main thread. This reduces
125 // thread hopping for incoming video frames and outgoing network packets. 112 // thread hopping for incoming video frames and outgoing network packets.
126 cast_environment_ = new CastEnvironment( 113 cast_environment_ = new CastEnvironment(
127 scoped_ptr<base::TickClock>(new base::DefaultTickClock()).Pass(), 114 scoped_ptr<base::TickClock>(new base::DefaultTickClock()).Pass(),
128 base::MessageLoopProxy::current(), 115 base::MessageLoopProxy::current(),
129 g_cast_threads.Get().GetAudioEncodeMessageLoopProxy(), 116 g_cast_threads.Get().GetAudioEncodeMessageLoopProxy(),
130 g_cast_threads.Get().GetVideoEncodeMessageLoopProxy()); 117 g_cast_threads.Get().GetVideoEncodeMessageLoopProxy());
131 118
119 event_subscribers_.reset(new RawEventSubscriberBundle(cast_environment_));
120
132 // Rationale for using unretained: The callback cannot be called after the 121 // Rationale for using unretained: The callback cannot be called after the
133 // destruction of CastTransportSenderIPC, and they both share the same thread. 122 // destruction of CastTransportSenderIPC, and they both share the same thread.
134 cast_transport_.reset(new CastTransportSenderIPC( 123 cast_transport_.reset(new CastTransportSenderIPC(
135 remote_endpoint, 124 remote_endpoint,
136 base::Bind(&CastSessionDelegate::StatusNotificationCB, 125 base::Bind(&CastSessionDelegate::StatusNotificationCB,
137 base::Unretained(this)), 126 base::Unretained(this)),
138 base::Bind(&CastSessionDelegate::LogRawEvents, base::Unretained(this)))); 127 base::Bind(&CastSessionDelegate::LogRawEvents, base::Unretained(this))));
139 128
140 cast_sender_ = CastSender::Create(cast_environment_, cast_transport_.get()); 129 cast_sender_ = CastSender::Create(cast_environment_, cast_transport_.get());
141 cast_transport_->SetPacketReceiver(cast_sender_->packet_receiver()); 130 cast_transport_->SetPacketReceiver(cast_sender_->packet_receiver());
142 } 131 }
143 132
133 RawEventSubscriberBundleForStream::RawEventSubscriberBundleForStream(
134 bool is_audio,
135 media::cast::ReceiverTimeOffsetEstimator* offset_estimator,
136 const scoped_refptr<media::cast::CastEnvironment>& cast_environment)
137 : cast_environment_(cast_environment),
138 event_subscriber_(
139 is_audio ? media::cast::AUDIO_EVENT : media::cast::VIDEO_EVENT,
140 is_audio ? kMaxAudioEventEntries : kMaxVideoEventEntries),
141 stats_subscriber_(
142 is_audio ? media::cast::AUDIO_EVENT : media::cast::VIDEO_EVENT,
143 cast_environment->Clock(), offset_estimator) {
144 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_);
145 cast_environment_->Logging()->AddRawEventSubscriber(&stats_subscriber_);
146 }
147
148 RawEventSubscriberBundleForStream::~RawEventSubscriberBundleForStream() {
149 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber_);
150 cast_environment_->Logging()->RemoveRawEventSubscriber(&stats_subscriber_);
151 }
152
153 media::cast::EncodingEventSubscriber*
154 RawEventSubscriberBundleForStream::GetEncodingEventSubscriber() {
155 return &event_subscriber_;
156 }
157
158 media::cast::StatsEventSubscriber*
159 RawEventSubscriberBundleForStream::GetStatsEventSubscriber() {
160 return &stats_subscriber_;
161 }
162
163 RawEventSubscriberBundle::RawEventSubscriberBundle(
164 const scoped_refptr<media::cast::CastEnvironment>& cast_environment)
165 : cast_environment_(cast_environment) {}
166
167 RawEventSubscriberBundle::~RawEventSubscriberBundle() {
168 if (receiver_offset_estimator_.get()) {
169 cast_environment_->Logging()->RemoveRawEventSubscriber(
170 receiver_offset_estimator_.get());
171 }
172 }
173
174 void RawEventSubscriberBundle::AddEventSubscribers(bool is_audio) {
175 if (!receiver_offset_estimator_.get()) {
176 receiver_offset_estimator_.reset(
177 new media::cast::ReceiverTimeOffsetEstimatorImpl);
178 cast_environment_->Logging()->AddRawEventSubscriber(
179 receiver_offset_estimator_.get());
180 }
181 SubscribersMapByStream::iterator it = subscribers_.find(is_audio);
182 if (it != subscribers_.end())
183 return;
184
185 subscribers_.insert(std::make_pair(
186 is_audio,
187 new RawEventSubscriberBundleForStream(
188 is_audio, receiver_offset_estimator_.get(), cast_environment_)));
189 }
190
191 void RawEventSubscriberBundle::RemoveEventSubscribers(bool is_audio) {
192 SubscribersMapByStream::iterator it = subscribers_.find(is_audio);
193 if (it == subscribers_.end())
194 return;
195
196 subscribers_.erase(it);
197 if (subscribers_.empty()) {
198 cast_environment_->Logging()->RemoveRawEventSubscriber(
199 receiver_offset_estimator_.get());
200 receiver_offset_estimator_.reset();
201 }
202 }
203
204 media::cast::EncodingEventSubscriber*
205 RawEventSubscriberBundle::GetEncodingEventSubscriber(bool is_audio) {
206 SubscribersMapByStream::iterator it = subscribers_.find(is_audio);
207 return it == subscribers_.end() ?
208 NULL : it->second->GetEncodingEventSubscriber();
209 }
210
211 media::cast::StatsEventSubscriber*
212 RawEventSubscriberBundle::GetStatsEventSubscriber(bool is_audio) {
213 SubscribersMapByStream::iterator it = subscribers_.find(is_audio);
214 return it == subscribers_.end() ?
215 NULL : it->second->GetStatsEventSubscriber();
216 }
217
144 void CastSessionDelegate::ToggleLogging(bool is_audio, bool enable) { 218 void CastSessionDelegate::ToggleLogging(bool is_audio, bool enable) {
145 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 219 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
146 if (!cast_environment_.get()) 220 if (!event_subscribers_.get())
147 return; 221 return;
148 if (enable) { 222
149 if (is_audio) { 223 if (enable)
150 if (!audio_event_subscriber_.get()) { 224 event_subscribers_->AddEventSubscribers(is_audio);
151 audio_event_subscriber_.reset(new media::cast::EncodingEventSubscriber( 225 else
152 media::cast::AUDIO_EVENT, kMaxAudioEventEntries)); 226 event_subscribers_->RemoveEventSubscribers(is_audio);
153 cast_environment_->Logging()->AddRawEventSubscriber(
154 audio_event_subscriber_.get());
155 }
156 if (!audio_stats_subscriber_.get()) {
157 audio_stats_subscriber_.reset(
158 new media::cast::StatsEventSubscriber(media::cast::AUDIO_EVENT));
159 cast_environment_->Logging()->AddRawEventSubscriber(
160 audio_stats_subscriber_.get());
161 }
162 } else {
163 if (!video_event_subscriber_.get()) {
164 video_event_subscriber_.reset(new media::cast::EncodingEventSubscriber(
165 media::cast::VIDEO_EVENT, kMaxVideoEventEntries));
166 cast_environment_->Logging()->AddRawEventSubscriber(
167 video_event_subscriber_.get());
168 }
169 if (!video_stats_subscriber_.get()) {
170 video_stats_subscriber_.reset(
171 new media::cast::StatsEventSubscriber(media::cast::VIDEO_EVENT));
172 cast_environment_->Logging()->AddRawEventSubscriber(
173 video_stats_subscriber_.get());
174 }
175 }
176 } else {
177 if (is_audio) {
178 if (audio_event_subscriber_.get()) {
179 cast_environment_->Logging()->RemoveRawEventSubscriber(
180 audio_event_subscriber_.get());
181 audio_event_subscriber_.reset();
182 }
183 if (audio_stats_subscriber_.get()) {
184 cast_environment_->Logging()->RemoveRawEventSubscriber(
185 audio_stats_subscriber_.get());
186 audio_stats_subscriber_.reset();
187 }
188 } else {
189 if (video_event_subscriber_.get()) {
190 cast_environment_->Logging()->RemoveRawEventSubscriber(
191 video_event_subscriber_.get());
192 video_event_subscriber_.reset();
193 }
194 if (video_stats_subscriber_.get()) {
195 cast_environment_->Logging()->RemoveRawEventSubscriber(
196 video_stats_subscriber_.get());
197 video_stats_subscriber_.reset();
198 }
199 }
200 }
201 } 227 }
202 228
203 void CastSessionDelegate::GetEventLogsAndReset( 229 void CastSessionDelegate::GetEventLogsAndReset(
204 bool is_audio, 230 bool is_audio,
205 const EventLogsCallback& callback) { 231 const EventLogsCallback& callback) {
206 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 232 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
207 233
234 if (!event_subscribers_.get()) {
235 callback.Run(make_scoped_ptr(new base::BinaryValue).Pass());
236 return;
237 }
238
208 media::cast::EncodingEventSubscriber* subscriber = 239 media::cast::EncodingEventSubscriber* subscriber =
209 is_audio ? audio_event_subscriber_.get() : video_event_subscriber_.get(); 240 event_subscribers_->GetEncodingEventSubscriber(is_audio);
210 if (!subscriber) { 241 if (!subscriber) {
211 callback.Run(make_scoped_ptr(new base::BinaryValue).Pass()); 242 callback.Run(make_scoped_ptr(new base::BinaryValue).Pass());
212 return; 243 return;
213 } 244 }
214 245
215 media::cast::proto::LogMetadata metadata; 246 media::cast::proto::LogMetadata metadata;
216 media::cast::FrameEventMap frame_events; 247 media::cast::FrameEventMap frame_events;
217 media::cast::PacketEventMap packet_events; 248 media::cast::PacketEventMap packet_events;
218 249
219 subscriber->GetEventsAndReset(&metadata, &frame_events, &packet_events); 250 subscriber->GetEventsAndReset(&metadata, &frame_events, &packet_events);
(...skipping 16 matching lines...) Expand all
236 267
237 DVLOG(2) << "Serialized log length: " << output_bytes; 268 DVLOG(2) << "Serialized log length: " << output_bytes;
238 269
239 scoped_ptr<base::BinaryValue> blob( 270 scoped_ptr<base::BinaryValue> blob(
240 new base::BinaryValue(serialized_log.Pass(), output_bytes)); 271 new base::BinaryValue(serialized_log.Pass(), output_bytes));
241 callback.Run(blob.Pass()); 272 callback.Run(blob.Pass());
242 } 273 }
243 274
244 void CastSessionDelegate::GetStatsAndReset(bool is_audio, 275 void CastSessionDelegate::GetStatsAndReset(bool is_audio,
245 const StatsCallback& callback) { 276 const StatsCallback& callback) {
277 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
278
279 if (!event_subscribers_.get()) {
280 callback.Run(make_scoped_ptr(new base::DictionaryValue).Pass());
281 return;
282 }
283
246 media::cast::StatsEventSubscriber* subscriber = 284 media::cast::StatsEventSubscriber* subscriber =
247 is_audio ? audio_stats_subscriber_.get() : video_stats_subscriber_.get(); 285 event_subscribers_->GetStatsEventSubscriber(is_audio);
248 if (!subscriber) { 286 if (!subscriber) {
249 callback.Run(make_scoped_ptr(new base::DictionaryValue).Pass()); 287 callback.Run(make_scoped_ptr(new base::DictionaryValue).Pass());
250 return; 288 return;
251 } 289 }
252 290
253 media::cast::FrameStatsMap frame_stats; 291 scoped_ptr<base::DictionaryValue> stats = subscriber->GetStats();
254 subscriber->GetFrameStats(&frame_stats);
255 media::cast::PacketStatsMap packet_stats;
256 subscriber->GetPacketStats(&packet_stats);
257 subscriber->Reset(); 292 subscriber->Reset();
258 293
259 scoped_ptr<base::DictionaryValue> stats = media::cast::ConvertStats(
260 frame_stats, packet_stats);
261
262 callback.Run(stats.Pass()); 294 callback.Run(stats.Pass());
263 } 295 }
264 296
265 void CastSessionDelegate::StatusNotificationCB( 297 void CastSessionDelegate::StatusNotificationCB(
266 media::cast::transport::CastTransportStatus unused_status) { 298 media::cast::transport::CastTransportStatus unused_status) {
267 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 299 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
268 // TODO(hubbe): Call javascript UDPTransport error function. 300 // TODO(hubbe): Call javascript UDPTransport error function.
269 } 301 }
270 302
271 void CastSessionDelegate::InitializationResultCB( 303 void CastSessionDelegate::InitializationResultCB(
(...skipping 20 matching lines...) Expand all
292 ++it) { 324 ++it) {
293 cast_environment_->Logging()->InsertPacketEvent(it->timestamp, 325 cast_environment_->Logging()->InsertPacketEvent(it->timestamp,
294 it->type, 326 it->type,
295 it->rtp_timestamp, 327 it->rtp_timestamp,
296 it->frame_id, 328 it->frame_id,
297 it->packet_id, 329 it->packet_id,
298 it->max_packet_id, 330 it->max_packet_id,
299 it->size); 331 it->size);
300 } 332 }
301 } 333 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698