| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/audio_debug_file_writer.h" | 5 #include "media/audio/audio_debug_file_writer.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <array> | 8 #include <array> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/sys_byteorder.h" | 14 #include "base/sys_byteorder.h" |
| 15 #include "media/base/audio_bus.h" | 15 #include "media/base/audio_bus.h" |
| 16 #include "media/base/audio_sample_types.h" |
| 16 | 17 |
| 17 namespace media { | 18 namespace media { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 // Windows WAVE format header | 22 // Windows WAVE format header |
| 22 // Byte order: Little-endian | 23 // Byte order: Little-endian |
| 23 // Offset Length Content | 24 // Offset Length Content |
| 24 // 0 4 "RIFF" | 25 // 0 4 "RIFF" |
| 25 // 4 4 <file length - 8> | 26 // 4 4 <file length - 8> |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 void WriteHeader(); | 164 void WriteHeader(); |
| 164 | 165 |
| 165 void CreateRecordingFile(const base::FilePath& file_name); | 166 void CreateRecordingFile(const base::FilePath& file_name); |
| 166 | 167 |
| 167 // The file to write to. | 168 // The file to write to. |
| 168 base::File file_; | 169 base::File file_; |
| 169 | 170 |
| 170 // Number of written samples. | 171 // Number of written samples. |
| 171 uint64_t samples_; | 172 uint64_t samples_; |
| 172 | 173 |
| 173 // Input audio parameters required to build wave header. | 174 // Audio parameters required to build wave header. Number of channels and |
| 175 // sample rate are used. |
| 174 const AudioParameters params_; | 176 const AudioParameters params_; |
| 175 | 177 |
| 176 // Intermediate buffer to be written to file. Interleaved 16 bit audio data. | 178 // Intermediate buffer to be written to file. Interleaved 16 bit audio data. |
| 177 std::unique_ptr<int16_t[]> interleaved_data_; | 179 std::unique_ptr<int16_t[]> interleaved_data_; |
| 178 int interleaved_data_size_; | 180 int interleaved_data_size_; |
| 179 | 181 |
| 180 // The task runner this class operates on. | 182 // The task runner this class operates on. |
| 181 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 183 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 182 }; | 184 }; |
| 183 | 185 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 base::Unretained(file_writer.get()), file_name)); | 225 base::Unretained(file_writer.get()), file_name)); |
| 224 return file_writer; | 226 return file_writer; |
| 225 } | 227 } |
| 226 | 228 |
| 227 AudioDebugFileWriter::AudioFileWriter::AudioFileWriter( | 229 AudioDebugFileWriter::AudioFileWriter::AudioFileWriter( |
| 228 const AudioParameters& params, | 230 const AudioParameters& params, |
| 229 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | 231 scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
| 230 : samples_(0), | 232 : samples_(0), |
| 231 params_(params), | 233 params_(params), |
| 232 interleaved_data_size_(0), | 234 interleaved_data_size_(0), |
| 233 task_runner_(std::move(task_runner)) { | 235 task_runner_(std::move(task_runner)) {} |
| 234 DCHECK_EQ(params.bits_per_sample(), kBytesPerSample * 8); | |
| 235 } | |
| 236 | 236 |
| 237 AudioDebugFileWriter::AudioFileWriter::~AudioFileWriter() { | 237 AudioDebugFileWriter::AudioFileWriter::~AudioFileWriter() { |
| 238 DCHECK(task_runner_->BelongsToCurrentThread()); | 238 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 239 if (file_.IsValid()) | 239 if (file_.IsValid()) |
| 240 WriteHeader(); | 240 WriteHeader(); |
| 241 } | 241 } |
| 242 | 242 |
| 243 void AudioDebugFileWriter::AudioFileWriter::Write(const AudioBus* data) { | 243 void AudioDebugFileWriter::AudioFileWriter::Write(const AudioBus* data) { |
| 244 DCHECK(task_runner_->BelongsToCurrentThread()); | 244 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 245 DCHECK_EQ(params_.channels(), data->channels()); |
| 245 if (!file_.IsValid()) | 246 if (!file_.IsValid()) |
| 246 return; | 247 return; |
| 247 | 248 |
| 248 // Convert to 16 bit audio and write to file. | 249 // Convert to 16 bit audio and write to file. |
| 249 int data_size = data->frames() * data->channels(); | 250 int data_size = data->frames() * data->channels(); |
| 250 if (!interleaved_data_ || interleaved_data_size_ < data_size) { | 251 if (!interleaved_data_ || interleaved_data_size_ < data_size) { |
| 251 interleaved_data_.reset(new int16_t[data_size]); | 252 interleaved_data_.reset(new int16_t[data_size]); |
| 252 interleaved_data_size_ = data_size; | 253 interleaved_data_size_ = data_size; |
| 253 } | 254 } |
| 254 samples_ += data_size; | 255 samples_ += data_size; |
| 255 data->ToInterleaved(data->frames(), sizeof(interleaved_data_[0]), | 256 data->ToInterleaved<media::SignedInt16SampleTypeTraits>( |
| 256 interleaved_data_.get()); | 257 data->frames(), interleaved_data_.get()); |
| 257 | 258 |
| 258 #ifndef ARCH_CPU_LITTLE_ENDIAN | 259 #ifndef ARCH_CPU_LITTLE_ENDIAN |
| 259 static_assert(sizeof(interleaved_data_[0]) == sizeof(uint16_t), | 260 static_assert(sizeof(interleaved_data_[0]) == sizeof(uint16_t), |
| 260 "Only 2 bytes per channel is supported."); | 261 "Only 2 bytes per channel is supported."); |
| 261 for (int i = 0; i < data_size; ++i) | 262 for (int i = 0; i < data_size; ++i) |
| 262 interleaved_data_[i] = base::ByteSwapToLE16(interleaved_data_[i]); | 263 interleaved_data_[i] = base::ByteSwapToLE16(interleaved_data_[i]); |
| 263 #endif | 264 #endif |
| 264 | 265 |
| 265 file_.WriteAtCurrentPos(reinterpret_cast<char*>(interleaved_data_.get()), | 266 file_.WriteAtCurrentPos(reinterpret_cast<char*>(interleaved_data_.get()), |
| 266 data_size * sizeof(interleaved_data_[0])); | 267 data_size * sizeof(interleaved_data_[0])); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 | 343 |
| 343 bool AudioDebugFileWriter::WillWrite() { | 344 bool AudioDebugFileWriter::WillWrite() { |
| 344 // Note that if this is called from any place other than | 345 // Note that if this is called from any place other than |
| 345 // |client_sequence_checker_| then there is a data race here, but it's fine, | 346 // |client_sequence_checker_| then there is a data race here, but it's fine, |
| 346 // because Write() will check for |file_writer_|. So, we are not very precise | 347 // because Write() will check for |file_writer_|. So, we are not very precise |
| 347 // here, but it's fine: we can afford missing some data or scheduling some | 348 // here, but it's fine: we can afford missing some data or scheduling some |
| 348 // no-op writes. | 349 // no-op writes. |
| 349 return !!file_writer_; | 350 return !!file_writer_; |
| 350 } | 351 } |
| 351 | 352 |
| 353 const base::FilePath::CharType* AudioDebugFileWriter::GetFileNameExtension() { |
| 354 return FILE_PATH_LITERAL("wav"); |
| 355 } |
| 356 |
| 352 } // namspace media | 357 } // namspace media |
| OLD | NEW |