1*b9df5ad1SAndroid Build Coastguard Worker /*
2*b9df5ad1SAndroid Build Coastguard Worker * Copyright 2018 The Android Open Source Project
3*b9df5ad1SAndroid Build Coastguard Worker *
4*b9df5ad1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*b9df5ad1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*b9df5ad1SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*b9df5ad1SAndroid Build Coastguard Worker *
8*b9df5ad1SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*b9df5ad1SAndroid Build Coastguard Worker *
10*b9df5ad1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*b9df5ad1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*b9df5ad1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b9df5ad1SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*b9df5ad1SAndroid Build Coastguard Worker * limitations under the License.
15*b9df5ad1SAndroid Build Coastguard Worker */
16*b9df5ad1SAndroid Build Coastguard Worker
17*b9df5ad1SAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*b9df5ad1SAndroid Build Coastguard Worker #define LOG_TAG "audio_utils_timestampverifier_tests"
19*b9df5ad1SAndroid Build Coastguard Worker
20*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/TimestampVerifier.h>
21*b9df5ad1SAndroid Build Coastguard Worker
22*b9df5ad1SAndroid Build Coastguard Worker #include <stdio.h>
23*b9df5ad1SAndroid Build Coastguard Worker #include <gtest/gtest.h>
24*b9df5ad1SAndroid Build Coastguard Worker
25*b9df5ad1SAndroid Build Coastguard Worker // Ensure that all TimestampVerifier mutators are really constexpr and free from
26*b9df5ad1SAndroid Build Coastguard Worker // nasty system calls (in case called from a SCHED_FIFO thread).
makeVerifier(size_t N,uint32_t sampleRate,size_t errors,size_t discontinuities)27*b9df5ad1SAndroid Build Coastguard Worker static constexpr auto makeVerifier(
28*b9df5ad1SAndroid Build Coastguard Worker size_t N, uint32_t sampleRate, size_t errors, size_t discontinuities) {
29*b9df5ad1SAndroid Build Coastguard Worker android::TimestampVerifier<int64_t, int64_t> tv;
30*b9df5ad1SAndroid Build Coastguard Worker
31*b9df5ad1SAndroid Build Coastguard Worker int64_t f = 0;
32*b9df5ad1SAndroid Build Coastguard Worker int64_t t = 0;
33*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < N; ++i) {
34*b9df5ad1SAndroid Build Coastguard Worker tv.add(f, t, sampleRate);
35*b9df5ad1SAndroid Build Coastguard Worker f += sampleRate;
36*b9df5ad1SAndroid Build Coastguard Worker t += (int64_t)1e9;
37*b9df5ad1SAndroid Build Coastguard Worker }
38*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < discontinuities; ++i) {
39*b9df5ad1SAndroid Build Coastguard Worker tv.discontinuity(tv.DISCONTINUITY_MODE_CONTINUOUS);
40*b9df5ad1SAndroid Build Coastguard Worker }
41*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < errors; ++i) {
42*b9df5ad1SAndroid Build Coastguard Worker tv.error();
43*b9df5ad1SAndroid Build Coastguard Worker }
44*b9df5ad1SAndroid Build Coastguard Worker return tv;
45*b9df5ad1SAndroid Build Coastguard Worker }
46*b9df5ad1SAndroid Build Coastguard Worker
TEST(TimestampVerifier,sanity)47*b9df5ad1SAndroid Build Coastguard Worker TEST(TimestampVerifier, sanity)
48*b9df5ad1SAndroid Build Coastguard Worker {
49*b9df5ad1SAndroid Build Coastguard Worker constexpr android::TimestampVerifier<int64_t, int64_t> tv;
50*b9df5ad1SAndroid Build Coastguard Worker
51*b9df5ad1SAndroid Build Coastguard Worker // The timestamp verifier must be embeddable in a memcpy structure just like pod.
52*b9df5ad1SAndroid Build Coastguard Worker // We use is_trivially_copyable and is_trivially_destructible for this test.
53*b9df5ad1SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<decltype(tv)>::value,
54*b9df5ad1SAndroid Build Coastguard Worker "TimestampVerifier must be trivially copyable");
55*b9df5ad1SAndroid Build Coastguard Worker static_assert(std::is_trivially_destructible<decltype(tv)>::value,
56*b9df5ad1SAndroid Build Coastguard Worker "TimestampVerifier must be trivially destructible");
57*b9df5ad1SAndroid Build Coastguard Worker
58*b9df5ad1SAndroid Build Coastguard Worker constexpr android::audio_utils::Statistics<double> s = tv.getJitterMs();
59*b9df5ad1SAndroid Build Coastguard Worker
60*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(std::numeric_limits<double>::infinity(), s.getMin());
61*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(-std::numeric_limits<double>::infinity(), s.getMax());
62*b9df5ad1SAndroid Build Coastguard Worker
63*b9df5ad1SAndroid Build Coastguard Worker constexpr int64_t frames[] { 0, 48000 };
64*b9df5ad1SAndroid Build Coastguard Worker constexpr int64_t timeNs[] { 0, 1000000000 };
65*b9df5ad1SAndroid Build Coastguard Worker constexpr android::TimestampVerifier<int64_t, int64_t> tv2(frames, timeNs, 48000);
66*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0., tv2.getJitterMs().getMax());
67*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0., tv2.getJitterMs().getMin());
68*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0., tv2.getJitterMs().getMean());
69*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(1, tv2.getJitterMs().getN());
70*b9df5ad1SAndroid Build Coastguard Worker
71*b9df5ad1SAndroid Build Coastguard Worker // We should get a perfect straight line estimate as there is no noise.
72*b9df5ad1SAndroid Build Coastguard Worker double a, b, r2;
73*b9df5ad1SAndroid Build Coastguard Worker tv2.estimateSampleRate(a, b, r2);
74*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0., a);
75*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(48000., b);
76*b9df5ad1SAndroid Build Coastguard Worker EXPECT_NEAR(1., r2, std::numeric_limits<double>::epsilon());
77*b9df5ad1SAndroid Build Coastguard Worker
78*b9df5ad1SAndroid Build Coastguard Worker constexpr android::TimestampVerifier<int64_t, int64_t> tv3 =
79*b9df5ad1SAndroid Build Coastguard Worker makeVerifier(8 /* N */, 48000 /* sampleRate */, 10 /* errors */, 10 /* disc */);
80*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(8, tv3.getN());
81*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(10, tv3.getErrors());
82*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(1, tv3.getDiscontinuities()); // consecutive discontinuities read as 1.
83*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0., tv3.getJitterMs().getMax());
84*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0., tv3.getJitterMs().getMin());
85*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0., tv3.getJitterMs().getMean());
86*b9df5ad1SAndroid Build Coastguard Worker
87*b9df5ad1SAndroid Build Coastguard Worker constexpr auto first = tv3.getFirstTimestamp();
88*b9df5ad1SAndroid Build Coastguard Worker constexpr auto last = tv3.getLastTimestamp();
89*b9df5ad1SAndroid Build Coastguard Worker
90*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, first.mFrames);
91*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, first.mTimeNs);
92*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(48000 * (8 - 1), last.mFrames);
93*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((int64_t)1e9 * (8 - 1), last.mTimeNs);
94*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((uint32_t)48000, tv3.getSampleRate());
95*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, tv3.getColds());
96*b9df5ad1SAndroid Build Coastguard Worker
97*b9df5ad1SAndroid Build Coastguard Worker tv3.estimateSampleRate(a, b, r2);
98*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0., a);
99*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(48000., b);
100*b9df5ad1SAndroid Build Coastguard Worker EXPECT_NEAR(1., r2, std::numeric_limits<double>::epsilon());
101*b9df5ad1SAndroid Build Coastguard Worker }
102*b9df5ad1SAndroid Build Coastguard Worker
TEST(TimestampVerifier,discontinuity_zero)103*b9df5ad1SAndroid Build Coastguard Worker TEST(TimestampVerifier, discontinuity_zero)
104*b9df5ad1SAndroid Build Coastguard Worker {
105*b9df5ad1SAndroid Build Coastguard Worker android::TimestampVerifier<int64_t, int64_t> tv;
106*b9df5ad1SAndroid Build Coastguard Worker
107*b9df5ad1SAndroid Build Coastguard Worker // Add timestamps advancing at normal rate over 2 seconds
108*b9df5ad1SAndroid Build Coastguard Worker tv.add(0, 0, 48000);
109*b9df5ad1SAndroid Build Coastguard Worker tv.add(48000, 1000000000, 48000);
110*b9df5ad1SAndroid Build Coastguard Worker tv.add(96000, 2000000000, 48000);
111*b9df5ad1SAndroid Build Coastguard Worker
112*b9df5ad1SAndroid Build Coastguard Worker // Raise (mode zero) discontinuity at "3 seconds"
113*b9df5ad1SAndroid Build Coastguard Worker tv.discontinuity(tv.DISCONTINUITY_MODE_ZERO);
114*b9df5ad1SAndroid Build Coastguard Worker // Add timestamp where frame count has reset to zero (and not advancing)
115*b9df5ad1SAndroid Build Coastguard Worker tv.add(0, 3000000000, 48000);
116*b9df5ad1SAndroid Build Coastguard Worker
117*b9df5ad1SAndroid Build Coastguard Worker // The last corrected timestamp after discontinuity (mode zero) should be zeroed
118*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0., tv.getLastCorrectedTimestamp().mFrames);
119*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(3000000000., tv.getLastCorrectedTimestamp().mTimeNs);
120*b9df5ad1SAndroid Build Coastguard Worker
121*b9df5ad1SAndroid Build Coastguard Worker // Add timestamp where frame count has not advanced from zero, but time has advanced 100 ms more
122*b9df5ad1SAndroid Build Coastguard Worker tv.add(0, 3100000000, 48000);
123*b9df5ad1SAndroid Build Coastguard Worker
124*b9df5ad1SAndroid Build Coastguard Worker // The last corrected frame should be the raw timestamp if not advancing at normal rate
125*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0., tv.getLastCorrectedTimestamp().mFrames);
126*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(3100000000., tv.getLastCorrectedTimestamp().mTimeNs);
127*b9df5ad1SAndroid Build Coastguard Worker
128*b9df5ad1SAndroid Build Coastguard Worker // Add imperfect normal advancing timestamps
129*b9df5ad1SAndroid Build Coastguard Worker tv.add(48000*0.9, 4100000000*1.1, 48000);
130*b9df5ad1SAndroid Build Coastguard Worker tv.add(96000*1.1, 5100000000*0.9, 48000);
131*b9df5ad1SAndroid Build Coastguard Worker
132*b9df5ad1SAndroid Build Coastguard Worker // Last corrected timestamp frame count should not be raw (or zero) as timestamps are now
133*b9df5ad1SAndroid Build Coastguard Worker // advancing at a (imperfect) normal rate (but the time should, as implementation uses frame
134*b9df5ad1SAndroid Build Coastguard Worker // rather than time correction).
135*b9df5ad1SAndroid Build Coastguard Worker EXPECT_NE(0, tv.getLastCorrectedTimestamp().mFrames);
136*b9df5ad1SAndroid Build Coastguard Worker EXPECT_NE(96000*1.1, tv.getLastCorrectedTimestamp().mFrames);
137*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(5100000000*0.9, tv.getLastCorrectedTimestamp().mTimeNs);
138*b9df5ad1SAndroid Build Coastguard Worker }
139