stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 11 | #include "modules/video_coding/timing.h" |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame^] | 12 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 13 | #include "system_wrappers/include/clock.h" |
| 14 | #include "test/gtest.h" |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 15 | |
| 16 | namespace webrtc { |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 17 | namespace { |
| 18 | const int kFps = 25; |
| 19 | } // namespace |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 20 | |
| 21 | TEST(ReceiverTiming, Tests) { |
| 22 | SimulatedClock clock(0); |
| 23 | VCMTiming timing(&clock); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 24 | timing.Reset(); |
| 25 | |
| 26 | uint32_t timestamp = 0; |
| 27 | timing.UpdateCurrentDelay(timestamp); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 28 | |
| 29 | timing.Reset(); |
| 30 | |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 31 | timing.IncomingTimestamp(timestamp, clock.TimeInMilliseconds()); |
| 32 | uint32_t jitter_delay_ms = 20; |
| 33 | timing.SetJitterDelay(jitter_delay_ms); |
| 34 | timing.UpdateCurrentDelay(timestamp); |
mikhal@webrtc.org | adc64a7 | 2013-05-30 16:20:18 +0000 | [diff] [blame] | 35 | timing.set_render_delay(0); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 36 | uint32_t wait_time_ms = timing.MaxWaitingTime( |
| 37 | timing.RenderTimeMs(timestamp, clock.TimeInMilliseconds()), |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 38 | clock.TimeInMilliseconds()); |
| 39 | // First update initializes the render time. Since we have no decode delay |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 40 | // we get wait_time_ms = renderTime - now - renderDelay = jitter. |
| 41 | EXPECT_EQ(jitter_delay_ms, wait_time_ms); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 42 | |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 43 | jitter_delay_ms += VCMTiming::kDelayMaxChangeMsPerS + 10; |
| 44 | timestamp += 90000; |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 45 | clock.AdvanceTimeMilliseconds(1000); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 46 | timing.SetJitterDelay(jitter_delay_ms); |
| 47 | timing.UpdateCurrentDelay(timestamp); |
| 48 | wait_time_ms = timing.MaxWaitingTime( |
| 49 | timing.RenderTimeMs(timestamp, clock.TimeInMilliseconds()), |
philipel | 5908c71 | 2015-12-21 08:23:20 -0800 | [diff] [blame] | 50 | clock.TimeInMilliseconds()); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 51 | // Since we gradually increase the delay we only get 100 ms every second. |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 52 | EXPECT_EQ(jitter_delay_ms - 10, wait_time_ms); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 53 | |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 54 | timestamp += 90000; |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 55 | clock.AdvanceTimeMilliseconds(1000); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 56 | timing.UpdateCurrentDelay(timestamp); |
| 57 | wait_time_ms = timing.MaxWaitingTime( |
| 58 | timing.RenderTimeMs(timestamp, clock.TimeInMilliseconds()), |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 59 | clock.TimeInMilliseconds()); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 60 | EXPECT_EQ(jitter_delay_ms, wait_time_ms); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 61 | |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 62 | // Insert frames without jitter, verify that this gives the exact wait time. |
| 63 | const int kNumFrames = 300; |
| 64 | for (int i = 0; i < kNumFrames; i++) { |
| 65 | clock.AdvanceTimeMilliseconds(1000 / kFps); |
| 66 | timestamp += 90000 / kFps; |
| 67 | timing.IncomingTimestamp(timestamp, clock.TimeInMilliseconds()); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 68 | } |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 69 | timing.UpdateCurrentDelay(timestamp); |
| 70 | wait_time_ms = timing.MaxWaitingTime( |
| 71 | timing.RenderTimeMs(timestamp, clock.TimeInMilliseconds()), |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 72 | clock.TimeInMilliseconds()); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 73 | EXPECT_EQ(jitter_delay_ms, wait_time_ms); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 74 | |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 75 | // Add decode time estimates for 1 second. |
| 76 | const uint32_t kDecodeTimeMs = 10; |
| 77 | for (int i = 0; i < kFps; i++) { |
| 78 | clock.AdvanceTimeMilliseconds(kDecodeTimeMs); |
Johannes Kron | bfd343b | 2019-07-01 10:07:50 +0200 | [diff] [blame] | 79 | timing.StopDecodeTimer(kDecodeTimeMs, clock.TimeInMilliseconds()); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 80 | timestamp += 90000 / kFps; |
| 81 | clock.AdvanceTimeMilliseconds(1000 / kFps - kDecodeTimeMs); |
| 82 | timing.IncomingTimestamp(timestamp, clock.TimeInMilliseconds()); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 83 | } |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 84 | timing.UpdateCurrentDelay(timestamp); |
| 85 | wait_time_ms = timing.MaxWaitingTime( |
| 86 | timing.RenderTimeMs(timestamp, clock.TimeInMilliseconds()), |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 87 | clock.TimeInMilliseconds()); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 88 | EXPECT_EQ(jitter_delay_ms, wait_time_ms); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 89 | |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 90 | const int kMinTotalDelayMs = 200; |
| 91 | timing.set_min_playout_delay(kMinTotalDelayMs); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 92 | clock.AdvanceTimeMilliseconds(5000); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 93 | timestamp += 5 * 90000; |
| 94 | timing.UpdateCurrentDelay(timestamp); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 95 | const int kRenderDelayMs = 10; |
mikhal@webrtc.org | adc64a7 | 2013-05-30 16:20:18 +0000 | [diff] [blame] | 96 | timing.set_render_delay(kRenderDelayMs); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 97 | wait_time_ms = timing.MaxWaitingTime( |
| 98 | timing.RenderTimeMs(timestamp, clock.TimeInMilliseconds()), |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 99 | clock.TimeInMilliseconds()); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 100 | // We should at least have kMinTotalDelayMs - decodeTime (10) - renderTime |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 101 | // (10) to wait. |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 102 | EXPECT_EQ(kMinTotalDelayMs - kDecodeTimeMs - kRenderDelayMs, wait_time_ms); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 103 | // The total video delay should be equal to the min total delay. |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 104 | EXPECT_EQ(kMinTotalDelayMs, timing.TargetVideoDelay()); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 105 | |
mikhal@webrtc.org | adc64a7 | 2013-05-30 16:20:18 +0000 | [diff] [blame] | 106 | // Reset playout delay. |
| 107 | timing.set_min_playout_delay(0); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 108 | clock.AdvanceTimeMilliseconds(5000); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 109 | timestamp += 5 * 90000; |
| 110 | timing.UpdateCurrentDelay(timestamp); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 111 | } |
| 112 | |
| 113 | TEST(ReceiverTiming, WrapAround) { |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 114 | SimulatedClock clock(0); |
| 115 | VCMTiming timing(&clock); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 116 | // Provoke a wrap-around. The fifth frame will have wrapped at 25 fps. |
| 117 | uint32_t timestamp = 0xFFFFFFFFu - 3 * 90000 / kFps; |
| 118 | for (int i = 0; i < 5; ++i) { |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 119 | timing.IncomingTimestamp(timestamp, clock.TimeInMilliseconds()); |
Åsa Persson | 8368d1a | 2018-01-05 12:44:45 +0100 | [diff] [blame] | 120 | clock.AdvanceTimeMilliseconds(1000 / kFps); |
| 121 | timestamp += 90000 / kFps; |
| 122 | EXPECT_EQ(3 * 1000 / kFps, |
| 123 | timing.RenderTimeMs(0xFFFFFFFFu, clock.TimeInMilliseconds())); |
| 124 | EXPECT_EQ(3 * 1000 / kFps + 1, |
| 125 | timing.RenderTimeMs(89u, // One ms later in 90 kHz. |
| 126 | clock.TimeInMilliseconds())); |
stefan@webrtc.org | 9f557c1 | 2013-05-17 12:55:07 +0000 | [diff] [blame] | 127 | } |
| 128 | } |
| 129 | |
| 130 | } // namespace webrtc |