| 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_renderer_host.h" | 5 #include "content/browser/renderer_host/media/audio_input_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_input_device_manager.h" | 11 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
| 12 #include "content/browser/renderer_host/media/audio_input_sync_writer.h" | 12 #include "content/browser/renderer_host/media/audio_input_sync_writer.h" |
| 13 #include "content/browser/renderer_host/media/media_stream_manager.h" | 13 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 14 #include "content/browser/renderer_host/media/web_contents_audio_input_stream.h" | 14 #include "content/browser/renderer_host/media/web_contents_audio_input_stream.h" |
| 15 #include "content/browser/renderer_host/media/web_contents_capture_util.h" | 15 #include "content/browser/renderer_host/media/web_contents_capture_util.h" |
| 16 #include "content/common/media/audio_messages.h" | 16 #include "content/common/media/audio_messages.h" |
| 17 | 17 |
| 18 namespace content { | 18 namespace content { |
| 19 | 19 |
| 20 struct AudioInputRendererHost::AudioEntry { | 20 struct AudioInputRendererHost::AudioEntry { |
| 21 AudioEntry(); | 21 AudioEntry(); |
| 22 ~AudioEntry(); | 22 ~AudioEntry(); |
| 23 | 23 |
| 24 // The AudioInputController that manages the audio input stream. | 24 // The AudioInputController that manages the audio input stream. |
| 25 scoped_refptr<media::AudioInputController> controller; | 25 scoped_refptr<media::AudioInputController> controller; |
| 26 | 26 |
| 27 // The audio input stream ID in the render view. | 27 // The audio input stream ID in the render view. |
| 28 int stream_id; | 28 int stream_id; |
| 29 | 29 |
| 30 // Shared memory for transmission of the audio data. | 30 // Shared memory buffers for transmission of the audio data. |
| 31 base::SharedMemory shared_memory; | 31 AudioInputSyncWriter::SharedMemoryVector shared_memory; |
| 32 | 32 |
| 33 // The synchronous writer to be used by the controller. We have the | 33 // The synchronous writer to be used by the controller. We have the |
| 34 // ownership of the writer. | 34 // ownership of the writer. |
| 35 scoped_ptr<media::AudioInputController::SyncWriter> writer; | 35 scoped_ptr<media::AudioInputController::SyncWriter> writer; |
| 36 | 36 |
| 37 // Set to true after we called Close() for the controller. | 37 // Set to true after we called Close() for the controller. |
| 38 bool pending_close; | 38 bool pending_close; |
| 39 }; | 39 }; |
| 40 | 40 |
| 41 AudioInputRendererHost::AudioEntry::AudioEntry() | 41 AudioInputRendererHost::AudioEntry::AudioEntry() |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 } | 120 } |
| 121 | 121 |
| 122 if (!entry->controller->LowLatencyMode()) { | 122 if (!entry->controller->LowLatencyMode()) { |
| 123 NOTREACHED() << "Only low-latency mode is supported."; | 123 NOTREACHED() << "Only low-latency mode is supported."; |
| 124 DeleteEntryOnError(entry); | 124 DeleteEntryOnError(entry); |
| 125 return; | 125 return; |
| 126 } | 126 } |
| 127 | 127 |
| 128 // Once the audio stream is created then complete the creation process by | 128 // Once the audio stream is created then complete the creation process by |
| 129 // mapping shared memory and sharing with the renderer process. | 129 // mapping shared memory and sharing with the renderer process. |
| 130 base::SharedMemoryHandle foreign_memory_handle; | |
| 131 if (!entry->shared_memory.ShareToProcess(peer_handle(), | |
| 132 &foreign_memory_handle)) { | |
| 133 // If we failed to map and share the shared memory then close the audio | |
| 134 // stream and send an error message. | |
| 135 DeleteEntryOnError(entry); | |
| 136 return; | |
| 137 } | |
| 138 | |
| 139 AudioInputSyncWriter* writer = | 130 AudioInputSyncWriter* writer = |
| 140 static_cast<AudioInputSyncWriter*>(entry->writer.get()); | 131 static_cast<AudioInputSyncWriter*>(entry->writer.get()); |
| 141 | 132 |
| 142 #if defined(OS_WIN) | 133 #if defined(OS_WIN) |
| 143 base::SyncSocket::Handle foreign_socket_handle; | 134 base::SyncSocket::Handle foreign_socket_handle; |
| 144 #else | 135 #else |
| 145 base::FileDescriptor foreign_socket_handle; | 136 base::FileDescriptor foreign_socket_handle; |
| 146 #endif | 137 #endif |
| 147 | 138 |
| 148 // If we failed to prepare the sync socket for the renderer then we fail | 139 // If we failed to prepare the sync socket for the renderer then we fail |
| 149 // the construction of audio input stream. | 140 // the construction of audio input stream. |
| 150 if (!writer->PrepareForeignSocketHandle(peer_handle(), | 141 if (!writer->PrepareForeignSocketHandle(peer_handle(), |
| 151 &foreign_socket_handle)) { | 142 &foreign_socket_handle)) { |
| 152 DeleteEntryOnError(entry); | 143 DeleteEntryOnError(entry); |
| 153 return; | 144 return; |
| 154 } | 145 } |
| 146 Send(new AudioInputMsg_NotifyStreamCreated(entry->stream_id, |
| 147 foreign_socket_handle, |
| 148 entry->shared_memory.size())); |
| 155 | 149 |
| 156 Send(new AudioInputMsg_NotifyStreamCreated(entry->stream_id, | 150 for (size_t i = 0; i < entry->shared_memory.size(); ++i) { |
| 157 foreign_memory_handle, foreign_socket_handle, | 151 base::SharedMemoryHandle foreign_memory_handle; |
| 158 entry->shared_memory.created_size())); | 152 if (!entry->shared_memory[i]->ShareToProcess(peer_handle(), |
| 153 &foreign_memory_handle)) { |
| 154 // If we failed to map and share the shared memory then close the audio |
| 155 // stream and send an error message. |
| 156 DeleteEntryOnError(entry); |
| 157 return; |
| 158 } |
| 159 Send(new AudioInputMsg_NotifySharedMemoryCreated(entry->stream_id, |
| 160 foreign_memory_handle, |
| 161 entry->shared_memory[i]->created_size(), i)); |
| 162 } |
| 159 } | 163 } |
| 160 | 164 |
| 161 void AudioInputRendererHost::DoSendRecordingMessage( | 165 void AudioInputRendererHost::DoSendRecordingMessage( |
| 162 media::AudioInputController* controller) { | 166 media::AudioInputController* controller) { |
| 163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 164 // TODO(henrika): See crbug.com/115262 for details on why this method | 168 // TODO(henrika): See crbug.com/115262 for details on why this method |
| 165 // should be implemented. | 169 // should be implemented. |
| 166 } | 170 } |
| 167 | 171 |
| 168 void AudioInputRendererHost::DoHandleError( | 172 void AudioInputRendererHost::DoHandleError( |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 | 206 |
| 203 // Add the session entry to the map. | 207 // Add the session entry to the map. |
| 204 session_entries_[session_id] = stream_id; | 208 session_entries_[session_id] = stream_id; |
| 205 | 209 |
| 206 // Start the device with the session_id. If the device is started | 210 // Start the device with the session_id. If the device is started |
| 207 // successfully, OnDeviceStarted() callback will be triggered. | 211 // successfully, OnDeviceStarted() callback will be triggered. |
| 208 media_stream_manager_->audio_input_device_manager()->Start(session_id, this); | 212 media_stream_manager_->audio_input_device_manager()->Start(session_id, this); |
| 209 } | 213 } |
| 210 | 214 |
| 211 void AudioInputRendererHost::OnCreateStream( | 215 void AudioInputRendererHost::OnCreateStream( |
| 212 int stream_id, const media::AudioParameters& params, | 216 int stream_id, |
| 213 const std::string& device_id, bool automatic_gain_control) { | 217 const media::AudioParameters& params, |
| 218 const std::string& device_id, |
| 219 bool automatic_gain_control, |
| 220 int shared_memory_count) { |
| 214 VLOG(1) << "AudioInputRendererHost::OnCreateStream(stream_id=" | 221 VLOG(1) << "AudioInputRendererHost::OnCreateStream(stream_id=" |
| 215 << stream_id << ")"; | 222 << stream_id << ")"; |
| 216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 217 // media::AudioParameters is validated in the deserializer. | 224 // media::AudioParameters is validated in the deserializer. |
| 218 if (LookupById(stream_id) != NULL) { | 225 if (LookupById(stream_id) != NULL) { |
| 219 SendErrorMessage(stream_id); | 226 SendErrorMessage(stream_id); |
| 220 return; | 227 return; |
| 221 } | 228 } |
| 222 | 229 |
| 223 media::AudioParameters audio_params(params); | 230 media::AudioParameters audio_params(params); |
| 224 | 231 |
| 225 if (media_stream_manager_->audio_input_device_manager()-> | 232 if (media_stream_manager_->audio_input_device_manager()-> |
| 226 ShouldUseFakeDevice()) { | 233 ShouldUseFakeDevice()) { |
| 227 audio_params.Reset(media::AudioParameters::AUDIO_FAKE, | 234 audio_params.Reset(media::AudioParameters::AUDIO_FAKE, |
| 228 params.channel_layout(), 0, params.sample_rate(), | 235 params.channel_layout(), 0, params.sample_rate(), |
| 229 params.bits_per_sample(), params.frames_per_buffer()); | 236 params.bits_per_sample(), params.frames_per_buffer()); |
| 230 } | 237 } |
| 231 | 238 |
| 232 uint32 buffer_size = audio_params.GetBytesPerBuffer(); | 239 uint32 buffer_size = audio_params.GetBytesPerBuffer(); |
| 233 | 240 |
| 234 // Create a new AudioEntry structure. | 241 // Create a new AudioEntry structure. |
| 235 scoped_ptr<AudioEntry> entry(new AudioEntry()); | 242 scoped_ptr<AudioEntry> entry(new AudioEntry()); |
| 236 | 243 |
| 237 uint32 mem_size = sizeof(media::AudioInputBufferParameters) + buffer_size; | 244 uint32 mem_size = sizeof(media::AudioInputBufferParameters) + buffer_size; |
| 238 | 245 |
| 239 // Create the shared memory and share it with the renderer process | 246 // Create the shared memory and share it with the renderer process |
| 240 // using a new SyncWriter object. | 247 // using a new SyncWriter object. |
| 241 if (!entry->shared_memory.CreateAndMapAnonymous(mem_size)) { | 248 entry->shared_memory.resize(shared_memory_count); |
| 242 // If creation of shared memory failed then send an error message. | 249 for (size_t i = 0; i < entry->shared_memory.size(); ++i) { |
| 243 SendErrorMessage(stream_id); | 250 entry->shared_memory[i] = new base::SharedMemory(); |
| 244 return; | 251 if (!entry->shared_memory[i]->CreateAndMapAnonymous(mem_size)) { |
| 252 // If creation of shared memory failed then send an error message. |
| 253 SendErrorMessage(stream_id); |
| 254 return; |
| 255 } |
| 245 } | 256 } |
| 246 | 257 |
| 247 scoped_ptr<AudioInputSyncWriter> writer( | 258 scoped_ptr<AudioInputSyncWriter> writer( |
| 248 new AudioInputSyncWriter(&entry->shared_memory)); | 259 new AudioInputSyncWriter(&entry->shared_memory)); |
| 249 | 260 |
| 250 if (!writer->Init()) { | 261 if (!writer->Init()) { |
| 251 SendErrorMessage(stream_id); | 262 SendErrorMessage(stream_id); |
| 252 return; | 263 return; |
| 253 } | 264 } |
| 254 | 265 |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 for (SessionEntryMap::iterator it = session_entries_.begin(); | 467 for (SessionEntryMap::iterator it = session_entries_.begin(); |
| 457 it != session_entries_.end(); ++it) { | 468 it != session_entries_.end(); ++it) { |
| 458 if (stream_id == it->second) { | 469 if (stream_id == it->second) { |
| 459 return it->first; | 470 return it->first; |
| 460 } | 471 } |
| 461 } | 472 } |
| 462 return 0; | 473 return 0; |
| 463 } | 474 } |
| 464 | 475 |
| 465 } // namespace content | 476 } // namespace content |
| OLD | NEW |