audio_input_renderer_host.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct AudioInputRendererHost::AudioEntry {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioEntry();
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~AudioEntry();
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The AudioInputController that manages the audio input stream.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<media::AudioInputController> controller;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The audio input stream ID in the render view.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int stream_id;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Shared memory for transmission of the audio data. It has
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |shared_memory_segment_count| equal lengthed segments.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SharedMemory shared_memory;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int shared_memory_segment_count;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The synchronous writer to be used by the controller. We have the
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ownership of the writer.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<media::AudioInputController::SyncWriter> writer;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set to true after we called Close() for the controller.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pending_close;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::AudioEntry::AudioEntry()
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : stream_id(0),
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      shared_memory_segment_count(0),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_close(false) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::AudioEntry::~AudioEntry() {}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::AudioInputRendererHost(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::AudioManager* audio_manager,
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MediaStreamManager* media_stream_manager,
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    AudioMirroringManager* audio_mirroring_manager,
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    media::UserInputMonitor* user_input_monitor)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : BrowserMessageFilter(AudioMsgStart),
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      audio_manager_(audio_manager),
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      media_stream_manager_(media_stream_manager),
623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      audio_mirroring_manager_(audio_mirroring_manager),
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      user_input_monitor_(user_input_monitor),
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      audio_log_(MediaInternals::GetInstance()->CreateAudioLog(
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          media::AudioLogFactory::AUDIO_INPUT_CONTROLLER)) {}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::~AudioInputRendererHost() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(audio_entries_.empty());
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnChannelClosing() {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since the IPC channel is gone, close all requested audio streams.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteEntries();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnDestruct() const {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::DeleteOnIOThread::Destruct(this);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnCreated(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::AudioInputController* controller) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &AudioInputRendererHost::DoCompleteCreation,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          make_scoped_refptr(controller)));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnRecording(
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::AudioInputController* controller) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &AudioInputRendererHost::DoSendRecordingMessage,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          make_scoped_refptr(controller)));
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AudioInputRendererHost::OnError(media::AudioInputController* controller,
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    media::AudioInputController::ErrorCode error_code) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &AudioInputRendererHost::DoHandleError,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          this,
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          make_scoped_refptr(controller),
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          error_code));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnData(media::AudioInputController* controller,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const uint8* data,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    uint32 size) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Only low-latency mode is supported.";
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::DoCompleteCreation(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::AudioInputController* controller) {
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioEntry* entry = LookupByController(controller);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!PeerHandle()) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Renderer process handle is invalid.";
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DeleteEntryOnError(entry, INVALID_PEER_HANDLE);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry->controller->LowLatencyMode()) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Only low-latency mode is supported.";
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DeleteEntryOnError(entry, INVALID_LATENCY_MODE);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Once the audio stream is created then complete the creation process by
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mapping shared memory and sharing with the renderer process.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SharedMemoryHandle foreign_memory_handle;
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!entry->shared_memory.ShareToProcess(PeerHandle(),
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           &foreign_memory_handle)) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we failed to map and share the shared memory then close the audio
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // stream and send an error message.
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DeleteEntryOnError(entry, MEMORY_SHARING_FAILED);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputSyncWriter* writer =
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<AudioInputSyncWriter*>(entry->writer.get());
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SyncSocket::Handle foreign_socket_handle;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::FileDescriptor foreign_socket_handle;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we failed to prepare the sync socket for the renderer then we fail
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the construction of audio input stream.
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!writer->PrepareForeignSocketHandle(PeerHandle(),
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          &foreign_socket_handle)) {
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DeleteEntryOnError(entry, SYNC_SOCKET_ERROR);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new AudioInputMsg_NotifyStreamCreated(entry->stream_id,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      foreign_memory_handle, foreign_socket_handle,
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      entry->shared_memory.requested_size(),
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      entry->shared_memory_segment_count));
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::DoSendRecordingMessage(
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::AudioInputController* controller) {
176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(henrika): See crbug.com/115262 for details on why this method
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be implemented.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::DoHandleError(
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    media::AudioInputController* controller,
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    media::AudioInputController::ErrorCode error_code) {
184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Log all errors even it is ignored later.
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamManager::SendMessageToNativeLog(
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::StringPrintf("AudioInputController error: %d", error_code));
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // This is a fix for crbug.com/357501. The error can be triggered when closing
190a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // the lid on Macs, which causes more problems than it fixes.
191a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Also, in crbug.com/357569, the goal is to remove usage of the error since
192a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // it was added to solve a crash on Windows that no longer can be reproduced.
193a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (error_code == media::AudioInputController::NO_DATA_ERROR) {
194a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    DVLOG(1) << "AudioInputRendererHost@" << this << "::DoHandleError: "
195a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch             << "NO_DATA_ERROR ignored.";
196a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
197a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
198a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioEntry* entry = LookupByController(controller);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  audio_log_->OnError(entry->stream_id);
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DeleteEntryOnError(entry, AUDIO_INPUT_CONTROLLER_ERROR);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AudioInputRendererHost::OnMessageReceived(const IPC::Message& message,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               bool* message_was_ok) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP_EX(AudioInputRendererHost, message, *message_was_ok)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AudioInputHostMsg_CreateStream, OnCreateStream)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AudioInputHostMsg_RecordStream, OnRecordStream)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AudioInputHostMsg_CloseStream, OnCloseStream)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AudioInputHostMsg_SetVolume, OnSetVolume)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP_EX()
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnCreateStream(
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int stream_id,
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int render_view_id,
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int session_id,
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const AudioInputHostMsg_CreateStream_Config& config) {
226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DVLOG(1) << "AudioInputRendererHost@" << this
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           << "::OnCreateStream(stream_id=" << stream_id
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           << ", render_view_id=" << render_view_id
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           << ", session_id=" << session_id << ")";
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_GT(render_view_id, 0);
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // media::AudioParameters is validated in the deserializer.
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (LookupById(stream_id) != NULL) {
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SendErrorMessage(stream_id, STREAM_ALREADY_EXISTS);
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  media::AudioParameters audio_params(config.params);
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (media_stream_manager_->audio_input_device_manager()->
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ShouldUseFakeDevice()) {
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    audio_params.Reset(
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        media::AudioParameters::AUDIO_FAKE,
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        config.params.channel_layout(), config.params.channels(), 0,
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        config.params.sample_rate(), config.params.bits_per_sample(),
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        config.params.frames_per_buffer());
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check if we have the permission to open the device and which device to use.
251a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::string device_name;
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string device_id = media::AudioManagerBase::kDefaultDeviceId;
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (audio_params.format() != media::AudioParameters::AUDIO_FAKE) {
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StreamDeviceInfo* info = media_stream_manager_->
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!info) {
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      SendErrorMessage(stream_id, PERMISSION_DENIED);
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(WARNING) << "No permission has been granted to input stream with "
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    << "session_id=" << session_id;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
263bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    device_id = info->device.id;
264a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    device_name = info->device.name;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a new AudioEntry structure.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioEntry> entry(new AudioEntry());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const uint32 segment_size = (sizeof(media::AudioInputBufferParameters) +
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               audio_params.GetBytesPerBuffer());
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  entry->shared_memory_segment_count = config.shared_memory_count;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the shared memory and share it with the renderer process
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using a new SyncWriter object.
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::CheckedNumeric<uint32> size = segment_size;
277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  size *= entry->shared_memory_segment_count;
278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!size.IsValid() ||
279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      !entry->shared_memory.CreateAndMapAnonymous(size.ValueOrDie())) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If creation of shared memory failed then send an error message.
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SendErrorMessage(stream_id, SHARED_MEMORY_CREATE_FAILED);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioInputSyncWriter> writer(
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new AudioInputSyncWriter(&entry->shared_memory,
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               entry->shared_memory_segment_count));
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!writer->Init()) {
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we have successfully created the SyncWriter then assign it to the
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // entry and construct an AudioInputController.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->writer.reset(writer.release());
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (WebContentsCaptureUtil::IsWebContentsDeviceId(device_id)) {
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    entry->controller = media::AudioInputController::CreateForStream(
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        audio_manager_->GetTaskRunner(),
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this,
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        WebContentsAudioInputStream::Create(
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            device_id,
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            audio_params,
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            audio_manager_->GetWorkerTaskRunner(),
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            audio_mirroring_manager_),
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        entry->writer.get(),
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        user_input_monitor_);
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(henrika): replace CreateLowLatency() with Create() as soon
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // as satish has ensured that Speech Input also uses the default low-
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // latency path. See crbug.com/112472 for details.
3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    entry->controller =
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        media::AudioInputController::CreateLowLatency(audio_manager_,
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                      this,
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                      audio_params,
3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                      device_id,
3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                      entry->writer.get(),
3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                      user_input_monitor_);
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!entry->controller.get()) {
322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SendErrorMessage(stream_id, STREAM_CREATE_ERROR);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the initial AGC state for the audio input stream. Note that, the AGC
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is only supported in AUDIO_PCM_LOW_LATENCY mode.
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (config.params.format() == media::AudioParameters::AUDIO_PCM_LOW_LATENCY)
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    entry->controller->SetAutomaticGainControl(config.automatic_gain_control);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Since the controller was created successfully, create an entry and add it
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the map.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->stream_id = stream_id;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_entries_.insert(std::make_pair(stream_id, entry.release()));
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamManager::SendMessageToNativeLog(
337a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      "Audio input stream created successfully. Device name: " + device_name);
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  audio_log_->OnCreated(stream_id, audio_params, device_id);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnRecordStream(int stream_id) {
342effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioEntry* entry = LookupById(stream_id);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry) {
346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SendErrorMessage(stream_id, INVALID_AUDIO_ENTRY);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->controller->Record();
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  audio_log_->OnStarted(stream_id);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnCloseStream(int stream_id) {
355effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioEntry* entry = LookupById(stream_id);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseAndDeleteStream(entry);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::OnSetVolume(int stream_id, double volume) {
364effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioEntry* entry = LookupById(stream_id);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry) {
368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SendErrorMessage(stream_id, INVALID_AUDIO_ENTRY);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->controller->SetVolume(volume);
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  audio_log_->OnSetVolume(stream_id, volume);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AudioInputRendererHost::SendErrorMessage(
377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int stream_id, ErrorCode error_code) {
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamManager::SendMessageToNativeLog(
379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::StringPrintf("AudioInputRendererHost error: %d", error_code));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new AudioInputMsg_NotifyStreamStateChanged(
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stream_id, media::AudioInputIPCDelegate::kError));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::DeleteEntries() {
385effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (AudioEntryMap::iterator i = audio_entries_.begin();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != audio_entries_.end(); ++i) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseAndDeleteStream(i->second);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
394effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry->pending_close) {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->controller->Close(base::Bind(&AudioInputRendererHost::DeleteEntry,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        this, entry));
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->pending_close = true;
400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    audio_log_->OnClosed(entry->stream_id);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) {
405effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete the entry when this method goes out of scope.
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioEntry> entry_deleter(entry);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Erase the entry from the map.
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_entries_.erase(entry->stream_id);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AudioInputRendererHost::DeleteEntryOnError(AudioEntry* entry,
415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ErrorCode error_code) {
416effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sends the error message first before we close the stream because
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |entry| is destroyed in DeleteEntry().
420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SendErrorMessage(entry->stream_id, error_code);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseAndDeleteStream(entry);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupById(
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int stream_id) {
426effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioEntryMap::iterator i = audio_entries_.find(stream_id);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != audio_entries_.end())
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return i->second;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupByController(
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::AudioInputController* controller) {
436effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Iterate the map of entries.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(hclam): Implement a faster look up method.
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (AudioEntryMap::iterator i = audio_entries_.begin();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != audio_entries_.end(); ++i) {
442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (controller == i->second->controller.get())
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i->second;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
449