Upload upstream chromium 114.0.5735.31
[platform/framework/web/chromium-efl.git] / media / filters / audio_timestamp_validator_unittest.cc
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/filters/audio_timestamp_validator.h"
6
7 #include <tuple>
8
9 #include "base/time/time.h"
10 #include "media/base/audio_decoder_config.h"
11 #include "media/base/media_util.h"
12 #include "media/base/mock_media_log.h"
13 #include "media/base/test_helpers.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 using ::testing::HasSubstr;
17
18 namespace media {
19
20 // Constants to specify the type of audio data used.
21 static const AudioCodec kCodec = AudioCodec::kVorbis;
22 static const SampleFormat kSampleFormat = kSampleFormatPlanarF32;
23 static const base::TimeDelta kSeekPreroll;
24 static const int kSamplesPerSecond = 10000;
25 static const base::TimeDelta kBufferDuration = base::Milliseconds(20);
26 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
27 static const int kChannelCount = 2;
28 static const int kChannels = ChannelLayoutToChannelCount(kChannelLayout);
29 static const int kFramesPerBuffer = kBufferDuration.InMicroseconds() *
30                                     kSamplesPerSecond /
31                                     base::Time::kMicrosecondsPerSecond;
32
33 // Params are:
34 // 1. Output delay: number of encoded buffers before first decoded output
35 // 2. Codec delay: number of frames of codec delay in decoder config
36 // 3. Front discard: front discard for the first buffer
37 using ValidatorTestParams = testing::tuple<int, int, base::TimeDelta>;
38
39 class AudioTimestampValidatorTest
40     : public testing::Test,
41       public ::testing::WithParamInterface<ValidatorTestParams> {
42  public:
43   AudioTimestampValidatorTest() = default;
44
45  protected:
46   void SetUp() override {
47     output_delay_ = testing::get<0>(GetParam());
48     codec_delay_ = testing::get<1>(GetParam());
49     front_discard_ = testing::get<2>(GetParam());
50   }
51
52   int output_delay_;
53
54   int codec_delay_;
55
56   base::TimeDelta front_discard_;
57
58   testing::StrictMock<MockMediaLog> media_log_;
59 };
60
61 TEST_P(AudioTimestampValidatorTest, WarnForEraticTimes) {
62   AudioDecoderConfig decoder_config;
63   decoder_config.Initialize(kCodec, kSampleFormat, kChannelLayout,
64                             kSamplesPerSecond, EmptyExtraData(),
65                             EncryptionScheme::kUnencrypted, kSeekPreroll,
66                             codec_delay_);
67
68   // Validator should fail to stabilize pattern for timestamp expectations.
69   EXPECT_MEDIA_LOG(
70       HasSubstr("Failed to reconcile encoded audio times "
71                 "with decoded output."));
72
73   // No gap warnings should be emitted because the timestamps expectations never
74   // stabilized.
75   EXPECT_MEDIA_LOG(HasSubstr("timestamp gap detected")).Times(0);
76
77   AudioTimestampValidator validator(decoder_config, &media_log_);
78
79   const base::TimeDelta kRandomOffsets[] = {base::Milliseconds(100),
80                                             base::Milliseconds(350)};
81
82   for (int i = 0; i < 100; ++i) {
83     // Each buffer's timestamp is kBufferDuration from the previous buffer.
84     auto encoded_buffer = base::MakeRefCounted<DecoderBuffer>(0);
85
86     // Ping-pong between two random offsets to prevent validator from
87     // stabilizing timestamp pattern.
88     base::TimeDelta randomOffset =
89         kRandomOffsets[i % std::size(kRandomOffsets)];
90     encoded_buffer->set_timestamp(i * kBufferDuration + randomOffset);
91
92     if (i == 0) {
93       encoded_buffer->set_discard_padding(
94           std::make_pair(front_discard_, base::TimeDelta()));
95     }
96
97     validator.CheckForTimestampGap(*encoded_buffer);
98
99     if (i >= output_delay_) {
100       // kFramesPerBuffer is derived to perfectly match kBufferDuration, so
101       // no gaps exists as long as timestamps are exactly kBufferDuration apart.
102       scoped_refptr<AudioBuffer> decoded_buffer = MakeAudioBuffer<float>(
103           kSampleFormat, kChannelLayout, kChannelCount, kSamplesPerSecond, 1.0f,
104           0.0f, kFramesPerBuffer, i * kBufferDuration);
105       validator.RecordOutputDuration(*decoded_buffer);
106     }
107   }
108 }
109
110 TEST_P(AudioTimestampValidatorTest, NoWarningForValidTimes) {
111   AudioDecoderConfig decoder_config;
112   decoder_config.Initialize(kCodec, kSampleFormat, kChannelLayout,
113                             kSamplesPerSecond, EmptyExtraData(),
114                             EncryptionScheme::kUnencrypted, kSeekPreroll,
115                             codec_delay_);
116
117   // Validator should quickly stabilize pattern for timestamp expectations.
118   EXPECT_MEDIA_LOG(HasSubstr("Failed to reconcile encoded audio times "
119                              "with decoded output."))
120       .Times(0);
121
122   // Expect no gap warnings for series of buffers with valid timestamps.
123   EXPECT_MEDIA_LOG(HasSubstr("timestamp gap detected")).Times(0);
124
125   AudioTimestampValidator validator(decoder_config, &media_log_);
126
127   for (int i = 0; i < 100; ++i) {
128     // Each buffer's timestamp is kBufferDuration from the previous buffer.
129     auto encoded_buffer = base::MakeRefCounted<DecoderBuffer>(0);
130     encoded_buffer->set_timestamp(i * kBufferDuration);
131
132     if (i == 0) {
133       encoded_buffer->set_discard_padding(
134           std::make_pair(front_discard_, base::TimeDelta()));
135     }
136
137     validator.CheckForTimestampGap(*encoded_buffer);
138
139     if (i >= output_delay_) {
140       // kFramesPerBuffer is derived to perfectly match kBufferDuration, so
141       // no gaps exists as long as timestamps are exactly kBufferDuration apart.
142       scoped_refptr<AudioBuffer> decoded_buffer = MakeAudioBuffer<float>(
143           kSampleFormat, kChannelLayout, kChannelCount, kSamplesPerSecond, 1.0f,
144           0.0f, kFramesPerBuffer, i * kBufferDuration);
145       validator.RecordOutputDuration(*decoded_buffer);
146     }
147   }
148 }
149
150 TEST_P(AudioTimestampValidatorTest, SingleWarnForSingleLargeGap) {
151   AudioDecoderConfig decoder_config;
152   decoder_config.Initialize(kCodec, kSampleFormat, kChannelLayout,
153                             kSamplesPerSecond, EmptyExtraData(),
154                             EncryptionScheme::kUnencrypted, kSeekPreroll,
155                             codec_delay_);
156
157   AudioTimestampValidator validator(decoder_config, &media_log_);
158
159   // Validator should quickly stabilize pattern for timestamp expectations.
160   EXPECT_MEDIA_LOG(HasSubstr("Failed to reconcile encoded audio times "
161                              "with decoded output."))
162       .Times(0);
163
164   for (int i = 0; i < 100; ++i) {
165     // Halfway through the stream, introduce sudden gap of 50 milliseconds.
166     base::TimeDelta offset;
167     if (i >= 50)
168       offset = base::Milliseconds(100);
169
170     // This gap never widens, so expect only a single warning when its first
171     // introduced.
172     if (i == 50)
173       EXPECT_MEDIA_LOG(HasSubstr("timestamp gap detected"));
174
175     auto encoded_buffer = base::MakeRefCounted<DecoderBuffer>(0);
176     encoded_buffer->set_timestamp(i * kBufferDuration + offset);
177
178     if (i == 0) {
179       encoded_buffer->set_discard_padding(
180           std::make_pair(front_discard_, base::TimeDelta()));
181     }
182
183     validator.CheckForTimestampGap(*encoded_buffer);
184
185     if (i >= output_delay_) {
186       // kFramesPerBuffer is derived to perfectly match kBufferDuration, so
187       // no gaps exists as long as timestamps are exactly kBufferDuration apart.
188       scoped_refptr<AudioBuffer> decoded_buffer = MakeAudioBuffer<float>(
189           kSampleFormat, kChannelLayout, kChannelCount, kSamplesPerSecond, 1.0f,
190           0.0f, kFramesPerBuffer, i * kBufferDuration);
191       validator.RecordOutputDuration(*decoded_buffer);
192     }
193   }
194 }
195
196 TEST_P(AudioTimestampValidatorTest, RepeatedWarnForSlowAccumulatingDrift) {
197   AudioDecoderConfig decoder_config;
198   decoder_config.Initialize(kCodec, kSampleFormat, kChannelLayout,
199                             kSamplesPerSecond, EmptyExtraData(),
200                             EncryptionScheme::kUnencrypted, kSeekPreroll,
201                             codec_delay_);
202
203   AudioTimestampValidator validator(decoder_config, &media_log_);
204
205   EXPECT_MEDIA_LOG(HasSubstr("Failed to reconcile encoded audio times "
206                              "with decoded output."))
207       .Times(0);
208
209   int num_timestamp_gap_warnings = 0;
210   const int kMaxTimestampGapWarnings = 10;  // Must be the same as in .cc
211
212   for (int i = 0; i < 100; ++i) {
213     // Wait for delayed output to begin plus an additional two iterations to
214     // start using drift offset. The the two iterations without offset will
215     // allow the validator to stabilize the pattern of timestamps and begin
216     // checking for gaps. Once stable, increase offset by 1 millisecond for each
217     // iteration.
218     base::TimeDelta offset;
219     if (i >= output_delay_ + 2)
220       offset = i * base::Milliseconds(1);
221
222     auto encoded_buffer = base::MakeRefCounted<DecoderBuffer>(0);
223     encoded_buffer->set_timestamp((i * kBufferDuration) + offset);
224
225     // Expect gap warnings to start when drift hits 50 milliseconds. Warnings
226     // should continue as the gap widens until log limit is hit.
227
228     if (offset > base::Milliseconds(50)) {
229       EXPECT_LIMITED_MEDIA_LOG(HasSubstr("timestamp gap detected"),
230                                num_timestamp_gap_warnings,
231                                kMaxTimestampGapWarnings);
232     }
233
234     validator.CheckForTimestampGap(*encoded_buffer);
235
236     if (i >= output_delay_) {
237       // kFramesPerBuffer is derived to perfectly match kBufferDuration, so
238       // no gaps exists as long as timestamps are exactly kBufferDuration apart.
239       scoped_refptr<AudioBuffer> decoded_buffer = MakeAudioBuffer<float>(
240           kSampleFormat, kChannelLayout, kChannelCount, kSamplesPerSecond, 1.0f,
241           0.0f, kFramesPerBuffer, i * kBufferDuration);
242       validator.RecordOutputDuration(*decoded_buffer);
243     }
244   }
245 }
246
247 // Test with cartesian product of various output delay, codec delay, and front
248 // discard values. These simulate configurations for different containers/codecs
249 // which present different challenges when building timestamp expectations.
250 INSTANTIATE_TEST_SUITE_P(
251     All,
252     AudioTimestampValidatorTest,
253     ::testing::Combine(::testing::Values(0, 10),             // output delay
254                        ::testing::Values(0, 512),            // codec delay
255                        ::testing::Values(base::TimeDelta(),  // front discard
256                                          base::Milliseconds(65))));
257
258 }  // namespace media