Upload upstream chromium 69.0.3497
[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/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 = kCodecVorbis;
22 static const SampleFormat kSampleFormat = kSampleFormatPlanarF32;
23 static const base::TimeDelta kSeekPreroll;
24 static const int kSamplesPerSecond = 10000;
25 static const base::TimeDelta kBufferDuration =
26     base::TimeDelta::FromMilliseconds(20);
27 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
28 static const int kChannelCount = 2;
29 static const int kChannels = ChannelLayoutToChannelCount(kChannelLayout);
30 static const int kFramesPerBuffer = kBufferDuration.InMicroseconds() *
31                                     kSamplesPerSecond /
32                                     base::Time::kMicrosecondsPerSecond;
33
34 // Params are:
35 // 1. Output delay: number of encoded buffers before first decoded output
36 // 2. Codec delay: number of frames of codec delay in decoder config
37 // 3. Front discard: front discard for the first buffer
38 using ValidatorTestParams = testing::tuple<int, int, base::TimeDelta>;
39
40 class AudioTimestampValidatorTest
41     : public testing::Test,
42       public ::testing::WithParamInterface<ValidatorTestParams> {
43  public:
44   AudioTimestampValidatorTest() = default;
45
46  protected:
47   void SetUp() override {
48     output_delay_ = testing::get<0>(GetParam());
49     codec_delay_ = testing::get<1>(GetParam());
50     front_discard_ = testing::get<2>(GetParam());
51   }
52
53   int output_delay_;
54
55   int codec_delay_;
56
57   base::TimeDelta front_discard_;
58
59   testing::StrictMock<MockMediaLog> media_log_;
60 };
61
62 TEST_P(AudioTimestampValidatorTest, WarnForEraticTimes) {
63   AudioDecoderConfig decoder_config;
64   decoder_config.Initialize(kCodec, kSampleFormat, kChannelLayout,
65                             kSamplesPerSecond, EmptyExtraData(), Unencrypted(),
66                             kSeekPreroll, 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[] = {
80       base::TimeDelta::FromMilliseconds(100),
81       base::TimeDelta::FromMilliseconds(350)};
82
83   for (int i = 0; i < 100; ++i) {
84     // Each buffer's timestamp is kBufferDuration from the previous buffer.
85     scoped_refptr<DecoderBuffer> encoded_buffer = new DecoderBuffer(0);
86
87     // Ping-pong between two random offsets to prevent validator from
88     // stabilizing timestamp pattern.
89     base::TimeDelta randomOffset =
90         kRandomOffsets[i % arraysize(kRandomOffsets)];
91     encoded_buffer->set_timestamp(i * kBufferDuration + randomOffset);
92
93     if (i == 0) {
94       encoded_buffer->set_discard_padding(
95           std::make_pair(front_discard_, base::TimeDelta()));
96     }
97
98     validator.CheckForTimestampGap(*encoded_buffer);
99
100     if (i >= output_delay_) {
101       // kFramesPerBuffer is derived to perfectly match kBufferDuration, so
102       // no gaps exists as long as timestamps are exactly kBufferDuration apart.
103       scoped_refptr<AudioBuffer> decoded_buffer = MakeAudioBuffer<float>(
104           kSampleFormat, kChannelLayout, kChannelCount, kSamplesPerSecond, 1.0f,
105           0.0f, kFramesPerBuffer, i * kBufferDuration);
106       validator.RecordOutputDuration(decoded_buffer.get());
107     }
108   }
109 }
110
111 TEST_P(AudioTimestampValidatorTest, NoWarningForValidTimes) {
112   AudioDecoderConfig decoder_config;
113   decoder_config.Initialize(kCodec, kSampleFormat, kChannelLayout,
114                             kSamplesPerSecond, EmptyExtraData(), Unencrypted(),
115                             kSeekPreroll, 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     scoped_refptr<DecoderBuffer> encoded_buffer = new 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.get());
146     }
147   }
148 }
149
150 TEST_P(AudioTimestampValidatorTest, SingleWarnForSingleLargeGap) {
151   AudioDecoderConfig decoder_config;
152   decoder_config.Initialize(kCodec, kSampleFormat, kChannelLayout,
153                             kSamplesPerSecond, EmptyExtraData(), Unencrypted(),
154                             kSeekPreroll, codec_delay_);
155
156   AudioTimestampValidator validator(decoder_config, &media_log_);
157
158   // Validator should quickly stabilize pattern for timestamp expectations.
159   EXPECT_MEDIA_LOG(HasSubstr("Failed to reconcile encoded audio times "
160                              "with decoded output."))
161       .Times(0);
162
163   for (int i = 0; i < 100; ++i) {
164     // Halfway through the stream, introduce sudden gap of 50 milliseconds.
165     base::TimeDelta offset;
166     if (i >= 50)
167       offset = base::TimeDelta::FromMilliseconds(100);
168
169     // This gap never widens, so expect only a single warning when its first
170     // introduced.
171     if (i == 50)
172       EXPECT_MEDIA_LOG(HasSubstr("timestamp gap detected"));
173
174     scoped_refptr<DecoderBuffer> encoded_buffer = new DecoderBuffer(0);
175     encoded_buffer->set_timestamp(i * kBufferDuration + offset);
176
177     if (i == 0) {
178       encoded_buffer->set_discard_padding(
179           std::make_pair(front_discard_, base::TimeDelta()));
180     }
181
182     validator.CheckForTimestampGap(*encoded_buffer);
183
184     if (i >= output_delay_) {
185       // kFramesPerBuffer is derived to perfectly match kBufferDuration, so
186       // no gaps exists as long as timestamps are exactly kBufferDuration apart.
187       scoped_refptr<AudioBuffer> decoded_buffer = MakeAudioBuffer<float>(
188           kSampleFormat, kChannelLayout, kChannelCount, kSamplesPerSecond, 1.0f,
189           0.0f, kFramesPerBuffer, i * kBufferDuration);
190       validator.RecordOutputDuration(decoded_buffer.get());
191     }
192   }
193 }
194
195 TEST_P(AudioTimestampValidatorTest, RepeatedWarnForSlowAccumulatingDrift) {
196   AudioDecoderConfig decoder_config;
197   decoder_config.Initialize(kCodec, kSampleFormat, kChannelLayout,
198                             kSamplesPerSecond, EmptyExtraData(), Unencrypted(),
199                             kSeekPreroll, codec_delay_);
200
201   AudioTimestampValidator validator(decoder_config, &media_log_);
202
203   EXPECT_MEDIA_LOG(HasSubstr("Failed to reconcile encoded audio times "
204                              "with decoded output."))
205       .Times(0);
206
207   int num_timestamp_gap_warnings = 0;
208   const int kMaxTimestampGapWarnings = 10;  // Must be the same as in .cc
209
210   for (int i = 0; i < 100; ++i) {
211     // Wait for delayed output to begin plus an additional two iterations to
212     // start using drift offset. The the two iterations without offset will
213     // allow the validator to stabilize the pattern of timestamps and begin
214     // checking for gaps. Once stable, increase offset by 1 millisecond for each
215     // iteration.
216     base::TimeDelta offset;
217     if (i >= output_delay_ + 2)
218       offset = i * base::TimeDelta::FromMilliseconds(1);
219
220     scoped_refptr<DecoderBuffer> encoded_buffer = new DecoderBuffer(0);
221     encoded_buffer->set_timestamp((i * kBufferDuration) + offset);
222
223     // Expect gap warnings to start when drift hits 50 milliseconds. Warnings
224     // should continue as the gap widens until log limit is hit.
225
226     if (offset > base::TimeDelta::FromMilliseconds(50)) {
227       EXPECT_LIMITED_MEDIA_LOG(HasSubstr("timestamp gap detected"),
228                                num_timestamp_gap_warnings,
229                                kMaxTimestampGapWarnings);
230     }
231
232     validator.CheckForTimestampGap(*encoded_buffer);
233
234     if (i >= output_delay_) {
235       // kFramesPerBuffer is derived to perfectly match kBufferDuration, so
236       // no gaps exists as long as timestamps are exactly kBufferDuration apart.
237       scoped_refptr<AudioBuffer> decoded_buffer = MakeAudioBuffer<float>(
238           kSampleFormat, kChannelLayout, kChannelCount, kSamplesPerSecond, 1.0f,
239           0.0f, kFramesPerBuffer, i * kBufferDuration);
240       validator.RecordOutputDuration(decoded_buffer.get());
241     }
242   }
243 }
244
245 // Test with cartesian product of various output delay, codec delay, and front
246 // discard values. These simulate configurations for different containers/codecs
247 // which present different challenges when building timestamp expectations.
248 INSTANTIATE_TEST_CASE_P(
249     ,
250     AudioTimestampValidatorTest,
251     ::testing::Combine(
252         ::testing::Values(0, 10),             // output delay
253         ::testing::Values(0, 512),            // codec delay
254         ::testing::Values(base::TimeDelta(),  // front discard
255                           base::TimeDelta::FromMilliseconds(65))));
256
257 }  // namespace media