Chromium Code Reviews| 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 "content/browser/renderer_host/media/audio_input_sync_writer.h" | 5 #include "content/browser/renderer_host/media/audio_input_sync_writer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 std::string log_string = base::StringPrintf( | 112 std::string log_string = base::StringPrintf( |
| 113 "AISW: number of detected audio glitches: %" PRIuS " out of %" PRIuS, | 113 "AISW: number of detected audio glitches: %" PRIuS " out of %" PRIuS, |
| 114 write_error_count_, write_count_); | 114 write_error_count_, write_count_); |
| 115 MediaStreamManager::SendMessageToNativeLog(log_string); | 115 MediaStreamManager::SendMessageToNativeLog(log_string); |
| 116 DVLOG(1) << log_string; | 116 DVLOG(1) << log_string; |
| 117 } | 117 } |
| 118 | 118 |
| 119 void AudioInputSyncWriter::Write(const AudioBus* data, | 119 void AudioInputSyncWriter::Write(const AudioBus* data, |
| 120 double volume, | 120 double volume, |
| 121 bool key_pressed, | 121 bool key_pressed, |
| 122 uint32_t hardware_delay_bytes) { | 122 base::TimeDelta delay, |
| 123 base::TimeTicks delay_timestamp) { | |
| 123 TRACE_EVENT0("audio", "AudioInputSyncWriter::Write"); | 124 TRACE_EVENT0("audio", "AudioInputSyncWriter::Write"); |
| 124 ++write_count_; | 125 ++write_count_; |
| 125 CheckTimeSinceLastWrite(); | 126 CheckTimeSinceLastWrite(); |
| 126 | 127 |
| 127 // Check that the renderer side has read data so that we don't overwrite data | 128 // Check that the renderer side has read data so that we don't overwrite data |
| 128 // that hasn't been read yet. The renderer side sends a signal over the socket | 129 // that hasn't been read yet. The renderer side sends a signal over the socket |
| 129 // each time it has read data. Here, we read those verifications before | 130 // each time it has read data. Here, we read those verifications before |
| 130 // writing. We verify that each buffer index is in sequence. | 131 // writing. We verify that each buffer index is in sequence. |
| 131 size_t number_of_indices_available = socket_->Peek() / sizeof(uint32_t); | 132 size_t number_of_indices_available = socket_->Peek() / sizeof(uint32_t); |
| 132 if (number_of_indices_available > 0) { | 133 if (number_of_indices_available > 0) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 143 CHECK_GE(number_of_filled_segments_, 0); | 144 CHECK_GE(number_of_filled_segments_, 0); |
| 144 } | 145 } |
| 145 } | 146 } |
| 146 | 147 |
| 147 bool write_error = !WriteDataFromFifoToSharedMemory(); | 148 bool write_error = !WriteDataFromFifoToSharedMemory(); |
| 148 | 149 |
| 149 // Write the current data to the shared memory if there is room, otherwise | 150 // Write the current data to the shared memory if there is room, otherwise |
| 150 // put it in the fifo. | 151 // put it in the fifo. |
| 151 if (number_of_filled_segments_ < | 152 if (number_of_filled_segments_ < |
| 152 static_cast<int>(shared_memory_segment_count_)) { | 153 static_cast<int>(shared_memory_segment_count_)) { |
| 153 WriteParametersToCurrentSegment(volume, key_pressed, hardware_delay_bytes); | 154 WriteParametersToCurrentSegment(volume, key_pressed, delay, |
| 155 delay_timestamp); | |
| 154 | 156 |
| 155 // Copy data into shared memory using pre-allocated audio buses. | 157 // Copy data into shared memory using pre-allocated audio buses. |
| 156 AudioBus* audio_bus = audio_buses_[current_segment_id_]; | 158 AudioBus* audio_bus = audio_buses_[current_segment_id_]; |
| 157 data->CopyTo(audio_bus); | 159 data->CopyTo(audio_bus); |
| 158 | 160 |
| 159 if (!SignalDataWrittenAndUpdateCounters()) | 161 if (!SignalDataWrittenAndUpdateCounters()) |
| 160 write_error = true; | 162 write_error = true; |
| 161 | 163 |
| 162 trailing_write_to_fifo_count_ = 0; | 164 trailing_write_to_fifo_count_ = 0; |
| 163 } else { | 165 } else { |
| 164 if (!PushDataToFifo(data, volume, key_pressed, hardware_delay_bytes)) | 166 if (!PushDataToFifo(data, volume, key_pressed, delay, delay_timestamp)) |
| 165 write_error = true; | 167 write_error = true; |
| 166 | 168 |
| 167 ++write_to_fifo_count_; | 169 ++write_to_fifo_count_; |
| 168 ++trailing_write_to_fifo_count_; | 170 ++trailing_write_to_fifo_count_; |
| 169 } | 171 } |
| 170 | 172 |
| 171 // Increase write error counts if error, or reset the trailing error counter | 173 // Increase write error counts if error, or reset the trailing error counter |
| 172 // if all write operations went well (no data dropped). | 174 // if all write operations went well (no data dropped). |
| 173 if (write_error) { | 175 if (write_error) { |
| 174 ++write_error_count_; | 176 ++write_error_count_; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 224 #endif | 226 #endif |
| 225 } | 227 } |
| 226 | 228 |
| 227 void AudioInputSyncWriter::AddToNativeLog(const std::string& message) { | 229 void AudioInputSyncWriter::AddToNativeLog(const std::string& message) { |
| 228 MediaStreamManager::SendMessageToNativeLog(message); | 230 MediaStreamManager::SendMessageToNativeLog(message); |
| 229 } | 231 } |
| 230 | 232 |
| 231 bool AudioInputSyncWriter::PushDataToFifo(const AudioBus* data, | 233 bool AudioInputSyncWriter::PushDataToFifo(const AudioBus* data, |
| 232 double volume, | 234 double volume, |
| 233 bool key_pressed, | 235 bool key_pressed, |
| 234 uint32_t hardware_delay_bytes) { | 236 base::TimeDelta delay, |
| 237 base::TimeTicks delay_timestamp) { | |
| 235 if (overflow_buses_.size() == kMaxOverflowBusesSize) { | 238 if (overflow_buses_.size() == kMaxOverflowBusesSize) { |
| 236 // We use |write_error_count_| for capping number of log messages. | 239 // We use |write_error_count_| for capping number of log messages. |
| 237 // |write_error_count_| also includes socket Send() errors, but those should | 240 // |write_error_count_| also includes socket Send() errors, but those should |
| 238 // be rare. | 241 // be rare. |
| 239 if (write_error_count_ <= 50) { | 242 if (write_error_count_ <= 50) { |
| 240 const std::string error_message = "AISW: No room in fifo."; | 243 const std::string error_message = "AISW: No room in fifo."; |
| 241 LOG(WARNING) << error_message; | 244 LOG(WARNING) << error_message; |
| 242 AddToNativeLog(error_message); | 245 AddToNativeLog(error_message); |
| 243 if (write_error_count_ == 50) { | 246 if (write_error_count_ == 50) { |
| 244 const std::string error_message = | 247 const std::string error_message = |
| 245 "AISW: Log cap reached, suppressing further fifo overflow logs."; | 248 "AISW: Log cap reached, suppressing further fifo overflow logs."; |
| 246 LOG(WARNING) << error_message; | 249 LOG(WARNING) << error_message; |
| 247 AddToNativeLog(error_message); | 250 AddToNativeLog(error_message); |
| 248 } | 251 } |
| 249 } | 252 } |
| 250 return false; | 253 return false; |
| 251 } | 254 } |
| 252 | 255 |
| 253 if (overflow_buses_.empty()) { | 256 if (overflow_buses_.empty()) { |
| 254 const std::string message = "AISW: Starting to use fifo."; | 257 const std::string message = "AISW: Starting to use fifo."; |
| 255 DVLOG(1) << message; | 258 DVLOG(1) << message; |
| 256 AddToNativeLog(message); | 259 AddToNativeLog(message); |
| 257 } | 260 } |
| 258 | 261 |
| 259 // Push parameters to fifo. | 262 // Push parameters to fifo. |
| 260 OverflowParams params = { volume, hardware_delay_bytes, key_pressed }; | 263 OverflowParams params = {volume, delay, delay_timestamp, key_pressed}; |
| 261 overflow_params_.push_back(params); | 264 overflow_params_.push_back(params); |
| 262 | 265 |
| 263 // Push audio data to fifo. | 266 // Push audio data to fifo. |
| 264 std::unique_ptr<AudioBus> audio_bus = | 267 std::unique_ptr<AudioBus> audio_bus = |
| 265 AudioBus::Create(data->channels(), data->frames()); | 268 AudioBus::Create(data->channels(), data->frames()); |
| 266 data->CopyTo(audio_bus.get()); | 269 data->CopyTo(audio_bus.get()); |
| 267 overflow_buses_.push_back(std::move(audio_bus)); | 270 overflow_buses_.push_back(std::move(audio_bus)); |
| 268 | 271 |
| 269 DCHECK_LE(overflow_buses_.size(), static_cast<size_t>(kMaxOverflowBusesSize)); | 272 DCHECK_LE(overflow_buses_.size(), static_cast<size_t>(kMaxOverflowBusesSize)); |
| 270 DCHECK_EQ(overflow_params_.size(), overflow_buses_.size()); | 273 DCHECK_EQ(overflow_params_.size(), overflow_buses_.size()); |
| 271 | 274 |
| 272 return true; | 275 return true; |
| 273 } | 276 } |
| 274 | 277 |
| 275 bool AudioInputSyncWriter::WriteDataFromFifoToSharedMemory() { | 278 bool AudioInputSyncWriter::WriteDataFromFifoToSharedMemory() { |
| 276 if (overflow_buses_.empty()) | 279 if (overflow_buses_.empty()) |
| 277 return true; | 280 return true; |
| 278 | 281 |
| 279 const int segment_count = static_cast<int>(shared_memory_segment_count_); | 282 const int segment_count = static_cast<int>(shared_memory_segment_count_); |
| 280 bool write_error = false; | 283 bool write_error = false; |
| 281 auto params_it = overflow_params_.begin(); | 284 auto params_it = overflow_params_.begin(); |
| 282 auto audio_bus_it = overflow_buses_.begin(); | 285 auto audio_bus_it = overflow_buses_.begin(); |
| 283 DCHECK_EQ(overflow_params_.size(), overflow_buses_.size()); | 286 DCHECK_EQ(overflow_params_.size(), overflow_buses_.size()); |
| 284 | 287 |
| 285 while (audio_bus_it != overflow_buses_.end() && | 288 while (audio_bus_it != overflow_buses_.end() && |
| 286 number_of_filled_segments_ < segment_count) { | 289 number_of_filled_segments_ < segment_count) { |
| 287 // Write parameters to shared memory. | 290 // Write parameters to shared memory. |
| 288 WriteParametersToCurrentSegment((*params_it).volume, | 291 WriteParametersToCurrentSegment( |
| 289 (*params_it).key_pressed, | 292 (*params_it).volume, (*params_it).key_pressed, (*params_it).delay, |
| 290 (*params_it).hardware_delay_bytes); | 293 (*params_it).delay_timestamp); |
| 291 | 294 |
| 292 // Copy data from the fifo into shared memory using pre-allocated audio | 295 // Copy data from the fifo into shared memory using pre-allocated audio |
| 293 // buses. | 296 // buses. |
| 294 (*audio_bus_it)->CopyTo(audio_buses_[current_segment_id_]); | 297 (*audio_bus_it)->CopyTo(audio_buses_[current_segment_id_]); |
| 295 | 298 |
| 296 if (!SignalDataWrittenAndUpdateCounters()) | 299 if (!SignalDataWrittenAndUpdateCounters()) |
| 297 write_error = true; | 300 write_error = true; |
| 298 | 301 |
| 299 ++params_it; | 302 ++params_it; |
| 300 ++audio_bus_it; | 303 ++audio_bus_it; |
| 301 } | 304 } |
| 302 | 305 |
| 303 // Erase all copied data from fifo. | 306 // Erase all copied data from fifo. |
| 304 overflow_params_.erase(overflow_params_.begin(), params_it); | 307 overflow_params_.erase(overflow_params_.begin(), params_it); |
| 305 overflow_buses_.erase(overflow_buses_.begin(), audio_bus_it); | 308 overflow_buses_.erase(overflow_buses_.begin(), audio_bus_it); |
| 306 | 309 |
| 307 if (overflow_buses_.empty()) { | 310 if (overflow_buses_.empty()) { |
| 308 const std::string message = "AISW: Fifo emptied."; | 311 const std::string message = "AISW: Fifo emptied."; |
| 309 DVLOG(1) << message; | 312 DVLOG(1) << message; |
| 310 AddToNativeLog(message); | 313 AddToNativeLog(message); |
| 311 } | 314 } |
| 312 | 315 |
| 313 DCHECK_EQ(overflow_params_.size(), overflow_buses_.size()); | 316 DCHECK_EQ(overflow_params_.size(), overflow_buses_.size()); |
| 314 return !write_error; | 317 return !write_error; |
| 315 } | 318 } |
| 316 | 319 |
| 317 void AudioInputSyncWriter::WriteParametersToCurrentSegment( | 320 void AudioInputSyncWriter::WriteParametersToCurrentSegment( |
| 318 double volume, | 321 double volume, |
| 319 bool key_pressed, | 322 bool key_pressed, |
| 320 uint32_t hardware_delay_bytes) { | 323 base::TimeDelta delay, |
| 324 base::TimeTicks delay_timestamp) { | |
| 321 uint8_t* ptr = shared_memory_; | 325 uint8_t* ptr = shared_memory_; |
| 322 ptr += current_segment_id_ * shared_memory_segment_size_; | 326 ptr += current_segment_id_ * shared_memory_segment_size_; |
| 323 AudioInputBuffer* buffer = reinterpret_cast<AudioInputBuffer*>(ptr); | 327 AudioInputBuffer* buffer = reinterpret_cast<AudioInputBuffer*>(ptr); |
| 324 buffer->params.volume = volume; | 328 buffer->params.volume = volume; |
| 325 buffer->params.size = audio_bus_memory_size_; | 329 buffer->params.size = audio_bus_memory_size_; |
| 326 buffer->params.key_pressed = key_pressed; | 330 buffer->params.key_pressed = key_pressed; |
| 327 buffer->params.hardware_delay_bytes = hardware_delay_bytes; | 331 buffer->params.delay = delay.InMicroseconds(); |
| 332 buffer->params.delay_timestamp = | |
|
o1ka
2017/02/10 13:28:50
Another reason to have very different names for th
DaleCurtis
2017/02/11 01:43:12
For now I'll keep the names the same since that's
o1ka
2017/02/13 14:00:20
I'm ok with naming now - I got the reasons why the
| |
| 333 (delay_timestamp - base::TimeTicks()).InMicroseconds(); | |
| 328 buffer->params.id = next_buffer_id_; | 334 buffer->params.id = next_buffer_id_; |
| 329 } | 335 } |
| 330 | 336 |
| 331 bool AudioInputSyncWriter::SignalDataWrittenAndUpdateCounters() { | 337 bool AudioInputSyncWriter::SignalDataWrittenAndUpdateCounters() { |
| 332 if (socket_->Send(¤t_segment_id_, sizeof(current_segment_id_)) != | 338 if (socket_->Send(¤t_segment_id_, sizeof(current_segment_id_)) != |
| 333 sizeof(current_segment_id_)) { | 339 sizeof(current_segment_id_)) { |
| 334 const std::string error_message = "AISW: No room in socket buffer."; | 340 const std::string error_message = "AISW: No room in socket buffer."; |
| 335 LOG(WARNING) << error_message; | 341 LOG(WARNING) << error_message; |
| 336 AddToNativeLog(error_message); | 342 AddToNativeLog(error_message); |
| 337 TRACE_EVENT_INSTANT0("audio", | 343 TRACE_EVENT_INSTANT0("audio", |
| 338 "AudioInputSyncWriter: No room in socket buffer", | 344 "AudioInputSyncWriter: No room in socket buffer", |
| 339 TRACE_EVENT_SCOPE_THREAD); | 345 TRACE_EVENT_SCOPE_THREAD); |
| 340 return false; | 346 return false; |
| 341 } | 347 } |
| 342 | 348 |
| 343 if (++current_segment_id_ >= shared_memory_segment_count_) | 349 if (++current_segment_id_ >= shared_memory_segment_count_) |
| 344 current_segment_id_ = 0; | 350 current_segment_id_ = 0; |
| 345 ++number_of_filled_segments_; | 351 ++number_of_filled_segments_; |
| 346 CHECK_LE(number_of_filled_segments_, | 352 CHECK_LE(number_of_filled_segments_, |
| 347 static_cast<int>(shared_memory_segment_count_)); | 353 static_cast<int>(shared_memory_segment_count_)); |
| 348 ++next_buffer_id_; | 354 ++next_buffer_id_; |
| 349 | 355 |
| 350 return true; | 356 return true; |
| 351 } | 357 } |
| 352 | 358 |
| 353 } // namespace content | 359 } // namespace content |
| OLD | NEW |