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

Side by Side Diff: media/cast/test/receiver.cc

Issue 257703002: Cast: Print out AV sync in cast receiver if playing test video (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: vlog(0) -> vlog(2) 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
« no previous file with comments | « no previous file | media/cast/test/utility/barcode.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <algorithm> 5 #include <algorithm>
6 #include <climits> 6 #include <climits>
7 #include <cstdarg> 7 #include <cstdarg>
8 #include <cstdio> 8 #include <cstdio>
9 #include <deque> 9 #include <deque>
10 #include <map>
10 #include <string> 11 #include <string>
11 #include <utility> 12 #include <utility>
12 13
13 #include "base/at_exit.h" 14 #include "base/at_exit.h"
14 #include "base/command_line.h" 15 #include "base/command_line.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
16 #include "base/memory/ref_counted.h" 17 #include "base/memory/ref_counted.h"
17 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/scoped_ptr.h"
18 #include "base/message_loop/message_loop.h" 19 #include "base/message_loop/message_loop.h"
19 #include "base/synchronization/lock.h" 20 #include "base/synchronization/lock.h"
20 #include "base/synchronization/waitable_event.h" 21 #include "base/synchronization/waitable_event.h"
21 #include "base/threading/thread.h" 22 #include "base/threading/thread.h"
22 #include "base/time/default_tick_clock.h" 23 #include "base/time/default_tick_clock.h"
23 #include "base/timer/timer.h" 24 #include "base/timer/timer.h"
24 #include "media/audio/audio_io.h" 25 #include "media/audio/audio_io.h"
25 #include "media/audio/audio_manager.h" 26 #include "media/audio/audio_manager.h"
26 #include "media/audio/audio_parameters.h" 27 #include "media/audio/audio_parameters.h"
27 #include "media/audio/fake_audio_log_factory.h" 28 #include "media/audio/fake_audio_log_factory.h"
28 #include "media/base/audio_bus.h" 29 #include "media/base/audio_bus.h"
29 #include "media/base/channel_layout.h" 30 #include "media/base/channel_layout.h"
30 #include "media/base/video_frame.h" 31 #include "media/base/video_frame.h"
31 #include "media/cast/cast_config.h" 32 #include "media/cast/cast_config.h"
32 #include "media/cast/cast_environment.h" 33 #include "media/cast/cast_environment.h"
33 #include "media/cast/cast_receiver.h" 34 #include "media/cast/cast_receiver.h"
34 #include "media/cast/logging/logging_defines.h" 35 #include "media/cast/logging/logging_defines.h"
36 #include "media/cast/test/utility/audio_utility.h"
37 #include "media/cast/test/utility/barcode.h"
35 #include "media/cast/test/utility/default_config.h" 38 #include "media/cast/test/utility/default_config.h"
36 #include "media/cast/test/utility/in_process_receiver.h" 39 #include "media/cast/test/utility/in_process_receiver.h"
37 #include "media/cast/test/utility/input_builder.h" 40 #include "media/cast/test/utility/input_builder.h"
38 #include "media/cast/test/utility/standalone_cast_environment.h" 41 #include "media/cast/test/utility/standalone_cast_environment.h"
39 #include "media/cast/transport/transport/udp_transport.h" 42 #include "media/cast/transport/transport/udp_transport.h"
40 #include "net/base/net_util.h" 43 #include "net/base/net_util.h"
41 44
42 #if defined(OS_LINUX) 45 #if defined(OS_LINUX)
43 #include "media/cast/test/linux_output_window.h" 46 #include "media/cast/test/linux_output_window.h"
44 #endif // OS_LINUX 47 #endif // OS_LINUX
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 // InProcessReceiver overrides. 266 // InProcessReceiver overrides.
264 267
265 virtual void OnVideoFrame(const scoped_refptr<VideoFrame>& video_frame, 268 virtual void OnVideoFrame(const scoped_refptr<VideoFrame>& video_frame,
266 const base::TimeTicks& playout_time, 269 const base::TimeTicks& playout_time,
267 bool is_continuous) OVERRIDE { 270 bool is_continuous) OVERRIDE {
268 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN)); 271 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN));
269 LOG_IF(WARNING, !is_continuous) 272 LOG_IF(WARNING, !is_continuous)
270 << "Video: Discontinuity in received frames."; 273 << "Video: Discontinuity in received frames.";
271 video_playout_queue_.push_back(std::make_pair(playout_time, video_frame)); 274 video_playout_queue_.push_back(std::make_pair(playout_time, video_frame));
272 ScheduleVideoPlayout(); 275 ScheduleVideoPlayout();
276 uint16 frame_no;
277 if (media::cast::test::DecodeBarcode(video_frame, &frame_no)) {
278 video_play_times_.insert(
279 std::pair<uint16, base::TimeTicks>(frame_no, playout_time));
280 } else {
281 VLOG(2) << "Barcode decode failed!";
282 }
273 } 283 }
274 284
275 virtual void OnAudioFrame(scoped_ptr<AudioBus> audio_frame, 285 virtual void OnAudioFrame(scoped_ptr<AudioBus> audio_frame,
276 const base::TimeTicks& playout_time, 286 const base::TimeTicks& playout_time,
277 bool is_continuous) OVERRIDE { 287 bool is_continuous) OVERRIDE {
278 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN)); 288 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN));
279 LOG_IF(WARNING, !is_continuous) 289 LOG_IF(WARNING, !is_continuous)
280 << "Audio: Discontinuity in received frames."; 290 << "Audio: Discontinuity in received frames.";
281 base::AutoLock auto_lock(audio_lock_); 291 base::AutoLock auto_lock(audio_lock_);
292 uint16 frame_no;
293 if (media::cast::DecodeTimestamp(audio_frame->channel(0),
294 audio_frame->frames(),
295 &frame_no)) {
296 // Since there are lots of audio packets with the same frame_no,
297 // we really want to make sure that we get the playout_time from
298 // the first one.
299 if (is_continuous && frame_no == last_audio_frame_no_ + 1) {
miu 2014/04/25 06:47:59 What is supposed to happen if !is_continuous? See
hubbe 2014/04/25 07:21:38 Comment added. Basically, we're supposed to ignore
300 audio_play_times_.insert(
301 std::pair<uint16, base::TimeTicks>(frame_no, playout_time));
302 }
303 last_audio_frame_no_ = frame_no;
304 } else {
305 VLOG(2) << "Audio decode failed!";
306 last_audio_frame_no_ = -2;
307 }
282 audio_playout_queue_.push_back( 308 audio_playout_queue_.push_back(
283 std::make_pair(playout_time, audio_frame.release())); 309 std::make_pair(playout_time, audio_frame.release()));
284 } 310 }
285 311
286 // End of InProcessReceiver overrides. 312 // End of InProcessReceiver overrides.
287 //////////////////////////////////////////////////////////////////// 313 ////////////////////////////////////////////////////////////////////
288 314
289 //////////////////////////////////////////////////////////////////// 315 ////////////////////////////////////////////////////////////////////
290 // AudioSourceCallback implementation. 316 // AudioSourceCallback implementation.
291 317
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 415
390 void PlayNextVideoFrame() { 416 void PlayNextVideoFrame() {
391 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN)); 417 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN));
392 if (!video_playout_queue_.empty()) { 418 if (!video_playout_queue_.empty()) {
393 const scoped_refptr<VideoFrame> video_frame = PopOneVideoFrame(false); 419 const scoped_refptr<VideoFrame> video_frame = PopOneVideoFrame(false);
394 #ifdef OS_LINUX 420 #ifdef OS_LINUX
395 render_.RenderFrame(video_frame); 421 render_.RenderFrame(video_frame);
396 #endif // OS_LINUX 422 #endif // OS_LINUX
397 } 423 }
398 ScheduleVideoPlayout(); 424 ScheduleVideoPlayout();
425 CheckAVSync();
399 } 426 }
400 427
401 scoped_refptr<VideoFrame> PopOneVideoFrame(bool is_being_skipped) { 428 scoped_refptr<VideoFrame> PopOneVideoFrame(bool is_being_skipped) {
402 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN)); 429 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN));
403 430
404 if (is_being_skipped) { 431 if (is_being_skipped) {
405 VLOG(1) << "VideoFrame[" << num_video_frames_processed_ << "]: Skipped."; 432 VLOG(1) << "VideoFrame[" << num_video_frames_processed_ << "]: Skipped.";
406 } else { 433 } else {
407 VLOG(1) << "VideoFrame[" << num_video_frames_processed_ << "]: Playing " 434 VLOG(1) << "VideoFrame[" << num_video_frames_processed_ << "]: Playing "
408 << (cast_env()->Clock()->NowTicks() - 435 << (cast_env()->Clock()->NowTicks() -
(...skipping 18 matching lines...) Expand all
427 audio_playout_queue_.front().first).InMicroseconds() 454 audio_playout_queue_.front().first).InMicroseconds()
428 << " usec later than intended."; 455 << " usec later than intended.";
429 } 456 }
430 457
431 scoped_ptr<AudioBus> ret(audio_playout_queue_.front().second); 458 scoped_ptr<AudioBus> ret(audio_playout_queue_.front().second);
432 audio_playout_queue_.pop_front(); 459 audio_playout_queue_.pop_front();
433 ++num_audio_frames_processed_; 460 ++num_audio_frames_processed_;
434 return ret.Pass(); 461 return ret.Pass();
435 } 462 }
436 463
464 void CheckAVSync() {
465 if (video_play_times_.size() > 30 &&
466 audio_play_times_.size() > 30) {
467 size_t num_events = 0;
468 base::TimeDelta delta;
469 std::map<uint16, base::TimeTicks>::iterator audio_iter, video_iter;
470 for (video_iter = video_play_times_.begin();
471 video_iter != video_play_times_.end();
472 ++video_iter) {
473 audio_iter = audio_play_times_.find(video_iter->first);
474 if (audio_iter != audio_play_times_.end()) {
475 num_events++;
476 // Positive values means audio is running behind video.
477 delta += audio_iter->second - video_iter->second;
478 }
479 }
480
481 if (num_events > 30) {
482 VLOG(0) << "AV sync: " << (delta / num_events).InMilliseconds() << "ms";
miu 2014/04/25 06:47:59 After "AV sync:" can you add "audio behind by"?
hubbe 2014/04/25 07:21:38 Changed it to just say "Audio behind by:".
483 video_play_times_.clear();
484 audio_play_times_.clear();
485 }
486 } else if (video_play_times_.size() + audio_play_times_.size() > 500) {
487 // We are decoding audio or video timestamps, but not both, clear it out.
488 video_play_times_.clear();
489 audio_play_times_.clear();
490 }
491 }
492
437 // Frames in the queue older than this (relative to NowTicks()) will be 493 // Frames in the queue older than this (relative to NowTicks()) will be
438 // dropped (i.e., playback is falling behind). 494 // dropped (i.e., playback is falling behind).
439 const base::TimeDelta max_frame_age_; 495 const base::TimeDelta max_frame_age_;
440 496
441 // Outputs created, started, and destroyed by this NaivePlayer. 497 // Outputs created, started, and destroyed by this NaivePlayer.
442 #ifdef OS_LINUX 498 #ifdef OS_LINUX
443 test::LinuxOutputWindow render_; 499 test::LinuxOutputWindow render_;
444 #endif // OS_LINUX 500 #endif // OS_LINUX
445 scoped_ptr<AudioOutputStream> audio_output_stream_; 501 scoped_ptr<AudioOutputStream> audio_output_stream_;
446 502
447 // Video playout queue. 503 // Video playout queue.
448 typedef std::pair<base::TimeTicks, scoped_refptr<VideoFrame> > 504 typedef std::pair<base::TimeTicks, scoped_refptr<VideoFrame> >
449 VideoQueueEntry; 505 VideoQueueEntry;
450 std::deque<VideoQueueEntry> video_playout_queue_; 506 std::deque<VideoQueueEntry> video_playout_queue_;
451 int64 num_video_frames_processed_; 507 int64 num_video_frames_processed_;
452 508
453 base::OneShotTimer<NaivePlayer> video_playout_timer_; 509 base::OneShotTimer<NaivePlayer> video_playout_timer_;
454 510
455 // Audio playout queue, synchronized by |audio_lock_|. 511 // Audio playout queue, synchronized by |audio_lock_|.
456 base::Lock audio_lock_; 512 base::Lock audio_lock_;
457 typedef std::pair<base::TimeTicks, AudioBus*> AudioQueueEntry; 513 typedef std::pair<base::TimeTicks, AudioBus*> AudioQueueEntry;
458 std::deque<AudioQueueEntry> audio_playout_queue_; 514 std::deque<AudioQueueEntry> audio_playout_queue_;
459 int64 num_audio_frames_processed_; 515 int64 num_audio_frames_processed_;
460 516
461 // These must only be used on the audio thread calling OnMoreData(). 517 // These must only be used on the audio thread calling OnMoreData().
462 scoped_ptr<AudioBus> currently_playing_audio_frame_; 518 scoped_ptr<AudioBus> currently_playing_audio_frame_;
463 int currently_playing_audio_frame_start_; 519 int currently_playing_audio_frame_start_;
520
521 std::map<uint16, base::TimeTicks> audio_play_times_;
522 std::map<uint16, base::TimeTicks> video_play_times_;
523 int32 last_audio_frame_no_;
464 }; 524 };
465 525
466 } // namespace cast 526 } // namespace cast
467 } // namespace media 527 } // namespace media
468 528
469 int main(int argc, char** argv) { 529 int main(int argc, char** argv) {
470 base::AtExitManager at_exit; 530 base::AtExitManager at_exit;
471 CommandLine::Init(argc, argv); 531 CommandLine::Init(argc, argv);
472 InitLogging(logging::LoggingSettings()); 532 InitLogging(logging::LoggingSettings());
473 533
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 audio_config, 579 audio_config,
520 video_config, 580 video_config,
521 window_width, 581 window_width,
522 window_height); 582 window_height);
523 player.Start(); 583 player.Start();
524 584
525 base::MessageLoop().Run(); // Run forever (i.e., until SIGTERM). 585 base::MessageLoop().Run(); // Run forever (i.e., until SIGTERM).
526 NOTREACHED(); 586 NOTREACHED();
527 return 0; 587 return 0;
528 } 588 }
OLDNEW
« no previous file with comments | « no previous file | media/cast/test/utility/barcode.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698