| 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> |
| (...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 oas->Close(); | 525 oas->Close(); |
| 526 } | 526 } |
| 527 | 527 |
| 528 // Simple source that uses a SyncSocket to retrieve the audio data | 528 // Simple source that uses a SyncSocket to retrieve the audio data |
| 529 // from a potentially remote thread. | 529 // from a potentially remote thread. |
| 530 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { | 530 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { |
| 531 public: | 531 public: |
| 532 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params) | 532 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params) |
| 533 : socket_(socket), params_(params) { | 533 : socket_(socket), params_(params) { |
| 534 // Setup AudioBus wrapping data we'll receive over the sync socket. | 534 // Setup AudioBus wrapping data we'll receive over the sync socket. |
| 535 data_size_ = AudioBus::CalculateMemorySize(params); | 535 packet_size_ = AudioBus::CalculateMemorySize(params); |
| 536 data_.reset(static_cast<float*>( | 536 data_.reset(static_cast<float*>( |
| 537 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment))); | 537 base::AlignedAlloc(packet_size_ + sizeof(AudioOutputBufferParameters), |
| 538 audio_bus_ = AudioBus::WrapMemory(params, data_.get()); | 538 AudioBus::kChannelAlignment))); |
| 539 audio_bus_ = AudioBus::WrapMemory(params, output_buffer()->audio); |
| 539 } | 540 } |
| 540 ~SyncSocketSource() override {} | 541 ~SyncSocketSource() override {} |
| 541 | 542 |
| 542 // AudioSourceCallback::OnMoreData implementation: | 543 // AudioSourceCallback::OnMoreData implementation: |
| 543 int OnMoreData(base::TimeDelta delay, | 544 int OnMoreData(base::TimeDelta delay, |
| 544 base::TimeTicks /* delay_timestamp */, | 545 base::TimeTicks delay_timestamp, |
| 545 int /* prior_frames_skipped */, | 546 int /* prior_frames_skipped */, |
| 546 AudioBus* dest) override { | 547 AudioBus* dest) override { |
| 547 uint32_t total_bytes_delay = | 548 uint32_t control_signal = 0; |
| 548 delay.InSecondsF() * params_.GetBytesPerSecond(); | 549 socket_->Send(&control_signal, sizeof(control_signal)); |
| 549 socket_->Send(&total_bytes_delay, sizeof(total_bytes_delay)); | 550 output_buffer()->params.delay = delay.InMicroseconds(); |
| 550 uint32_t size = socket_->Receive(data_.get(), data_size_); | 551 output_buffer()->params.delay_timestamp = |
| 552 (delay_timestamp - base::TimeTicks()).InMicroseconds(); |
| 553 uint32_t size = socket_->Receive(data_.get(), packet_size_); |
| 554 |
| 551 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U); | 555 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U); |
| 552 audio_bus_->CopyTo(dest); | 556 audio_bus_->CopyTo(dest); |
| 553 return audio_bus_->frames(); | 557 return audio_bus_->frames(); |
| 554 } | 558 } |
| 559 int packet_size() const { return packet_size_; } |
| 560 AudioOutputBuffer* output_buffer() const { |
| 561 return reinterpret_cast<AudioOutputBuffer*>(data_.get()); |
| 562 } |
| 555 | 563 |
| 556 // AudioSourceCallback::OnError implementation: | 564 // AudioSourceCallback::OnError implementation: |
| 557 void OnError(AudioOutputStream* stream) override {} | 565 void OnError(AudioOutputStream* stream) override {} |
| 558 | 566 |
| 559 private: | 567 private: |
| 560 base::SyncSocket* socket_; | 568 base::SyncSocket* socket_; |
| 561 const AudioParameters params_; | 569 const AudioParameters params_; |
| 562 int data_size_; | 570 int packet_size_; |
| 563 std::unique_ptr<float, base::AlignedFreeDeleter> data_; | 571 std::unique_ptr<float, base::AlignedFreeDeleter> data_; |
| 564 std::unique_ptr<AudioBus> audio_bus_; | 572 std::unique_ptr<AudioBus> audio_bus_; |
| 565 }; | 573 }; |
| 566 | 574 |
| 567 struct SyncThreadContext { | 575 struct SyncThreadContext { |
| 568 base::SyncSocket* socket; | 576 base::SyncSocket* socket; |
| 569 int sample_rate; | 577 int sample_rate; |
| 570 int channels; | 578 int channels; |
| 571 int frames; | 579 int frames; |
| 572 double sine_freq; | 580 double sine_freq; |
| 573 uint32_t packet_size_bytes; | 581 uint32_t packet_size_bytes; |
| 574 int bytes_per_second; | 582 AudioOutputBuffer* buffer; |
| 575 }; | 583 }; |
| 576 | 584 |
| 577 // This thread provides the data that the SyncSocketSource above needs | 585 // This thread provides the data that the SyncSocketSource above needs |
| 578 // using the other end of a SyncSocket. The protocol is as follows: | 586 // using the other end of a SyncSocket. The protocol is as follows: |
| 579 // | 587 // |
| 580 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread | 588 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread |
| 581 // <--- audio packet ---------- | 589 // <--- audio packet ---------- |
| 582 // | 590 // |
| 583 DWORD __stdcall SyncSocketThread(void* context) { | 591 DWORD __stdcall SyncSocketThread(void* context) { |
| 584 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); | 592 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); |
| 585 | 593 |
| 586 // Setup AudioBus wrapping data we'll pass over the sync socket. | 594 // Setup AudioBus wrapping data we'll pass over the sync socket. |
| 587 std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>( | 595 std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>( |
| 588 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment))); | 596 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment))); |
| 589 std::unique_ptr<AudioBus> audio_bus = | 597 std::unique_ptr<AudioBus> audio_bus = |
| 590 AudioBus::WrapMemory(ctx.channels, ctx.frames, data.get()); | 598 AudioBus::WrapMemory(ctx.channels, ctx.frames, data.get()); |
| 591 | 599 |
| 592 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate); | 600 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate); |
| 593 const int kTwoSecFrames = ctx.sample_rate * 2; | 601 const int kTwoSecFrames = ctx.sample_rate * 2; |
| 594 | 602 |
| 595 uint32_t total_bytes_delay = 0; | 603 uint32_t control_signal = 0; |
| 596 int times = 0; | |
| 597 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) { | 604 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) { |
| 598 if (ctx.socket->Receive(&total_bytes_delay, sizeof(total_bytes_delay)) == 0) | 605 if (ctx.socket->Receive(&control_signal, sizeof(control_signal)) == 0) |
| 599 break; | 606 break; |
| 600 if ((times > 0) && (total_bytes_delay < 1000)) __debugbreak(); | 607 base::TimeDelta delay = |
| 601 base::TimeDelta delay = base::TimeDelta::FromSecondsD( | 608 base::TimeDelta::FromMicroseconds(ctx.buffer->params.delay); |
| 602 static_cast<double>(total_bytes_delay) / ctx.bytes_per_second); | 609 base::TimeTicks delay_timestamp = |
| 603 sine.OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get()); | 610 base::TimeTicks() + |
| 611 base::TimeDelta::FromMicroseconds(ctx.buffer->params.delay_timestamp); |
| 612 sine.OnMoreData(delay, delay_timestamp, 0, audio_bus.get()); |
| 604 ctx.socket->Send(data.get(), ctx.packet_size_bytes); | 613 ctx.socket->Send(data.get(), ctx.packet_size_bytes); |
| 605 ++times; | |
| 606 } | 614 } |
| 607 | 615 |
| 608 return 0; | 616 return 0; |
| 609 } | 617 } |
| 610 | 618 |
| 611 // Test the basic operation of AudioOutputStream used with a SyncSocket. | 619 // Test the basic operation of AudioOutputStream used with a SyncSocket. |
| 612 // The emphasis is to verify that it is possible to feed data to the audio | 620 // The emphasis is to verify that it is possible to feed data to the audio |
| 613 // layer using a source based on SyncSocket. In a real situation we would | 621 // layer using a source based on SyncSocket. In a real situation we would |
| 614 // go for the low-latency version in combination with SyncSocket, but to keep | 622 // go for the low-latency version in combination with SyncSocket, but to keep |
| 615 // the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main | 623 // the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main |
| (...skipping 15 matching lines...) Expand all Loading... |
| 631 ASSERT_TRUE(oas->Open()); | 639 ASSERT_TRUE(oas->Open()); |
| 632 | 640 |
| 633 base::SyncSocket sockets[2]; | 641 base::SyncSocket sockets[2]; |
| 634 ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1])); | 642 ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1])); |
| 635 | 643 |
| 636 SyncSocketSource source(&sockets[0], params); | 644 SyncSocketSource source(&sockets[0], params); |
| 637 | 645 |
| 638 SyncThreadContext thread_context; | 646 SyncThreadContext thread_context; |
| 639 thread_context.sample_rate = params.sample_rate(); | 647 thread_context.sample_rate = params.sample_rate(); |
| 640 thread_context.sine_freq = 200.0; | 648 thread_context.sine_freq = 200.0; |
| 641 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params); | 649 thread_context.packet_size_bytes = source.packet_size(); |
| 642 thread_context.frames = params.frames_per_buffer(); | 650 thread_context.frames = params.frames_per_buffer(); |
| 643 thread_context.channels = params.channels(); | 651 thread_context.channels = params.channels(); |
| 644 thread_context.socket = &sockets[1]; | 652 thread_context.socket = &sockets[1]; |
| 645 thread_context.bytes_per_second = params.GetBytesPerSecond(); | 653 thread_context.buffer = source.output_buffer(); |
| 646 | 654 |
| 647 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, | 655 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, |
| 648 &thread_context, 0, NULL); | 656 &thread_context, 0, NULL); |
| 649 | 657 |
| 650 oas->Start(&source); | 658 oas->Start(&source); |
| 651 | 659 |
| 652 ::WaitForSingleObject(thread, INFINITE); | 660 ::WaitForSingleObject(thread, INFINITE); |
| 653 ::CloseHandle(thread); | 661 ::CloseHandle(thread); |
| 654 | 662 |
| 655 oas->Stop(); | 663 oas->Stop(); |
| 656 oas->Close(); | 664 oas->Close(); |
| 657 } | 665 } |
| 658 | 666 |
| 659 } // namespace media | 667 } // namespace media |
| OLD | NEW |