| 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/memory/aligned_memory.h" | 10 #include "base/memory/aligned_memory.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 using ::testing::NotNull; | 30 using ::testing::NotNull; |
| 31 using ::testing::Return; | 31 using ::testing::Return; |
| 32 | 32 |
| 33 using base::win::ScopedCOMInitializer; | 33 using base::win::ScopedCOMInitializer; |
| 34 | 34 |
| 35 namespace media { | 35 namespace media { |
| 36 | 36 |
| 37 static const wchar_t kAudioFile1_16b_m_16K[] | 37 static const wchar_t kAudioFile1_16b_m_16K[] |
| 38 = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw"; | 38 = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw"; |
| 39 | 39 |
| 40 static int ClearData(AudioBus* audio_bus, AudioBuffersState buffers_state) { | 40 static int ClearData(AudioBus* audio_bus, int total_bytes_delay) { |
| 41 audio_bus->Zero(); | 41 audio_bus->Zero(); |
| 42 return audio_bus->frames(); | 42 return audio_bus->frames(); |
| 43 } | 43 } |
| 44 | 44 |
| 45 // This class allows to find out if the callbacks are occurring as | 45 // This class allows to find out if the callbacks are occurring as |
| 46 // expected and if any error has been reported. | 46 // expected and if any error has been reported. |
| 47 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { | 47 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { |
| 48 public: | 48 public: |
| 49 explicit TestSourceBasic() | 49 explicit TestSourceBasic() |
| 50 : callback_count_(0), | 50 : callback_count_(0), |
| 51 had_error_(0) { | 51 had_error_(0) { |
| 52 } | 52 } |
| 53 // AudioSourceCallback::OnMoreData implementation: | 53 // AudioSourceCallback::OnMoreData implementation: |
| 54 virtual int OnMoreData(AudioBus* audio_bus, | 54 virtual int OnMoreData(AudioBus* audio_bus, |
| 55 AudioBuffersState buffers_state) { | 55 int total_bytes_delay) { |
| 56 ++callback_count_; | 56 ++callback_count_; |
| 57 // Touch the channel memory value to make sure memory is good. | 57 // Touch the channel memory value to make sure memory is good. |
| 58 audio_bus->Zero(); | 58 audio_bus->Zero(); |
| 59 return audio_bus->frames(); | 59 return audio_bus->frames(); |
| 60 } | 60 } |
| 61 // AudioSourceCallback::OnError implementation: | 61 // AudioSourceCallback::OnError implementation: |
| 62 virtual void OnError(AudioOutputStream* stream) { | 62 virtual void OnError(AudioOutputStream* stream) { |
| 63 ++had_error_; | 63 ++had_error_; |
| 64 } | 64 } |
| 65 // Returns how many times OnMoreData() has been called. | 65 // Returns how many times OnMoreData() has been called. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 82 | 82 |
| 83 const int kMaxNumBuffers = 3; | 83 const int kMaxNumBuffers = 3; |
| 84 // Specializes TestSourceBasic to simulate a source that blocks for some time | 84 // Specializes TestSourceBasic to simulate a source that blocks for some time |
| 85 // in the OnMoreData callback. | 85 // in the OnMoreData callback. |
| 86 class TestSourceLaggy : public TestSourceBasic { | 86 class TestSourceLaggy : public TestSourceBasic { |
| 87 public: | 87 public: |
| 88 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms) | 88 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms) |
| 89 : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) { | 89 : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) { |
| 90 } | 90 } |
| 91 virtual int OnMoreData(AudioBus* audio_bus, | 91 virtual int OnMoreData(AudioBus* audio_bus, |
| 92 AudioBuffersState buffers_state) { | 92 int total_bytes_delay) { |
| 93 // Call the base, which increments the callback_count_. | 93 // Call the base, which increments the callback_count_. |
| 94 TestSourceBasic::OnMoreData(audio_bus, buffers_state); | 94 TestSourceBasic::OnMoreData(audio_bus, total_bytes_delay); |
| 95 if (callback_count() > kMaxNumBuffers) { | 95 if (callback_count() > kMaxNumBuffers) { |
| 96 ::Sleep(lag_in_ms_); | 96 ::Sleep(lag_in_ms_); |
| 97 } | 97 } |
| 98 return audio_bus->frames(); | 98 return audio_bus->frames(); |
| 99 } | 99 } |
| 100 private: | 100 private: |
| 101 int laggy_after_buffer_; | 101 int laggy_after_buffer_; |
| 102 int lag_in_ms_; | 102 int lag_in_ms_; |
| 103 }; | 103 }; |
| 104 | 104 |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 uint32 bytes_100_ms = samples_100_ms * 2; | 513 uint32 bytes_100_ms = samples_100_ms * 2; |
| 514 | 514 |
| 515 // Audio output stream has either a double or triple buffer scheme. | 515 // Audio output stream has either a double or triple buffer scheme. |
| 516 // We expect the amount of pending bytes will reaching up to 2 times of | 516 // We expect the amount of pending bytes will reaching up to 2 times of |
| 517 // |bytes_100_ms| depending on number of buffers used. | 517 // |bytes_100_ms| depending on number of buffers used. |
| 518 // From that it would decrease as we are playing the data but not providing | 518 // From that it would decrease as we are playing the data but not providing |
| 519 // new one. And then we will try to provide zero data so the amount of | 519 // new one. And then we will try to provide zero data so the amount of |
| 520 // pending bytes will go down and eventually read zero. | 520 // pending bytes will go down and eventually read zero. |
| 521 InSequence s; | 521 InSequence s; |
| 522 | 522 |
| 523 EXPECT_CALL(source, OnMoreData(NotNull(), | 523 EXPECT_CALL(source, OnMoreData(NotNull(), 0)) |
| 524 Field(&AudioBuffersState::pending_bytes, 0))) | |
| 525 .WillOnce(Invoke(ClearData)); | 524 .WillOnce(Invoke(ClearData)); |
| 526 | 525 |
| 527 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this | 526 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this |
| 528 // test is run on Vista, these expectations will fail. | 527 // test is run on Vista, these expectations will fail. |
| 529 EXPECT_CALL(source, OnMoreData(NotNull(), | 528 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms)) |
| 530 Field(&AudioBuffersState::pending_bytes, | |
| 531 bytes_100_ms))) | |
| 532 .WillOnce(Invoke(ClearData)); | 529 .WillOnce(Invoke(ClearData)); |
| 533 EXPECT_CALL(source, OnMoreData(NotNull(), | 530 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms)) |
| 534 Field(&AudioBuffersState::pending_bytes, | |
| 535 2 * bytes_100_ms))) | |
| 536 .WillOnce(Invoke(ClearData)); | 531 .WillOnce(Invoke(ClearData)); |
| 537 EXPECT_CALL(source, OnMoreData(NotNull(), | 532 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms)) |
| 538 Field(&AudioBuffersState::pending_bytes, | |
| 539 2 * bytes_100_ms))) | |
| 540 .Times(AnyNumber()) | 533 .Times(AnyNumber()) |
| 541 .WillRepeatedly(Return(0)); | 534 .WillRepeatedly(Return(0)); |
| 542 EXPECT_CALL(source, OnMoreData(NotNull(), | 535 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms)) |
| 543 Field(&AudioBuffersState::pending_bytes, | |
| 544 bytes_100_ms))) | |
| 545 .Times(AnyNumber()) | 536 .Times(AnyNumber()) |
| 546 .WillRepeatedly(Return(0)); | 537 .WillRepeatedly(Return(0)); |
| 547 EXPECT_CALL(source, OnMoreData(NotNull(), | 538 EXPECT_CALL(source, OnMoreData(NotNull(), 0)) |
| 548 Field(&AudioBuffersState::pending_bytes, 0))) | |
| 549 .Times(AnyNumber()) | 539 .Times(AnyNumber()) |
| 550 .WillRepeatedly(Return(0)); | 540 .WillRepeatedly(Return(0)); |
| 551 | 541 |
| 552 oas->Start(&source); | 542 oas->Start(&source); |
| 553 ::Sleep(500); | 543 ::Sleep(500); |
| 554 oas->Stop(); | 544 oas->Stop(); |
| 555 oas->Close(); | 545 oas->Close(); |
| 556 } | 546 } |
| 557 | 547 |
| 558 // Simple source that uses a SyncSocket to retrieve the audio data | 548 // Simple source that uses a SyncSocket to retrieve the audio data |
| 559 // from a potentially remote thread. | 549 // from a potentially remote thread. |
| 560 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { | 550 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { |
| 561 public: | 551 public: |
| 562 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params) | 552 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params) |
| 563 : socket_(socket) { | 553 : socket_(socket) { |
| 564 // Setup AudioBus wrapping data we'll receive over the sync socket. | 554 // Setup AudioBus wrapping data we'll receive over the sync socket. |
| 565 data_size_ = AudioBus::CalculateMemorySize(params); | 555 data_size_ = AudioBus::CalculateMemorySize(params); |
| 566 data_.reset(static_cast<float*>( | 556 data_.reset(static_cast<float*>( |
| 567 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment))); | 557 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment))); |
| 568 audio_bus_ = AudioBus::WrapMemory(params, data_.get()); | 558 audio_bus_ = AudioBus::WrapMemory(params, data_.get()); |
| 569 } | 559 } |
| 570 ~SyncSocketSource() {} | 560 ~SyncSocketSource() {} |
| 571 | 561 |
| 572 // AudioSourceCallback::OnMoreData implementation: | 562 // AudioSourceCallback::OnMoreData implementation: |
| 573 virtual int OnMoreData(AudioBus* audio_bus, | 563 virtual int OnMoreData(AudioBus* audio_bus, |
| 574 AudioBuffersState buffers_state) { | 564 int total_bytes_delay) { |
| 575 socket_->Send(&buffers_state, sizeof(buffers_state)); | 565 socket_->Send(&total_bytes_delay, sizeof(total_bytes_delay)); |
| 576 uint32 size = socket_->Receive(data_.get(), data_size_); | 566 uint32 size = socket_->Receive(data_.get(), data_size_); |
| 577 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U); | 567 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U); |
| 578 audio_bus_->CopyTo(audio_bus); | 568 audio_bus_->CopyTo(audio_bus); |
| 579 return audio_bus_->frames(); | 569 return audio_bus_->frames(); |
| 580 } | 570 } |
| 581 virtual int OnMoreIOData(AudioBus* source, | 571 virtual int OnMoreIOData(AudioBus* source, |
| 582 AudioBus* dest, | 572 AudioBus* dest, |
| 583 AudioBuffersState buffers_state) { | 573 int total_bytes_delay) { |
| 584 NOTREACHED(); | 574 NOTREACHED(); |
| 585 return 0; | 575 return 0; |
| 586 } | 576 } |
| 587 // AudioSourceCallback::OnError implementation: | 577 // AudioSourceCallback::OnError implementation: |
| 588 virtual void OnError(AudioOutputStream* stream) { | 578 virtual void OnError(AudioOutputStream* stream) { |
| 589 } | 579 } |
| 590 | 580 |
| 591 private: | 581 private: |
| 592 base::SyncSocket* socket_; | 582 base::SyncSocket* socket_; |
| 593 int data_size_; | 583 int data_size_; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 615 | 605 |
| 616 // Setup AudioBus wrapping data we'll pass over the sync socket. | 606 // Setup AudioBus wrapping data we'll pass over the sync socket. |
| 617 scoped_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>( | 607 scoped_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>( |
| 618 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment))); | 608 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment))); |
| 619 scoped_ptr<AudioBus> audio_bus = AudioBus::WrapMemory( | 609 scoped_ptr<AudioBus> audio_bus = AudioBus::WrapMemory( |
| 620 ctx.channels, ctx.frames, data.get()); | 610 ctx.channels, ctx.frames, data.get()); |
| 621 | 611 |
| 622 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate); | 612 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate); |
| 623 const int kTwoSecFrames = ctx.sample_rate * 2; | 613 const int kTwoSecFrames = ctx.sample_rate * 2; |
| 624 | 614 |
| 625 AudioBuffersState buffers_state; | 615 int total_bytes_delay = 0; |
| 626 int times = 0; | 616 int times = 0; |
| 627 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) { | 617 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) { |
| 628 if (ctx.socket->Receive(&buffers_state, sizeof(buffers_state)) == 0) | 618 if (ctx.socket->Receive(&total_bytes_delay, sizeof(total_bytes_delay)) == 0) |
| 629 break; | 619 break; |
| 630 if ((times > 0) && (buffers_state.pending_bytes < 1000)) __debugbreak(); | 620 if ((times > 0) && (total_bytes_delay < 1000)) __debugbreak(); |
| 631 sine.OnMoreData(audio_bus.get(), buffers_state); | 621 sine.OnMoreData(audio_bus.get(), total_bytes_delay); |
| 632 ctx.socket->Send(data.get(), ctx.packet_size_bytes); | 622 ctx.socket->Send(data.get(), ctx.packet_size_bytes); |
| 633 ++times; | 623 ++times; |
| 634 } | 624 } |
| 635 | 625 |
| 636 return 0; | 626 return 0; |
| 637 } | 627 } |
| 638 | 628 |
| 639 // Test the basic operation of AudioOutputStream used with a SyncSocket. | 629 // Test the basic operation of AudioOutputStream used with a SyncSocket. |
| 640 // The emphasis is to verify that it is possible to feed data to the audio | 630 // The emphasis is to verify that it is possible to feed data to the audio |
| 641 // layer using a source based on SyncSocket. In a real situation we would | 631 // layer using a source based on SyncSocket. In a real situation we would |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 682 oas->Start(&source); | 672 oas->Start(&source); |
| 683 | 673 |
| 684 ::WaitForSingleObject(thread, INFINITE); | 674 ::WaitForSingleObject(thread, INFINITE); |
| 685 ::CloseHandle(thread); | 675 ::CloseHandle(thread); |
| 686 | 676 |
| 687 oas->Stop(); | 677 oas->Stop(); |
| 688 oas->Close(); | 678 oas->Close(); |
| 689 } | 679 } |
| 690 | 680 |
| 691 } // namespace media | 681 } // namespace media |
| OLD | NEW |