| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <windows.h> | 5 #include <windows.h> |
| 6 #include <mmsystem.h> | 6 #include <mmsystem.h> |
| 7 | 7 |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/base_paths.h" | 9 #include "base/base_paths.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 | 69 |
| 70 void set_error(bool error) { | 70 void set_error(bool error) { |
| 71 had_error_ += error ? 1 : 0; | 71 had_error_ += error ? 1 : 0; |
| 72 } | 72 } |
| 73 | 73 |
| 74 private: | 74 private: |
| 75 int callback_count_; | 75 int callback_count_; |
| 76 int had_error_; | 76 int had_error_; |
| 77 }; | 77 }; |
| 78 | 78 |
| 79 const int kMaxNumBuffers = 3; | 79 const int kNumBuffers = 3; |
| 80 // Specializes TestSourceBasic to detect that the AudioStream is using | 80 // Specializes TestSourceBasic to detect that the AudioStream is using |
| 81 // triple buffering correctly. | 81 // triple buffering correctly. |
| 82 class TestSourceTripleBuffer : public TestSourceBasic { | 82 class TestSourceTripleBuffer : public TestSourceBasic { |
| 83 public: | 83 public: |
| 84 TestSourceTripleBuffer() { | 84 TestSourceTripleBuffer() { |
| 85 buffer_address_[0] = NULL; | 85 buffer_address_[0] = NULL; |
| 86 buffer_address_[1] = NULL; | 86 buffer_address_[1] = NULL; |
| 87 buffer_address_[2] = NULL; | 87 buffer_address_[2] = NULL; |
| 88 } | 88 } |
| 89 // Override of TestSourceBasic::OnMoreData. | 89 // Override of TestSourceBasic::OnMoreData. |
| 90 virtual uint32 OnMoreData(uint8* dest, | 90 virtual uint32 OnMoreData(uint8* dest, |
| 91 uint32 max_size, | 91 uint32 max_size, |
| 92 AudioBuffersState buffers_state) { | 92 AudioBuffersState buffers_state) { |
| 93 // Call the base, which increments the callback_count_. | 93 // Call the base, which increments the callback_count_. |
| 94 TestSourceBasic::OnMoreData(dest, max_size, buffers_state); | 94 TestSourceBasic::OnMoreData(dest, max_size, buffers_state); |
| 95 if (callback_count() % NumberOfWaveOutBuffers() == 2) { | 95 if (callback_count() % kNumBuffers == 2) { |
| 96 set_error(!CompareExistingIfNotNULL(2, dest)); | 96 set_error(!CompareExistingIfNotNULL(2, dest)); |
| 97 } else if (callback_count() % NumberOfWaveOutBuffers() == 1) { | 97 } else if (callback_count() % kNumBuffers == 1) { |
| 98 set_error(!CompareExistingIfNotNULL(1, dest)); | 98 set_error(!CompareExistingIfNotNULL(1, dest)); |
| 99 } else { | 99 } else { |
| 100 set_error(!CompareExistingIfNotNULL(0, dest)); | 100 set_error(!CompareExistingIfNotNULL(0, dest)); |
| 101 } | 101 } |
| 102 if (callback_count() > kMaxNumBuffers) { | 102 if (callback_count() > kNumBuffers) { |
| 103 set_error(buffer_address_[0] == buffer_address_[1]); | 103 set_error(buffer_address_[0] == buffer_address_[1]); |
| 104 set_error(buffer_address_[1] == buffer_address_[2]); | 104 set_error(buffer_address_[1] == buffer_address_[2]); |
| 105 } | 105 } |
| 106 return max_size; | 106 return max_size; |
| 107 } | 107 } |
| 108 | 108 |
| 109 private: | 109 private: |
| 110 bool CompareExistingIfNotNULL(uint32 index, void* address) { | 110 bool CompareExistingIfNotNULL(uint32 index, void* address) { |
| 111 void*& entry = buffer_address_[index]; | 111 void*& entry = buffer_address_[index]; |
| 112 if (!entry) | 112 if (!entry) |
| 113 entry = address; | 113 entry = address; |
| 114 return (entry == address); | 114 return (entry == address); |
| 115 } | 115 } |
| 116 | 116 |
| 117 void* buffer_address_[kMaxNumBuffers]; | 117 void* buffer_address_[kNumBuffers]; |
| 118 }; | 118 }; |
| 119 | 119 |
| 120 // Specializes TestSourceBasic to simulate a source that blocks for some time | 120 // Specializes TestSourceBasic to simulate a source that blocks for some time |
| 121 // in the OnMoreData callback. | 121 // in the OnMoreData callback. |
| 122 class TestSourceLaggy : public TestSourceBasic { | 122 class TestSourceLaggy : public TestSourceBasic { |
| 123 public: | 123 public: |
| 124 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms) | 124 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms) |
| 125 : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) { | 125 : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) { |
| 126 } | 126 } |
| 127 virtual uint32 OnMoreData(uint8* dest, | 127 virtual uint32 OnMoreData(uint8* dest, |
| 128 uint32 max_size, | 128 uint32 max_size, |
| 129 AudioBuffersState buffers_state) { | 129 AudioBuffersState buffers_state) { |
| 130 // Call the base, which increments the callback_count_. | 130 // Call the base, which increments the callback_count_. |
| 131 TestSourceBasic::OnMoreData(dest, max_size, buffers_state); | 131 TestSourceBasic::OnMoreData(dest, max_size, buffers_state); |
| 132 if (callback_count() > kMaxNumBuffers) { | 132 if (callback_count() > kNumBuffers) { |
| 133 ::Sleep(lag_in_ms_); | 133 ::Sleep(lag_in_ms_); |
| 134 } | 134 } |
| 135 return max_size; | 135 return max_size; |
| 136 } | 136 } |
| 137 private: | 137 private: |
| 138 int laggy_after_buffer_; | 138 int laggy_after_buffer_; |
| 139 int lag_in_ms_; | 139 int lag_in_ms_; |
| 140 }; | 140 }; |
| 141 | 141 |
| 142 class MockAudioSource : public AudioOutputStream::AudioSourceCallback { | 142 class MockAudioSource : public AudioOutputStream::AudioSourceCallback { |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 } | 305 } |
| 306 | 306 |
| 307 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( | 307 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( |
| 308 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, | 308 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, |
| 309 16000, 16, 256)); | 309 16000, 16, 256)); |
| 310 ASSERT_TRUE(NULL != oas); | 310 ASSERT_TRUE(NULL != oas); |
| 311 TestSourceTripleBuffer test_triple_buffer; | 311 TestSourceTripleBuffer test_triple_buffer; |
| 312 EXPECT_TRUE(oas->Open()); | 312 EXPECT_TRUE(oas->Open()); |
| 313 oas->Start(&test_triple_buffer); | 313 oas->Start(&test_triple_buffer); |
| 314 ::Sleep(300); | 314 ::Sleep(300); |
| 315 EXPECT_GT(test_triple_buffer.callback_count(), kMaxNumBuffers); | 315 EXPECT_GT(test_triple_buffer.callback_count(), kNumBuffers); |
| 316 EXPECT_FALSE(test_triple_buffer.had_error()); | 316 EXPECT_FALSE(test_triple_buffer.had_error()); |
| 317 oas->Stop(); | 317 oas->Stop(); |
| 318 ::Sleep(500); | 318 ::Sleep(500); |
| 319 oas->Close(); | 319 oas->Close(); |
| 320 } | 320 } |
| 321 | 321 |
| 322 // Test potential deadlock situation if the source is slow or blocks for some | 322 // Test potential deadlock situation if the source is slow or blocks for some |
| 323 // time. The actual EXPECT_GT are mostly meaningless and the real test is that | 323 // time. The actual EXPECT_GT are mostly meaningless and the real test is that |
| 324 // the test completes in reasonable time. | 324 // the test completes in reasonable time. |
| 325 TEST(WinAudioTest, PCMWaveSlowSource) { | 325 TEST(WinAudioTest, PCMWaveSlowSource) { |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( | 593 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( |
| 594 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, | 594 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, |
| 595 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); | 595 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); |
| 596 ASSERT_TRUE(NULL != oas); | 596 ASSERT_TRUE(NULL != oas); |
| 597 | 597 |
| 598 NiceMock<MockAudioSource> source; | 598 NiceMock<MockAudioSource> source; |
| 599 EXPECT_TRUE(oas->Open()); | 599 EXPECT_TRUE(oas->Open()); |
| 600 | 600 |
| 601 uint32 bytes_100_ms = samples_100_ms * 2; | 601 uint32 bytes_100_ms = samples_100_ms * 2; |
| 602 | 602 |
| 603 // Audio output stream has either a double or triple buffer scheme. | 603 // We expect the amount of pending bytes will reaching 2 times of |
| 604 // We expect the amount of pending bytes will reaching up to 2 times of | 604 // |bytes_100_ms| because the audio output stream has a triple buffer scheme. |
| 605 // |bytes_100_ms| depending on number of buffers used. | |
| 606 // From that it would decrease as we are playing the data but not providing | 605 // From that it would decrease as we are playing the data but not providing |
| 607 // new one. And then we will try to provide zero data so the amount of | 606 // new one. And then we will try to provide zero data so the amount of |
| 608 // pending bytes will go down and eventually read zero. | 607 // pending bytes will go down and eventually read zero. |
| 609 InSequence s; | 608 InSequence s; |
| 610 | |
| 611 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 609 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
| 612 Field(&AudioBuffersState::pending_bytes, 0))) | 610 Field(&AudioBuffersState::pending_bytes, 0))) |
| 613 .WillOnce(Return(bytes_100_ms)); | 611 .WillOnce(Return(bytes_100_ms)); |
| 614 switch (NumberOfWaveOutBuffers()) { | 612 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
| 615 case 2: | 613 Field(&AudioBuffersState::pending_bytes, |
| 616 break; // Calls are the same as at end of 3-buffer scheme. | 614 bytes_100_ms))) |
| 617 case 3: | 615 .WillOnce(Return(bytes_100_ms)); |
| 618 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 616 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
| 619 Field(&AudioBuffersState::pending_bytes, | 617 Field(&AudioBuffersState::pending_bytes, |
| 620 bytes_100_ms))) | 618 2 * bytes_100_ms))) |
| 621 .WillOnce(Return(bytes_100_ms)); | 619 .WillOnce(Return(bytes_100_ms)); |
| 622 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 620 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
| 623 Field(&AudioBuffersState::pending_bytes, | 621 Field(&AudioBuffersState::pending_bytes, |
| 624 2 * bytes_100_ms))) | 622 2 * bytes_100_ms))) |
| 625 .WillOnce(Return(bytes_100_ms)); | 623 .Times(AnyNumber()) |
| 626 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 624 .WillRepeatedly(Return(0)); |
| 627 Field(&AudioBuffersState::pending_bytes, | |
| 628 2 * bytes_100_ms))) | |
| 629 .Times(AnyNumber()) | |
| 630 .WillRepeatedly(Return(0)); | |
| 631 default: | |
| 632 ASSERT_TRUE(false) << "Unexpected number of buffers"; | |
| 633 } | |
| 634 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 625 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
| 635 Field(&AudioBuffersState::pending_bytes, | 626 Field(&AudioBuffersState::pending_bytes, |
| 636 bytes_100_ms))) | 627 bytes_100_ms))) |
| 637 .Times(AnyNumber()) | 628 .Times(AnyNumber()) |
| 638 .WillRepeatedly(Return(0)); | 629 .WillRepeatedly(Return(0)); |
| 639 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 630 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
| 640 Field(&AudioBuffersState::pending_bytes, 0))) | 631 Field(&AudioBuffersState::pending_bytes, 0))) |
| 641 .Times(AnyNumber()) | 632 .Times(AnyNumber()) |
| 642 .WillRepeatedly(Return(0)); | 633 .WillRepeatedly(Return(0)); |
| 643 | 634 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 oas->Start(&source); | 742 oas->Start(&source); |
| 752 | 743 |
| 753 ::WaitForSingleObject(thread, INFINITE); | 744 ::WaitForSingleObject(thread, INFINITE); |
| 754 ::CloseHandle(thread); | 745 ::CloseHandle(thread); |
| 755 | 746 |
| 756 oas->Stop(); | 747 oas->Stop(); |
| 757 oas->Close(); | 748 oas->Close(); |
| 758 } | 749 } |
| 759 | 750 |
| 760 } // namespace media | 751 } // namespace media |
| OLD | NEW |