15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/audio_input_renderer_host.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/memory/shared_memory.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/numerics/safe_math.h" 11a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/process.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/stringprintf.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/media/capture/web_contents_audio_input_stream.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/media/capture/web_contents_capture_util.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/browser/media/media_internals.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/audio_input_device_manager.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/audio_input_sync_writer.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_manager.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_manager_base.h" 206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "media/base/audio_bus.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace { 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid LogMessage(int stream_id, const std::string& msg, bool add_prefix) { 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::ostringstream oss; 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci oss << "[stream_id=" << stream_id << "] "; 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (add_prefix) 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci oss << "AIRH::"; 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci oss << msg; 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::MediaStreamManager::SendMessageToNativeLog(oss.str()); 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DVLOG(1) << oss.str(); 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct AudioInputRendererHost::AudioEntry { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioEntry(); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~AudioEntry(); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The AudioInputController that manages the audio input stream. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<media::AudioInputController> controller; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The audio input stream ID in the render view. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int stream_id; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Shared memory for transmission of the audio data. It has 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |shared_memory_segment_count| equal lengthed segments. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SharedMemory shared_memory; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int shared_memory_segment_count; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The synchronous writer to be used by the controller. We have the 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ownership of the writer. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<media::AudioInputController::SyncWriter> writer; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set to true after we called Close() for the controller. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool pending_close; 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If this entry's layout has a keyboard mic channel. 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool has_keyboard_mic_; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::AudioEntry::AudioEntry() 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : stream_id(0), 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shared_memory_segment_count(0), 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_close(false), 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci has_keyboard_mic_(false) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::AudioEntry::~AudioEntry() {} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::AudioInputRendererHost( 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::AudioManager* audio_manager, 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MediaStreamManager* media_stream_manager, 763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) AudioMirroringManager* audio_mirroring_manager, 773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) media::UserInputMonitor* user_input_monitor) 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : BrowserMessageFilter(AudioMsgStart), 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_manager_(audio_manager), 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch media_stream_manager_(media_stream_manager), 813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) audio_mirroring_manager_(audio_mirroring_manager), 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) user_input_monitor_(user_input_monitor), 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) audio_log_(MediaInternals::GetInstance()->CreateAudioLog( 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::AudioLogFactory::AUDIO_INPUT_CONTROLLER)) {} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::~AudioInputRendererHost() { 87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(audio_entries_.empty()); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnChannelClosing() { 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Since the IPC sender is gone, close all requested audio streams. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteEntries(); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnDestruct() const { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::DeleteOnIOThread::Destruct(this); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnCreated( 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::AudioInputController* controller) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind( 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &AudioInputRendererHost::DoCompleteCreation, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_scoped_refptr(controller))); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnRecording( 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::AudioInputController* controller) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind( 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &AudioInputRendererHost::DoSendRecordingMessage, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) make_scoped_refptr(controller))); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AudioInputRendererHost::OnError(media::AudioInputController* controller, 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::AudioInputController::ErrorCode error_code) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind( 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &AudioInputRendererHost::DoHandleError, 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) make_scoped_refptr(controller), 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) error_code)); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnData(media::AudioInputController* controller, 1356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const media::AudioBus* data) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Only low-latency mode is supported."; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AudioInputRendererHost::OnLog(media::AudioInputController* controller, 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& message) { 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::IO, 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&AudioInputRendererHost::DoLog, 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this, 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) make_scoped_refptr(controller), 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) message)); 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::DoCompleteCreation( 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::AudioInputController* controller) { 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioEntry* entry = LookupByController(controller); 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!entry) { 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NOTREACHED() << "AudioInputController is invalid."; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!PeerHandle()) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Renderer process handle is invalid."; 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DeleteEntryOnError(entry, INVALID_PEER_HANDLE); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!entry->controller->SharedMemoryAndSyncSocketMode()) { 166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NOTREACHED() << "Only shared-memory/sync-socket mode is supported."; 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DeleteEntryOnError(entry, INVALID_LATENCY_MODE); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Once the audio stream is created then complete the creation process by 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mapping shared memory and sharing with the renderer process. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SharedMemoryHandle foreign_memory_handle; 1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!entry->shared_memory.ShareToProcess(PeerHandle(), 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &foreign_memory_handle)) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we failed to map and share the shared memory then close the audio 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stream and send an error message. 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DeleteEntryOnError(entry, MEMORY_SHARING_FAILED); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioInputSyncWriter* writer = 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<AudioInputSyncWriter*>(entry->writer.get()); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::SyncSocket::TransitDescriptor socket_transit_descriptor; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we failed to prepare the sync socket for the renderer then we fail 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the construction of audio input stream. 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!writer->PrepareForeignSocket(PeerHandle(), &socket_transit_descriptor)) { 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DeleteEntryOnError(entry, SYNC_SOCKET_ERROR); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LogMessage(entry->stream_id, 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "DoCompleteCreation: IPC channel and stream are now open", 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci true); 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Send(new AudioInputMsg_NotifyStreamCreated( 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci entry->stream_id, foreign_memory_handle, socket_transit_descriptor, 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) entry->shared_memory.requested_size(), 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) entry->shared_memory_segment_count)); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::DoSendRecordingMessage( 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::AudioInputController* controller) { 206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(henrika): See crbug.com/115262 for details on why this method 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should be implemented. 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AudioEntry* entry = LookupByController(controller); 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!entry) { 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NOTREACHED() << "AudioInputController is invalid."; 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LogMessage( 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci entry->stream_id, "DoSendRecordingMessage: stream is now started", true); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::DoHandleError( 219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::AudioInputController* controller, 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::AudioInputController::ErrorCode error_code) { 221effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AudioEntry* entry = LookupByController(controller); 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!entry) { 2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NOTREACHED() << "AudioInputController is invalid."; 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 228a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // This is a fix for crbug.com/357501. The error can be triggered when closing 229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // the lid on Macs, which causes more problems than it fixes. 230a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Also, in crbug.com/357569, the goal is to remove usage of the error since 231a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // it was added to solve a crash on Windows that no longer can be reproduced. 232a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (error_code == media::AudioInputController::NO_DATA_ERROR) { 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(henrika): it might be possible to do something other than just 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // logging when we detect many NO_DATA_ERROR calls for a stream. 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LogMessage(entry->stream_id, "AIC::DoCheckForNoData: NO_DATA_ERROR", false); 236a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return; 237a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 238a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::ostringstream oss; 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci oss << "AIC reports error_code=" << error_code; 2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LogMessage(entry->stream_id, oss.str(), false); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) audio_log_->OnError(entry->stream_id); 244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DeleteEntryOnError(entry, AUDIO_INPUT_CONTROLLER_ERROR); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AudioInputRendererHost::DoLog(media::AudioInputController* controller, 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& message) { 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AudioEntry* entry = LookupByController(controller); 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!entry) { 2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NOTREACHED() << "AudioInputController is invalid."; 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Add stream ID and current audio level reported by AIC to native log. 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LogMessage(entry->stream_id, message, false); 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool AudioInputRendererHost::OnMessageReceived(const IPC::Message& message) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool handled = true; 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(AudioInputRendererHost, message) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(AudioInputHostMsg_CreateStream, OnCreateStream) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(AudioInputHostMsg_RecordStream, OnRecordStream) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(AudioInputHostMsg_CloseStream, OnCloseStream) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(AudioInputHostMsg_SetVolume, OnSetVolume) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IPC_END_MESSAGE_MAP() 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handled; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnCreateStream( 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int stream_id, 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int render_view_id, 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int session_id, 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const AudioInputHostMsg_CreateStream_Config& config) { 278effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS) 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (config.params.channel_layout() == 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media_stream_manager_->audio_input_device_manager() 2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ->RegisterKeyboardMicStream( 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&AudioInputRendererHost::DoCreateStream, 2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this, 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci stream_id, 2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_view_id, 2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci session_id, 2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci config)); 2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DoCreateStream(stream_id, render_view_id, session_id, config); 2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else 2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DoCreateStream(stream_id, render_view_id, session_id, config); 2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AudioInputRendererHost::DoCreateStream( 3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int stream_id, 3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int render_view_id, 3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int session_id, 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const AudioInputHostMsg_CreateStream_Config& config) { 3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_CURRENTLY_ON(BrowserThread::IO); 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::ostringstream oss; 3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci oss << "[stream_id=" << stream_id << "] " 3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << "AIRH::OnCreateStream(render_view_id=" << render_view_id 3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << ", session_id=" << session_id << ")"; 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GT(render_view_id, 0); 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // media::AudioParameters is validated in the deserializer. 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (LookupById(stream_id) != NULL) { 314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SendErrorMessage(stream_id, STREAM_ALREADY_EXISTS); 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MaybeUnregisterKeyboardMicStream(config); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) media::AudioParameters audio_params(config.params); 320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (media_stream_manager_->audio_input_device_manager()-> 321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ShouldUseFakeDevice()) { 322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) audio_params.Reset( 323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) media::AudioParameters::AUDIO_FAKE, 3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci config.params.channel_layout(), config.params.channels(), 325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) config.params.sample_rate(), config.params.bits_per_sample(), 326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) config.params.frames_per_buffer()); 327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check if we have the permission to open the device and which device to use. 330a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string device_name; 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string device_id = media::AudioManagerBase::kDefaultDeviceId; 332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (audio_params.format() != media::AudioParameters::AUDIO_FAKE) { 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const StreamDeviceInfo* info = media_stream_manager_-> 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_input_device_manager()->GetOpenedDeviceInfoById(session_id); 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!info) { 336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SendErrorMessage(stream_id, PERMISSION_DENIED); 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DLOG(WARNING) << "No permission has been granted to input stream with " 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "session_id=" << session_id; 3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MaybeUnregisterKeyboardMicStream(config); 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 343bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch device_id = info->device.id; 344a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch device_name = info->device.name; 3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci oss << ": device_name=" << device_name; 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a new AudioEntry structure. 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioEntry> entry(new AudioEntry()); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const uint32 segment_size = 3526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) (sizeof(media::AudioInputBufferParameters) + 3536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) media::AudioBus::CalculateMemorySize(audio_params)); 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) entry->shared_memory_segment_count = config.shared_memory_count; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the shared memory and share it with the renderer process 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // using a new SyncWriter object. 358c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::CheckedNumeric<uint32> size = segment_size; 359c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch size *= entry->shared_memory_segment_count; 360c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!size.IsValid() || 361c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch !entry->shared_memory.CreateAndMapAnonymous(size.ValueOrDie())) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If creation of shared memory failed then send an error message. 363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SendErrorMessage(stream_id, SHARED_MEMORY_CREATE_FAILED); 3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MaybeUnregisterKeyboardMicStream(config); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) scoped_ptr<AudioInputSyncWriter> writer(new AudioInputSyncWriter( 3696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) &entry->shared_memory, entry->shared_memory_segment_count, audio_params)); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!writer->Init()) { 372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED); 3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MaybeUnregisterKeyboardMicStream(config); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have successfully created the SyncWriter then assign it to the 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // entry and construct an AudioInputController. 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->writer.reset(writer.release()); 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (WebContentsCaptureUtil::IsWebContentsDeviceId(device_id)) { 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) entry->controller = media::AudioInputController::CreateForStream( 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_manager_->GetTaskRunner(), 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebContentsAudioInputStream::Create( 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_id, 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_params, 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_manager_->GetWorkerTaskRunner(), 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_mirroring_manager_), 3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entry->writer.get(), 3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) user_input_monitor_); 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(henrika): replace CreateLowLatency() with Create() as soon 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // as satish has ensured that Speech Input also uses the default low- 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // latency path. See crbug.com/112472 for details. 3953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entry->controller = 3963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) media::AudioInputController::CreateLowLatency(audio_manager_, 3973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this, 3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) audio_params, 3993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) device_id, 4003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) entry->writer.get(), 4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) user_input_monitor_); 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->controller.get()) { 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SendErrorMessage(stream_id, STREAM_CREATE_ERROR); 4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MaybeUnregisterKeyboardMicStream(config); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the initial AGC state for the audio input stream. Note that, the AGC 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is only supported in AUDIO_PCM_LOW_LATENCY mode. 4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (config.params.format() == media::AudioParameters::AUDIO_PCM_LOW_LATENCY) { 413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) entry->controller->SetAutomaticGainControl(config.automatic_gain_control); 4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci oss << ", AGC=" << config.automatic_gain_control; 4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 41734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#if defined(OS_CHROMEOS) 41834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (config.params.channel_layout() == 41934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { 42034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) entry->has_keyboard_mic_ = true; 42134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 42234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#endif 42334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MediaStreamManager::SendMessageToNativeLog(oss.str()); 4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DVLOG(1) << oss.str(); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Since the controller was created successfully, create an entry and add it 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the map. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->stream_id = stream_id; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_entries_.insert(std::make_pair(stream_id, entry.release())); 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_log_->OnCreated(stream_id, audio_params, device_id); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnRecordStream(int stream_id) { 435effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LogMessage(stream_id, "OnRecordStream", true); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioEntry* entry = LookupById(stream_id); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!entry) { 440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SendErrorMessage(stream_id, INVALID_AUDIO_ENTRY); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->controller->Record(); 445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) audio_log_->OnStarted(stream_id); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnCloseStream(int stream_id) { 449effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LogMessage(stream_id, "OnCloseStream", true); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioEntry* entry = LookupById(stream_id); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAndDeleteStream(entry); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnSetVolume(int stream_id, double volume) { 459effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioEntry* entry = LookupById(stream_id); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!entry) { 463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SendErrorMessage(stream_id, INVALID_AUDIO_ENTRY); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->controller->SetVolume(volume); 468f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) audio_log_->OnSetVolume(stream_id, volume); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AudioInputRendererHost::SendErrorMessage( 472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int stream_id, ErrorCode error_code) { 4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string err_msg = 4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::StringPrintf("SendErrorMessage(error_code=%d)", error_code); 4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LogMessage(stream_id, err_msg, true); 4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Send(new AudioInputMsg_NotifyStreamStateChanged( 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_id, media::AudioInputIPCDelegate::kError)); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::DeleteEntries() { 482effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AudioEntryMap::iterator i = audio_entries_.begin(); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != audio_entries_.end(); ++i) { 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAndDeleteStream(i->second); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::CloseAndDeleteStream(AudioEntry* entry) { 491effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!entry->pending_close) { 4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LogMessage(entry->stream_id, "CloseAndDeleteStream", true); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->controller->Close(base::Bind(&AudioInputRendererHost::DeleteEntry, 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, entry)); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->pending_close = true; 498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) audio_log_->OnClosed(entry->stream_id); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) { 503effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LogMessage(entry->stream_id, "DeleteEntry: stream is now closed", true); 5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS) 5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (entry->has_keyboard_mic_) { 5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media_stream_manager_->audio_input_device_manager() 5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ->UnregisterKeyboardMicStream(); 5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the entry when this method goes out of scope. 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioEntry> entry_deleter(entry); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Erase the entry from the map. 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_entries_.erase(entry->stream_id); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 520a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AudioInputRendererHost::DeleteEntryOnError(AudioEntry* entry, 521a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ErrorCode error_code) { 522effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sends the error message first before we close the stream because 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |entry| is destroyed in DeleteEntry(). 526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SendErrorMessage(entry->stream_id, error_code); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAndDeleteStream(entry); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupById( 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int stream_id) { 532effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioEntryMap::iterator i = audio_entries_.find(stream_id); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i != audio_entries_.end()) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i->second; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupByController( 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::AudioInputController* controller) { 542effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterate the map of entries. 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(hclam): Implement a faster look up method. 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AudioEntryMap::iterator i = audio_entries_.begin(); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != audio_entries_.end(); ++i) { 548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (controller == i->second->controller.get()) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i->second; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AudioInputRendererHost::MaybeUnregisterKeyboardMicStream( 5551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const AudioInputHostMsg_CreateStream_Config& config) { 5561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS) 5571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (config.params.channel_layout() == 5581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { 5591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media_stream_manager_->audio_input_device_manager() 5601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ->UnregisterKeyboardMicStream(); 5611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 5631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 566