explicit LoopBackTransport(scoped_refptr<CastEnvironment> cast_environment)
: send_packets_(true),
drop_packets_belonging_to_odd_frames_(false),
- cast_environment_(cast_environment) {}
+ cast_environment_(cast_environment),
+ bytes_sent_(0) {}
void SetPacketReceiver(
const PacketReceiverCallback& packet_receiver,
const base::Closure& cb) OVERRIDE {
DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
if (!send_packets_)
- return false;
+ return true;
+ bytes_sent_ += packet->data.size();
if (drop_packets_belonging_to_odd_frames_) {
uint32 frame_id = packet->data[13];
if (frame_id % 2 == 1)
return true;
}
+ virtual int64 GetBytesSent() OVERRIDE {
+ return bytes_sent_;
+ }
+
void SetSendPackets(bool send_packets) { send_packets_ = send_packets; }
void DropAllPacketsBelongingToOddFrames() {
bool drop_packets_belonging_to_odd_frames_;
scoped_refptr<CastEnvironment> cast_environment_;
scoped_ptr<test::PacketPipe> packet_pipe_;
+ int64 bytes_sent_;
};
// Class that verifies the audio frames coming out of the receiver.
bool is_continuous) {
++num_called_;
- ASSERT_TRUE(!!video_frame);
+ ASSERT_TRUE(!!video_frame.get());
ASSERT_FALSE(expected_frame_.empty());
ExpectedVideoFrame expected_video_frame = expected_frame_.front();
expected_frame_.pop_front();
scoped_refptr<media::VideoFrame> expected_I420_frame =
media::VideoFrame::CreateFrame(
VideoFrame::I420, size, gfx::Rect(size), size, base::TimeDelta());
- PopulateVideoFrame(expected_I420_frame, expected_video_frame.start_value);
+ PopulateVideoFrame(expected_I420_frame.get(),
+ expected_video_frame.start_value);
- EXPECT_GE(I420PSNR(expected_I420_frame, video_frame), kVideoAcceptedPSNR);
+ if (expected_video_frame.should_be_continuous) {
+ EXPECT_GE(I420PSNR(expected_I420_frame, video_frame), kVideoAcceptedPSNR);
+ }
EXPECT_NEAR(
(playout_time - expected_video_frame.playout_time).InMillisecondsF(),
int max_number_of_video_buffers_used) {
audio_sender_config_.ssrc = 1;
audio_sender_config_.incoming_feedback_ssrc = 2;
- audio_sender_config_.target_playout_delay =
+ audio_sender_config_.max_playout_delay =
base::TimeDelta::FromMilliseconds(kTargetPlayoutDelayMs);
audio_sender_config_.rtp_payload_type = 96;
audio_sender_config_.use_external_encoder = false;
video_sender_config_.ssrc = 3;
video_sender_config_.incoming_feedback_ssrc = 4;
- video_sender_config_.target_playout_delay =
+ video_sender_config_.max_playout_delay =
base::TimeDelta::FromMilliseconds(kTargetPlayoutDelayMs);
video_sender_config_.rtp_payload_type = 97;
video_sender_config_.use_external_encoder = false;
NULL,
testing_clock_sender_,
dummy_endpoint,
+ make_scoped_ptr(new base::DictionaryValue),
base::Bind(&UpdateCastTransportStatus),
base::Bind(&End2EndTest::LogRawEvents, base::Unretained(this)),
base::TimeDelta::FromMilliseconds(1),
base::Bind(&VideoInitializationStatus),
CreateDefaultVideoEncodeAcceleratorCallback(),
CreateDefaultVideoEncodeMemoryCallback());
+ task_runner_->RunTasks();
receiver_to_sender_.SetPacketReceiver(
transport_sender_->PacketReceiverForTesting(),
scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::CreateFrame(
VideoFrame::I420, size, gfx::Rect(size), size, time_diff);
- PopulateVideoFrame(video_frame, start_value);
+ PopulateVideoFrame(video_frame.get(), start_value);
video_frame_input_->InsertRawVideoFrame(video_frame, capture_time);
}
EXPECT_EQ(10, test_receiver_video_callback_->number_times_called());
}
-// This tests a network glitch lasting for 10 video frames.
-// Flaky. See crbug.com/351596.
-TEST_F(End2EndTest, DISABLED_GlitchWith3Buffers) {
- Configure(CODEC_VIDEO_VP8, CODEC_AUDIO_OPUS,
- kDefaultAudioSamplingRate, 3);
- video_sender_config_.target_playout_delay =
- base::TimeDelta::FromMilliseconds(67);
- video_receiver_config_.rtp_max_delay_ms = 67;
- Create();
-
- int video_start = kVideoStart;
- base::TimeTicks capture_time;
- // Frames will rendered on completion until the render time stabilizes, i.e.
- // we got enough data.
- const int frames_before_glitch = 20;
- for (int i = 0; i < frames_before_glitch; ++i) {
- capture_time = testing_clock_sender_->NowTicks();
- SendVideoFrame(video_start, capture_time);
- test_receiver_video_callback_->AddExpectedResult(
- video_start,
- video_sender_config_.width,
- video_sender_config_.height,
- capture_time + base::TimeDelta::FromMilliseconds(kTargetPlayoutDelayMs),
- true);
- cast_receiver_->RequestDecodedVideoFrame(
- base::Bind(&TestReceiverVideoCallback::CheckVideoFrame,
- test_receiver_video_callback_));
- RunTasks(kFrameTimerMs);
- video_start++;
- }
-
- // Introduce a glitch lasting for 10 frames.
- sender_to_receiver_.SetSendPackets(false);
- for (int i = 0; i < 10; ++i) {
- capture_time = testing_clock_sender_->NowTicks();
- // First 3 will be sent and lost.
- SendVideoFrame(video_start, capture_time);
- RunTasks(kFrameTimerMs);
- video_start++;
- }
- sender_to_receiver_.SetSendPackets(true);
- RunTasks(100);
- capture_time = testing_clock_sender_->NowTicks();
-
- // Frame 1 should be acked by now and we should have an opening to send 4.
- SendVideoFrame(video_start, capture_time);
- RunTasks(kFrameTimerMs);
-
- // Frames 1-3 are old frames by now, and therefore should be decoded, but
- // not rendered. The next frame we expect to render is frame #4.
- test_receiver_video_callback_->AddExpectedResult(
- video_start,
- video_sender_config_.width,
- video_sender_config_.height,
- capture_time + base::TimeDelta::FromMilliseconds(kTargetPlayoutDelayMs),
- true);
-
- cast_receiver_->RequestDecodedVideoFrame(
- base::Bind(&TestReceiverVideoCallback::CheckVideoFrame,
- test_receiver_video_callback_));
-
- RunTasks(2 * kFrameTimerMs + 1); // Empty the receiver pipeline.
- EXPECT_EQ(frames_before_glitch + 1,
- test_receiver_video_callback_->number_times_called());
-}
-
-// Disabled due to flakiness and crashiness. http://crbug.com/360951
-TEST_F(End2EndTest, DISABLED_DropEveryOtherFrame3Buffers) {
- Configure(CODEC_VIDEO_VP8, CODEC_AUDIO_OPUS,
- kDefaultAudioSamplingRate, 3);
- video_sender_config_.target_playout_delay =
- base::TimeDelta::FromMilliseconds(67);
- video_receiver_config_.rtp_max_delay_ms = 67;
+TEST_F(End2EndTest, DropEveryOtherFrame3Buffers) {
+ Configure(CODEC_VIDEO_VP8, CODEC_AUDIO_OPUS, kDefaultAudioSamplingRate, 3);
+ int target_delay = 300;
+ video_sender_config_.max_playout_delay =
+ base::TimeDelta::FromMilliseconds(target_delay);
+ audio_sender_config_.max_playout_delay =
+ base::TimeDelta::FromMilliseconds(target_delay);
+ video_receiver_config_.rtp_max_delay_ms = target_delay;
Create();
sender_to_receiver_.DropAllPacketsBelongingToOddFrames();
video_sender_config_.width,
video_sender_config_.height,
capture_time +
- base::TimeDelta::FromMilliseconds(kTargetPlayoutDelayMs),
+ base::TimeDelta::FromMilliseconds(target_delay),
i == 0);
// GetRawVideoFrame will not return the frame until we are close in
video_start++;
}
- RunTasks(2 * kFrameTimerMs + 1); // Empty the pipeline.
+ RunTasks(2 * kFrameTimerMs + target_delay); // Empty the pipeline.
EXPECT_EQ(i / 2, test_receiver_video_callback_->number_times_called());
}
base::TimeTicks test_end = testing_clock_receiver_->NowTicks();
RunTasks(100 * kFrameTimerMs + 1); // Empty the pipeline.
EXPECT_GT(video_ticks_.size(), 100ul);
+ VLOG(1) << "Fully transmitted " << video_ticks_.size()
+ << " out of 10000 frames.";
EXPECT_LT((video_ticks_.back().second - test_end).InMilliseconds(), 1000);
}
+// Tests that a system configured for 30 FPS drops frames when input is provided
+// at a much higher frame rate.
+TEST_F(End2EndTest, ShoveHighFrameRateDownYerThroat) {
+ Configure(CODEC_VIDEO_FAKE, CODEC_AUDIO_PCM16, 32000,
+ 1);
+ receiver_to_sender_.SetPacketPipe(test::EvilNetwork().Pass());
+ sender_to_receiver_.SetPacketPipe(test::EvilNetwork().Pass());
+ Create();
+ StartBasicPlayer();
+
+ int frames_counter = 0;
+ for (; frames_counter < 10000; ++frames_counter) {
+ SendFakeVideoFrame(testing_clock_sender_->NowTicks());
+ RunTasks(10 /* 10 ms, but 33.3 expected by system */);
+ }
+ base::TimeTicks test_end = testing_clock_receiver_->NowTicks();
+ RunTasks(100 * kFrameTimerMs + 1); // Empty the pipeline.
+ EXPECT_LT(100ul, video_ticks_.size());
+ EXPECT_GE(3334ul, video_ticks_.size());
+ VLOG(1) << "Fully transmitted " << video_ticks_.size()
+ << " out of 10000 frames.";
+ EXPECT_LT((video_ticks_.back().second - test_end).InMilliseconds(), 1000);
+}
+
+TEST_F(End2EndTest, OldPacketNetwork) {
+ Configure(CODEC_VIDEO_FAKE, CODEC_AUDIO_PCM16, 32000, 1);
+ sender_to_receiver_.SetPacketPipe(test::NewRandomDrop(0.01));
+ scoped_ptr<test::PacketPipe> echo_chamber(
+ test::NewDuplicateAndDelay(1, 10 * kFrameTimerMs));
+ echo_chamber->AppendToPipe(
+ test::NewDuplicateAndDelay(1, 20 * kFrameTimerMs));
+ echo_chamber->AppendToPipe(
+ test::NewDuplicateAndDelay(1, 40 * kFrameTimerMs));
+ echo_chamber->AppendToPipe(
+ test::NewDuplicateAndDelay(1, 80 * kFrameTimerMs));
+ echo_chamber->AppendToPipe(
+ test::NewDuplicateAndDelay(1, 160 * kFrameTimerMs));
+
+ receiver_to_sender_.SetPacketPipe(echo_chamber.Pass());
+ Create();
+ StartBasicPlayer();
+
+ SetExpectedVideoPlayoutSmoothness(
+ base::TimeDelta::FromMilliseconds(kFrameTimerMs) * 90 / 100,
+ base::TimeDelta::FromMilliseconds(kFrameTimerMs) * 110 / 100,
+ base::TimeDelta::FromMilliseconds(kFrameTimerMs) / 10);
+
+ int frames_counter = 0;
+ for (; frames_counter < 10000; ++frames_counter) {
+ SendFakeVideoFrame(testing_clock_sender_->NowTicks());
+ RunTasks(kFrameTimerMs);
+ }
+ RunTasks(100 * kFrameTimerMs + 1); // Empty the pipeline.
+
+ EXPECT_EQ(10000ul, video_ticks_.size());
+}
+
+TEST_F(End2EndTest, TestSetPlayoutDelay) {
+ Configure(CODEC_VIDEO_FAKE, CODEC_AUDIO_PCM16, 32000, 1);
+ video_sender_config_.min_playout_delay =
+ video_sender_config_.max_playout_delay;
+ audio_sender_config_.min_playout_delay =
+ audio_sender_config_.max_playout_delay;
+ video_sender_config_.max_playout_delay = base::TimeDelta::FromSeconds(1);
+ audio_sender_config_.max_playout_delay = base::TimeDelta::FromSeconds(1);
+ Create();
+ StartBasicPlayer();
+ const int kNewDelay = 600;
+
+ int frames_counter = 0;
+ for (; frames_counter < 200; ++frames_counter) {
+ SendFakeVideoFrame(testing_clock_sender_->NowTicks());
+ RunTasks(kFrameTimerMs);
+ }
+ cast_sender_->SetTargetPlayoutDelay(
+ base::TimeDelta::FromMilliseconds(kNewDelay));
+ for (; frames_counter < 400; ++frames_counter) {
+ SendFakeVideoFrame(testing_clock_sender_->NowTicks());
+ RunTasks(kFrameTimerMs);
+ }
+ RunTasks(100 * kFrameTimerMs + 1); // Empty the pipeline.
+ size_t jump = 0;
+ for (size_t i = 1; i < video_ticks_.size(); i++) {
+ int64 delta = (video_ticks_[i].second -
+ video_ticks_[i-1].second).InMilliseconds();
+ if (delta > 100) {
+ EXPECT_EQ(delta, kNewDelay - kTargetPlayoutDelayMs + kFrameTimerMs);
+ EXPECT_EQ(0u, jump);
+ jump = i;
+ }
+ }
+ EXPECT_GT(jump, 199u);
+ EXPECT_LT(jump, 220u);
+}
+
// TODO(pwestin): Add repeatable packet loss test.
// TODO(pwestin): Add test for misaligned send get calls.
// TODO(pwestin): Add more tests that does not resample.