Index: media/audio/fake_audio_input_stream.cc |
diff --git a/media/audio/fake_audio_input_stream.cc b/media/audio/fake_audio_input_stream.cc |
index 4632b258eda2abaf261bb7dba214ab6aba15d8bb..679052d31c17f515eb22629732bab65251be82e8 100644 |
--- a/media/audio/fake_audio_input_stream.cc |
+++ b/media/audio/fake_audio_input_stream.cc |
@@ -5,16 +5,20 @@ |
#include "media/audio/fake_audio_input_stream.h" |
#include "base/bind.h" |
+#include "base/bind_helpers.h" |
#include "base/command_line.h" |
#include "base/files/file.h" |
+#include "base/files/file_path.h" |
#include "base/lazy_instance.h" |
+#include "base/location.h" |
+#include "base/single_thread_task_runner.h" |
+#include "base/time/time.h" |
#include "media/audio/audio_manager_base.h" |
+#include "media/audio/sounds/wav_audio_handler.h" |
#include "media/base/audio_bus.h" |
+#include "media/base/audio_converter.h" |
#include "media/base/media_switches.h" |
-using base::TimeTicks; |
-using base::TimeDelta; |
- |
namespace media { |
namespace { |
@@ -102,95 +106,37 @@ static base::LazyInstance<BeepContext> g_beep_context = |
} // namespace |
-AudioInputStream* FakeAudioInputStream::MakeFakeStream( |
- AudioManagerBase* manager, |
- const AudioParameters& params) { |
- return new FakeAudioInputStream(manager, params); |
-} |
- |
-FakeAudioInputStream::FakeAudioInputStream(AudioManagerBase* manager, |
- const AudioParameters& params) |
- : audio_manager_(manager), |
- callback_(NULL), |
- buffer_size_((params.channels() * params.bits_per_sample() * |
- params.frames_per_buffer()) / |
- 8), |
- params_(params), |
- task_runner_(manager->GetTaskRunner()), |
- callback_interval_(base::TimeDelta::FromMilliseconds( |
- (params.frames_per_buffer() * 1000) / params.sample_rate())), |
- beep_duration_in_buffers_(kBeepDurationMilliseconds * |
- params.sample_rate() / |
- params.frames_per_buffer() / |
- 1000), |
- beep_generated_in_buffers_(0), |
- beep_period_in_frames_(params.sample_rate() / kBeepFrequency), |
- audio_bus_(AudioBus::Create(params)), |
- wav_file_read_pos_(0), |
- weak_factory_(this) { |
- DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
-} |
- |
-FakeAudioInputStream::~FakeAudioInputStream() {} |
- |
-bool FakeAudioInputStream::Open() { |
- DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
- buffer_.reset(new uint8[buffer_size_]); |
- memset(buffer_.get(), 0, buffer_size_); |
- audio_bus_->Zero(); |
- |
- if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kUseFileForFakeAudioCapture)) { |
- OpenInFileMode(base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( |
- switches::kUseFileForFakeAudioCapture)); |
- } |
- |
- return true; |
-} |
- |
-void FakeAudioInputStream::Start(AudioInputCallback* callback) { |
- DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
- DCHECK(!callback_); |
- callback_ = callback; |
- last_callback_time_ = TimeTicks::Now(); |
- |
- task_runner_->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&FakeAudioInputStream::DoCallback, weak_factory_.GetWeakPtr()), |
- callback_interval_); |
-} |
- |
-void FakeAudioInputStream::DoCallback() { |
- DCHECK(callback_); |
- |
- const TimeTicks now = TimeTicks::Now(); |
- base::TimeDelta next_callback_time = |
- last_callback_time_ + callback_interval_ * 2 - now; |
- |
- // If we are falling behind, try to catch up as much as we can in the next |
- // callback. |
- if (next_callback_time < base::TimeDelta()) |
- next_callback_time = base::TimeDelta(); |
+class FakeAudioInputStream::FileSource : public AudioConverter::InputCallback, |
phoglund_chromium
2015/02/18 16:38:15
It felt wrong to toss back all the state into the
DaleCurtis
2015/02/18 19:04:49
Good idea. Take a look at media/audio/simple_sourc
phoglund_chromium
2015/02/19 15:44:10
Sure, done.
|
+ public FakeAudioInputStream::Source { |
+ public: |
+ FileSource(const AudioParameters& params); |
+ ~FileSource() override {} |
- if (PlayingFromFile()) { |
- PlayFile(); |
- } else { |
- PlayBeep(); |
- } |
+ void Open(const base::FilePath& path_to_wav_file); |
+ void PlayInto(AudioBus* audio_bus, int* buffer_size) override; |
- last_callback_time_ = now; |
+ private: |
+ AudioParameters params_; |
+ scoped_ptr<uint8[]> wav_file_data_; |
+ scoped_ptr<media::WavAudioHandler> wav_audio_handler_; |
+ scoped_ptr<media::AudioConverter> file_audio_converter_; |
+ int wav_file_read_pos_; |
+ int buffer_size_; |
+ |
+ // Provides audio data from wav_audio_handler_ into the file audio converter. |
+ double ProvideInput(AudioBus* audio_bus, |
+ base::TimeDelta buffer_delay) override; |
+}; |
- task_runner_->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&FakeAudioInputStream::DoCallback, weak_factory_.GetWeakPtr()), |
- next_callback_time); |
+FakeAudioInputStream::FileSource::FileSource(const AudioParameters& params) |
+ : params_(params), |
+ wav_file_read_pos_(0), |
+ buffer_size_(params.channels() * params.bits_per_sample() * |
+ params.frames_per_buffer() / 8) { |
} |
-void FakeAudioInputStream::OpenInFileMode(const base::FilePath& wav_filename) { |
- CHECK(!wav_filename.empty()) |
- << "You must pass the file to use as argument to --" |
- << switches::kUseFileForFakeAudioCapture << "."; |
- |
+void FakeAudioInputStream::FileSource::Open( |
+ const base::FilePath& wav_filename) { |
// Read the file, and put its data in a scoped_ptr so it gets deleted later. |
size_t file_length = 0; |
wav_file_data_ = ReadWavFile(wav_filename, &file_length); |
@@ -212,22 +158,68 @@ void FakeAudioInputStream::OpenInFileMode(const base::FilePath& wav_filename) { |
file_audio_converter_->AddInput(this); |
} |
-bool FakeAudioInputStream::PlayingFromFile() { |
- return wav_audio_handler_.get() != nullptr; |
-} |
+void FakeAudioInputStream::FileSource::PlayInto(AudioBus* audio_bus, |
+ int* buffer_size) { |
+ DCHECK(wav_audio_handler_.get() != nullptr); |
-void FakeAudioInputStream::PlayFile() { |
// Stop playing if we've played out the whole file. |
if (wav_audio_handler_->AtEnd(wav_file_read_pos_)) |
return; |
- file_audio_converter_->Convert(audio_bus_.get()); |
- callback_->OnData(this, audio_bus_.get(), buffer_size_, 1.0); |
+ // This pulls data from ProvideInput. |
+ file_audio_converter_->Convert(audio_bus); |
+ *buffer_size = buffer_size_; |
} |
-void FakeAudioInputStream::PlayBeep() { |
+double FakeAudioInputStream::FileSource::ProvideInput( |
+ AudioBus* audio_bus_into_converter, |
+ base::TimeDelta buffer_delay) { |
+ // Unfilled frames will be zeroed by CopyTo. |
+ size_t bytes_written; |
+ wav_audio_handler_->CopyTo(audio_bus_into_converter, wav_file_read_pos_, |
+ &bytes_written); |
+ wav_file_read_pos_ += bytes_written; |
+ return 1.0; |
+}; |
+ |
+class FakeAudioInputStream::BeepingSource |
+ : public FakeAudioInputStream::Source { |
+ public: |
+ BeepingSource(const AudioParameters& params); |
+ ~BeepingSource() override {} |
+ |
+ void PlayInto(AudioBus* audio_bus, int* buffer_size) override; |
+ private: |
+ scoped_ptr<uint8[]> buffer_; |
+ int buffer_size_; |
+ AudioParameters params_; |
+ base::TimeTicks last_callback_time_; |
+ base::TimeDelta interval_from_last_beep_; |
+ int beep_duration_in_buffers_; |
+ int beep_generated_in_buffers_; |
+ int beep_period_in_frames_; |
+}; |
+ |
+FakeAudioInputStream::BeepingSource::BeepingSource( |
+ const AudioParameters& params) |
+ : buffer_size_(params.channels() * params.bits_per_sample() * |
+ params.frames_per_buffer() / 8), |
+ params_(params), |
+ beep_duration_in_buffers_(kBeepDurationMilliseconds * |
+ params.sample_rate() / |
+ params.frames_per_buffer() / |
+ 1000), |
+ beep_generated_in_buffers_(0), |
+ beep_period_in_frames_(params.sample_rate() / kBeepFrequency) { |
+ buffer_.reset(new uint8[buffer_size_]); |
+ memset(buffer_.get(), 0, buffer_size_); |
+} |
+ |
+void FakeAudioInputStream::BeepingSource::PlayInto(AudioBus* audio_bus, |
+ int* buffer_size) { |
// Accumulate the time from the last beep. |
- interval_from_last_beep_ += TimeTicks::Now() - last_callback_time_; |
+ interval_from_last_beep_ += base::TimeTicks::Now() - last_callback_time_; |
+ last_callback_time_ = base::TimeTicks::Now(); |
memset(buffer_.get(), 0, buffer_size_); |
bool should_beep = false; |
@@ -235,7 +227,7 @@ void FakeAudioInputStream::PlayBeep() { |
BeepContext* beep_context = g_beep_context.Pointer(); |
if (beep_context->automatic_beep()) { |
base::TimeDelta delta = interval_from_last_beep_ - |
- TimeDelta::FromMilliseconds(kAutomaticBeepIntervalInMs); |
+ base::TimeDelta::FromMilliseconds(kAutomaticBeepIntervalInMs); |
if (delta > base::TimeDelta()) { |
should_beep = true; |
interval_from_last_beep_ = delta; |
@@ -270,19 +262,73 @@ void FakeAudioInputStream::PlayBeep() { |
beep_generated_in_buffers_ = 0; |
} |
- audio_bus_->FromInterleaved( |
- buffer_.get(), audio_bus_->frames(), params_.bits_per_sample() / 8); |
- callback_->OnData(this, audio_bus_.get(), buffer_size_, 1.0); |
+ *buffer_size = buffer_size_; |
phoglund_chromium
2015/02/18 16:38:15
Not sure about this: I do feel the sources know be
DaleCurtis
2015/02/18 19:04:49
I don't think you need this, it seems like an inco
phoglund_chromium
2015/02/19 15:44:11
Just passing 0 seems to work so I'll go with that.
|
+ audio_bus->FromInterleaved( |
+ buffer_.get(), audio_bus->frames(), params_.bits_per_sample() / 8); |
+} |
+ |
+AudioInputStream* FakeAudioInputStream::MakeFakeStream( |
+ AudioManagerBase* manager, |
+ const AudioParameters& params) { |
+ return new FakeAudioInputStream(manager, params); |
+} |
+ |
+FakeAudioInputStream::FakeAudioInputStream(AudioManagerBase* manager, |
+ const AudioParameters& params) |
+ : audio_manager_(manager), |
+ callback_(NULL), |
+ fake_audio_worker_(manager->GetWorkerTaskRunner(), params), |
+ params_(params), |
+ audio_bus_(AudioBus::Create(params)) { |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
+} |
+ |
+FakeAudioInputStream::~FakeAudioInputStream() { |
+ DCHECK(!callback_); |
+} |
+ |
+bool FakeAudioInputStream::Open() { |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
+ audio_bus_->Zero(); |
+ |
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kUseFileForFakeAudioCapture)) { |
+ base::FilePath path_to_wav_file = |
+ base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( |
+ switches::kUseFileForFakeAudioCapture); |
+ CHECK(!path_to_wav_file.empty()) |
+ << "You must pass the file to use as argument to --" |
+ << switches::kUseFileForFakeAudioCapture << "."; |
+ |
+ FileSource* file_source = new FileSource(params_); |
+ audio_source_.reset(file_source); |
+ audio_manager_->GetWorkerTaskRunner()->PostTask( |
phoglund_chromium
2015/02/18 16:38:15
This is the file loading I talked about earlier. A
DaleCurtis
2015/02/18 19:04:49
I think loading the file source on the first callb
phoglund_chromium
2015/02/19 15:44:11
Done.
|
+ FROM_HERE, |
+ base::Bind(&FileSource::Open, |
+ base::Unretained(file_source), |
+ path_to_wav_file)); |
+ } else { |
+ audio_source_.reset(new BeepingSource(params_)); |
+ } |
+ return true; |
+} |
+ |
+void FakeAudioInputStream::Start(AudioInputCallback* callback) { |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
+ callback_ = callback; |
+ fake_audio_worker_.Start(base::Bind( |
+ &FakeAudioInputStream::ReadAudioFromSource, base::Unretained(this))); |
} |
void FakeAudioInputStream::Stop() { |
DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
- weak_factory_.InvalidateWeakPtrs(); |
+ fake_audio_worker_.Stop(); |
callback_ = NULL; |
} |
void FakeAudioInputStream::Close() { |
DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
+ DCHECK(!callback_); |
audio_manager_->ReleaseInputStream(this); |
} |
@@ -313,20 +359,17 @@ bool FakeAudioInputStream::GetAutomaticGainControl() { |
return false; |
} |
-// static |
+void FakeAudioInputStream::ReadAudioFromSource() { |
+ DCHECK(audio_manager_->GetWorkerTaskRunner()->BelongsToCurrentThread()); |
+ DCHECK(callback_); |
+ int buffer_size; |
+ audio_source_->PlayInto(audio_bus_.get(), &buffer_size); |
+ callback_->OnData(this, audio_bus_.get(), buffer_size, 1.0); |
DaleCurtis
2015/02/18 19:04:49
Why are you returning the buffer_size like this? I
phoglund_chromium
2015/02/19 15:44:11
Done.
|
+} |
+ |
void FakeAudioInputStream::BeepOnce() { |
BeepContext* beep_context = g_beep_context.Pointer(); |
beep_context->SetBeepOnce(true); |
} |
-double FakeAudioInputStream::ProvideInput(AudioBus* audio_bus_into_converter, |
- base::TimeDelta buffer_delay) { |
- // Unfilled frames will be zeroed by CopyTo. |
- size_t bytes_written; |
- wav_audio_handler_->CopyTo(audio_bus_into_converter, wav_file_read_pos_, |
- &bytes_written); |
- wav_file_read_pos_ += bytes_written; |
- return 1.0; |
-}; |
- |
} // namespace media |