| 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 | 
|---|