xref: /aosp_15_r20/system/media/audio_utils/tests/timestampverifier_tests.cpp (revision b9df5ad1c9ac98a7fefaac271a55f7ae3db05414)
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