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 "media/audio/win/audio_low_latency_output_win.h" | 5 #include "media/audio/win/audio_low_latency_output_win.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <mmsystem.h> | 8 #include <mmsystem.h> |
9 #include <stddef.h> | 9 #include <stddef.h> |
10 #include <stdint.h> | 10 #include <stdint.h> |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 size_t elements_written = 0; | 101 size_t elements_written = 0; |
102 while (elements_written < elements_to_write_) { | 102 while (elements_written < elements_to_write_) { |
103 fprintf(text_file_, "%d\n", delta_times_[elements_written]); | 103 fprintf(text_file_, "%d\n", delta_times_[elements_written]); |
104 ++elements_written; | 104 ++elements_written; |
105 } | 105 } |
106 | 106 |
107 base::CloseFile(text_file_); | 107 base::CloseFile(text_file_); |
108 } | 108 } |
109 | 109 |
110 // AudioOutputStream::AudioSourceCallback implementation. | 110 // AudioOutputStream::AudioSourceCallback implementation. |
111 int OnMoreData(AudioBus* audio_bus, | 111 int OnMoreData(base::TimeDelta /* delay */, |
112 uint32_t total_bytes_delay, | 112 base::TimeTicks /* delay_timestamp */, |
113 uint32_t frames_skipped) override { | 113 int /* prior_frames_skipped */, |
| 114 AudioBus* dest) override { |
114 // Store time difference between two successive callbacks in an array. | 115 // Store time difference between two successive callbacks in an array. |
115 // These values will be written to a file in the destructor. | 116 // These values will be written to a file in the destructor. |
116 const base::TimeTicks now_time = base::TimeTicks::Now(); | 117 const base::TimeTicks now_time = base::TimeTicks::Now(); |
117 const int diff = (now_time - previous_call_time_).InMilliseconds(); | 118 const int diff = (now_time - previous_call_time_).InMilliseconds(); |
118 previous_call_time_ = now_time; | 119 previous_call_time_ = now_time; |
119 if (elements_to_write_ < kMaxDeltaSamples) { | 120 if (elements_to_write_ < kMaxDeltaSamples) { |
120 delta_times_[elements_to_write_] = diff; | 121 delta_times_[elements_to_write_] = diff; |
121 ++elements_to_write_; | 122 ++elements_to_write_; |
122 } | 123 } |
123 | 124 |
124 int max_size = | 125 int max_size = dest->frames() * dest->channels() * kBitsPerSample / 8; |
125 audio_bus->frames() * audio_bus->channels() * kBitsPerSample / 8; | |
126 | 126 |
127 // Use samples read from a data file and fill up the audio buffer | 127 // Use samples read from a data file and fill up the audio buffer |
128 // provided to us in the callback. | 128 // provided to us in the callback. |
129 if (pos_ + static_cast<int>(max_size) > file_size()) | 129 if (pos_ + static_cast<int>(max_size) > file_size()) |
130 max_size = file_size() - pos_; | 130 max_size = file_size() - pos_; |
131 int frames = max_size / (audio_bus->channels() * kBitsPerSample / 8); | 131 int frames = max_size / (dest->channels() * kBitsPerSample / 8); |
132 if (max_size) { | 132 if (max_size) { |
133 audio_bus->FromInterleaved( | 133 dest->FromInterleaved(file_->data() + pos_, frames, kBitsPerSample / 8); |
134 file_->data() + pos_, frames, kBitsPerSample / 8); | |
135 pos_ += max_size; | 134 pos_ += max_size; |
136 } | 135 } |
137 return frames; | 136 return frames; |
138 } | 137 } |
139 | 138 |
140 void OnError(AudioOutputStream* stream) override {} | 139 void OnError(AudioOutputStream* stream) override {} |
141 | 140 |
142 int file_size() { return file_->data_size(); } | 141 int file_size() { return file_->data_size(); } |
143 | 142 |
144 private: | 143 private: |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 TEST_F(WASAPIAudioOutputStreamTest, ValidPacketSize) { | 382 TEST_F(WASAPIAudioOutputStreamTest, ValidPacketSize) { |
384 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get())); | 383 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get())); |
385 | 384 |
386 MockAudioSourceCallback source; | 385 MockAudioSourceCallback source; |
387 // Create default WASAPI output stream which plays out in stereo using | 386 // Create default WASAPI output stream which plays out in stereo using |
388 // the shared mixing rate. The default buffer size is 10ms. | 387 // the shared mixing rate. The default buffer size is 10ms. |
389 AudioOutputStreamWrapper aosw(audio_manager_.get()); | 388 AudioOutputStreamWrapper aosw(audio_manager_.get()); |
390 AudioOutputStream* aos = aosw.Create(); | 389 AudioOutputStream* aos = aosw.Create(); |
391 EXPECT_TRUE(aos->Open()); | 390 EXPECT_TRUE(aos->Open()); |
392 | 391 |
393 // Derive the expected size in bytes of each packet. | 392 // Derive the expected duration of each packet. |
394 uint32_t bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 393 base::TimeDelta packet_duration = base::TimeDelta::FromSecondsD( |
395 (aosw.bits_per_sample() / 8); | 394 static_cast<double>(aosw.samples_per_packet()) / aosw.sample_rate()); |
396 | 395 |
397 // Wait for the first callback and verify its parameters. Ignore any | 396 // Wait for the first callback and verify its parameters. Ignore any |
398 // subsequent callbacks that might arrive. | 397 // subsequent callbacks that might arrive. |
399 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(bytes_per_packet), 0)) | 398 EXPECT_CALL(source, |
| 399 OnMoreData(HasValidDelay(packet_duration), _, 0, NotNull())) |
400 .WillOnce(DoAll(QuitLoop(message_loop_.task_runner()), | 400 .WillOnce(DoAll(QuitLoop(message_loop_.task_runner()), |
401 Return(aosw.samples_per_packet()))) | 401 Return(aosw.samples_per_packet()))) |
402 .WillRepeatedly(Return(0)); | 402 .WillRepeatedly(Return(0)); |
403 | 403 |
404 aos->Start(&source); | 404 aos->Start(&source); |
405 message_loop_.task_runner()->PostDelayedTask( | 405 message_loop_.task_runner()->PostDelayedTask( |
406 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), | 406 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), |
407 TestTimeouts::action_timeout()); | 407 TestTimeouts::action_timeout()); |
408 base::RunLoop().Run(); | 408 base::RunLoop().Run(); |
409 aos->Stop(); | 409 aos->Stop(); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 ExclusiveModeIsEnabled()); | 575 ExclusiveModeIsEnabled()); |
576 | 576 |
577 MockAudioSourceCallback source; | 577 MockAudioSourceCallback source; |
578 // Create exclusive-mode WASAPI output stream which plays out in stereo | 578 // Create exclusive-mode WASAPI output stream which plays out in stereo |
579 // using the minimum buffer size at 48kHz sample rate. | 579 // using the minimum buffer size at 48kHz sample rate. |
580 AudioOutputStreamWrapper aosw(audio_manager_.get()); | 580 AudioOutputStreamWrapper aosw(audio_manager_.get()); |
581 AudioOutputStream* aos = aosw.Create(48000, 160); | 581 AudioOutputStream* aos = aosw.Create(48000, 160); |
582 EXPECT_TRUE(aos->Open()); | 582 EXPECT_TRUE(aos->Open()); |
583 | 583 |
584 // Derive the expected size in bytes of each packet. | 584 // Derive the expected size in bytes of each packet. |
585 uint32_t bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 585 base::TimeDelta packet_duration = base::TimeDelta::FromSecondsD( |
586 (aosw.bits_per_sample() / 8); | 586 static_cast<double>(aosw.samples_per_packet()) / aosw.sample_rate()); |
587 | 587 |
588 // Wait for the first callback and verify its parameters. | 588 // Wait for the first callback and verify its parameters. |
589 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(bytes_per_packet), 0)) | 589 EXPECT_CALL(source, |
| 590 OnMoreData(HasValidDelay(packet_duration), _, 0, NotNull())) |
590 .WillOnce(DoAll(QuitLoop(message_loop_.task_runner()), | 591 .WillOnce(DoAll(QuitLoop(message_loop_.task_runner()), |
591 Return(aosw.samples_per_packet()))) | 592 Return(aosw.samples_per_packet()))) |
592 .WillRepeatedly(Return(aosw.samples_per_packet())); | 593 .WillRepeatedly(Return(aosw.samples_per_packet())); |
593 | 594 |
594 aos->Start(&source); | 595 aos->Start(&source); |
595 message_loop_.task_runner()->PostDelayedTask( | 596 message_loop_.task_runner()->PostDelayedTask( |
596 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), | 597 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), |
597 TestTimeouts::action_timeout()); | 598 TestTimeouts::action_timeout()); |
598 base::RunLoop().Run(); | 599 base::RunLoop().Run(); |
599 aos->Stop(); | 600 aos->Stop(); |
600 aos->Close(); | 601 aos->Close(); |
601 } | 602 } |
602 | 603 |
603 // Verify that we can open and start the output stream in exclusive mode at | 604 // Verify that we can open and start the output stream in exclusive mode at |
604 // the lowest possible delay at 44.1kHz. | 605 // the lowest possible delay at 44.1kHz. |
605 // It's disabled by default because a flag is required to enable exclusive mode. | 606 // It's disabled by default because a flag is required to enable exclusive mode. |
606 TEST_F(WASAPIAudioOutputStreamTest, | 607 TEST_F(WASAPIAudioOutputStreamTest, |
607 DISABLED_ExclusiveModeMinBufferSizeAt44kHz) { | 608 DISABLED_ExclusiveModeMinBufferSizeAt44kHz) { |
608 ABORT_AUDIO_TEST_IF_NOT(ExclusiveModeIsEnabled()); | 609 ABORT_AUDIO_TEST_IF_NOT(ExclusiveModeIsEnabled()); |
609 | 610 |
610 MockAudioSourceCallback source; | 611 MockAudioSourceCallback source; |
611 // Create exclusive-mode WASAPI output stream which plays out in stereo | 612 // Create exclusive-mode WASAPI output stream which plays out in stereo |
612 // using the minimum buffer size at 44.1kHz sample rate. | 613 // using the minimum buffer size at 44.1kHz sample rate. |
613 AudioOutputStreamWrapper aosw(audio_manager_.get()); | 614 AudioOutputStreamWrapper aosw(audio_manager_.get()); |
614 AudioOutputStream* aos = aosw.Create(44100, 160); | 615 AudioOutputStream* aos = aosw.Create(44100, 160); |
615 EXPECT_TRUE(aos->Open()); | 616 EXPECT_TRUE(aos->Open()); |
616 | 617 |
617 // Derive the expected size in bytes of each packet. | 618 // Derive the expected size in bytes of each packet. |
618 uint32_t bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * | 619 base::TimeDelta packet_duration = base::TimeDelta::FromSecondsD( |
619 (aosw.bits_per_sample() / 8); | 620 static_cast<double>(aosw.samples_per_packet()) / aosw.sample_rate()); |
620 | 621 |
621 // Wait for the first callback and verify its parameters. | 622 // Wait for the first callback and verify its parameters. |
622 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(bytes_per_packet), 0)) | 623 EXPECT_CALL(source, |
| 624 OnMoreData(HasValidDelay(packet_duration), _, 0, NotNull())) |
623 .WillOnce(DoAll(QuitLoop(message_loop_.task_runner()), | 625 .WillOnce(DoAll(QuitLoop(message_loop_.task_runner()), |
624 Return(aosw.samples_per_packet()))) | 626 Return(aosw.samples_per_packet()))) |
625 .WillRepeatedly(Return(aosw.samples_per_packet())); | 627 .WillRepeatedly(Return(aosw.samples_per_packet())); |
626 | 628 |
627 aos->Start(&source); | 629 aos->Start(&source); |
628 message_loop_.task_runner()->PostDelayedTask( | 630 message_loop_.task_runner()->PostDelayedTask( |
629 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), | 631 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), |
630 TestTimeouts::action_timeout()); | 632 TestTimeouts::action_timeout()); |
631 base::RunLoop().Run(); | 633 base::RunLoop().Run(); |
632 aos->Stop(); | 634 aos->Stop(); |
633 aos->Close(); | 635 aos->Close(); |
634 } | 636 } |
635 | 637 |
636 } // namespace media | 638 } // namespace media |
OLD | NEW |