Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 | 7 |
| 8 #include <deque> | |
| 9 #include <vector> | 8 #include <vector> |
| 10 | 9 |
| 11 #include "base/bind.h" | 10 #include "base/bind.h" |
| 12 #include "base/format_macros.h" | 11 #include "base/format_macros.h" |
| 13 #include "base/macros.h" | 12 #include "base/macros.h" |
| 14 #include "base/md5.h" | 13 #include "base/md5.h" |
| 15 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 16 #include "base/run_loop.h" | 15 #include "base/run_loop.h" |
| 17 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 18 #include "base/sys_byteorder.h" | 17 #include "base/sys_byteorder.h" |
| 18 #include "base/threading/platform_thread.h" | |
| 19 #include "build/build_config.h" | 19 #include "build/build_config.h" |
| 20 #include "media/base/audio_buffer.h" | 20 #include "media/base/audio_buffer.h" |
| 21 #include "media/base/audio_bus.h" | 21 #include "media/base/audio_bus.h" |
| 22 #include "media/base/audio_hash.h" | 22 #include "media/base/audio_hash.h" |
| 23 #include "media/base/decoder_buffer.h" | 23 #include "media/base/decoder_buffer.h" |
| 24 #include "media/base/media_util.h" | 24 #include "media/base/media_util.h" |
| 25 #include "media/base/test_data_util.h" | 25 #include "media/base/test_data_util.h" |
| 26 #include "media/base/test_helpers.h" | 26 #include "media/base/test_helpers.h" |
| 27 #include "media/base/timestamp_constants.h" | 27 #include "media/base/timestamp_constants.h" |
| 28 #include "media/ffmpeg/ffmpeg_common.h" | 28 #include "media/ffmpeg/ffmpeg_common.h" |
| 29 #include "media/filters/audio_file_reader.h" | 29 #include "media/filters/audio_file_reader.h" |
| 30 #include "media/filters/ffmpeg_audio_decoder.h" | 30 #include "media/filters/ffmpeg_audio_decoder.h" |
| 31 #include "media/filters/in_memory_url_protocol.h" | 31 #include "media/filters/in_memory_url_protocol.h" |
| 32 #include "media/filters/opus_audio_decoder.h" | 32 #include "media/filters/opus_audio_decoder.h" |
| 33 #include "testing/gtest/include/gtest/gtest.h" | 33 #include "testing/gtest/include/gtest/gtest.h" |
| 34 | 34 |
| 35 #if defined(OS_ANDROID) | |
| 36 #include "media/filters/android/media_codec_audio_decoder.h" | |
| 37 #endif | |
| 38 | |
| 35 namespace media { | 39 namespace media { |
| 36 | 40 |
| 37 // The number of packets to read and then decode from each file. | 41 // The number of packets to read and then decode from each file. |
| 38 static const size_t kDecodeRuns = 3; | 42 static const size_t kDecodeRuns = 3; |
| 39 static const uint8_t kOpusExtraData[] = { | 43 static const uint8_t kOpusExtraData[] = { |
| 40 0x4f, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64, 0x01, 0x02, | 44 0x4f, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64, 0x01, 0x02, |
| 41 // The next two bytes represent the codec delay. | 45 // The next two bytes represent the codec delay. |
| 42 0x00, 0x00, 0x80, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00}; | 46 0x00, 0x00, 0x80, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00}; |
| 43 | 47 |
| 44 enum AudioDecoderType { | 48 enum AudioDecoderType { |
| 45 FFMPEG, | 49 FFMPEG, |
| 46 OPUS, | 50 OPUS, |
| 51 #if defined(OS_ANDROID) | |
| 52 MEDIA_CODEC, | |
| 53 #endif | |
| 47 }; | 54 }; |
| 48 | 55 |
| 49 struct DecodedBufferExpectations { | 56 struct DecodedBufferExpectations { |
| 50 const int64_t timestamp; | 57 const int64_t timestamp; |
| 51 const int64_t duration; | 58 const int64_t duration; |
| 52 const char* hash; | 59 const char* hash; |
| 53 }; | 60 }; |
| 54 | 61 |
| 55 struct DecoderTestData { | 62 struct DecoderTestData { |
| 56 const AudioDecoderType decoder_type; | 63 const AudioDecoderType decoder_type; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 last_decode_status_(AudioDecoder::kDecodeError) { | 113 last_decode_status_(AudioDecoder::kDecodeError) { |
| 107 switch (GetParam().decoder_type) { | 114 switch (GetParam().decoder_type) { |
| 108 case FFMPEG: | 115 case FFMPEG: |
| 109 decoder_.reset(new FFmpegAudioDecoder(message_loop_.task_runner(), | 116 decoder_.reset(new FFmpegAudioDecoder(message_loop_.task_runner(), |
| 110 new MediaLog())); | 117 new MediaLog())); |
| 111 break; | 118 break; |
| 112 case OPUS: | 119 case OPUS: |
| 113 decoder_.reset( | 120 decoder_.reset( |
| 114 new OpusAudioDecoder(message_loop_.task_runner())); | 121 new OpusAudioDecoder(message_loop_.task_runner())); |
| 115 break; | 122 break; |
| 123 #if defined(OS_ANDROID) | |
| 124 case MEDIA_CODEC: | |
| 125 decoder_.reset(new MediaCodecAudioDecoder(message_loop_.task_runner())); | |
| 126 break; | |
| 127 #endif | |
| 116 } | 128 } |
| 117 } | 129 } |
| 118 | 130 |
| 119 virtual ~AudioDecoderTest() { | 131 virtual ~AudioDecoderTest() { |
| 120 EXPECT_FALSE(pending_decode_); | 132 EXPECT_FALSE(pending_decode_); |
| 121 EXPECT_FALSE(pending_reset_); | 133 EXPECT_FALSE(pending_reset_); |
| 122 } | 134 } |
| 123 | 135 |
| 124 protected: | 136 protected: |
| 125 void DecodeBuffer(const scoped_refptr<DecoderBuffer>& buffer) { | 137 void DecodeBuffer(const scoped_refptr<DecoderBuffer>& buffer) { |
| 126 ASSERT_FALSE(pending_decode_); | 138 ASSERT_FALSE(pending_decode_); |
| 127 pending_decode_ = true; | 139 pending_decode_ = true; |
| 128 last_decode_status_ = AudioDecoder::kDecodeError; | 140 last_decode_status_ = AudioDecoder::kDecodeError; |
| 129 decoder_->Decode( | 141 decoder_->Decode( |
| 130 buffer, | 142 buffer, |
| 131 base::Bind(&AudioDecoderTest::DecodeFinished, base::Unretained(this))); | 143 base::Bind(&AudioDecoderTest::DecodeFinished, base::Unretained(this))); |
| 132 base::RunLoop().RunUntilIdle(); | 144 WaitForDecodeResponse(); |
| 133 ASSERT_FALSE(pending_decode_); | 145 ASSERT_FALSE(pending_decode_); |
| 134 } | 146 } |
| 135 | 147 |
| 148 void WaitForDecodeResponse() { | |
|
liberato (no reviews please)
2016/02/29 17:08:57
"do work for 100msec" seems flaky. i see that the
Tima Vaisburd
2016/02/29 21:01:03
I think that mocking MediaCodec is a good idea, as
liberato (no reviews please)
2016/03/01 22:20:39
i was thinking about a very simple MediaCodec mock
Tima Vaisburd
2016/03/01 23:35:33
Even if the MediaCodec returns the output buffer i
liberato (no reviews please)
2016/03/02 15:02:01
flakiness: a delay of 100msec seems like something
| |
| 149 const base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(100); | |
| 150 const base::TimeDelta sleep_time = base::TimeDelta::FromMilliseconds(10); | |
| 151 | |
| 152 for (int i = 0; i < timeout / sleep_time; ++i) { | |
|
liberato (no reviews please)
2016/02/29 17:08:57
not sure if ::Sleep guarantees not to wake up earl
Tima Vaisburd
2016/02/29 21:01:03
Yes, I was not sure whether to use the Sleep(), or
liberato (no reviews please)
2016/03/02 15:02:01
i think that i like dale's suggestion better than
| |
| 153 base::RunLoop().RunUntilIdle(); | |
| 154 if (!pending_decode_) | |
| 155 break; | |
| 156 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); | |
| 157 } | |
| 158 } | |
| 159 | |
| 136 void SendEndOfStream() { | 160 void SendEndOfStream() { |
| 137 DecodeBuffer(DecoderBuffer::CreateEOSBuffer()); | 161 DecodeBuffer(DecoderBuffer::CreateEOSBuffer()); |
| 138 } | 162 } |
| 139 | 163 |
| 140 void Initialize() { | 164 void Initialize() { |
| 141 // Load the test data file. | 165 // Load the test data file. |
| 142 data_ = ReadTestDataFile(GetParam().filename); | 166 data_ = ReadTestDataFile(GetParam().filename); |
| 143 protocol_.reset( | 167 protocol_.reset( |
| 144 new InMemoryUrlProtocol(data_->data(), data_->data_size(), false)); | 168 new InMemoryUrlProtocol(data_->data(), data_->data_size(), false)); |
| 145 reader_.reset(new AudioFileReader(protocol_.get())); | 169 reader_.reset(new AudioFileReader(protocol_.get())); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 ASSERT_NO_FATAL_FAILURE(Initialize()); | 348 ASSERT_NO_FATAL_FAILURE(Initialize()); |
| 325 } | 349 } |
| 326 | 350 |
| 327 // Verifies decode audio as well as the Decode() -> Reset() sequence. | 351 // Verifies decode audio as well as the Decode() -> Reset() sequence. |
| 328 TEST_P(AudioDecoderTest, ProduceAudioSamples) { | 352 TEST_P(AudioDecoderTest, ProduceAudioSamples) { |
| 329 ASSERT_NO_FATAL_FAILURE(Initialize()); | 353 ASSERT_NO_FATAL_FAILURE(Initialize()); |
| 330 | 354 |
| 331 // Run the test multiple times with a seek back to the beginning in between. | 355 // Run the test multiple times with a seek back to the beginning in between. |
| 332 std::vector<std::string> decoded_audio_md5_hashes; | 356 std::vector<std::string> decoded_audio_md5_hashes; |
| 333 for (int i = 0; i < 2; ++i) { | 357 for (int i = 0; i < 2; ++i) { |
| 334 for (size_t j = 0; j < kDecodeRuns; ++j) { | 358 // Run decoder until we get at least |kDecodeRuns| output buffers. |
| 335 do { | 359 do { |
| 336 Decode(); | 360 Decode(); |
| 337 ASSERT_EQ(last_decode_status(), AudioDecoder::kOk); | 361 ASSERT_EQ(last_decode_status(), AudioDecoder::kOk); |
| 338 // Some codecs have a multiple buffer delay and require an extra | 362 } while (decoded_audio_size() < kDecodeRuns); |
|
liberato (no reviews please)
2016/02/29 17:08:57
why did this change?
does MediaCodec have a varia
Tima Vaisburd
2016/02/29 21:01:03
I think first. See below.
| |
| 339 // Decode() step to extract the desired number of output buffers. | |
| 340 } while (j == 0 && decoded_audio_size() == 0); | |
| 341 | 363 |
| 342 // On the first pass record the exact MD5 hash for each decoded buffer. | 364 // On the first pass record the exact MD5 hash for each decoded buffer. |
| 343 if (i == 0) | 365 if (i == 0) { |
| 366 for (size_t j = 0; j < kDecodeRuns; ++j) | |
| 344 decoded_audio_md5_hashes.push_back(GetDecodedAudioMD5(j)); | 367 decoded_audio_md5_hashes.push_back(GetDecodedAudioMD5(j)); |
| 345 } | 368 } |
| 346 | 369 |
| 347 ASSERT_EQ(kDecodeRuns, decoded_audio_size()); | 370 ASSERT_LE(kDecodeRuns, decoded_audio_size()); |
|
liberato (no reviews please)
2016/02/29 17:08:57
why can't we guarantee EQ here? is it because one
Tima Vaisburd
2016/02/29 21:01:03
As far as I understand, this is the consequence of
liberato (no reviews please)
2016/03/01 22:20:39
i don't think eq is important, but it's probably w
Tima Vaisburd
2016/03/01 23:35:33
I went a little deeper to see why we cannot ASSERT
| |
| 348 | 371 |
| 349 // On the first pass verify the basic audio hash and sample info. On the | 372 // On the first pass verify the basic audio hash and sample info. On the |
| 350 // second, verify the exact MD5 sum for each packet. It shouldn't change. | 373 // second, verify the exact MD5 sum for each packet. It shouldn't change. |
| 351 for (size_t j = 0; j < kDecodeRuns; ++j) { | 374 for (size_t j = 0; j < kDecodeRuns; ++j) { |
| 352 SCOPED_TRACE(base::StringPrintf("i = %d, j = %" PRIuS, i, j)); | 375 SCOPED_TRACE(base::StringPrintf("i = %d, j = %" PRIuS, i, j)); |
| 353 ExpectDecodedAudio(j, i == 0 ? "" : decoded_audio_md5_hashes[j]); | 376 ExpectDecodedAudio(j, i == 0 ? "" : decoded_audio_md5_hashes[j]); |
| 354 } | 377 } |
| 355 | 378 |
| 356 SendEndOfStream(); | 379 SendEndOfStream(); |
| 357 ASSERT_EQ(kDecodeRuns, decoded_audio_size()); | |
| 358 | 380 |
| 359 // Seek back to the beginning. Calls Reset() on the decoder. | 381 // Seek back to the beginning. Calls Reset() on the decoder. |
| 360 Seek(start_timestamp()); | 382 Seek(start_timestamp()); |
| 361 } | 383 } |
| 362 } | 384 } |
| 363 | 385 |
| 364 TEST_P(AudioDecoderTest, Decode) { | 386 TEST_P(AudioDecoderTest, Decode) { |
| 365 ASSERT_NO_FATAL_FAILURE(Initialize()); | 387 ASSERT_NO_FATAL_FAILURE(Initialize()); |
| 366 Decode(); | 388 Decode(); |
| 367 EXPECT_EQ(AudioDecoder::kOk, last_decode_status()); | 389 EXPECT_EQ(AudioDecoder::kOk, last_decode_status()); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 448 {OPUS, kUnknownAudioCodec, "", NULL, 0, 0, CHANNEL_LAYOUT_NONE}, | 470 {OPUS, kUnknownAudioCodec, "", NULL, 0, 0, CHANNEL_LAYOUT_NONE}, |
| 449 }; | 471 }; |
| 450 | 472 |
| 451 INSTANTIATE_TEST_CASE_P(OpusAudioDecoderTest, | 473 INSTANTIATE_TEST_CASE_P(OpusAudioDecoderTest, |
| 452 AudioDecoderTest, | 474 AudioDecoderTest, |
| 453 testing::ValuesIn(kOpusTests)); | 475 testing::ValuesIn(kOpusTests)); |
| 454 INSTANTIATE_TEST_CASE_P(OpusAudioDecoderBehavioralTest, | 476 INSTANTIATE_TEST_CASE_P(OpusAudioDecoderBehavioralTest, |
| 455 OpusAudioDecoderBehavioralTest, | 477 OpusAudioDecoderBehavioralTest, |
| 456 testing::ValuesIn(kOpusBehavioralTest)); | 478 testing::ValuesIn(kOpusBehavioralTest)); |
| 457 | 479 |
| 480 #if defined(OS_ANDROID) | |
| 481 | |
| 482 const DecoderTestData kMediaCodecTests[] = { | |
| 483 {MEDIA_CODEC, kCodecOpus, "bear-opus.ogg", kBearOpusExpectations, 24, 48000, | |
| 484 CHANNEL_LAYOUT_STEREO}, | |
| 485 }; | |
| 486 | |
| 487 INSTANTIATE_TEST_CASE_P(MediaCodecAudioDecoderTest, | |
| 488 AudioDecoderTest, | |
| 489 testing::ValuesIn(kMediaCodecTests)); | |
| 490 | |
| 491 #else // !defined(OS_ANDROID) | |
| 492 | |
| 458 // Disable all FFmpeg decoder tests on Android. http://crbug.com/570762. | 493 // Disable all FFmpeg decoder tests on Android. http://crbug.com/570762. |
| 459 #if !defined(OS_ANDROID) | |
| 460 | 494 |
| 461 #if defined(USE_PROPRIETARY_CODECS) | 495 #if defined(USE_PROPRIETARY_CODECS) |
| 462 const DecodedBufferExpectations kSfxMp3Expectations[] = { | 496 const DecodedBufferExpectations kSfxMp3Expectations[] = { |
| 463 {0, 1065, "2.81,3.99,4.53,4.10,3.08,2.46,"}, | 497 {0, 1065, "2.81,3.99,4.53,4.10,3.08,2.46,"}, |
| 464 {1065, 26122, "-3.81,-4.14,-3.90,-3.36,-3.03,-3.23,"}, | 498 {1065, 26122, "-3.81,-4.14,-3.90,-3.36,-3.03,-3.23,"}, |
| 465 {27188, 26122, "4.24,3.95,4.22,4.78,5.13,4.93,"}, | 499 {27188, 26122, "4.24,3.95,4.22,4.78,5.13,4.93,"}, |
| 466 }; | 500 }; |
| 467 | 501 |
| 468 const DecodedBufferExpectations kSfxAdtsExpectations[] = { | 502 const DecodedBufferExpectations kSfxAdtsExpectations[] = { |
| 469 {0, 23219, "-1.90,-1.53,-0.15,1.28,1.23,-0.33,"}, | 503 {0, 23219, "-1.90,-1.53,-0.15,1.28,1.23,-0.33,"}, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 535 INSTANTIATE_TEST_CASE_P(FFmpegAudioDecoderTest, | 569 INSTANTIATE_TEST_CASE_P(FFmpegAudioDecoderTest, |
| 536 AudioDecoderTest, | 570 AudioDecoderTest, |
| 537 testing::ValuesIn(kFFmpegTests)); | 571 testing::ValuesIn(kFFmpegTests)); |
| 538 INSTANTIATE_TEST_CASE_P(FFmpegAudioDecoderBehavioralTest, | 572 INSTANTIATE_TEST_CASE_P(FFmpegAudioDecoderBehavioralTest, |
| 539 FFmpegAudioDecoderBehavioralTest, | 573 FFmpegAudioDecoderBehavioralTest, |
| 540 testing::ValuesIn(kFFmpegBehavioralTest)); | 574 testing::ValuesIn(kFFmpegBehavioralTest)); |
| 541 | 575 |
| 542 #endif // !defined(OS_ANDROID) | 576 #endif // !defined(OS_ANDROID) |
| 543 | 577 |
| 544 } // namespace media | 578 } // namespace media |
| OLD | NEW |