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 |