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 27 matching lines...) Expand all Loading... |
38 | 38 |
39 // This class allows to find out if the callbacks are occurring as | 39 // This class allows to find out if the callbacks are occurring as |
40 // expected and if any error has been reported. | 40 // expected and if any error has been reported. |
41 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { | 41 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { |
42 public: | 42 public: |
43 explicit TestSourceBasic() | 43 explicit TestSourceBasic() |
44 : callback_count_(0), | 44 : callback_count_(0), |
45 had_error_(0) { | 45 had_error_(0) { |
46 } | 46 } |
47 // AudioSourceCallback::OnMoreData implementation: | 47 // AudioSourceCallback::OnMoreData implementation: |
48 virtual uint32 OnMoreData(AudioOutputStream* stream, uint8* dest, | 48 virtual uint32 OnMoreData(uint8* dest, |
49 uint32 max_size, AudioBuffersState buffers_state) { | 49 uint32 max_size, |
| 50 AudioBuffersState buffers_state) { |
50 ++callback_count_; | 51 ++callback_count_; |
51 // Touch the first byte to make sure memory is good. | 52 // Touch the first byte to make sure memory is good. |
52 if (max_size) | 53 if (max_size) |
53 reinterpret_cast<char*>(dest)[0] = 1; | 54 reinterpret_cast<char*>(dest)[0] = 1; |
54 return max_size; | 55 return max_size; |
55 } | 56 } |
56 // AudioSourceCallback::OnError implementation: | 57 // AudioSourceCallback::OnError implementation: |
57 virtual void OnError(AudioOutputStream* stream, int code) { | 58 virtual void OnError(AudioOutputStream* stream, int code) { |
58 ++had_error_; | 59 ++had_error_; |
59 } | 60 } |
(...skipping 19 matching lines...) Expand all Loading... |
79 // Specializes TestSourceBasic to detect that the AudioStream is using | 80 // Specializes TestSourceBasic to detect that the AudioStream is using |
80 // triple buffering correctly. | 81 // triple buffering correctly. |
81 class TestSourceTripleBuffer : public TestSourceBasic { | 82 class TestSourceTripleBuffer : public TestSourceBasic { |
82 public: | 83 public: |
83 TestSourceTripleBuffer() { | 84 TestSourceTripleBuffer() { |
84 buffer_address_[0] = NULL; | 85 buffer_address_[0] = NULL; |
85 buffer_address_[1] = NULL; | 86 buffer_address_[1] = NULL; |
86 buffer_address_[2] = NULL; | 87 buffer_address_[2] = NULL; |
87 } | 88 } |
88 // Override of TestSourceBasic::OnMoreData. | 89 // Override of TestSourceBasic::OnMoreData. |
89 virtual uint32 OnMoreData(AudioOutputStream* stream, | 90 virtual uint32 OnMoreData(uint8* dest, |
90 uint8* dest, uint32 max_size, | 91 uint32 max_size, |
91 AudioBuffersState buffers_state) { | 92 AudioBuffersState buffers_state) { |
92 // Call the base, which increments the callback_count_. | 93 // Call the base, which increments the callback_count_. |
93 TestSourceBasic::OnMoreData(stream, dest, max_size, buffers_state); | 94 TestSourceBasic::OnMoreData(dest, max_size, buffers_state); |
94 if (callback_count() % kNumBuffers == 2) { | 95 if (callback_count() % kNumBuffers == 2) { |
95 set_error(!CompareExistingIfNotNULL(2, dest)); | 96 set_error(!CompareExistingIfNotNULL(2, dest)); |
96 } else if (callback_count() % kNumBuffers == 1) { | 97 } else if (callback_count() % kNumBuffers == 1) { |
97 set_error(!CompareExistingIfNotNULL(1, dest)); | 98 set_error(!CompareExistingIfNotNULL(1, dest)); |
98 } else { | 99 } else { |
99 set_error(!CompareExistingIfNotNULL(0, dest)); | 100 set_error(!CompareExistingIfNotNULL(0, dest)); |
100 } | 101 } |
101 if (callback_count() > kNumBuffers) { | 102 if (callback_count() > kNumBuffers) { |
102 set_error(buffer_address_[0] == buffer_address_[1]); | 103 set_error(buffer_address_[0] == buffer_address_[1]); |
103 set_error(buffer_address_[1] == buffer_address_[2]); | 104 set_error(buffer_address_[1] == buffer_address_[2]); |
(...skipping 12 matching lines...) Expand all Loading... |
116 void* buffer_address_[kNumBuffers]; | 117 void* buffer_address_[kNumBuffers]; |
117 }; | 118 }; |
118 | 119 |
119 // Specializes TestSourceBasic to simulate a source that blocks for some time | 120 // Specializes TestSourceBasic to simulate a source that blocks for some time |
120 // in the OnMoreData callback. | 121 // in the OnMoreData callback. |
121 class TestSourceLaggy : public TestSourceBasic { | 122 class TestSourceLaggy : public TestSourceBasic { |
122 public: | 123 public: |
123 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms) | 124 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms) |
124 : 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) { |
125 } | 126 } |
126 virtual uint32 OnMoreData(AudioOutputStream* stream, | 127 virtual uint32 OnMoreData(uint8* dest, |
127 uint8* dest, uint32 max_size, | 128 uint32 max_size, |
128 AudioBuffersState buffers_state) { | 129 AudioBuffersState buffers_state) { |
129 // Call the base, which increments the callback_count_. | 130 // Call the base, which increments the callback_count_. |
130 TestSourceBasic::OnMoreData(stream, dest, max_size, buffers_state); | 131 TestSourceBasic::OnMoreData(dest, max_size, buffers_state); |
131 if (callback_count() > kNumBuffers) { | 132 if (callback_count() > kNumBuffers) { |
132 ::Sleep(lag_in_ms_); | 133 ::Sleep(lag_in_ms_); |
133 } | 134 } |
134 return max_size; | 135 return max_size; |
135 } | 136 } |
136 private: | 137 private: |
137 int laggy_after_buffer_; | 138 int laggy_after_buffer_; |
138 int lag_in_ms_; | 139 int lag_in_ms_; |
139 }; | 140 }; |
140 | 141 |
141 class MockAudioSource : public AudioOutputStream::AudioSourceCallback { | 142 class MockAudioSource : public AudioOutputStream::AudioSourceCallback { |
142 public: | 143 public: |
143 MOCK_METHOD4(OnMoreData, uint32(AudioOutputStream* stream, uint8* dest, | 144 MOCK_METHOD3(OnMoreData, uint32(uint8* dest, |
144 uint32 max_size, | 145 uint32 max_size, |
145 AudioBuffersState buffers_state)); | 146 AudioBuffersState buffers_state)); |
146 MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); | 147 MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); |
147 }; | 148 }; |
148 | 149 |
149 // Helper class to memory map an entire file. The mapping is read-only. Don't | 150 // Helper class to memory map an entire file. The mapping is read-only. Don't |
150 // use for gigabyte-sized files. Attempts to write to this memory generate | 151 // use for gigabyte-sized files. Attempts to write to this memory generate |
151 // memory access violations. | 152 // memory access violations. |
152 class ReadOnlyMappedFile { | 153 class ReadOnlyMappedFile { |
153 public: | 154 public: |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 EXPECT_TRUE(oas->Open()); | 599 EXPECT_TRUE(oas->Open()); |
599 | 600 |
600 uint32 bytes_100_ms = samples_100_ms * 2; | 601 uint32 bytes_100_ms = samples_100_ms * 2; |
601 | 602 |
602 // We expect the amount of pending bytes will reaching 2 times of | 603 // We expect the amount of pending bytes will reaching 2 times of |
603 // |bytes_100_ms| because the audio output stream has a triple buffer scheme. | 604 // |bytes_100_ms| because the audio output stream has a triple buffer scheme. |
604 // 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 |
605 // 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 |
606 // pending bytes will go down and eventually read zero. | 607 // pending bytes will go down and eventually read zero. |
607 InSequence s; | 608 InSequence s; |
608 EXPECT_CALL(source, OnMoreData(oas, NotNull(), bytes_100_ms, | 609 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
609 Field(&AudioBuffersState::pending_bytes, 0))) | 610 Field(&AudioBuffersState::pending_bytes, 0))) |
610 .WillOnce(Return(bytes_100_ms)); | 611 .WillOnce(Return(bytes_100_ms)); |
611 EXPECT_CALL(source, OnMoreData(oas, NotNull(), bytes_100_ms, | 612 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
612 Field(&AudioBuffersState::pending_bytes, | 613 Field(&AudioBuffersState::pending_bytes, |
613 bytes_100_ms))) | 614 bytes_100_ms))) |
614 .WillOnce(Return(bytes_100_ms)); | 615 .WillOnce(Return(bytes_100_ms)); |
615 EXPECT_CALL(source, OnMoreData(oas, NotNull(), bytes_100_ms, | 616 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
616 Field(&AudioBuffersState::pending_bytes, | 617 Field(&AudioBuffersState::pending_bytes, |
617 2 * bytes_100_ms))) | 618 2 * bytes_100_ms))) |
618 .WillOnce(Return(bytes_100_ms)); | 619 .WillOnce(Return(bytes_100_ms)); |
619 EXPECT_CALL(source, OnMoreData(oas, NotNull(), bytes_100_ms, | 620 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
620 Field(&AudioBuffersState::pending_bytes, | 621 Field(&AudioBuffersState::pending_bytes, |
621 2 * bytes_100_ms))) | 622 2 * bytes_100_ms))) |
622 .Times(AnyNumber()) | 623 .Times(AnyNumber()) |
623 .WillRepeatedly(Return(0)); | 624 .WillRepeatedly(Return(0)); |
624 EXPECT_CALL(source, OnMoreData(oas, NotNull(), bytes_100_ms, | 625 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
625 Field(&AudioBuffersState::pending_bytes, | 626 Field(&AudioBuffersState::pending_bytes, |
626 bytes_100_ms))) | 627 bytes_100_ms))) |
627 .Times(AnyNumber()) | 628 .Times(AnyNumber()) |
628 .WillRepeatedly(Return(0)); | 629 .WillRepeatedly(Return(0)); |
629 EXPECT_CALL(source, OnMoreData(oas, NotNull(), bytes_100_ms, | 630 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, |
630 Field(&AudioBuffersState::pending_bytes, 0))) | 631 Field(&AudioBuffersState::pending_bytes, 0))) |
631 .Times(AnyNumber()) | 632 .Times(AnyNumber()) |
632 .WillRepeatedly(Return(0)); | 633 .WillRepeatedly(Return(0)); |
633 | 634 |
634 oas->Start(&source); | 635 oas->Start(&source); |
635 ::Sleep(500); | 636 ::Sleep(500); |
636 oas->Stop(); | 637 oas->Stop(); |
637 oas->Close(); | 638 oas->Close(); |
638 } | 639 } |
639 | 640 |
640 // Simple source that uses a SyncSocket to retrieve the audio data | 641 // Simple source that uses a SyncSocket to retrieve the audio data |
641 // from a potentially remote thread. | 642 // from a potentially remote thread. |
642 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { | 643 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { |
643 public: | 644 public: |
644 explicit SyncSocketSource(base::SyncSocket* socket) | 645 explicit SyncSocketSource(base::SyncSocket* socket) |
645 : socket_(socket) {} | 646 : socket_(socket) {} |
646 | 647 |
647 ~SyncSocketSource() { | 648 ~SyncSocketSource() { |
648 } | 649 } |
649 | 650 |
650 // AudioSourceCallback::OnMoreData implementation: | 651 // AudioSourceCallback::OnMoreData implementation: |
651 virtual uint32 OnMoreData(AudioOutputStream* stream, | 652 virtual uint32 OnMoreData(uint8* dest, |
652 uint8* dest, uint32 max_size, | 653 uint32 max_size, |
653 AudioBuffersState buffers_state) { | 654 AudioBuffersState buffers_state) { |
654 socket_->Send(&buffers_state, sizeof(buffers_state)); | 655 socket_->Send(&buffers_state, sizeof(buffers_state)); |
655 uint32 got = socket_->Receive(dest, max_size); | 656 uint32 got = socket_->Receive(dest, max_size); |
656 return got; | 657 return got; |
657 } | 658 } |
658 // AudioSourceCallback::OnError implementation: | 659 // AudioSourceCallback::OnError implementation: |
659 virtual void OnError(AudioOutputStream* stream, int code) { | 660 virtual void OnError(AudioOutputStream* stream, int code) { |
660 } | 661 } |
661 | 662 |
662 private: | 663 private: |
(...skipping 14 matching lines...) Expand all Loading... |
677 // <--- audio packet ---------- | 678 // <--- audio packet ---------- |
678 // | 679 // |
679 DWORD __stdcall SyncSocketThread(void* context) { | 680 DWORD __stdcall SyncSocketThread(void* context) { |
680 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); | 681 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); |
681 | 682 |
682 const int kTwoSecBytes = | 683 const int kTwoSecBytes = |
683 AudioParameters::kAudioCDSampleRate * 2 * sizeof(uint16); // NOLINT | 684 AudioParameters::kAudioCDSampleRate * 2 * sizeof(uint16); // NOLINT |
684 uint8* buffer = new uint8[kTwoSecBytes]; | 685 uint8* buffer = new uint8[kTwoSecBytes]; |
685 SineWaveAudioSource sine(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, | 686 SineWaveAudioSource sine(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, |
686 1, ctx.sine_freq, ctx.sample_rate); | 687 1, ctx.sine_freq, ctx.sample_rate); |
687 sine.OnMoreData(NULL, buffer, kTwoSecBytes, AudioBuffersState()); | 688 sine.OnMoreData(buffer, kTwoSecBytes, AudioBuffersState()); |
688 | 689 |
689 AudioBuffersState buffers_state; | 690 AudioBuffersState buffers_state; |
690 int times = 0; | 691 int times = 0; |
691 for (int ix = 0; ix < kTwoSecBytes; ix += ctx.packet_size_bytes) { | 692 for (int ix = 0; ix < kTwoSecBytes; ix += ctx.packet_size_bytes) { |
692 if (ctx.socket->Receive(&buffers_state, sizeof(buffers_state)) == 0) | 693 if (ctx.socket->Receive(&buffers_state, sizeof(buffers_state)) == 0) |
693 break; | 694 break; |
694 if ((times > 0) && (buffers_state.pending_bytes < 1000)) __debugbreak(); | 695 if ((times > 0) && (buffers_state.pending_bytes < 1000)) __debugbreak(); |
695 ctx.socket->Send(&buffer[ix], ctx.packet_size_bytes); | 696 ctx.socket->Send(&buffer[ix], ctx.packet_size_bytes); |
696 ++times; | 697 ++times; |
697 } | 698 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 oas->Start(&source); | 742 oas->Start(&source); |
742 | 743 |
743 ::WaitForSingleObject(thread, INFINITE); | 744 ::WaitForSingleObject(thread, INFINITE); |
744 ::CloseHandle(thread); | 745 ::CloseHandle(thread); |
745 | 746 |
746 oas->Stop(); | 747 oas->Stop(); |
747 oas->Close(); | 748 oas->Close(); |
748 } | 749 } |
749 | 750 |
750 } // namespace media | 751 } // namespace media |
OLD | NEW |