| 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 |