OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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 <deque> | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/format_macros.h" | |
9 #include "base/md5.h" | |
10 #include "base/message_loop/message_loop.h" | |
11 #include "base/run_loop.h" | |
12 #include "base/strings/stringprintf.h" | |
13 #include "base/sys_byteorder.h" | |
14 #include "build/build_config.h" | |
15 #include "media/base/audio_buffer.h" | |
16 #include "media/base/audio_bus.h" | |
17 #include "media/base/audio_hash.h" | |
18 #include "media/base/decoder_buffer.h" | |
19 #include "media/base/test_data_util.h" | |
20 #include "media/base/test_helpers.h" | |
21 #include "media/ffmpeg/ffmpeg_common.h" | |
22 #include "media/filters/audio_file_reader.h" | |
23 #include "media/filters/ffmpeg_audio_decoder.h" | |
24 #include "media/filters/in_memory_url_protocol.h" | |
25 #include "media/filters/opus_audio_decoder.h" | |
26 #include "testing/gtest/include/gtest/gtest.h" | |
27 | |
28 namespace media { | |
29 | |
30 // The number of packets to read and then decode from each file. | |
31 static const size_t kDecodeRuns = 3; | |
32 | |
33 enum AudioDecoderType { | |
34 FFMPEG, | |
35 OPUS, | |
36 }; | |
37 | |
38 struct DecodedBufferExpectations { | |
39 const int64 timestamp; | |
40 const int64 duration; | |
41 const char* hash; | |
42 }; | |
43 | |
44 struct DecoderTestData { | |
45 const AudioDecoderType decoder_type; | |
46 const AudioCodec codec; | |
47 const char* filename; | |
48 const DecodedBufferExpectations* expectations; | |
49 const int first_packet_pts; | |
50 const int samples_per_second; | |
51 const ChannelLayout channel_layout; | |
52 }; | |
53 | |
54 // Tells gtest how to print our DecoderTestData structure. | |
55 std::ostream& operator<<(std::ostream& os, const DecoderTestData& data) { | |
56 return os << data.filename; | |
57 } | |
58 | |
59 // Marks negative timestamp buffers for discard or transfers FFmpeg's built in | |
60 // discard metadata in favor of setting DiscardPadding on the DecoderBuffer. | |
61 // Allows better testing of AudioDiscardHelper usage. | |
62 static void SetDiscardPadding(AVPacket* packet, | |
wolenetz
2014/06/19 20:56:47
nit: as mentioned offline, this looks similar to w
DaleCurtis
2014/06/20 01:17:57
Leaving here as its different enough that lifting
| |
63 const scoped_refptr<DecoderBuffer> buffer, | |
64 double samples_per_second) { | |
65 // Discard negative timestamps. | |
66 if (buffer->timestamp() + buffer->duration() < base::TimeDelta()) { | |
67 buffer->set_discard_padding( | |
68 std::make_pair(kInfiniteDuration(), base::TimeDelta())); | |
69 return; | |
70 } | |
71 if (buffer->timestamp() < base::TimeDelta()) { | |
72 buffer->set_discard_padding( | |
73 std::make_pair(-buffer->timestamp(), base::TimeDelta())); | |
74 return; | |
75 } | |
76 | |
77 // If the timestamp is positive, try to use FFmpeg's discard data. | |
78 int skip_samples_size = 0; | |
79 const uint32* skip_samples_ptr = | |
80 reinterpret_cast<const uint32*>(av_packet_get_side_data( | |
81 packet, AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size)); | |
82 if (skip_samples_size < 4) | |
wolenetz
2014/06/19 20:56:47
nit: why just 4 here, versus 10 in ffmpegdemuxer?
DaleCurtis
2014/06/20 01:17:57
We only use the skip_samples and not the discard e
| |
83 return; | |
84 buffer->set_discard_padding(std::make_pair( | |
85 base::TimeDelta::FromSecondsD(base::ByteSwapToLE32(*skip_samples_ptr) / | |
86 samples_per_second), | |
87 base::TimeDelta())); | |
88 } | |
89 | |
90 class AudioDecoderTest : public testing::TestWithParam<DecoderTestData> { | |
91 public: | |
92 AudioDecoderTest() | |
93 : pending_decode_(false), | |
94 pending_reset_(false), | |
95 last_decode_status_(AudioDecoder::kDecodeError) { | |
96 switch (GetParam().decoder_type) { | |
97 case FFMPEG: | |
98 decoder_.reset(new FFmpegAudioDecoder( | |
99 message_loop_.message_loop_proxy(), LogCB())); | |
100 break; | |
101 case OPUS: | |
102 decoder_.reset( | |
103 new OpusAudioDecoder(message_loop_.message_loop_proxy())); | |
104 break; | |
105 } | |
106 } | |
107 | |
108 virtual ~AudioDecoderTest() { | |
109 // Always issue a Stop() even if it's already been sent to avoid assertion | |
110 // failures causing crashes. | |
111 Stop(); | |
112 EXPECT_FALSE(pending_decode_); | |
113 EXPECT_FALSE(pending_reset_); | |
114 } | |
115 | |
116 protected: | |
117 void DecodeBuffer(const scoped_refptr<DecoderBuffer>& buffer) { | |
118 ASSERT_FALSE(pending_decode_); | |
119 pending_decode_ = true; | |
120 last_decode_status_ = AudioDecoder::kDecodeError; | |
121 decoder_->Decode( | |
122 buffer, | |
123 base::Bind(&AudioDecoderTest::DecodeFinished, base::Unretained(this))); | |
124 base::RunLoop().RunUntilIdle(); | |
125 ASSERT_FALSE(pending_decode_); | |
126 } | |
127 | |
128 void SendEndOfStream() { | |
129 DecodeBuffer(DecoderBuffer::CreateEOSBuffer()); | |
130 } | |
131 | |
132 void Initialize() { | |
133 // Load the test data file. | |
134 data_ = ReadTestDataFile(GetParam().filename); | |
135 protocol_.reset( | |
136 new InMemoryUrlProtocol(data_->data(), data_->data_size(), false)); | |
137 reader_.reset(new AudioFileReader(protocol_.get())); | |
138 ASSERT_TRUE(reader_->OpenDemuxerForTesting()); | |
139 | |
140 // Load the first packet and check its timestamp. | |
141 AVPacket packet; | |
142 ASSERT_TRUE(reader_->ReadPacketForTesting(&packet)); | |
143 EXPECT_EQ(GetParam().first_packet_pts, packet.pts); | |
144 start_timestamp_ = ConvertFromTimeBase( | |
145 reader_->GetAVStreamForTesting()->time_base, packet.pts); | |
146 av_free_packet(&packet); | |
147 | |
148 // Seek back to the beginning. | |
149 ASSERT_TRUE(reader_->SeekForTesting(start_timestamp_)); | |
150 | |
151 AudioDecoderConfig config; | |
152 AVCodecContextToAudioDecoderConfig( | |
153 reader_->codec_context_for_testing(), false, &config, false); | |
154 | |
155 EXPECT_EQ(GetParam().codec, config.codec()); | |
156 EXPECT_EQ(GetParam().samples_per_second, config.samples_per_second()); | |
157 EXPECT_EQ(GetParam().channel_layout, config.channel_layout()); | |
158 | |
159 InitializeDecoder(config); | |
160 } | |
161 | |
162 void InitializeDecoder(const AudioDecoderConfig& config) { | |
163 InitializeDecoderWithStatus(config, PIPELINE_OK); | |
164 } | |
165 | |
166 void InitializeDecoderWithStatus(const AudioDecoderConfig& config, | |
167 PipelineStatus status) { | |
168 decoder_->Initialize( | |
169 config, | |
170 NewExpectedStatusCB(status), | |
171 base::Bind(&AudioDecoderTest::OnDecoderOutput, base::Unretained(this))); | |
172 base::RunLoop().RunUntilIdle(); | |
173 } | |
174 | |
175 void Decode() { | |
176 AVPacket packet; | |
177 ASSERT_TRUE(reader_->ReadPacketForTesting(&packet)); | |
178 | |
179 // Split out packet metadata before making a copy. | |
180 av_packet_split_side_data(&packet); | |
181 | |
182 scoped_refptr<DecoderBuffer> buffer = | |
183 DecoderBuffer::CopyFrom(packet.data, packet.size); | |
184 buffer->set_timestamp(ConvertFromTimeBase( | |
185 reader_->GetAVStreamForTesting()->time_base, packet.pts)); | |
186 buffer->set_duration(ConvertFromTimeBase( | |
187 reader_->GetAVStreamForTesting()->time_base, packet.duration)); | |
188 | |
189 // Don't set discard padding for Opus, it already has discard behavior set | |
190 // based on the codec delay in the AudioDecoderConfig. | |
191 if (GetParam().decoder_type == FFMPEG) | |
192 SetDiscardPadding(&packet, buffer, GetParam().samples_per_second); | |
193 | |
194 // DecodeBuffer() shouldn't need the original packet since it uses the copy. | |
195 av_free_packet(&packet); | |
196 DecodeBuffer(buffer); | |
197 } | |
198 | |
199 void Reset() { | |
200 ASSERT_FALSE(pending_reset_); | |
201 pending_reset_ = true; | |
202 decoder_->Reset( | |
203 base::Bind(&AudioDecoderTest::ResetFinished, base::Unretained(this))); | |
204 base::RunLoop().RunUntilIdle(); | |
205 ASSERT_FALSE(pending_reset_); | |
206 } | |
207 | |
208 void Stop() { | |
209 decoder_->Stop(); | |
210 } | |
211 | |
212 void Seek(base::TimeDelta seek_time) { | |
213 Reset(); | |
214 decoded_audio_.clear(); | |
215 ASSERT_TRUE(reader_->SeekForTesting(seek_time)); | |
216 } | |
217 | |
218 void OnDecoderOutput(const scoped_refptr<AudioBuffer>& buffer) { | |
219 EXPECT_FALSE(buffer->end_of_stream()); | |
220 decoded_audio_.push_back(buffer); | |
221 } | |
222 | |
223 void DecodeFinished(AudioDecoder::Status status) { | |
224 EXPECT_TRUE(pending_decode_); | |
225 EXPECT_FALSE(pending_reset_); | |
226 pending_decode_ = false; | |
227 last_decode_status_ = status; | |
228 } | |
229 | |
230 void ResetFinished() { | |
231 EXPECT_TRUE(pending_reset_); | |
232 EXPECT_FALSE(pending_decode_); | |
233 pending_reset_ = false; | |
234 } | |
235 | |
236 // Generates an MD5 hash of the audio signal. Should not be used for checks | |
237 // across platforms as audio varies slightly across platforms. | |
238 std::string GetDecodedAudioMD5(size_t i) { | |
239 CHECK_LT(i, decoded_audio_.size()); | |
240 const scoped_refptr<AudioBuffer>& buffer = decoded_audio_[i]; | |
241 | |
242 scoped_ptr<AudioBus> output = | |
243 AudioBus::Create(buffer->channel_count(), buffer->frame_count()); | |
244 buffer->ReadFrames(buffer->frame_count(), 0, 0, output.get()); | |
245 | |
246 base::MD5Context context; | |
247 base::MD5Init(&context); | |
248 for (int ch = 0; ch < output->channels(); ++ch) { | |
249 base::MD5Update( | |
250 &context, | |
251 base::StringPiece(reinterpret_cast<char*>(output->channel(ch)), | |
252 output->frames() * sizeof(*output->channel(ch)))); | |
253 } | |
254 base::MD5Digest digest; | |
255 base::MD5Final(&digest, &context); | |
256 return base::MD5DigestToBase16(digest); | |
257 } | |
258 | |
259 void ExpectDecodedAudio(size_t i, const std::string& exact_hash) { | |
260 CHECK_LT(i, decoded_audio_.size()); | |
261 const scoped_refptr<AudioBuffer>& buffer = decoded_audio_[i]; | |
262 | |
263 const DecodedBufferExpectations& sample_info = GetParam().expectations[i]; | |
264 EXPECT_EQ(sample_info.timestamp, buffer->timestamp().InMicroseconds()); | |
265 EXPECT_EQ(sample_info.duration, buffer->duration().InMicroseconds()); | |
266 EXPECT_FALSE(buffer->end_of_stream()); | |
267 | |
268 scoped_ptr<AudioBus> output = | |
269 AudioBus::Create(buffer->channel_count(), buffer->frame_count()); | |
270 buffer->ReadFrames(buffer->frame_count(), 0, 0, output.get()); | |
271 | |
272 // Generate a lossy hash of the audio used for comparison across platforms. | |
273 AudioHash audio_hash; | |
274 audio_hash.Update(output.get(), output->frames()); | |
275 EXPECT_EQ(sample_info.hash, audio_hash.ToString()); | |
276 | |
277 if (!exact_hash.empty()) { | |
278 EXPECT_EQ(exact_hash, GetDecodedAudioMD5(i)); | |
279 | |
280 // Verify different hashes are being generated. None of our test data | |
281 // files have audio that hashes out exactly the same. | |
282 if (i > 0) | |
283 EXPECT_NE(exact_hash, GetDecodedAudioMD5(i - 1)); | |
284 } | |
285 } | |
286 | |
287 size_t decoded_audio_size() const { return decoded_audio_.size(); } | |
288 base::TimeDelta start_timestamp() const { return start_timestamp_; } | |
289 const scoped_refptr<AudioBuffer>& decoded_audio(size_t i) { | |
290 return decoded_audio_[i]; | |
291 } | |
292 AudioDecoder::Status last_decode_status() const { | |
293 return last_decode_status_; | |
294 } | |
295 | |
296 private: | |
297 base::MessageLoop message_loop_; | |
298 scoped_refptr<DecoderBuffer> data_; | |
299 scoped_ptr<InMemoryUrlProtocol> protocol_; | |
300 scoped_ptr<AudioFileReader> reader_; | |
301 | |
302 scoped_ptr<AudioDecoder> decoder_; | |
303 bool pending_decode_; | |
304 bool pending_reset_; | |
305 AudioDecoder::Status last_decode_status_; | |
306 | |
307 std::deque<scoped_refptr<AudioBuffer> > decoded_audio_; | |
308 base::TimeDelta start_timestamp_; | |
309 | |
310 DISALLOW_COPY_AND_ASSIGN(AudioDecoderTest); | |
311 }; | |
312 | |
313 class OpusAudioDecoderBehavioralTest : public AudioDecoderTest {}; | |
314 class FFmpegAudioDecoderBehavioralTest : public AudioDecoderTest {}; | |
315 | |
316 TEST_P(AudioDecoderTest, Initialize) { | |
317 ASSERT_NO_FATAL_FAILURE(Initialize()); | |
318 Stop(); | |
319 } | |
320 | |
321 // Verifies decode audio as well as the Decode() -> Reset() -> Stop() sequence. | |
322 TEST_P(AudioDecoderTest, ProduceAudioSamples) { | |
323 ASSERT_NO_FATAL_FAILURE(Initialize()); | |
324 | |
325 // Run the test multiple times with a seek back to the beginning in between. | |
326 std::vector<std::string> decoded_audio_md5_hashes; | |
327 for (int i = 0; i < 2; ++i) { | |
328 for (size_t j = 0; j < kDecodeRuns; ++j) { | |
329 do { | |
330 Decode(); | |
331 ASSERT_EQ(last_decode_status(), AudioDecoder::kOk); | |
332 // Some codecs have a multiple buffer delay and require an extra | |
333 // Decode() step to extract the desired number of output buffers. | |
334 } while (j == 0 && decoded_audio_size() == 0); | |
335 | |
336 // On the first pass record the exact MD5 hash for each decoded buffer. | |
337 if (i == 0) | |
338 decoded_audio_md5_hashes.push_back(GetDecodedAudioMD5(j)); | |
339 } | |
340 | |
341 ASSERT_EQ(kDecodeRuns, decoded_audio_size()); | |
342 | |
343 // On the first pass verify the basic audio hash and sample info. On the | |
344 // second, verify the exact MD5 sum for each packet. It shouldn't change. | |
345 for (size_t j = 0; j < kDecodeRuns; ++j) { | |
346 SCOPED_TRACE(base::StringPrintf("i = %d, j = %" PRIuS, i, j)); | |
347 ExpectDecodedAudio(j, i == 0 ? "" : decoded_audio_md5_hashes[j]); | |
348 } | |
349 | |
350 SendEndOfStream(); | |
351 ASSERT_EQ(kDecodeRuns, decoded_audio_size()); | |
352 | |
353 // Seek back to the beginning. Calls Reset() on the decoder. | |
354 Seek(start_timestamp()); | |
355 } | |
356 | |
357 Stop(); | |
358 } | |
359 | |
360 TEST_P(AudioDecoderTest, DecodeStop) { | |
361 ASSERT_NO_FATAL_FAILURE(Initialize()); | |
362 Decode(); | |
363 EXPECT_EQ(AudioDecoder::kOk, last_decode_status()); | |
364 Stop(); | |
365 } | |
366 | |
367 TEST_P(AudioDecoderTest, ResetStop) { | |
368 ASSERT_NO_FATAL_FAILURE(Initialize()); | |
369 Reset(); | |
370 Stop(); | |
371 } | |
372 | |
373 TEST_P(AudioDecoderTest, NoTimestamp) { | |
374 ASSERT_NO_FATAL_FAILURE(Initialize()); | |
375 scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(0)); | |
376 buffer->set_timestamp(kNoTimestamp()); | |
377 DecodeBuffer(buffer); | |
378 EXPECT_EQ(AudioDecoder::kDecodeError, last_decode_status()); | |
379 Stop(); | |
380 } | |
381 | |
382 TEST_P(OpusAudioDecoderBehavioralTest, InitializeWithNoCodecDelay) { | |
383 ASSERT_EQ(GetParam().decoder_type, OPUS); | |
384 const uint8_t kOpusExtraData[] = { | |
385 0x4f, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64, 0x01, 0x02, | |
386 // The next two bytes represent the codec delay. | |
387 0x00, 0x00, 0x80, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
388 AudioDecoderConfig decoder_config; | |
389 decoder_config.Initialize(kCodecOpus, | |
390 kSampleFormatF32, | |
391 CHANNEL_LAYOUT_STEREO, | |
392 48000, | |
393 kOpusExtraData, | |
394 ARRAYSIZE_UNSAFE(kOpusExtraData), | |
395 false, | |
396 false, | |
397 base::TimeDelta::FromMilliseconds(80), | |
398 0); | |
399 InitializeDecoder(decoder_config); | |
400 Stop(); | |
401 } | |
402 | |
403 TEST_P(OpusAudioDecoderBehavioralTest, InitializeWithBadCodecDelay) { | |
404 ASSERT_EQ(GetParam().decoder_type, OPUS); | |
405 const uint8_t kOpusExtraData[] = { | |
wolenetz
2014/06/19 20:56:47
nit: Lift this duplicate to common definition (sam
DaleCurtis
2014/06/20 01:17:57
Done.
| |
406 0x4f, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64, 0x01, 0x02, | |
407 // The next two bytes represent the codec delay. | |
408 0x00, 0x00, 0x80, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
409 AudioDecoderConfig decoder_config; | |
410 decoder_config.Initialize( | |
411 kCodecOpus, | |
412 kSampleFormatF32, | |
413 CHANNEL_LAYOUT_STEREO, | |
414 48000, | |
415 kOpusExtraData, | |
416 ARRAYSIZE_UNSAFE(kOpusExtraData), | |
417 false, | |
418 false, | |
419 base::TimeDelta::FromMilliseconds(80), | |
420 // Use a different codec delay than in the extradata. | |
421 100); | |
422 InitializeDecoderWithStatus(decoder_config, DECODER_ERROR_NOT_SUPPORTED); | |
423 Stop(); | |
424 } | |
425 | |
426 TEST_P(FFmpegAudioDecoderBehavioralTest, InitializeWithBadConfig) { | |
427 const AudioDecoderConfig decoder_config(kCodecVorbis, | |
428 kSampleFormatF32, | |
429 CHANNEL_LAYOUT_STEREO, | |
430 // Invalid sample rate of zero. | |
431 0, | |
432 NULL, | |
433 0, | |
434 false); | |
435 InitializeDecoderWithStatus(decoder_config, DECODER_ERROR_NOT_SUPPORTED); | |
436 Stop(); | |
437 } | |
438 | |
439 const DecodedBufferExpectations kSfxOpusExpectations[] = { | |
440 {0, 13500, "-2.70,-1.41,-0.78,-1.27,-2.56,-3.73,"}, | |
441 {13500, 20000, "5.48,5.93,6.04,5.83,5.54,5.45,"}, | |
442 {33500, 20000, "-3.45,-3.35,-3.57,-4.12,-4.74,-5.14,"}, | |
443 }; | |
444 | |
445 const DecodedBufferExpectations kBearOpusExpectations[] = { | |
446 {500, 3500, "-0.26,0.87,1.36,0.84,-0.30,-1.22,"}, | |
447 {4000, 10000, "0.09,0.23,0.21,0.03,-0.17,-0.24,"}, | |
448 {14000, 10000, "0.10,0.24,0.23,0.04,-0.14,-0.23,"}, | |
449 }; | |
450 | |
451 const DecoderTestData kOpusTests[] = { | |
452 {OPUS, kCodecOpus, "sfx-opus.ogg", kSfxOpusExpectations, -312, 48000, | |
453 CHANNEL_LAYOUT_MONO}, | |
454 {OPUS, kCodecOpus, "bear-opus.ogg", kBearOpusExpectations, 24, 48000, | |
455 CHANNEL_LAYOUT_STEREO}, | |
456 }; | |
457 | |
458 // Dummy data for behavioral tests. | |
459 const DecoderTestData kOpusBehavioralTest[] = { | |
460 {OPUS, kUnknownAudioCodec, "", NULL, 0, 0, CHANNEL_LAYOUT_NONE}, | |
461 }; | |
462 | |
463 INSTANTIATE_TEST_CASE_P(OpusAudioDecoderTest, | |
464 AudioDecoderTest, | |
465 testing::ValuesIn(kOpusTests)); | |
466 INSTANTIATE_TEST_CASE_P(OpusAudioDecoderBehavioralTest, | |
467 OpusAudioDecoderBehavioralTest, | |
468 testing::ValuesIn(kOpusBehavioralTest)); | |
469 | |
470 #if defined(USE_PROPRIETARY_CODECS) | |
471 const DecodedBufferExpectations kSfxMp3Expectations[] = { | |
472 {0, 1065, "2.81,3.99,4.53,4.10,3.08,2.46,"}, | |
473 {1065, 26122, "-3.81,-4.14,-3.90,-3.36,-3.03,-3.23,"}, | |
474 {27188, 26122, "4.24,3.95,4.22,4.78,5.13,4.93,"}, | |
475 }; | |
476 | |
477 const DecodedBufferExpectations kSfxAdtsExpectations[] = { | |
478 {0, 23219, "-1.90,-1.53,-0.15,1.28,1.23,-0.33,"}, | |
479 {23219, 23219, "0.54,0.88,2.19,3.54,3.24,1.63,"}, | |
480 {46439, 23219, "1.42,1.69,2.95,4.23,4.02,2.36,"}, | |
481 }; | |
482 #endif | |
483 | |
484 #if defined(OS_CHROMEOS) | |
485 const DecodedBufferExpectations kSfxFlacExpectations[] = { | |
486 {0, 104489, "-2.42,-1.12,0.71,1.70,1.09,-0.68,"}, | |
487 {104489, 104489, "-1.99,-0.67,1.18,2.19,1.60,-0.16,"}, | |
488 {208979, 79433, "2.84,2.70,3.23,4.06,4.59,4.44,"}, | |
489 }; | |
490 #endif | |
491 | |
492 const DecodedBufferExpectations kSfxWaveExpectations[] = { | |
493 {0, 23219, "-1.23,-0.87,0.47,1.85,1.88,0.29,"}, | |
494 {23219, 23219, "0.75,1.10,2.43,3.78,3.53,1.93,"}, | |
495 {46439, 23219, "1.27,1.56,2.83,4.13,3.87,2.23,"}, | |
496 }; | |
497 | |
498 const DecodedBufferExpectations kFourChannelWaveExpectations[] = { | |
499 {0, 11609, "-1.68,1.68,0.89,-3.45,1.52,1.15,"}, | |
500 {11609, 11609, "43.26,9.06,18.27,35.98,19.45,7.46,"}, | |
501 {23219, 11609, "36.37,9.45,16.04,27.67,18.81,10.15,"}, | |
502 }; | |
503 | |
504 const DecodedBufferExpectations kSfxOggExpectations[] = { | |
505 {0, 13061, "-0.33,1.25,2.86,3.26,2.09,0.14,"}, | |
506 {13061, 23219, "-2.79,-2.42,-1.06,0.33,0.93,-0.64,"}, | |
507 {36281, 23219, "-1.19,-0.80,0.57,1.97,2.08,0.51,"}, | |
508 }; | |
509 | |
510 const DecodedBufferExpectations kBearOgvExpectations[] = { | |
511 {0, 13061, "-1.25,0.10,2.11,2.29,1.50,-0.68,"}, | |
512 {13061, 23219, "-1.80,-1.41,-0.13,1.30,1.65,0.01,"}, | |
513 {36281, 23219, "-1.43,-1.25,0.11,1.29,1.86,0.14,"}, | |
514 }; | |
515 | |
516 const DecoderTestData kFFmpegTests[] = { | |
517 #if defined(USE_PROPRIETARY_CODECS) | |
518 {FFMPEG, kCodecMP3, "sfx.mp3", kSfxMp3Expectations, 0, 44100, | |
519 CHANNEL_LAYOUT_MONO}, | |
520 {FFMPEG, kCodecAAC, "sfx.adts", kSfxAdtsExpectations, 0, 44100, | |
521 CHANNEL_LAYOUT_MONO}, | |
522 #endif | |
523 #if defined(OS_CHROMEOS) | |
524 {FFMPEG, kCodecFLAC, "sfx.flac", kSfxFlacExpectations, 0, 44100, | |
525 CHANNEL_LAYOUT_MONO}, | |
526 #endif | |
527 {FFMPEG, kCodecPCM, "sfx_f32le.wav", kSfxWaveExpectations, 0, 44100, | |
528 CHANNEL_LAYOUT_MONO}, | |
529 {FFMPEG, kCodecPCM, "4ch.wav", kFourChannelWaveExpectations, 0, 44100, | |
530 CHANNEL_LAYOUT_QUAD}, | |
531 {FFMPEG, kCodecVorbis, "sfx.ogg", kSfxOggExpectations, 0, 44100, | |
532 CHANNEL_LAYOUT_MONO}, | |
533 // Note: bear.ogv is incorrectly muxed such that valid samples are given | |
534 // negative timestamps, this marks them for discard per the ogg vorbis spec. | |
535 {FFMPEG, kCodecVorbis, "bear.ogv", kBearOgvExpectations, -704, 44100, | |
536 CHANNEL_LAYOUT_STEREO}, | |
537 }; | |
538 | |
539 // Dummy data for behavioral tests. | |
540 const DecoderTestData kFFmpegBehavioralTest[] = { | |
541 {FFMPEG, kUnknownAudioCodec, "", NULL, 0, 0, CHANNEL_LAYOUT_NONE}, | |
542 }; | |
543 | |
544 INSTANTIATE_TEST_CASE_P(FFmpegAudioDecoderTest, | |
545 AudioDecoderTest, | |
546 testing::ValuesIn(kFFmpegTests)); | |
547 INSTANTIATE_TEST_CASE_P(FFmpegAudioDecoderBehavioralTest, | |
548 FFmpegAudioDecoderBehavioralTest, | |
549 testing::ValuesIn(kFFmpegBehavioralTest)); | |
550 | |
551 } // namespace media | |
OLD | NEW |