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

Side by Side Diff: webrtc/modules/video_coding/main/source/receiver_unittest.cc

Issue 1173253008: Unit Test For VCMReceiver::FrameForDecoding Timing Test (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 6 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
OLDNEW
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
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
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/main/source/receiver.cc ('k') | webrtc/modules/video_coding/main/source/test/stream_generator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698