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

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

Issue 9121062: Remove "high"-latency audio code path (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase ToT Created 8 years, 10 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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_renderer_host.h" 5 #include "content/browser/renderer_host/media/audio_renderer_host.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/process.h" 9 #include "base/process.h"
10 #include "base/shared_memory.h" 10 #include "base/shared_memory.h"
11 #include "content/browser/renderer_host/media/audio_common.h" 11 #include "content/browser/renderer_host/media/audio_common.h"
12 #include "content/browser/renderer_host/media/audio_sync_reader.h" 12 #include "content/browser/renderer_host/media/audio_sync_reader.h"
13 #include "content/browser/renderer_host/media/media_observer.h" 13 #include "content/browser/renderer_host/media/media_observer.h"
14 #include "content/browser/resource_context.h" 14 #include "content/browser/resource_context.h"
15 #include "content/common/media/audio_messages.h" 15 #include "content/common/media/audio_messages.h"
16 #include "media/audio/audio_util.h" 16 #include "media/audio/audio_util.h"
17 #include "ipc/ipc_logging.h" 17 #include "ipc/ipc_logging.h"
18 18
19 using content::BrowserMessageFilter; 19 using content::BrowserMessageFilter;
20 using content::BrowserThread; 20 using content::BrowserThread;
21 21
22 AudioRendererHost::AudioEntry::AudioEntry() 22 AudioRendererHost::AudioEntry::AudioEntry()
23 : stream_id(0), 23 : stream_id(0),
24 pending_buffer_request(false),
25 pending_close(false) { 24 pending_close(false) {
26 } 25 }
27 26
28 AudioRendererHost::AudioEntry::~AudioEntry() {} 27 AudioRendererHost::AudioEntry::~AudioEntry() {}
29 28
30 /////////////////////////////////////////////////////////////////////////////// 29 ///////////////////////////////////////////////////////////////////////////////
31 // AudioRendererHost implementations. 30 // AudioRendererHost implementations.
32 AudioRendererHost::AudioRendererHost( 31 AudioRendererHost::AudioRendererHost(
33 const content::ResourceContext* resource_context) 32 const content::ResourceContext* resource_context)
34 : resource_context_(resource_context), 33 : resource_context_(resource_context),
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 83
85 void AudioRendererHost::OnError(media::AudioOutputController* controller, 84 void AudioRendererHost::OnError(media::AudioOutputController* controller,
86 int error_code) { 85 int error_code) {
87 BrowserThread::PostTask( 86 BrowserThread::PostTask(
88 BrowserThread::IO, 87 BrowserThread::IO,
89 FROM_HERE, 88 FROM_HERE,
90 base::Bind(&AudioRendererHost::DoHandleError, 89 base::Bind(&AudioRendererHost::DoHandleError,
91 this, make_scoped_refptr(controller), error_code)); 90 this, make_scoped_refptr(controller), error_code));
92 } 91 }
93 92
94 void AudioRendererHost::OnMoreData(media::AudioOutputController* controller,
95 AudioBuffersState buffers_state) {
96 BrowserThread::PostTask(
97 BrowserThread::IO,
98 FROM_HERE,
99 base::Bind(&AudioRendererHost::DoRequestMoreData,
100 this, make_scoped_refptr(controller),
101 buffers_state));
102 }
103
104 void AudioRendererHost::DoCompleteCreation( 93 void AudioRendererHost::DoCompleteCreation(
105 media::AudioOutputController* controller) { 94 media::AudioOutputController* controller) {
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
107 96
108 AudioEntry* entry = LookupByController(controller); 97 AudioEntry* entry = LookupByController(controller);
109 if (!entry) 98 if (!entry)
110 return; 99 return;
111 100
112 if (!peer_handle()) { 101 if (!peer_handle()) {
113 NOTREACHED() << "Renderer process handle is invalid."; 102 NOTREACHED() << "Renderer process handle is invalid.";
114 DeleteEntryOnError(entry); 103 DeleteEntryOnError(entry);
115 return; 104 return;
116 } 105 }
117 106
118 // Once the audio stream is created then complete the creation process by 107 // Once the audio stream is created then complete the creation process by
119 // mapping shared memory and sharing with the renderer process. 108 // mapping shared memory and sharing with the renderer process.
120 base::SharedMemoryHandle foreign_memory_handle; 109 base::SharedMemoryHandle foreign_memory_handle;
121 if (!entry->shared_memory.ShareToProcess(peer_handle(), 110 if (!entry->shared_memory.ShareToProcess(peer_handle(),
122 &foreign_memory_handle)) { 111 &foreign_memory_handle)) {
123 // If we failed to map and share the shared memory then close the audio 112 // If we failed to map and share the shared memory then close the audio
124 // stream and send an error message. 113 // stream and send an error message.
125 DeleteEntryOnError(entry); 114 DeleteEntryOnError(entry);
126 return; 115 return;
127 } 116 }
128 117
129 if (entry->controller->LowLatencyMode()) { 118 AudioSyncReader* reader =
130 AudioSyncReader* reader = 119 static_cast<AudioSyncReader*>(entry->reader.get());
131 static_cast<AudioSyncReader*>(entry->reader.get());
132 120
133 #if defined(OS_WIN) 121 #if defined(OS_WIN)
134 base::SyncSocket::Handle foreign_socket_handle; 122 base::SyncSocket::Handle foreign_socket_handle;
135 #else 123 #else
136 base::FileDescriptor foreign_socket_handle; 124 base::FileDescriptor foreign_socket_handle;
137 #endif 125 #endif
138 126
139 // If we failed to prepare the sync socket for the renderer then we fail 127 // If we failed to prepare the sync socket for the renderer then we fail
140 // the construction of audio stream. 128 // the construction of audio stream.
141 if (!reader->PrepareForeignSocketHandle(peer_handle(), 129 if (!reader->PrepareForeignSocketHandle(peer_handle(),
142 &foreign_socket_handle)) { 130 &foreign_socket_handle)) {
143 DeleteEntryOnError(entry); 131 DeleteEntryOnError(entry);
144 return;
145 }
146
147 Send(new AudioMsg_NotifyLowLatencyStreamCreated(
148 entry->stream_id,
149 foreign_memory_handle,
150 foreign_socket_handle,
151 media::PacketSizeSizeInBytes(entry->shared_memory.created_size())));
152 return; 132 return;
153 } 133 }
154 134
155 // The normal audio stream has created, send a message to the renderer
156 // process.
157 Send(new AudioMsg_NotifyStreamCreated( 135 Send(new AudioMsg_NotifyStreamCreated(
158 entry->stream_id, foreign_memory_handle, 136 entry->stream_id,
159 entry->shared_memory.created_size())); 137 foreign_memory_handle,
138 foreign_socket_handle,
139 media::PacketSizeSizeInBytes(entry->shared_memory.created_size())));
160 } 140 }
161 141
162 void AudioRendererHost::DoSendPlayingMessage( 142 void AudioRendererHost::DoSendPlayingMessage(
163 media::AudioOutputController* controller) { 143 media::AudioOutputController* controller) {
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
165 145
166 AudioEntry* entry = LookupByController(controller); 146 AudioEntry* entry = LookupByController(controller);
167 if (!entry) 147 if (!entry)
168 return; 148 return;
169 149
170 Send(new AudioMsg_NotifyStreamStateChanged( 150 Send(new AudioMsg_NotifyStreamStateChanged(
171 entry->stream_id, kAudioStreamPlaying)); 151 entry->stream_id, kAudioStreamPlaying));
172 } 152 }
173 153
174 void AudioRendererHost::DoSendPausedMessage( 154 void AudioRendererHost::DoSendPausedMessage(
175 media::AudioOutputController* controller) { 155 media::AudioOutputController* controller) {
176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
177 157
178 AudioEntry* entry = LookupByController(controller); 158 AudioEntry* entry = LookupByController(controller);
179 if (!entry) 159 if (!entry)
180 return; 160 return;
181 161
182 Send(new AudioMsg_NotifyStreamStateChanged( 162 Send(new AudioMsg_NotifyStreamStateChanged(
183 entry->stream_id, kAudioStreamPaused)); 163 entry->stream_id, kAudioStreamPaused));
184 } 164 }
185 165
186 void AudioRendererHost::DoRequestMoreData(
187 media::AudioOutputController* controller,
188 AudioBuffersState buffers_state) {
189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
190
191 // If we already have a pending request then return.
192 AudioEntry* entry = LookupByController(controller);
193 if (!entry || entry->pending_buffer_request)
194 return;
195
196 DCHECK(!entry->controller->LowLatencyMode());
197 entry->pending_buffer_request = true;
198 Send(new AudioMsg_RequestPacket(
199 entry->stream_id, buffers_state));
200 }
201
202 void AudioRendererHost::DoHandleError(media::AudioOutputController* controller, 166 void AudioRendererHost::DoHandleError(media::AudioOutputController* controller,
203 int error_code) { 167 int error_code) {
204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
205 169
206 AudioEntry* entry = LookupByController(controller); 170 AudioEntry* entry = LookupByController(controller);
207 if (!entry) 171 if (!entry)
208 return; 172 return;
209 173
210 DeleteEntryOnError(entry); 174 DeleteEntryOnError(entry);
211 } 175 }
212 176
213 /////////////////////////////////////////////////////////////////////////////// 177 ///////////////////////////////////////////////////////////////////////////////
214 // IPC Messages handler 178 // IPC Messages handler
215 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message, 179 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message,
216 bool* message_was_ok) { 180 bool* message_was_ok) {
217 bool handled = true; 181 bool handled = true;
218 IPC_BEGIN_MESSAGE_MAP_EX(AudioRendererHost, message, *message_was_ok) 182 IPC_BEGIN_MESSAGE_MAP_EX(AudioRendererHost, message, *message_was_ok)
219 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream) 183 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream)
220 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) 184 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream)
221 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) 185 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream)
222 IPC_MESSAGE_HANDLER(AudioHostMsg_FlushStream, OnFlushStream) 186 IPC_MESSAGE_HANDLER(AudioHostMsg_FlushStream, OnFlushStream)
223 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) 187 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream)
224 IPC_MESSAGE_HANDLER(AudioHostMsg_NotifyPacketReady, OnNotifyPacketReady)
225 IPC_MESSAGE_HANDLER(AudioHostMsg_GetVolume, OnGetVolume)
226 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) 188 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume)
227 IPC_MESSAGE_UNHANDLED(handled = false) 189 IPC_MESSAGE_UNHANDLED(handled = false)
228 IPC_END_MESSAGE_MAP_EX() 190 IPC_END_MESSAGE_MAP_EX()
229 191
230 return handled; 192 return handled;
231 } 193 }
232 194
233 void AudioRendererHost::OnCreateStream( 195 void AudioRendererHost::OnCreateStream(
234 int stream_id, const AudioParameters& params, bool low_latency) { 196 int stream_id, const AudioParameters& params) {
235 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
236 DCHECK(LookupById(stream_id) == NULL); 198 DCHECK(LookupById(stream_id) == NULL);
237 199
238 AudioParameters audio_params(params); 200 AudioParameters audio_params(params);
239 201
240 // Select the hardware packet size if not specified. 202 // Select the hardware packet size if not specified.
241 if (!audio_params.samples_per_packet) { 203 if (!audio_params.samples_per_packet) {
242 audio_params.samples_per_packet = SelectSamplesPerPacket(audio_params); 204 audio_params.samples_per_packet = SelectSamplesPerPacket(audio_params);
243 } 205 }
244 uint32 packet_size = audio_params.GetPacketSize(); 206 uint32 packet_size = audio_params.GetPacketSize();
245 207
246 scoped_ptr<AudioEntry> entry(new AudioEntry()); 208 scoped_ptr<AudioEntry> entry(new AudioEntry());
209
247 // Create the shared memory and share with the renderer process. 210 // Create the shared memory and share with the renderer process.
248 uint32 shared_memory_size = packet_size; 211 uint32 shared_memory_size =
249 if (low_latency) { 212 media::TotalSharedMemorySizeInBytes(packet_size);
250 shared_memory_size =
251 media::TotalSharedMemorySizeInBytes(shared_memory_size);
252 }
253 if (!entry->shared_memory.CreateAndMapAnonymous(shared_memory_size)) { 213 if (!entry->shared_memory.CreateAndMapAnonymous(shared_memory_size)) {
254 // If creation of shared memory failed then send an error message. 214 // If creation of shared memory failed then send an error message.
255 SendErrorMessage(stream_id); 215 SendErrorMessage(stream_id);
256 return; 216 return;
257 } 217 }
258 218
259 if (low_latency) { 219 // Create sync reader and try to initialize it.
260 // If this is the low latency mode, we need to construct a SyncReader first. 220 scoped_ptr<AudioSyncReader> reader(
261 scoped_ptr<AudioSyncReader> reader( 221 new AudioSyncReader(&entry->shared_memory));
262 new AudioSyncReader(&entry->shared_memory));
263 222
264 // Then try to initialize the sync reader. 223 if (!reader->Init()) {
265 if (!reader->Init()) { 224 SendErrorMessage(stream_id);
266 SendErrorMessage(stream_id); 225 return;
267 return; 226 }
268 }
269 227
270 // If we have successfully created the SyncReader then assign it to the 228 // If we have successfully created the SyncReader then assign it to the
271 // entry and construct an AudioOutputController. 229 // entry and construct an AudioOutputController.
272 entry->reader.reset(reader.release()); 230 entry->reader.reset(reader.release());
273 entry->controller = 231 entry->controller = media::AudioOutputController::Create(
274 media::AudioOutputController::CreateLowLatency( 232 resource_context_->audio_manager(), this, audio_params,
275 resource_context_->audio_manager(), this, audio_params, 233 entry->reader.get());
276 entry->reader.get());
277 } else {
278 // The choice of buffer capacity is based on experiment.
279 entry->controller =
280 media::AudioOutputController::Create(
281 resource_context_->audio_manager(), this, audio_params,
282 3 * packet_size);
283 }
284 234
285 if (!entry->controller) { 235 if (!entry->controller) {
286 SendErrorMessage(stream_id); 236 SendErrorMessage(stream_id);
287 return; 237 return;
288 } 238 }
289 239
290 // If we have created the controller successfully create a entry and add it 240 // If we have created the controller successfully, create an entry and add it
291 // to the map. 241 // to the map.
292 entry->stream_id = stream_id; 242 entry->stream_id = stream_id;
293 audio_entries_.insert(std::make_pair(stream_id, entry.release())); 243 audio_entries_.insert(std::make_pair(stream_id, entry.release()));
294 media_observer()->OnSetAudioStreamStatus(this, stream_id, "created"); 244 media_observer()->OnSetAudioStreamStatus(this, stream_id, "created");
295 } 245 }
296 246
297 void AudioRendererHost::OnPlayStream(int stream_id) { 247 void AudioRendererHost::OnPlayStream(int stream_id) {
298 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
299 249
300 AudioEntry* entry = LookupById(stream_id); 250 AudioEntry* entry = LookupById(stream_id);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 return; 303 return;
354 } 304 }
355 305
356 // Make sure the volume is valid. 306 // Make sure the volume is valid.
357 if (volume < 0 || volume > 1.0) 307 if (volume < 0 || volume > 1.0)
358 return; 308 return;
359 entry->controller->SetVolume(volume); 309 entry->controller->SetVolume(volume);
360 media_observer()->OnSetAudioStreamVolume(this, stream_id, volume); 310 media_observer()->OnSetAudioStreamVolume(this, stream_id, volume);
361 } 311 }
362 312
363 void AudioRendererHost::OnGetVolume(int stream_id) {
364 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
365 NOTREACHED() << "This message shouldn't be received";
366 }
367
368 void AudioRendererHost::OnNotifyPacketReady(int stream_id, uint32 packet_size) {
369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
370
371 AudioEntry* entry = LookupById(stream_id);
372 if (!entry) {
373 SendErrorMessage(stream_id);
374 return;
375 }
376
377 DCHECK(!entry->controller->LowLatencyMode());
378 CHECK(packet_size <= entry->shared_memory.created_size());
379
380 if (!entry->pending_buffer_request) {
381 NOTREACHED() << "Buffer received but no such pending request";
382 }
383 entry->pending_buffer_request = false;
384
385 // Enqueue the data to media::AudioOutputController.
386 entry->controller->EnqueueData(
387 reinterpret_cast<uint8*>(entry->shared_memory.memory()),
388 packet_size);
389 }
390
391 void AudioRendererHost::SendErrorMessage(int32 stream_id) { 313 void AudioRendererHost::SendErrorMessage(int32 stream_id) {
392 Send(new AudioMsg_NotifyStreamStateChanged(stream_id, kAudioStreamError)); 314 Send(new AudioMsg_NotifyStreamStateChanged(stream_id, kAudioStreamError));
393 } 315 }
394 316
395 void AudioRendererHost::DeleteEntries() { 317 void AudioRendererHost::DeleteEntries() {
396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
397 319
398 for (AudioEntryMap::iterator i = audio_entries_.begin(); 320 for (AudioEntryMap::iterator i = audio_entries_.begin();
399 i != audio_entries_.end(); ++i) { 321 i != audio_entries_.end(); ++i) {
400 CloseAndDeleteStream(i->second); 322 CloseAndDeleteStream(i->second);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 } 387 }
466 return NULL; 388 return NULL;
467 } 389 }
468 390
469 MediaObserver* AudioRendererHost::media_observer() { 391 MediaObserver* AudioRendererHost::media_observer() {
470 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
471 if (!media_observer_) 393 if (!media_observer_)
472 media_observer_ = resource_context_->media_observer(); 394 media_observer_ = resource_context_->media_observer();
473 return media_observer_; 395 return media_observer_;
474 } 396 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698