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