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

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: comments addressed 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. If is_continous is true, then it's possible
299 // that we already missed the first one.
300 if (is_continuous && frame_no == last_audio_frame_no_ + 1) {
301 audio_play_times_.insert(
302 std::pair<uint16, base::TimeTicks>(frame_no, playout_time));
303 }
304 last_audio_frame_no_ = frame_no;
305 } else {
306 VLOG(2) << "Audio decode failed!";
307 last_audio_frame_no_ = -2;
308 }
282 audio_playout_queue_.push_back( 309 audio_playout_queue_.push_back(
283 std::make_pair(playout_time, audio_frame.release())); 310 std::make_pair(playout_time, audio_frame.release()));
284 } 311 }
285 312
286 // End of InProcessReceiver overrides. 313 // End of InProcessReceiver overrides.
287 //////////////////////////////////////////////////////////////////// 314 ////////////////////////////////////////////////////////////////////
288 315
289 //////////////////////////////////////////////////////////////////// 316 ////////////////////////////////////////////////////////////////////
290 // AudioSourceCallback implementation. 317 // AudioSourceCallback implementation.
291 318
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 416
390 void PlayNextVideoFrame() { 417 void PlayNextVideoFrame() {
391 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN)); 418 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN));
392 if (!video_playout_queue_.empty()) { 419 if (!video_playout_queue_.empty()) {
393 const scoped_refptr<VideoFrame> video_frame = PopOneVideoFrame(false); 420 const scoped_refptr<VideoFrame> video_frame = PopOneVideoFrame(false);
394 #ifdef OS_LINUX 421 #ifdef OS_LINUX
395 render_.RenderFrame(video_frame); 422 render_.RenderFrame(video_frame);
396 #endif // OS_LINUX 423 #endif // OS_LINUX
397 } 424 }
398 ScheduleVideoPlayout(); 425 ScheduleVideoPlayout();
426 CheckAVSync();
399 } 427 }
400 428
401 scoped_refptr<VideoFrame> PopOneVideoFrame(bool is_being_skipped) { 429 scoped_refptr<VideoFrame> PopOneVideoFrame(bool is_being_skipped) {
402 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN)); 430 DCHECK(cast_env()->CurrentlyOn(CastEnvironment::MAIN));
403 431
404 if (is_being_skipped) { 432 if (is_being_skipped) {
405 VLOG(1) << "VideoFrame[" << num_video_frames_processed_ << "]: Skipped."; 433 VLOG(1) << "VideoFrame[" << num_video_frames_processed_ << "]: Skipped.";
406 } else { 434 } else {
407 VLOG(1) << "VideoFrame[" << num_video_frames_processed_ << "]: Playing " 435 VLOG(1) << "VideoFrame[" << num_video_frames_processed_ << "]: Playing "
408 << (cast_env()->Clock()->NowTicks() - 436 << (cast_env()->Clock()->NowTicks() -
(...skipping 18 matching lines...) Expand all
427 audio_playout_queue_.front().first).InMicroseconds() 455 audio_playout_queue_.front().first).InMicroseconds()
428 << " usec later than intended."; 456 << " usec later than intended.";
429 } 457 }
430 458
431 scoped_ptr<AudioBus> ret(audio_playout_queue_.front().second); 459 scoped_ptr<AudioBus> ret(audio_playout_queue_.front().second);
432 audio_playout_queue_.pop_front(); 460 audio_playout_queue_.pop_front();
433 ++num_audio_frames_processed_; 461 ++num_audio_frames_processed_;
434 return ret.Pass(); 462 return ret.Pass();
435 } 463 }
436 464
465 void CheckAVSync() {
466 if (video_play_times_.size() > 30 &&
467 audio_play_times_.size() > 30) {
468 size_t num_events = 0;
469 base::TimeDelta delta;
470 std::map<uint16, base::TimeTicks>::iterator audio_iter, video_iter;
471 for (video_iter = video_play_times_.begin();
472 video_iter != video_play_times_.end();
473 ++video_iter) {
474 audio_iter = audio_play_times_.find(video_iter->first);
475 if (audio_iter != audio_play_times_.end()) {
476 num_events++;
477 // Positive values means audio is running behind video.
478 delta += audio_iter->second - video_iter->second;
479 }
480 }
481
482 if (num_events > 30) {
483 VLOG(0) << "Audio behind by: "
484 << (delta / num_events).InMilliseconds()
485 << "ms";
486 video_play_times_.clear();
487 audio_play_times_.clear();
488 }
489 } else if (video_play_times_.size() + audio_play_times_.size() > 500) {
490 // We are decoding audio or video timestamps, but not both, clear it out.
491 video_play_times_.clear();
492 audio_play_times_.clear();
493 }
494 }
495
437 // Frames in the queue older than this (relative to NowTicks()) will be 496 // Frames in the queue older than this (relative to NowTicks()) will be
438 // dropped (i.e., playback is falling behind). 497 // dropped (i.e., playback is falling behind).
439 const base::TimeDelta max_frame_age_; 498 const base::TimeDelta max_frame_age_;
440 499
441 // Outputs created, started, and destroyed by this NaivePlayer. 500 // Outputs created, started, and destroyed by this NaivePlayer.
442 #ifdef OS_LINUX 501 #ifdef OS_LINUX
443 test::LinuxOutputWindow render_; 502 test::LinuxOutputWindow render_;
444 #endif // OS_LINUX 503 #endif // OS_LINUX
445 scoped_ptr<AudioOutputStream> audio_output_stream_; 504 scoped_ptr<AudioOutputStream> audio_output_stream_;
446 505
447 // Video playout queue. 506 // Video playout queue.
448 typedef std::pair<base::TimeTicks, scoped_refptr<VideoFrame> > 507 typedef std::pair<base::TimeTicks, scoped_refptr<VideoFrame> >
449 VideoQueueEntry; 508 VideoQueueEntry;
450 std::deque<VideoQueueEntry> video_playout_queue_; 509 std::deque<VideoQueueEntry> video_playout_queue_;
451 int64 num_video_frames_processed_; 510 int64 num_video_frames_processed_;
452 511
453 base::OneShotTimer<NaivePlayer> video_playout_timer_; 512 base::OneShotTimer<NaivePlayer> video_playout_timer_;
454 513
455 // Audio playout queue, synchronized by |audio_lock_|. 514 // Audio playout queue, synchronized by |audio_lock_|.
456 base::Lock audio_lock_; 515 base::Lock audio_lock_;
457 typedef std::pair<base::TimeTicks, AudioBus*> AudioQueueEntry; 516 typedef std::pair<base::TimeTicks, AudioBus*> AudioQueueEntry;
458 std::deque<AudioQueueEntry> audio_playout_queue_; 517 std::deque<AudioQueueEntry> audio_playout_queue_;
459 int64 num_audio_frames_processed_; 518 int64 num_audio_frames_processed_;
460 519
461 // These must only be used on the audio thread calling OnMoreData(). 520 // These must only be used on the audio thread calling OnMoreData().
462 scoped_ptr<AudioBus> currently_playing_audio_frame_; 521 scoped_ptr<AudioBus> currently_playing_audio_frame_;
463 int currently_playing_audio_frame_start_; 522 int currently_playing_audio_frame_start_;
523
524 std::map<uint16, base::TimeTicks> audio_play_times_;
525 std::map<uint16, base::TimeTicks> video_play_times_;
526 int32 last_audio_frame_no_;
464 }; 527 };
465 528
466 } // namespace cast 529 } // namespace cast
467 } // namespace media 530 } // namespace media
468 531
469 int main(int argc, char** argv) { 532 int main(int argc, char** argv) {
470 base::AtExitManager at_exit; 533 base::AtExitManager at_exit;
471 CommandLine::Init(argc, argv); 534 CommandLine::Init(argc, argv);
472 InitLogging(logging::LoggingSettings()); 535 InitLogging(logging::LoggingSettings());
473 536
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 audio_config, 582 audio_config,
520 video_config, 583 video_config,
521 window_width, 584 window_width,
522 window_height); 585 window_height);
523 player.Start(); 586 player.Start();
524 587
525 base::MessageLoop().Run(); // Run forever (i.e., until SIGTERM). 588 base::MessageLoop().Run(); // Run forever (i.e., until SIGTERM).
526 NOTREACHED(); 589 NOTREACHED();
527 return 0; 590 return 0;
528 } 591 }
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