| Index: media/cast/test/receiver.cc
|
| diff --git a/media/cast/test/receiver.cc b/media/cast/test/receiver.cc
|
| index 3f5f4de3f947ad934e663d43416a4d7e1d9c1fd4..f80f5bee28660c1edfed745be1303105bba840a2 100644
|
| --- a/media/cast/test/receiver.cc
|
| +++ b/media/cast/test/receiver.cc
|
| @@ -7,6 +7,7 @@
|
| #include <cstdarg>
|
| #include <cstdio>
|
| #include <deque>
|
| +#include <map>
|
| #include <string>
|
| #include <utility>
|
|
|
| @@ -32,6 +33,8 @@
|
| #include "media/cast/cast_environment.h"
|
| #include "media/cast/cast_receiver.h"
|
| #include "media/cast/logging/logging_defines.h"
|
| +#include "media/cast/test/utility/audio_utility.h"
|
| +#include "media/cast/test/utility/barcode.h"
|
| #include "media/cast/test/utility/default_config.h"
|
| #include "media/cast/test/utility/in_process_receiver.h"
|
| #include "media/cast/test/utility/input_builder.h"
|
| @@ -270,6 +273,13 @@ class NaivePlayer : public InProcessReceiver,
|
| << "Video: Discontinuity in received frames.";
|
| video_playout_queue_.push_back(std::make_pair(playout_time, video_frame));
|
| ScheduleVideoPlayout();
|
| + uint16 frame_no;
|
| + if (media::cast::test::DecodeBarcode(video_frame, &frame_no)) {
|
| + video_play_times_.insert(
|
| + std::pair<uint16, base::TimeTicks>(frame_no, playout_time));
|
| + } else {
|
| + VLOG(2) << "Barcode decode failed!";
|
| + }
|
| }
|
|
|
| virtual void OnAudioFrame(scoped_ptr<AudioBus> audio_frame,
|
| @@ -279,6 +289,23 @@ class NaivePlayer : public InProcessReceiver,
|
| LOG_IF(WARNING, !is_continuous)
|
| << "Audio: Discontinuity in received frames.";
|
| base::AutoLock auto_lock(audio_lock_);
|
| + uint16 frame_no;
|
| + if (media::cast::DecodeTimestamp(audio_frame->channel(0),
|
| + audio_frame->frames(),
|
| + &frame_no)) {
|
| + // Since there are lots of audio packets with the same frame_no,
|
| + // we really want to make sure that we get the playout_time from
|
| + // the first one. If is_continous is true, then it's possible
|
| + // that we already missed the first one.
|
| + if (is_continuous && frame_no == last_audio_frame_no_ + 1) {
|
| + audio_play_times_.insert(
|
| + std::pair<uint16, base::TimeTicks>(frame_no, playout_time));
|
| + }
|
| + last_audio_frame_no_ = frame_no;
|
| + } else {
|
| + VLOG(2) << "Audio decode failed!";
|
| + last_audio_frame_no_ = -2;
|
| + }
|
| audio_playout_queue_.push_back(
|
| std::make_pair(playout_time, audio_frame.release()));
|
| }
|
| @@ -396,6 +423,7 @@ class NaivePlayer : public InProcessReceiver,
|
| #endif // OS_LINUX
|
| }
|
| ScheduleVideoPlayout();
|
| + CheckAVSync();
|
| }
|
|
|
| scoped_refptr<VideoFrame> PopOneVideoFrame(bool is_being_skipped) {
|
| @@ -434,6 +462,37 @@ class NaivePlayer : public InProcessReceiver,
|
| return ret.Pass();
|
| }
|
|
|
| + void CheckAVSync() {
|
| + if (video_play_times_.size() > 30 &&
|
| + audio_play_times_.size() > 30) {
|
| + size_t num_events = 0;
|
| + base::TimeDelta delta;
|
| + std::map<uint16, base::TimeTicks>::iterator audio_iter, video_iter;
|
| + for (video_iter = video_play_times_.begin();
|
| + video_iter != video_play_times_.end();
|
| + ++video_iter) {
|
| + audio_iter = audio_play_times_.find(video_iter->first);
|
| + if (audio_iter != audio_play_times_.end()) {
|
| + num_events++;
|
| + // Positive values means audio is running behind video.
|
| + delta += audio_iter->second - video_iter->second;
|
| + }
|
| + }
|
| +
|
| + if (num_events > 30) {
|
| + VLOG(0) << "Audio behind by: "
|
| + << (delta / num_events).InMilliseconds()
|
| + << "ms";
|
| + video_play_times_.clear();
|
| + audio_play_times_.clear();
|
| + }
|
| + } else if (video_play_times_.size() + audio_play_times_.size() > 500) {
|
| + // We are decoding audio or video timestamps, but not both, clear it out.
|
| + video_play_times_.clear();
|
| + audio_play_times_.clear();
|
| + }
|
| + }
|
| +
|
| // Frames in the queue older than this (relative to NowTicks()) will be
|
| // dropped (i.e., playback is falling behind).
|
| const base::TimeDelta max_frame_age_;
|
| @@ -461,6 +520,10 @@ class NaivePlayer : public InProcessReceiver,
|
| // These must only be used on the audio thread calling OnMoreData().
|
| scoped_ptr<AudioBus> currently_playing_audio_frame_;
|
| int currently_playing_audio_frame_start_;
|
| +
|
| + std::map<uint16, base::TimeTicks> audio_play_times_;
|
| + std::map<uint16, base::TimeTicks> video_play_times_;
|
| + int32 last_audio_frame_no_;
|
| };
|
|
|
| } // namespace cast
|
|
|