Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: media/audio/win/audio_output_win_unittest.cc

Issue 2517503003: Reland: Make more media APIs aware of |delay| and |delay_timestamp| (Closed)
Patch Set: Comments from chcunningham@ and Dale Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/audio/null_audio_sink.cc ('k') | media/base/audio_bus_perftest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « media/audio/null_audio_sink.cc ('k') | media/base/audio_bus_perftest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698