OLD | NEW |
1 /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 1 /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
2 * | 2 * |
3 * Use of this source code is governed by a BSD-style license | 3 * Use of this source code is governed by a BSD-style license |
4 * that can be found in the LICENSE file in the root of the source | 4 * that can be found in the LICENSE file in the root of the source |
5 * tree. An additional intellectual property rights grant can be found | 5 * tree. An additional intellectual property rights grant can be found |
6 * in the file PATENTS. All contributing project authors may | 6 * in the file PATENTS. All contributing project authors may |
7 * be found in the AUTHORS file in the root of the source tree. | 7 * be found in the AUTHORS file in the root of the source tree. |
8 */ | 8 */ |
9 | 9 |
10 #include <string.h> | 10 #include <string.h> |
11 | 11 |
12 #include <list> | 12 #include <list> |
| 13 #include <queue> |
13 | 14 |
14 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 #include "webrtc/base/checks.h" |
15 #include "webrtc/modules/video_coding/main/source/packet.h" | 17 #include "webrtc/modules/video_coding/main/source/packet.h" |
16 #include "webrtc/modules/video_coding/main/source/receiver.h" | 18 #include "webrtc/modules/video_coding/main/source/receiver.h" |
17 #include "webrtc/modules/video_coding/main/source/test/stream_generator.h" | 19 #include "webrtc/modules/video_coding/main/source/test/stream_generator.h" |
18 #include "webrtc/modules/video_coding/main/source/timing.h" | 20 #include "webrtc/modules/video_coding/main/source/timing.h" |
19 #include "webrtc/modules/video_coding/main/test/test_util.h" | 21 #include "webrtc/modules/video_coding/main/test/test_util.h" |
20 #include "webrtc/system_wrappers/interface/clock.h" | 22 #include "webrtc/system_wrappers/interface/clock.h" |
21 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" | 23 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" |
22 | 24 |
23 namespace webrtc { | 25 namespace webrtc { |
24 | 26 |
25 class TestVCMReceiver : public ::testing::Test { | 27 class TestVCMReceiver : public ::testing::Test { |
26 protected: | 28 protected: |
27 enum { kWidth = 640 }; | 29 enum { kWidth = 640 }; |
28 enum { kHeight = 480 }; | 30 enum { kHeight = 480 }; |
29 | 31 |
30 TestVCMReceiver() | 32 TestVCMReceiver() |
31 : clock_(new SimulatedClock(0)), | 33 : clock_(new SimulatedClock(0)), |
32 timing_(clock_.get()), | 34 timing_(clock_.get()), |
33 receiver_(&timing_, clock_.get(), &event_factory_) { | 35 receiver_(&timing_, clock_.get(), &event_factory_) { |
34 stream_generator_.reset( | 36 |
35 new StreamGenerator(0, clock_->TimeInMilliseconds())); | 37 stream_generator_.reset(new |
| 38 StreamGenerator(0, clock_->TimeInMilliseconds())); |
36 } | 39 } |
37 | 40 |
38 virtual void SetUp() { | 41 virtual void SetUp() { |
39 receiver_.Reset(); | 42 receiver_.Reset(); |
40 } | 43 } |
41 | 44 |
42 int32_t InsertPacket(int index) { | 45 int32_t InsertPacket(int index) { |
43 VCMPacket packet; | 46 VCMPacket packet; |
44 bool packet_available = stream_generator_->GetPacket(&packet, index); | 47 bool packet_available = stream_generator_->GetPacket(&packet, index); |
45 EXPECT_TRUE(packet_available); | 48 EXPECT_TRUE(packet_available); |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 // Advance time until it's time to decode the key frame. | 310 // Advance time until it's time to decode the key frame. |
308 clock_->AdvanceTimeMilliseconds(kMinDelayMs - clock_->TimeInMilliseconds() - | 311 clock_->AdvanceTimeMilliseconds(kMinDelayMs - clock_->TimeInMilliseconds() - |
309 key_frame_inserted); | 312 key_frame_inserted); |
310 EXPECT_TRUE(DecodeNextFrame()); | 313 EXPECT_TRUE(DecodeNextFrame()); |
311 // Make sure we don't get a key frame request since we have a key frame | 314 // Make sure we don't get a key frame request since we have a key frame |
312 // in the list. | 315 // in the list. |
313 bool request_key_frame = false; | 316 bool request_key_frame = false; |
314 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame); | 317 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame); |
315 EXPECT_FALSE(request_key_frame); | 318 EXPECT_FALSE(request_key_frame); |
316 } | 319 } |
| 320 |
| 321 // A simulated clock, when time elapses, will insert frames into the jitter |
| 322 // buffer, based on initial settings. |
| 323 class SimulatedClockWithFrames : public SimulatedClock { |
| 324 public: |
| 325 SimulatedClockWithFrames(StreamGenerator* stream_generator, |
| 326 VCMReceiver* receiver) |
| 327 : SimulatedClock(0), |
| 328 stream_generator_(stream_generator), |
| 329 receiver_(receiver) {} |
| 330 virtual ~SimulatedClockWithFrames() {} |
| 331 |
| 332 // If |stop_on_frame| is true and next frame arrives between now and |
| 333 // now+|milliseconds|, the clock will be advanced to the arrival time of next |
| 334 // frame. |
| 335 // Otherwise, the clock will be advanced by |milliseconds|. |
| 336 // |
| 337 // For both cases, a frame will be inserted into the jitter buffer at the |
| 338 // instant when the clock time is timestamps_.front().arrive_time. |
| 339 // |
| 340 // Return true if some frame arrives between now and now+|milliseconds|. |
| 341 bool AdvanceTimeMilliseconds(int64_t milliseconds, bool stop_on_frame) { |
| 342 return AdvanceTimeMicroseconds(milliseconds * 1000, stop_on_frame); |
| 343 }; |
| 344 |
| 345 bool AdvanceTimeMicroseconds(int64_t microseconds, bool stop_on_frame) { |
| 346 int64_t start_time = TimeInMicroseconds(); |
| 347 int64_t end_time = start_time + microseconds; |
| 348 bool frame_injected = false; |
| 349 while (!timestamps_.empty() && |
| 350 timestamps_.front().arrive_time <= end_time) { |
| 351 DCHECK(timestamps_.front().arrive_time >= start_time); |
| 352 |
| 353 SimulatedClock::AdvanceTimeMicroseconds(timestamps_.front().arrive_time - |
| 354 TimeInMicroseconds()); |
| 355 GenerateAndInsertFrame((timestamps_.front().render_time + 500) / 1000); |
| 356 timestamps_.pop(); |
| 357 frame_injected = true; |
| 358 |
| 359 if (stop_on_frame) |
| 360 return frame_injected; |
| 361 } |
| 362 |
| 363 if (TimeInMicroseconds() < end_time) { |
| 364 SimulatedClock::AdvanceTimeMicroseconds(end_time - TimeInMicroseconds()); |
| 365 } |
| 366 return frame_injected; |
| 367 }; |
| 368 |
| 369 // Input timestamps are in unit Milliseconds. |
| 370 // And |arrive_timestamps| must be positive and in increasing order. |
| 371 // |arrive_timestamps| determine when we are going to insert frames into the |
| 372 // jitter buffer. |
| 373 // |render_timestamps| are the timestamps on the frame. |
| 374 void SetFrames(const int64_t* arrive_timestamps, |
| 375 const int64_t* render_timestamps, |
| 376 size_t size) { |
| 377 int64_t previous_arrive_timestamp = 0; |
| 378 for (size_t i = 0; i < size; i++) { |
| 379 CHECK(arrive_timestamps[i] >= previous_arrive_timestamp); |
| 380 timestamps_.push(TimestampPair(arrive_timestamps[i] * 1000, |
| 381 render_timestamps[i] * 1000)); |
| 382 previous_arrive_timestamp = arrive_timestamps[i]; |
| 383 } |
| 384 } |
| 385 |
| 386 private: |
| 387 struct TimestampPair { |
| 388 TimestampPair(int64_t arrive_timestamp, int64_t render_timestamp) |
| 389 : arrive_time(arrive_timestamp), render_time(render_timestamp) {} |
| 390 |
| 391 int64_t arrive_time; |
| 392 int64_t render_time; |
| 393 }; |
| 394 |
| 395 void GenerateAndInsertFrame(int64_t render_timestamp_ms) { |
| 396 VCMPacket packet; |
| 397 stream_generator_->GenerateFrame(FrameType::kVideoFrameKey, |
| 398 1, // media packets |
| 399 0, // empty packets |
| 400 render_timestamp_ms); |
| 401 |
| 402 bool packet_available = stream_generator_->PopPacket(&packet, 0); |
| 403 EXPECT_TRUE(packet_available); |
| 404 if (!packet_available) |
| 405 return; // Return here to avoid crashes below. |
| 406 receiver_->InsertPacket(packet, 640, 480); |
| 407 } |
| 408 |
| 409 std::queue<TimestampPair> timestamps_; |
| 410 StreamGenerator* stream_generator_; |
| 411 VCMReceiver* receiver_; |
| 412 }; |
| 413 |
| 414 // Use a SimulatedClockWithFrames |
| 415 // Wait call will do either of these: |
| 416 // 1. If |stop_on_frame| is true, the clock will be turned to the exact instant |
| 417 // that the first frame comes and the frame will be inserted into the jitter |
| 418 // buffer, or the clock will be turned to now + |max_time| if no frame comes in |
| 419 // the window. |
| 420 // 2. If |stop_on_frame| is false, the clock will be turn to now + |max_time|, |
| 421 // and all the frames arriving between now and now + |max_time| will be |
| 422 // inserted into the jitter buffer. |
| 423 // |
| 424 // This is used to simulate the JitterBuffer getting packets from internet as |
| 425 // time elapses. |
| 426 |
| 427 class FrameInjectEvent : public EventWrapper { |
| 428 public: |
| 429 FrameInjectEvent(SimulatedClockWithFrames* clock, bool stop_on_frame) |
| 430 : clock_(clock), stop_on_frame_(stop_on_frame) {} |
| 431 |
| 432 bool Set() override { return true; } |
| 433 |
| 434 EventTypeWrapper Wait(unsigned long max_time) override { |
| 435 if (clock_->AdvanceTimeMilliseconds(max_time, stop_on_frame_) && |
| 436 stop_on_frame_) { |
| 437 return EventTypeWrapper::kEventSignaled; |
| 438 } else { |
| 439 return EventTypeWrapper::kEventTimeout; |
| 440 } |
| 441 } |
| 442 |
| 443 private: |
| 444 SimulatedClockWithFrames* clock_; |
| 445 bool stop_on_frame_; |
| 446 }; |
| 447 |
| 448 class VCMReceiverTimingTest : public ::testing::Test { |
| 449 protected: |
| 450 |
| 451 VCMReceiverTimingTest() |
| 452 |
| 453 : clock_(&stream_generator_, &receiver_), |
| 454 stream_generator_(0, clock_.TimeInMilliseconds()), |
| 455 timing_(&clock_), |
| 456 receiver_( |
| 457 &timing_, |
| 458 &clock_, |
| 459 rtc::scoped_ptr<EventWrapper>(new FrameInjectEvent(&clock_, false)), |
| 460 rtc::scoped_ptr<EventWrapper>( |
| 461 new FrameInjectEvent(&clock_, true))) {} |
| 462 |
| 463 |
| 464 virtual void SetUp() { receiver_.Reset(); } |
| 465 |
| 466 SimulatedClockWithFrames clock_; |
| 467 StreamGenerator stream_generator_; |
| 468 VCMTiming timing_; |
| 469 VCMReceiver receiver_; |
| 470 }; |
| 471 |
| 472 // Test whether VCMReceiver::FrameForDecoding handles parameter |
| 473 // |max_wait_time_ms| correctly: |
| 474 // 1. The function execution should never take more than |max_wait_time_ms|. |
| 475 // 2. If the function exit before now + |max_wait_time_ms|, a frame must be |
| 476 // returned. |
| 477 TEST_F(VCMReceiverTimingTest, FrameForDecoding) { |
| 478 const size_t kNumFrames = 100; |
| 479 const int kFramePeriod = 40; |
| 480 int64_t arrive_timestamps[kNumFrames]; |
| 481 int64_t render_timestamps[kNumFrames]; |
| 482 int64_t next_render_time; |
| 483 |
| 484 // Construct test samples. |
| 485 // render_timestamps are the timestamps stored in the Frame; |
| 486 // arrive_timestamps controls when the Frame packet got received. |
| 487 for (size_t i = 0; i < kNumFrames; i++) { |
| 488 // Preset frame rate to 25Hz. |
| 489 // But we add a reasonable deviation to arrive_timestamps to mimic Internet |
| 490 // fluctuation. |
| 491 arrive_timestamps[i] = |
| 492 (i + 1) * kFramePeriod + (i % 10) * ((i % 2) ? 1 : -1); |
| 493 render_timestamps[i] = (i + 1) * kFramePeriod; |
| 494 } |
| 495 |
| 496 clock_.SetFrames(arrive_timestamps, render_timestamps, kNumFrames); |
| 497 |
| 498 // Record how many frames we finally get out of the receiver. |
| 499 size_t num_frames_return = 0; |
| 500 |
| 501 const int64_t kMaxWaitTime = 30; |
| 502 |
| 503 // Ideally, we should get all frames that we input in InitializeFrames. |
| 504 // In the case that FrameForDecoding kills frames by error, we rely on the |
| 505 // build bot to kill the test. |
| 506 while (num_frames_return < kNumFrames) { |
| 507 int64_t start_time = clock_.TimeInMilliseconds(); |
| 508 VCMEncodedFrame* frame = |
| 509 receiver_.FrameForDecoding(kMaxWaitTime, next_render_time, false); |
| 510 int64_t end_time = clock_.TimeInMilliseconds(); |
| 511 |
| 512 // In any case the FrameForDecoding should not wait longer than |
| 513 // max_wait_time. |
| 514 // In the case that we did not get a frame, it should have been waiting for |
| 515 // exactly max_wait_time. (By the testing samples we constructed above, we |
| 516 // are sure there is no timing error, so the only case it returns with NULL |
| 517 // is that it runs out of time.) |
| 518 if (frame) { |
| 519 receiver_.ReleaseFrame(frame); |
| 520 ++num_frames_return; |
| 521 EXPECT_GE(kMaxWaitTime, end_time - start_time); |
| 522 } else { |
| 523 EXPECT_EQ(kMaxWaitTime, end_time - start_time); |
| 524 } |
| 525 } |
| 526 } |
| 527 |
317 } // namespace webrtc | 528 } // namespace webrtc |
OLD | NEW |