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