| 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 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| 11 | 11 |
| 12 #include "base/base_paths.h" | 12 #include "base/base_paths.h" |
| 13 #include "base/memory/aligned_memory.h" | 13 #include "base/memory/aligned_memory.h" |
| 14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 15 #include "base/run_loop.h" | 15 #include "base/run_loop.h" |
| 16 #include "base/sync_socket.h" | 16 #include "base/sync_socket.h" |
| 17 #include "base/time/time.h" |
| 17 #include "base/win/scoped_com_initializer.h" | 18 #include "base/win/scoped_com_initializer.h" |
| 18 #include "base/win/windows_version.h" | 19 #include "base/win/windows_version.h" |
| 19 #include "media/audio/audio_io.h" | 20 #include "media/audio/audio_io.h" |
| 20 #include "media/audio/audio_manager.h" | 21 #include "media/audio/audio_manager.h" |
| 21 #include "media/audio/audio_unittest_util.h" | 22 #include "media/audio/audio_unittest_util.h" |
| 22 #include "media/audio/mock_audio_source_callback.h" | 23 #include "media/audio/mock_audio_source_callback.h" |
| 23 #include "media/audio/simple_sources.h" | 24 #include "media/audio/simple_sources.h" |
| 24 #include "media/base/limits.h" | 25 #include "media/base/limits.h" |
| 25 #include "testing/gmock/include/gmock/gmock.h" | 26 #include "testing/gmock/include/gmock/gmock.h" |
| 26 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
| 27 | 28 |
| 28 using ::testing::_; | 29 using ::testing::_; |
| 29 using ::testing::AnyNumber; | 30 using ::testing::AnyNumber; |
| 30 using ::testing::DoAll; | 31 using ::testing::DoAll; |
| 31 using ::testing::Field; | 32 using ::testing::Field; |
| 32 using ::testing::Invoke; | 33 using ::testing::Invoke; |
| 33 using ::testing::InSequence; | 34 using ::testing::InSequence; |
| 34 using ::testing::NiceMock; | 35 using ::testing::NiceMock; |
| 35 using ::testing::NotNull; | 36 using ::testing::NotNull; |
| 36 using ::testing::Return; | 37 using ::testing::Return; |
| 37 | 38 |
| 38 namespace media { | 39 namespace media { |
| 39 | 40 |
| 40 static int ClearData(AudioBus* audio_bus, | 41 static int ClearData(base::TimeDelta /* delay */, |
| 41 uint32_t total_bytes_delay, | 42 base::TimeTicks /* delay_timestamp */, |
| 42 uint32_t frames_skipped) { | 43 int /* prior_frames_skipped */, |
| 43 audio_bus->Zero(); | 44 AudioBus* dest) { |
| 44 return audio_bus->frames(); | 45 dest->Zero(); |
| 46 return dest->frames(); |
| 45 } | 47 } |
| 46 | 48 |
| 47 // This class allows to find out if the callbacks are occurring as | 49 // This class allows to find out if the callbacks are occurring as |
| 48 // expected and if any error has been reported. | 50 // expected and if any error has been reported. |
| 49 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { | 51 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { |
| 50 public: | 52 public: |
| 51 TestSourceBasic() | 53 TestSourceBasic() |
| 52 : callback_count_(0), | 54 : callback_count_(0), |
| 53 had_error_(0) { | 55 had_error_(0) { |
| 54 } | 56 } |
| 55 // AudioSourceCallback::OnMoreData implementation: | 57 // AudioSourceCallback::OnMoreData implementation: |
| 56 int OnMoreData(AudioBus* audio_bus, | 58 int OnMoreData(base::TimeDelta /* delay */, |
| 57 uint32_t total_bytes_delay, | 59 base::TimeTicks /* delay_timestamp */, |
| 58 uint32_t frames_skipped) override { | 60 int /* prior_frames_skipped */, |
| 61 AudioBus* dest) override { |
| 59 ++callback_count_; | 62 ++callback_count_; |
| 60 // Touch the channel memory value to make sure memory is good. | 63 // Touch the channel memory value to make sure memory is good. |
| 61 audio_bus->Zero(); | 64 dest->Zero(); |
| 62 return audio_bus->frames(); | 65 return dest->frames(); |
| 63 } | 66 } |
| 64 // AudioSourceCallback::OnError implementation: | 67 // AudioSourceCallback::OnError implementation: |
| 65 void OnError(AudioOutputStream* stream) override { ++had_error_; } | 68 void OnError(AudioOutputStream* stream) override { ++had_error_; } |
| 66 // Returns how many times OnMoreData() has been called. | 69 // Returns how many times OnMoreData() has been called. |
| 67 int callback_count() const { | 70 int callback_count() const { |
| 68 return callback_count_; | 71 return callback_count_; |
| 69 } | 72 } |
| 70 // Returns how many times the OnError callback was called. | 73 // Returns how many times the OnError callback was called. |
| 71 int had_error() const { | 74 int had_error() const { |
| 72 return had_error_; | 75 return had_error_; |
| 73 } | 76 } |
| 74 | 77 |
| 75 void set_error(bool error) { | 78 void set_error(bool error) { |
| 76 had_error_ += error ? 1 : 0; | 79 had_error_ += error ? 1 : 0; |
| 77 } | 80 } |
| 78 | 81 |
| 79 private: | 82 private: |
| 80 int callback_count_; | 83 int callback_count_; |
| 81 int had_error_; | 84 int had_error_; |
| 82 }; | 85 }; |
| 83 | 86 |
| 84 const int kMaxNumBuffers = 3; | 87 const int kMaxNumBuffers = 3; |
| 85 // Specializes TestSourceBasic to simulate a source that blocks for some time | 88 // Specializes TestSourceBasic to simulate a source that blocks for some time |
| 86 // in the OnMoreData callback. | 89 // in the OnMoreData callback. |
| 87 class TestSourceLaggy : public TestSourceBasic { | 90 class TestSourceLaggy : public TestSourceBasic { |
| 88 public: | 91 public: |
| 89 explicit TestSourceLaggy(int lag_in_ms) | 92 explicit TestSourceLaggy(int lag_in_ms) |
| 90 : lag_in_ms_(lag_in_ms) { | 93 : lag_in_ms_(lag_in_ms) { |
| 91 } | 94 } |
| 92 int OnMoreData(AudioBus* audio_bus, | 95 int OnMoreData(base::TimeDelta delay, |
| 93 uint32_t total_bytes_delay, | 96 base::TimeTicks delay_timestamp, |
| 94 uint32_t frames_skipped) override { | 97 int prior_frames_skipped, |
| 98 AudioBus* dest) override { |
| 95 // Call the base, which increments the callback_count_. | 99 // Call the base, which increments the callback_count_. |
| 96 TestSourceBasic::OnMoreData(audio_bus, total_bytes_delay, frames_skipped); | 100 TestSourceBasic::OnMoreData(delay, delay_timestamp, prior_frames_skipped, |
| 101 dest); |
| 97 if (callback_count() > kMaxNumBuffers) { | 102 if (callback_count() > kMaxNumBuffers) { |
| 98 ::Sleep(lag_in_ms_); | 103 ::Sleep(lag_in_ms_); |
| 99 } | 104 } |
| 100 return audio_bus->frames(); | 105 return dest->frames(); |
| 101 } | 106 } |
| 102 private: | 107 private: |
| 103 int lag_in_ms_; | 108 int lag_in_ms_; |
| 104 }; | 109 }; |
| 105 | 110 |
| 106 // Helper class to memory map an entire file. The mapping is read-only. Don't | 111 // Helper class to memory map an entire file. The mapping is read-only. Don't |
| 107 // use for gigabyte-sized files. Attempts to write to this memory generate | 112 // use for gigabyte-sized files. Attempts to write to this memory generate |
| 108 // memory access violations. | 113 // memory access violations. |
| 109 class ReadOnlyMappedFile { | 114 class ReadOnlyMappedFile { |
| 110 public: | 115 public: |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 uint32_t samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; | 485 uint32_t samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; |
| 481 AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream( | 486 AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream( |
| 482 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, | 487 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, |
| 483 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms), | 488 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms), |
| 484 std::string(), AudioManager::LogCallback()); | 489 std::string(), AudioManager::LogCallback()); |
| 485 ASSERT_TRUE(NULL != oas); | 490 ASSERT_TRUE(NULL != oas); |
| 486 | 491 |
| 487 NiceMock<MockAudioSourceCallback> source; | 492 NiceMock<MockAudioSourceCallback> source; |
| 488 EXPECT_TRUE(oas->Open()); | 493 EXPECT_TRUE(oas->Open()); |
| 489 | 494 |
| 490 uint32_t bytes_100_ms = samples_100_ms * 2; | 495 const base::TimeDelta delay_100_ms = base::TimeDelta::FromMilliseconds(100); |
| 496 const base::TimeDelta delay_200_ms = base::TimeDelta::FromMilliseconds(200); |
| 491 | 497 |
| 492 // Audio output stream has either a double or triple buffer scheme. | 498 // Audio output stream has either a double or triple buffer scheme. We expect |
| 493 // We expect the amount of pending bytes will reaching up to 2 times of | 499 // the delay to reach up to 200 ms depending on the number of buffers used. |
| 494 // |bytes_100_ms| depending on number of buffers used. | |
| 495 // From that it would decrease as we are playing the data but not providing | 500 // From that it would decrease as we are playing the data but not providing |
| 496 // new one. And then we will try to provide zero data so the amount of | 501 // new one. And then we will try to provide zero data so the amount of |
| 497 // pending bytes will go down and eventually read zero. | 502 // pending bytes will go down and eventually read zero. |
| 498 InSequence s; | 503 InSequence s; |
| 499 | 504 |
| 500 EXPECT_CALL(source, OnMoreData(NotNull(), 0, 0)).WillOnce(Invoke(ClearData)); | 505 EXPECT_CALL(source, OnMoreData(base::TimeDelta(), _, 0, NotNull())) |
| 506 .WillOnce(Invoke(ClearData)); |
| 501 | 507 |
| 502 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this | 508 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this |
| 503 // test is run on Vista, these expectations will fail. | 509 // test is run on Vista, these expectations will fail. |
| 504 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 0)) | 510 EXPECT_CALL(source, OnMoreData(delay_100_ms, _, 0, NotNull())) |
| 505 .WillOnce(Invoke(ClearData)); | 511 .WillOnce(Invoke(ClearData)); |
| 506 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms, 0)) | 512 EXPECT_CALL(source, OnMoreData(delay_200_ms, _, 0, NotNull())) |
| 507 .WillOnce(Invoke(ClearData)); | 513 .WillOnce(Invoke(ClearData)); |
| 508 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms, 0)) | 514 EXPECT_CALL(source, OnMoreData(delay_200_ms, _, 0, NotNull())) |
| 509 .Times(AnyNumber()) | 515 .Times(AnyNumber()) |
| 510 .WillRepeatedly(Return(0)); | 516 .WillRepeatedly(Return(0)); |
| 511 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 0)) | 517 EXPECT_CALL(source, OnMoreData(delay_100_ms, _, 0, NotNull())) |
| 512 .Times(AnyNumber()) | 518 .Times(AnyNumber()) |
| 513 .WillRepeatedly(Return(0)); | 519 .WillRepeatedly(Return(0)); |
| 514 EXPECT_CALL(source, OnMoreData(NotNull(), 0, 0)) | 520 EXPECT_CALL(source, OnMoreData(base::TimeDelta(), _, 0, NotNull())) |
| 515 .Times(AnyNumber()) | 521 .Times(AnyNumber()) |
| 516 .WillRepeatedly(Return(0)); | 522 .WillRepeatedly(Return(0)); |
| 517 | 523 |
| 518 oas->Start(&source); | 524 oas->Start(&source); |
| 519 ::Sleep(500); | 525 ::Sleep(500); |
| 520 oas->Stop(); | 526 oas->Stop(); |
| 521 oas->Close(); | 527 oas->Close(); |
| 522 } | 528 } |
| 523 | 529 |
| 524 // Simple source that uses a SyncSocket to retrieve the audio data | 530 // Simple source that uses a SyncSocket to retrieve the audio data |
| 525 // from a potentially remote thread. | 531 // from a potentially remote thread. |
| 526 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { | 532 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { |
| 527 public: | 533 public: |
| 528 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params) | 534 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params) |
| 529 : socket_(socket) { | 535 : socket_(socket), params_(params) { |
| 530 // Setup AudioBus wrapping data we'll receive over the sync socket. | 536 // Setup AudioBus wrapping data we'll receive over the sync socket. |
| 531 data_size_ = AudioBus::CalculateMemorySize(params); | 537 data_size_ = AudioBus::CalculateMemorySize(params); |
| 532 data_.reset(static_cast<float*>( | 538 data_.reset(static_cast<float*>( |
| 533 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment))); | 539 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment))); |
| 534 audio_bus_ = AudioBus::WrapMemory(params, data_.get()); | 540 audio_bus_ = AudioBus::WrapMemory(params, data_.get()); |
| 535 } | 541 } |
| 536 ~SyncSocketSource() override {} | 542 ~SyncSocketSource() override {} |
| 537 | 543 |
| 538 // AudioSourceCallback::OnMoreData implementation: | 544 // AudioSourceCallback::OnMoreData implementation: |
| 539 int OnMoreData(AudioBus* audio_bus, | 545 int OnMoreData(base::TimeDelta delay, |
| 540 uint32_t total_bytes_delay, | 546 base::TimeTicks /* delay_timestamp */, |
| 541 uint32_t frames_skipped) override { | 547 int /* prior_frames_skipped */, |
| 548 AudioBus* dest) override { |
| 549 uint32_t total_bytes_delay = |
| 550 delay.InSecondsF() * params_.GetBytesPerSecond(); |
| 542 socket_->Send(&total_bytes_delay, sizeof(total_bytes_delay)); | 551 socket_->Send(&total_bytes_delay, sizeof(total_bytes_delay)); |
| 543 uint32_t size = socket_->Receive(data_.get(), data_size_); | 552 uint32_t size = socket_->Receive(data_.get(), data_size_); |
| 544 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U); | 553 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U); |
| 545 audio_bus_->CopyTo(audio_bus); | 554 audio_bus_->CopyTo(dest); |
| 546 return audio_bus_->frames(); | 555 return audio_bus_->frames(); |
| 547 } | 556 } |
| 548 | 557 |
| 549 // AudioSourceCallback::OnError implementation: | 558 // AudioSourceCallback::OnError implementation: |
| 550 void OnError(AudioOutputStream* stream) override {} | 559 void OnError(AudioOutputStream* stream) override {} |
| 551 | 560 |
| 552 private: | 561 private: |
| 553 base::SyncSocket* socket_; | 562 base::SyncSocket* socket_; |
| 563 const AudioParameters params_; |
| 554 int data_size_; | 564 int data_size_; |
| 555 std::unique_ptr<float, base::AlignedFreeDeleter> data_; | 565 std::unique_ptr<float, base::AlignedFreeDeleter> data_; |
| 556 std::unique_ptr<AudioBus> audio_bus_; | 566 std::unique_ptr<AudioBus> audio_bus_; |
| 557 }; | 567 }; |
| 558 | 568 |
| 559 struct SyncThreadContext { | 569 struct SyncThreadContext { |
| 560 base::SyncSocket* socket; | 570 base::SyncSocket* socket; |
| 561 int sample_rate; | 571 int sample_rate; |
| 562 int channels; | 572 int channels; |
| 563 int frames; | 573 int frames; |
| 564 double sine_freq; | 574 double sine_freq; |
| 565 uint32_t packet_size_bytes; | 575 uint32_t packet_size_bytes; |
| 576 int bytes_per_second; |
| 566 }; | 577 }; |
| 567 | 578 |
| 568 // This thread provides the data that the SyncSocketSource above needs | 579 // This thread provides the data that the SyncSocketSource above needs |
| 569 // using the other end of a SyncSocket. The protocol is as follows: | 580 // using the other end of a SyncSocket. The protocol is as follows: |
| 570 // | 581 // |
| 571 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread | 582 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread |
| 572 // <--- audio packet ---------- | 583 // <--- audio packet ---------- |
| 573 // | 584 // |
| 574 DWORD __stdcall SyncSocketThread(void* context) { | 585 DWORD __stdcall SyncSocketThread(void* context) { |
| 575 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); | 586 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); |
| 576 | 587 |
| 577 // Setup AudioBus wrapping data we'll pass over the sync socket. | 588 // Setup AudioBus wrapping data we'll pass over the sync socket. |
| 578 std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>( | 589 std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>( |
| 579 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment))); | 590 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment))); |
| 580 std::unique_ptr<AudioBus> audio_bus = | 591 std::unique_ptr<AudioBus> audio_bus = |
| 581 AudioBus::WrapMemory(ctx.channels, ctx.frames, data.get()); | 592 AudioBus::WrapMemory(ctx.channels, ctx.frames, data.get()); |
| 582 | 593 |
| 583 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate); | 594 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate); |
| 584 const int kTwoSecFrames = ctx.sample_rate * 2; | 595 const int kTwoSecFrames = ctx.sample_rate * 2; |
| 585 | 596 |
| 586 uint32_t total_bytes_delay = 0; | 597 uint32_t total_bytes_delay = 0; |
| 587 int times = 0; | 598 int times = 0; |
| 588 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) { | 599 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) { |
| 589 if (ctx.socket->Receive(&total_bytes_delay, sizeof(total_bytes_delay)) == 0) | 600 if (ctx.socket->Receive(&total_bytes_delay, sizeof(total_bytes_delay)) == 0) |
| 590 break; | 601 break; |
| 591 if ((times > 0) && (total_bytes_delay < 1000)) __debugbreak(); | 602 if ((times > 0) && (total_bytes_delay < 1000)) __debugbreak(); |
| 592 sine.OnMoreData(audio_bus.get(), total_bytes_delay, 0); | 603 base::TimeDelta delay = base::TimeDelta::FromSecondsD( |
| 604 static_cast<double>(total_bytes_delay) / ctx.bytes_per_second); |
| 605 sine.OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get()); |
| 593 ctx.socket->Send(data.get(), ctx.packet_size_bytes); | 606 ctx.socket->Send(data.get(), ctx.packet_size_bytes); |
| 594 ++times; | 607 ++times; |
| 595 } | 608 } |
| 596 | 609 |
| 597 return 0; | 610 return 0; |
| 598 } | 611 } |
| 599 | 612 |
| 600 // Test the basic operation of AudioOutputStream used with a SyncSocket. | 613 // Test the basic operation of AudioOutputStream used with a SyncSocket. |
| 601 // The emphasis is to verify that it is possible to feed data to the audio | 614 // The emphasis is to verify that it is possible to feed data to the audio |
| 602 // layer using a source based on SyncSocket. In a real situation we would | 615 // layer using a source based on SyncSocket. In a real situation we would |
| (...skipping 21 matching lines...) Expand all Loading... |
| 624 | 637 |
| 625 SyncSocketSource source(&sockets[0], params); | 638 SyncSocketSource source(&sockets[0], params); |
| 626 | 639 |
| 627 SyncThreadContext thread_context; | 640 SyncThreadContext thread_context; |
| 628 thread_context.sample_rate = params.sample_rate(); | 641 thread_context.sample_rate = params.sample_rate(); |
| 629 thread_context.sine_freq = 200.0; | 642 thread_context.sine_freq = 200.0; |
| 630 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params); | 643 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params); |
| 631 thread_context.frames = params.frames_per_buffer(); | 644 thread_context.frames = params.frames_per_buffer(); |
| 632 thread_context.channels = params.channels(); | 645 thread_context.channels = params.channels(); |
| 633 thread_context.socket = &sockets[1]; | 646 thread_context.socket = &sockets[1]; |
| 647 thread_context.bytes_per_second = params.GetBytesPerSecond(); |
| 634 | 648 |
| 635 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, | 649 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, |
| 636 &thread_context, 0, NULL); | 650 &thread_context, 0, NULL); |
| 637 | 651 |
| 638 oas->Start(&source); | 652 oas->Start(&source); |
| 639 | 653 |
| 640 ::WaitForSingleObject(thread, INFINITE); | 654 ::WaitForSingleObject(thread, INFINITE); |
| 641 ::CloseHandle(thread); | 655 ::CloseHandle(thread); |
| 642 | 656 |
| 643 oas->Stop(); | 657 oas->Stop(); |
| 644 oas->Close(); | 658 oas->Close(); |
| 645 } | 659 } |
| 646 | 660 |
| 647 } // namespace media | 661 } // namespace media |
| OLD | NEW |