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