Index: media/audio/audio_output_resampler.cc |
diff --git a/media/audio/audio_output_resampler.cc b/media/audio/audio_output_resampler.cc |
index 9439a634fcdb45a6e38d32768662c8310a5c888e..dac341336aae2418d989576b355436dc3e8411ee 100644 |
--- a/media/audio/audio_output_resampler.cc |
+++ b/media/audio/audio_output_resampler.cc |
@@ -18,8 +18,10 @@ |
#include "base/metrics/sparse_histogram.h" |
#include "base/numerics/safe_conversions.h" |
#include "base/single_thread_task_runner.h" |
+#include "base/strings/string_number_conversions.h" |
#include "base/trace_event/trace_event.h" |
#include "build/build_config.h" |
+#include "media/audio/audio_debug_recording_helper.h" |
#include "media/audio/audio_output_proxy.h" |
#include "media/audio/sample_rates.h" |
#include "media/base/audio_converter.h" |
@@ -28,12 +30,33 @@ |
namespace media { |
+namespace { |
+ |
+// Running id to append to debug recording filename. |
+int g_next_debug_recording_filename_id = 1; |
+ |
+#if defined(OS_WIN) |
+#define IntToStringType base::IntToString16 |
+#else |
+#define IntToStringType base::IntToString |
+#endif |
+ |
+// Adds debug recording filename running id as an extension. |
+base::FilePath AddDebugRecordingFilenameId(const base::FilePath& file_name) { |
+ return file_name.AddExtension( |
+ IntToStringType(g_next_debug_recording_filename_id++)); |
+} |
+ |
+} // namespace |
+ |
class OnMoreDataConverter |
: public AudioOutputStream::AudioSourceCallback, |
public AudioConverter::InputCallback { |
public: |
- OnMoreDataConverter(const AudioParameters& input_params, |
- const AudioParameters& output_params); |
+ OnMoreDataConverter( |
+ const AudioParameters& input_params, |
+ const AudioParameters& output_params, |
+ std::unique_ptr<AudioDebugRecordingHelper> debug_recording_helper); |
~OnMoreDataConverter() override; |
// AudioSourceCallback interface. |
@@ -50,6 +73,10 @@ class OnMoreDataConverter |
// Clears |source_callback_| and flushes the resampler. |
void Stop(); |
+ // Controls debug recording. |
+ void EnableDebugRecording(const base::FilePath& file_name); |
+ void DisableDebugRecording(); |
+ |
bool started() const { return source_callback_ != nullptr; } |
bool error_occurred() const { return error_occurred_; } |
@@ -84,6 +111,10 @@ class OnMoreDataConverter |
const int input_buffer_size_; |
const int output_buffer_size_; |
+ // Used for audio debug recordings. |
+ std::unique_ptr<AudioDebugRecordingHelper> debug_recording_helper_; |
+ AudioParameters output_params_; |
+ |
DISALLOW_COPY_AND_ASSIGN(OnMoreDataConverter); |
}; |
@@ -221,6 +252,7 @@ AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager, |
const std::string& output_device_id, |
const base::TimeDelta& close_delay) |
: AudioOutputDispatcher(audio_manager, input_params, output_device_id), |
+ audio_manager_(audio_manager), |
close_delay_(close_delay), |
output_params_(output_params), |
original_output_params_(output_params), |
@@ -341,9 +373,17 @@ bool AudioOutputResampler::StartStream( |
OnMoreDataConverter* resampler_callback = nullptr; |
CallbackMap::iterator it = callbacks_.find(stream_proxy); |
if (it == callbacks_.end()) { |
- resampler_callback = new OnMoreDataConverter(params_, output_params_); |
+ resampler_callback = new OnMoreDataConverter( |
+ params_, output_params_, |
+ base::MakeUnique<AudioDebugRecordingHelper>( |
+ audio_manager_, audio_manager_->GetTaskRunner())); |
callbacks_[stream_proxy] = |
base::WrapUnique<OnMoreDataConverter>(resampler_callback); |
+ |
+ // If debug recording is enabled, enable it on the new OnMoreDataConverter. |
+ if (!debug_recording_file_name_.empty()) |
+ resampler_callback->EnableDebugRecording( |
+ AddDebugRecordingFilenameId(debug_recording_file_name_)); |
} else { |
resampler_callback = it->second.get(); |
} |
@@ -387,6 +427,21 @@ void AudioOutputResampler::CloseStream(AudioOutputProxy* stream_proxy) { |
} |
} |
+void AudioOutputResampler::EnableDebugRecording( |
+ const base::FilePath& file_name) { |
+ DCHECK(task_runner_->BelongsToCurrentThread()); |
+ for (const auto& item : callbacks_) |
+ item.second->EnableDebugRecording(AddDebugRecordingFilenameId(file_name)); |
+ debug_recording_file_name_ = file_name; |
+} |
+ |
+void AudioOutputResampler::DisableDebugRecording() { |
+ DCHECK(task_runner_->BelongsToCurrentThread()); |
+ for (const auto& item : callbacks_) |
+ item.second->DisableDebugRecording(); |
+ debug_recording_file_name_.clear(); |
+} |
+ |
void AudioOutputResampler::StopStreamInternal( |
const CallbackMap::value_type& item) { |
AudioOutputProxy* stream_proxy = item.first; |
@@ -408,8 +463,10 @@ void AudioOutputResampler::StopStreamInternal( |
dispatcher_->CloseAllIdleStreams(); |
} |
-OnMoreDataConverter::OnMoreDataConverter(const AudioParameters& input_params, |
- const AudioParameters& output_params) |
+OnMoreDataConverter::OnMoreDataConverter( |
+ const AudioParameters& input_params, |
+ const AudioParameters& output_params, |
+ std::unique_ptr<AudioDebugRecordingHelper> debug_recording_helper) |
: io_ratio_(static_cast<double>(input_params.GetBytesPerSecond()) / |
output_params.GetBytesPerSecond()), |
source_callback_(nullptr), |
@@ -417,7 +474,9 @@ OnMoreDataConverter::OnMoreDataConverter(const AudioParameters& input_params, |
audio_converter_(input_params, output_params, false), |
error_occurred_(false), |
input_buffer_size_(input_params.frames_per_buffer()), |
- output_buffer_size_(output_params.frames_per_buffer()) { |
+ output_buffer_size_(output_params.frames_per_buffer()), |
+ debug_recording_helper_(std::move(debug_recording_helper)), |
+ output_params_(output_params) { |
RecordRebufferingStats(input_params, output_params); |
} |
@@ -454,6 +513,8 @@ int OnMoreDataConverter::OnMoreData(base::TimeDelta delay, |
current_delay_timestamp_ = delay_timestamp; |
audio_converter_.Convert(dest); |
+ debug_recording_helper_->MaybeWrite(dest); |
+ |
// Always return the full number of frames requested, ProvideInput() |
// will pad with silence if it wasn't able to acquire enough data. |
return dest->frames(); |
@@ -480,4 +541,13 @@ void OnMoreDataConverter::OnError(AudioOutputStream* stream) { |
source_callback_->OnError(stream); |
} |
+void OnMoreDataConverter::EnableDebugRecording( |
+ const base::FilePath& file_name) { |
+ debug_recording_helper_->EnableDebugRecording(output_params_, file_name); |
+} |
+ |
+void OnMoreDataConverter::DisableDebugRecording() { |
+ debug_recording_helper_->DisableDebugRecording(); |
+} |
+ |
} // namespace media |