stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [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 | |
pbos@webrtc.org | 3f45c2e | 2013-08-05 16:22:53 | [diff] [blame] | 11 | #include <math.h> |
| 12 | #include <stdio.h> |
| 13 | #include <stdlib.h> |
| 14 | |
Henrik Kjellander | fe7633e | 2015-11-18 21:00:21 | [diff] [blame] | 15 | #include "webrtc/modules/video_coding/include/video_coding.h" |
| 16 | #include "webrtc/modules/video_coding/internal_defines.h" |
kwiberg | 36a2479 | 2016-10-01 05:29:43 | [diff] [blame] | 17 | #include "webrtc/modules/video_coding/timing.h" |
Henrik Kjellander | 78f65d0 | 2015-10-28 17:17:40 | [diff] [blame] | 18 | #include "webrtc/system_wrappers/include/clock.h" |
kwiberg | 36a2479 | 2016-10-01 05:29:43 | [diff] [blame] | 19 | #include "webrtc/test/gtest.h" |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 20 | #include "webrtc/test/testsupport/fileutils.h" |
| 21 | |
| 22 | namespace webrtc { |
| 23 | |
| 24 | TEST(ReceiverTiming, Tests) { |
| 25 | SimulatedClock clock(0); |
| 26 | VCMTiming timing(&clock); |
| 27 | uint32_t waitTime = 0; |
| 28 | uint32_t jitterDelayMs = 0; |
magjed | 42c4e1a | 2016-03-22 12:12:09 | [diff] [blame] | 29 | uint32_t requiredDecodeTimeMs = 0; |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 30 | uint32_t timeStamp = 0; |
| 31 | |
| 32 | timing.Reset(); |
| 33 | |
| 34 | timing.UpdateCurrentDelay(timeStamp); |
| 35 | |
| 36 | timing.Reset(); |
| 37 | |
| 38 | timing.IncomingTimestamp(timeStamp, clock.TimeInMilliseconds()); |
| 39 | jitterDelayMs = 20; |
mikhal@webrtc.org | e477574 | 2013-05-30 16:20:18 | [diff] [blame] | 40 | timing.SetJitterDelay(jitterDelayMs); |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 41 | timing.UpdateCurrentDelay(timeStamp); |
mikhal@webrtc.org | e477574 | 2013-05-30 16:20:18 | [diff] [blame] | 42 | timing.set_render_delay(0); |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 43 | waitTime = timing.MaxWaitingTime( |
| 44 | timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds()), |
| 45 | clock.TimeInMilliseconds()); |
| 46 | // First update initializes the render time. Since we have no decode delay |
| 47 | // we get waitTime = renderTime - now - renderDelay = jitter. |
| 48 | EXPECT_EQ(jitterDelayMs, waitTime); |
| 49 | |
| 50 | jitterDelayMs += VCMTiming::kDelayMaxChangeMsPerS + 10; |
| 51 | timeStamp += 90000; |
| 52 | clock.AdvanceTimeMilliseconds(1000); |
mikhal@webrtc.org | e477574 | 2013-05-30 16:20:18 | [diff] [blame] | 53 | timing.SetJitterDelay(jitterDelayMs); |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 54 | timing.UpdateCurrentDelay(timeStamp); |
philipel | 288c2b6 | 2015-12-21 16:23:20 | [diff] [blame] | 55 | waitTime = timing.MaxWaitingTime( |
| 56 | timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds()), |
| 57 | clock.TimeInMilliseconds()); |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 58 | // Since we gradually increase the delay we only get 100 ms every second. |
| 59 | EXPECT_EQ(jitterDelayMs - 10, waitTime); |
| 60 | |
| 61 | timeStamp += 90000; |
| 62 | clock.AdvanceTimeMilliseconds(1000); |
| 63 | timing.UpdateCurrentDelay(timeStamp); |
| 64 | waitTime = timing.MaxWaitingTime( |
| 65 | timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds()), |
| 66 | clock.TimeInMilliseconds()); |
| 67 | EXPECT_EQ(waitTime, jitterDelayMs); |
| 68 | |
| 69 | // 300 incoming frames without jitter, verify that this gives the exact wait |
| 70 | // time. |
| 71 | for (int i = 0; i < 300; i++) { |
| 72 | clock.AdvanceTimeMilliseconds(1000 / 25); |
| 73 | timeStamp += 90000 / 25; |
| 74 | timing.IncomingTimestamp(timeStamp, clock.TimeInMilliseconds()); |
| 75 | } |
| 76 | timing.UpdateCurrentDelay(timeStamp); |
| 77 | waitTime = timing.MaxWaitingTime( |
| 78 | timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds()), |
| 79 | clock.TimeInMilliseconds()); |
| 80 | EXPECT_EQ(waitTime, jitterDelayMs); |
| 81 | |
| 82 | // Add decode time estimates. |
| 83 | for (int i = 0; i < 10; i++) { |
| 84 | int64_t startTimeMs = clock.TimeInMilliseconds(); |
| 85 | clock.AdvanceTimeMilliseconds(10); |
philipel | 288c2b6 | 2015-12-21 16:23:20 | [diff] [blame] | 86 | timing.StopDecodeTimer( |
| 87 | timeStamp, clock.TimeInMilliseconds() - startTimeMs, |
| 88 | clock.TimeInMilliseconds(), |
| 89 | timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds())); |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 90 | timeStamp += 90000 / 25; |
| 91 | clock.AdvanceTimeMilliseconds(1000 / 25 - 10); |
| 92 | timing.IncomingTimestamp(timeStamp, clock.TimeInMilliseconds()); |
| 93 | } |
magjed | 42c4e1a | 2016-03-22 12:12:09 | [diff] [blame] | 94 | requiredDecodeTimeMs = 10; |
mikhal@webrtc.org | e477574 | 2013-05-30 16:20:18 | [diff] [blame] | 95 | timing.SetJitterDelay(jitterDelayMs); |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 96 | clock.AdvanceTimeMilliseconds(1000); |
| 97 | timeStamp += 90000; |
| 98 | timing.UpdateCurrentDelay(timeStamp); |
| 99 | waitTime = timing.MaxWaitingTime( |
| 100 | timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds()), |
| 101 | clock.TimeInMilliseconds()); |
| 102 | EXPECT_EQ(waitTime, jitterDelayMs); |
| 103 | |
isheriff | 00cc045 | 2016-06-08 07:24:21 | [diff] [blame] | 104 | int minTotalDelayMs = 200; |
mikhal@webrtc.org | e477574 | 2013-05-30 16:20:18 | [diff] [blame] | 105 | timing.set_min_playout_delay(minTotalDelayMs); |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 106 | clock.AdvanceTimeMilliseconds(5000); |
philipel | 288c2b6 | 2015-12-21 16:23:20 | [diff] [blame] | 107 | timeStamp += 5 * 90000; |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 108 | timing.UpdateCurrentDelay(timeStamp); |
| 109 | const int kRenderDelayMs = 10; |
mikhal@webrtc.org | e477574 | 2013-05-30 16:20:18 | [diff] [blame] | 110 | timing.set_render_delay(kRenderDelayMs); |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 111 | waitTime = timing.MaxWaitingTime( |
| 112 | timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds()), |
| 113 | clock.TimeInMilliseconds()); |
| 114 | // We should at least have minTotalDelayMs - decodeTime (10) - renderTime |
| 115 | // (10) to wait. |
magjed | 42c4e1a | 2016-03-22 12:12:09 | [diff] [blame] | 116 | EXPECT_EQ(waitTime, minTotalDelayMs - requiredDecodeTimeMs - kRenderDelayMs); |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 117 | // The total video delay should be equal to the min total delay. |
| 118 | EXPECT_EQ(minTotalDelayMs, timing.TargetVideoDelay()); |
| 119 | |
mikhal@webrtc.org | e477574 | 2013-05-30 16:20:18 | [diff] [blame] | 120 | // Reset playout delay. |
| 121 | timing.set_min_playout_delay(0); |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 122 | clock.AdvanceTimeMilliseconds(5000); |
philipel | 288c2b6 | 2015-12-21 16:23:20 | [diff] [blame] | 123 | timeStamp += 5 * 90000; |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 124 | timing.UpdateCurrentDelay(timeStamp); |
| 125 | } |
| 126 | |
| 127 | TEST(ReceiverTiming, WrapAround) { |
| 128 | const int kFramerate = 25; |
| 129 | SimulatedClock clock(0); |
| 130 | VCMTiming timing(&clock); |
| 131 | // Provoke a wrap-around. The forth frame will have wrapped at 25 fps. |
| 132 | uint32_t timestamp = 0xFFFFFFFFu - 3 * 90000 / kFramerate; |
| 133 | for (int i = 0; i < 4; ++i) { |
| 134 | timing.IncomingTimestamp(timestamp, clock.TimeInMilliseconds()); |
| 135 | clock.AdvanceTimeMilliseconds(1000 / kFramerate); |
| 136 | timestamp += 90000 / kFramerate; |
philipel | 288c2b6 | 2015-12-21 16:23:20 | [diff] [blame] | 137 | int64_t render_time = |
| 138 | timing.RenderTimeMs(0xFFFFFFFFu, clock.TimeInMilliseconds()); |
stefan@webrtc.org | c7979e0 | 2013-05-17 12:55:07 | [diff] [blame] | 139 | EXPECT_EQ(3 * 1000 / kFramerate, render_time); |
| 140 | render_time = timing.RenderTimeMs(89u, // One second later in 90 kHz. |
| 141 | clock.TimeInMilliseconds()); |
| 142 | EXPECT_EQ(3 * 1000 / kFramerate + 1, render_time); |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | } // namespace webrtc |