OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // TODO(hclam): Several changes need to be made to this code: | 5 // TODO(hclam): Several changes need to be made to this code: |
6 // 1. We should host AudioRendererHost on a dedicated audio thread. Doing | 6 // 1. We should host AudioRendererHost on a dedicated audio thread. Doing |
7 // so we don't have to worry about blocking method calls such as | 7 // so we don't have to worry about blocking method calls such as |
8 // play / stop an audio stream. | 8 // play / stop an audio stream. |
9 // 2. Move locked data structures into a separate structure that sanity | 9 // 2. Move locked data structures into a separate structure that sanity |
10 // checks access by different threads that use it. | 10 // checks access by different threads that use it. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 AudioRendererHost* host, | 88 AudioRendererHost* host, |
89 int process_id, | 89 int process_id, |
90 int route_id, | 90 int route_id, |
91 int stream_id, | 91 int stream_id, |
92 base::ProcessHandle process_handle, | 92 base::ProcessHandle process_handle, |
93 AudioManager::Format format, | 93 AudioManager::Format format, |
94 int channels, | 94 int channels, |
95 int sample_rate, | 95 int sample_rate, |
96 char bits_per_sample, | 96 char bits_per_sample, |
97 uint32 decoded_packet_size, | 97 uint32 decoded_packet_size, |
98 uint32 buffer_capacity) { | 98 uint32 buffer_capacity, |
| 99 bool low_latency) { |
99 // Perform come preliminary checks on the parameters. | 100 // Perform come preliminary checks on the parameters. |
100 // Make sure the renderer didn't ask for too much memory. | 101 // Make sure the renderer didn't ask for too much memory. |
101 if (buffer_capacity > kMaxBufferCapacity || | 102 if (buffer_capacity > kMaxBufferCapacity || |
102 decoded_packet_size > kMaxDecodedPacketSize) | 103 decoded_packet_size > kMaxDecodedPacketSize) |
103 return NULL; | 104 return NULL; |
104 | 105 |
105 // Make sure the packet size and buffer capacity parameters are valid. | 106 // Make sure the packet size and buffer capacity parameters are valid. |
106 if (buffer_capacity < decoded_packet_size) | 107 if (buffer_capacity < decoded_packet_size) |
107 return NULL; | 108 return NULL; |
108 | 109 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 // Note that the low latency mode is not yet ready and the if part of this | 147 // Note that the low latency mode is not yet ready and the if part of this |
147 // method is never executed. TODO(cpu): Enable this mode. | 148 // method is never executed. TODO(cpu): Enable this mode. |
148 | 149 |
149 if (source->shared_memory_.Create(L"", | 150 if (source->shared_memory_.Create(L"", |
150 false, | 151 false, |
151 false, | 152 false, |
152 decoded_packet_size) && | 153 decoded_packet_size) && |
153 source->shared_memory_.Map(decoded_packet_size) && | 154 source->shared_memory_.Map(decoded_packet_size) && |
154 source->shared_memory_.ShareToProcess(process_handle, | 155 source->shared_memory_.ShareToProcess(process_handle, |
155 &foreign_memory_handle)) { | 156 &foreign_memory_handle)) { |
156 // TODO(cpu): better define what triggers the low latency mode. | 157 if (low_latency) { |
157 if (decoded_packet_size > kLowLatencyPacketThreshold) { | |
158 // Regular latency mode. | |
159 host->Send(new ViewMsg_NotifyAudioStreamCreated( | |
160 route_id, stream_id, foreign_memory_handle, decoded_packet_size)); | |
161 | |
162 // Also request the first packet to kick start the pre-rolling. | |
163 source->StartBuffering(); | |
164 return source; | |
165 } else { | |
166 // Low latency mode. We use SyncSocket to signal. | 158 // Low latency mode. We use SyncSocket to signal. |
167 base::SyncSocket* sockets[2] = {0}; | 159 base::SyncSocket* sockets[2] = {0}; |
168 if (base::SyncSocket::CreatePair(sockets)) { | 160 if (base::SyncSocket::CreatePair(sockets)) { |
169 source->shared_socket_.reset(sockets[0]); | 161 source->shared_socket_.reset(sockets[0]); |
170 #if defined(OS_WIN) | 162 #if defined(OS_WIN) |
171 HANDLE foreign_socket_handle = 0; | 163 HANDLE foreign_socket_handle = 0; |
172 ::DuplicateHandle(GetCurrentProcess(), sockets[1]->handle(), | 164 ::DuplicateHandle(GetCurrentProcess(), sockets[1]->handle(), |
173 process_handle, &foreign_socket_handle, | 165 process_handle, &foreign_socket_handle, |
174 0, FALSE, DUPLICATE_SAME_ACCESS); | 166 0, FALSE, DUPLICATE_SAME_ACCESS); |
175 bool valid = foreign_socket_handle != 0; | 167 bool valid = foreign_socket_handle != 0; |
176 #else | 168 #else |
177 base::FileDescriptor foreign_socket_handle(sockets[1]->handle(), | 169 base::FileDescriptor foreign_socket_handle(sockets[1]->handle(), |
178 false); | 170 false); |
179 bool valid = foreign_socket_handle.fd != -1; | 171 bool valid = foreign_socket_handle.fd != -1; |
180 #endif | 172 #endif |
181 | 173 |
182 if (valid) { | 174 if (valid) { |
183 host->Send(new ViewMsg_NotifyLowLatencyAudioStreamCreated( | 175 host->Send(new ViewMsg_NotifyLowLatencyAudioStreamCreated( |
184 route_id, stream_id, foreign_memory_handle, | 176 route_id, stream_id, foreign_memory_handle, |
185 foreign_socket_handle, decoded_packet_size)); | 177 foreign_socket_handle, decoded_packet_size)); |
186 return source; | 178 return source; |
187 } | 179 } |
188 } | 180 } |
| 181 } else { |
| 182 // Regular latency mode. |
| 183 host->Send(new ViewMsg_NotifyAudioStreamCreated( |
| 184 route_id, stream_id, foreign_memory_handle, decoded_packet_size)); |
| 185 |
| 186 // Also request the first packet to kick start the pre-rolling. |
| 187 source->StartBuffering(); |
| 188 return source; |
189 } | 189 } |
190 } | 190 } |
191 // Failure. Close and free acquired resources. | 191 // Failure. Close and free acquired resources. |
192 source->Close(); | 192 source->Close(); |
193 delete source; | 193 delete source; |
194 } | 194 } |
195 | 195 |
196 host->SendErrorMessage(route_id, stream_id); | 196 host->SendErrorMessage(route_id, stream_id); |
197 return NULL; | 197 return NULL; |
198 } | 198 } |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 case ViewHostMsg_SetAudioVolume::ID: | 455 case ViewHostMsg_SetAudioVolume::ID: |
456 return true; | 456 return true; |
457 default: | 457 default: |
458 break; | 458 break; |
459 } | 459 } |
460 return false; | 460 return false; |
461 } | 461 } |
462 | 462 |
463 void AudioRendererHost::OnCreateStream( | 463 void AudioRendererHost::OnCreateStream( |
464 const IPC::Message& msg, int stream_id, | 464 const IPC::Message& msg, int stream_id, |
465 const ViewHostMsg_Audio_CreateStream_Params& params) { | 465 const ViewHostMsg_Audio_CreateStream_Params& params, bool low_latency) { |
466 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 466 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
467 DCHECK(Lookup(msg.routing_id(), stream_id) == NULL); | 467 DCHECK(Lookup(msg.routing_id(), stream_id) == NULL); |
468 | 468 |
469 IPCAudioSource* source = IPCAudioSource::CreateIPCAudioSource( | 469 IPCAudioSource* source = IPCAudioSource::CreateIPCAudioSource( |
470 this, | 470 this, |
471 process_id_, | 471 process_id_, |
472 msg.routing_id(), | 472 msg.routing_id(), |
473 stream_id, | 473 stream_id, |
474 process_handle_, | 474 process_handle_, |
475 params.format, | 475 params.format, |
476 params.channels, | 476 params.channels, |
477 params.sample_rate, | 477 params.sample_rate, |
478 params.bits_per_sample, | 478 params.bits_per_sample, |
479 params.packet_size, | 479 params.packet_size, |
480 params.buffer_capacity); | 480 params.buffer_capacity, |
| 481 low_latency); |
481 | 482 |
482 // If we have created the source successfully, adds it to the map. | 483 // If we have created the source successfully, adds it to the map. |
483 if (source) { | 484 if (source) { |
484 sources_.insert( | 485 sources_.insert( |
485 std::make_pair( | 486 std::make_pair( |
486 SourceID(source->route_id(), source->stream_id()), source)); | 487 SourceID(source->route_id(), source->stream_id()), source)); |
487 } else { | 488 } else { |
488 SendErrorMessage(msg.routing_id(), stream_id); | 489 SendErrorMessage(msg.routing_id(), stream_id); |
489 } | 490 } |
490 } | 491 } |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 | 617 |
617 void AudioRendererHost::DestroySource(IPCAudioSource* source) { | 618 void AudioRendererHost::DestroySource(IPCAudioSource* source) { |
618 if (ChromeThread::CurrentlyOn(ChromeThread::IO)) { | 619 if (ChromeThread::CurrentlyOn(ChromeThread::IO)) { |
619 OnDestroySource(source); | 620 OnDestroySource(source); |
620 } else { | 621 } else { |
621 ChromeThread::PostTask( | 622 ChromeThread::PostTask( |
622 ChromeThread::IO, FROM_HERE, | 623 ChromeThread::IO, FROM_HERE, |
623 NewRunnableMethod(this, &AudioRendererHost::OnDestroySource, source)); | 624 NewRunnableMethod(this, &AudioRendererHost::OnDestroySource, source)); |
624 } | 625 } |
625 } | 626 } |
OLD | NEW |