Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: content/browser/renderer_host/media/audio_sync_reader.cc

Issue 22886005: Switch audio synchronization from sleep() based to select() based. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_sync_reader.h" 5 #include "content/browser/renderer_host/media/audio_sync_reader.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/memory/shared_memory.h" 10 #include "base/memory/shared_memory.h"
11 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
12 #include "content/public/common/content_switches.h" 12 #include "content/public/common/content_switches.h"
13 #include "media/audio/audio_buffers_state.h" 13 #include "media/audio/audio_buffers_state.h"
14 #include "media/audio/audio_parameters.h" 14 #include "media/audio/audio_parameters.h"
15 #include "media/audio/shared_memory_util.h" 15 #include "media/audio/shared_memory_util.h"
16 16
17 using media::AudioBus; 17 using media::AudioBus;
18 18
19 namespace content { 19 namespace content {
20 20
21 AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory, 21 AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory,
22 const media::AudioParameters& params, 22 const media::AudioParameters& params,
23 int input_channels) 23 int input_channels)
24 : shared_memory_(shared_memory), 24 : shared_memory_(shared_memory),
25 input_channels_(input_channels), 25 input_channels_(input_channels),
26 mute_audio_(CommandLine::ForCurrentProcess()->HasSwitch( 26 mute_audio_(CommandLine::ForCurrentProcess()->HasSwitch(
27 switches::kMuteAudio)), 27 switches::kMuteAudio)),
28 renderer_callback_count_(0), 28 renderer_callback_count_(0),
29 renderer_missed_callback_count_(0) { 29 renderer_missed_callback_count_(0),
30 // TODO(dalecurtis): Cap it at 20ms?
31 maximum_wait_time_(params.GetBufferDuration() / 2),
henrika (OOO until Aug 14) 2013/08/20 07:50:30 Just checking; what is the unit of GetBufferDurati
DaleCurtis 2013/09/11 01:16:03 base::TimeDelta
32 buffer_index_(0) {
30 packet_size_ = media::PacketSizeInBytes(shared_memory_->requested_size()); 33 packet_size_ = media::PacketSizeInBytes(shared_memory_->requested_size());
31 int input_memory_size = 0; 34 int input_memory_size = 0;
32 int output_memory_size = AudioBus::CalculateMemorySize(params); 35 int output_memory_size = AudioBus::CalculateMemorySize(params);
33 if (input_channels_ > 0) { 36 if (input_channels_ > 0) {
34 // The input storage is after the output storage. 37 // The input storage is after the output storage.
35 int frames = params.frames_per_buffer(); 38 int frames = params.frames_per_buffer();
36 input_memory_size = AudioBus::CalculateMemorySize(input_channels_, frames); 39 input_memory_size = AudioBus::CalculateMemorySize(input_channels_, frames);
37 char* input_data = 40 char* input_data =
38 static_cast<char*>(shared_memory_->memory()) + output_memory_size; 41 static_cast<char*>(shared_memory_->memory()) + output_memory_size;
39 input_bus_ = AudioBus::WrapMemory(input_channels_, frames, input_data); 42 input_bus_ = AudioBus::WrapMemory(input_channels_, frames, input_data);
(...skipping 21 matching lines...) Expand all
61 // media::AudioOutputController::SyncReader implementations. 64 // media::AudioOutputController::SyncReader implementations.
62 void AudioSyncReader::UpdatePendingBytes(uint32 bytes) { 65 void AudioSyncReader::UpdatePendingBytes(uint32 bytes) {
63 if (bytes != static_cast<uint32>(media::kPauseMark)) { 66 if (bytes != static_cast<uint32>(media::kPauseMark)) {
64 // Store unknown length of data into buffer, so we later 67 // Store unknown length of data into buffer, so we later
65 // can find out if data became available. 68 // can find out if data became available.
66 media::SetUnknownDataSize(shared_memory_, packet_size_); 69 media::SetUnknownDataSize(shared_memory_, packet_size_);
67 } 70 }
68 71
69 if (socket_) { 72 if (socket_) {
70 socket_->Send(&bytes, sizeof(bytes)); 73 socket_->Send(&bytes, sizeof(bytes));
74 buffer_index_++;
tommi (sloooow) - chröme 2013/08/20 10:55:57 nit: ++buffer_index_;
DaleCurtis 2013/09/11 01:16:03 Done.
71 } 75 }
72 } 76 }
73 77
74 int AudioSyncReader::Read(bool block, const AudioBus* source, AudioBus* dest) { 78 int AudioSyncReader::Read(bool block, const AudioBus* source, AudioBus* dest) {
75 ++renderer_callback_count_; 79 ++renderer_callback_count_;
76 if (!DataReady()) { 80 if (!WaitTillDataReady()) {
77 ++renderer_missed_callback_count_; 81 ++renderer_missed_callback_count_;
78 82 return 0;
79 if (block)
80 WaitTillDataReady();
81 } 83 }
82 84
83 // Copy optional synchronized live audio input for consumption by renderer 85 // Copy optional synchronized live audio input for consumption by renderer
84 // process. 86 // process.
85 if (source && input_bus_) { 87 if (source && input_bus_) {
86 DCHECK_EQ(source->channels(), input_bus_->channels()); 88 DCHECK_EQ(source->channels(), input_bus_->channels());
87 // TODO(crogers): In some cases with device and sample-rate changes 89 // TODO(crogers): In some cases with device and sample-rate changes
88 // it's possible for an AOR to insert a resampler in the path. 90 // it's possible for an AOR to insert a resampler in the path.
89 // Because this is used with the Web Audio API, it'd be better 91 // Because this is used with the Web Audio API, it'd be better
90 // to bypass the device change handling in AOR and instead let 92 // to bypass the device change handling in AOR and instead let
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 base::ProcessHandle process_handle, 168 base::ProcessHandle process_handle,
167 base::FileDescriptor* foreign_handle) { 169 base::FileDescriptor* foreign_handle) {
168 foreign_handle->fd = foreign_socket_->handle(); 170 foreign_handle->fd = foreign_socket_->handle();
169 foreign_handle->auto_close = false; 171 foreign_handle->auto_close = false;
170 if (foreign_handle->fd != -1) 172 if (foreign_handle->fd != -1)
171 return true; 173 return true;
172 return false; 174 return false;
173 } 175 }
174 #endif 176 #endif
175 177
176 void AudioSyncReader::WaitTillDataReady() { 178 bool AudioSyncReader::WaitTillDataReady() {
179 if (!socket_)
tommi (sloooow) - chröme 2013/08/20 10:55:57 is this something exected or unexpected (i.e. [D]C
DaleCurtis 2013/09/11 01:16:03 Set during Init() and never changed. Checks remov
180 return false;
181
182 size_t bytes_received = 0;
183 uint32 renderer_buffer_index = 0;
184
177 base::TimeTicks start = base::TimeTicks::Now(); 185 base::TimeTicks start = base::TimeTicks::Now();
178 const base::TimeDelta kMaxWait = base::TimeDelta::FromMilliseconds(20);
179 #if defined(OS_WIN)
180 // Sleep(0) on Windows lets the other threads run.
181 const base::TimeDelta kSleep = base::TimeDelta::FromMilliseconds(0);
182 #else
183 // We want to sleep for a bit here, as otherwise a backgrounded renderer won't
184 // get enough cpu to send the data and the high priority thread in the browser
185 // will use up a core causing even more skips.
186 const base::TimeDelta kSleep = base::TimeDelta::FromMilliseconds(2);
187 #endif
188 base::TimeDelta time_since_start;
189 do { 186 do {
190 base::PlatformThread::Sleep(kSleep); 187 bytes_received = socket_->Receive(
tommi (sloooow) - chröme 2013/08/20 10:55:57 Since we're using sockets, we should be able to ch
DaleCurtis 2013/08/20 18:27:51 Not sure I follow which "multiple" items you want
tommi (sloooow) - chröme 2013/08/21 12:33:26 Sorry, for some reason I parsed this loop as cycli
191 time_since_start = base::TimeTicks::Now() - start; 188 &renderer_buffer_index, sizeof(renderer_buffer_index),
192 } while (!DataReady() && time_since_start < kMaxWait); 189 maximum_wait_time_);
DaveMoore 2013/08/19 22:49:43 Does it mean anything (skipping) if something othe
DaleCurtis 2013/08/19 23:08:22 It means we timed out on one or more previous call
190 } while (bytes_received > 0 && renderer_buffer_index != buffer_index_);
191
192 base::TimeDelta time_since_start = base::TimeTicks::Now() - start;
193 UMA_HISTOGRAM_CUSTOM_TIMES("Media.AudioOutputControllerDataNotReady", 193 UMA_HISTOGRAM_CUSTOM_TIMES("Media.AudioOutputControllerDataNotReady",
194 time_since_start, 194 time_since_start,
195 base::TimeDelta::FromMilliseconds(1), 195 base::TimeDelta::FromMilliseconds(1),
196 base::TimeDelta::FromMilliseconds(1000), 196 base::TimeDelta::FromMilliseconds(1000),
197 50); 197 50);
198
199 // Receive() timed out or another unknown error occurred.
henrika (OOO until Aug 14) 2013/08/20 07:50:30 Could you add some more details about what can cau
DaleCurtis 2013/09/11 01:16:03 Done.
200 if (!bytes_received) {
201 DVLOG(2) << "AudioSyncReader::WaitTillDataReady() timed out.";
202 return false;
203 }
204
205 DCHECK_EQ(bytes_received, sizeof(renderer_buffer_index));
206 DCHECK(DataReady());
207 return true;
198 } 208 }
199 209
200 } // namespace content 210 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698