1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4//
5// AudioInputRendererHost serves audio related requests from audio capturer
6// which lives inside the render process and provide access to audio hardware.
7//
8// Create stream sequence (AudioInputController = AIC):
9//
10// AudioInputHostMsg_CreateStream -> OnCreateStream -> AIC::CreateLowLatency ->
11//   <- AudioInputMsg_NotifyStreamCreated <- DoCompleteCreation <- OnCreated <-
12//
13// Close stream sequence:
14//
15// AudioInputHostMsg_CloseStream -> OnCloseStream -> AIC::Close ->
16//
17// This class is owned by BrowserRenderProcessHost and instantiated on UI
18// thread. All other operations and method calls happen on IO thread, so we
19// need to be extra careful about the lifetime of this object.
20//
21// To ensure low latency audio, a SyncSocket pair is used to signal buffer
22// readiness without having to route messages using the IO thread.
23
24#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_RENDERER_HOST_H_
25#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_RENDERER_HOST_H_
26
27#include <map>
28#include <string>
29
30#include "base/compiler_specific.h"
31#include "base/gtest_prod_util.h"
32#include "base/memory/ref_counted.h"
33#include "base/memory/scoped_ptr.h"
34#include "base/memory/shared_memory.h"
35#include "base/process/process.h"
36#include "base/sequenced_task_runner_helpers.h"
37#include "content/common/media/audio_messages.h"
38#include "content/public/browser/browser_message_filter.h"
39#include "content/public/browser/browser_thread.h"
40#include "media/audio/audio_input_controller.h"
41#include "media/audio/audio_io.h"
42#include "media/audio/audio_logging.h"
43#include "media/audio/simple_sources.h"
44
45namespace media {
46class AudioManager;
47class AudioParameters;
48class UserInputMonitor;
49}
50
51namespace content {
52class AudioMirroringManager;
53class MediaStreamManager;
54
55class CONTENT_EXPORT AudioInputRendererHost
56    : public BrowserMessageFilter,
57      public media::AudioInputController::EventHandler {
58 public:
59
60  // Error codes to make native loggin more clear. These error codes are added
61  // to generic error strings to provide a higher degree of details.
62  // Changing these values can lead to problems when matching native debug
63  // logs with the actual cause of error.
64  enum ErrorCode {
65    // An unspecified error occured.
66    UNKNOWN_ERROR = 0,
67
68    // Failed to look up audio intry for the provided stream id.
69    INVALID_AUDIO_ENTRY,  // = 1
70
71    // A stream with the specified stream id already exists.
72    STREAM_ALREADY_EXISTS,  // = 2
73
74    // The page does not have permission to open the specified capture device.
75    PERMISSION_DENIED,  // = 3
76
77    // Failed to create shared memory.
78    SHARED_MEMORY_CREATE_FAILED,  // = 4
79
80    // Failed to initialize the AudioInputSyncWriter instance.
81    SYNC_WRITER_INIT_FAILED,  // = 5
82
83    // Failed to create native audio input stream.
84    STREAM_CREATE_ERROR,  // = 6
85
86    // Renderer process handle is invalid.
87    INVALID_PEER_HANDLE,  // = 7
88
89    // Only low-latency mode is supported.
90    INVALID_LATENCY_MODE,  // = 8
91
92    // Failed to map and share the shared memory.
93    MEMORY_SHARING_FAILED,  // = 9
94
95    // Unable to prepare the foreign socket handle.
96    SYNC_SOCKET_ERROR,  // = 10
97
98    // This error message comes from the AudioInputController instance.
99    AUDIO_INPUT_CONTROLLER_ERROR,  // = 11
100  };
101
102  // Called from UI thread from the owner of this object.
103  // |user_input_monitor| is used for typing detection and can be NULL.
104  AudioInputRendererHost(media::AudioManager* audio_manager,
105                         MediaStreamManager* media_stream_manager,
106                         AudioMirroringManager* audio_mirroring_manager,
107                         media::UserInputMonitor* user_input_monitor);
108
109  // BrowserMessageFilter implementation.
110  virtual void OnChannelClosing() OVERRIDE;
111  virtual void OnDestruct() const OVERRIDE;
112  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
113
114  // AudioInputController::EventHandler implementation.
115  virtual void OnCreated(media::AudioInputController* controller) OVERRIDE;
116  virtual void OnRecording(media::AudioInputController* controller) OVERRIDE;
117  virtual void OnError(media::AudioInputController* controller,
118      media::AudioInputController::ErrorCode error_code) OVERRIDE;
119  virtual void OnData(media::AudioInputController* controller,
120                      const media::AudioBus* data) OVERRIDE;
121  virtual void OnLog(media::AudioInputController* controller,
122                     const std::string& message) OVERRIDE;
123
124 private:
125  // TODO(henrika): extend test suite (compare AudioRenderHost)
126  friend class BrowserThread;
127  friend class TestAudioInputRendererHost;
128  friend class base::DeleteHelper<AudioInputRendererHost>;
129
130  struct AudioEntry;
131  typedef std::map<int, AudioEntry*> AudioEntryMap;
132
133  virtual ~AudioInputRendererHost();
134
135  // Methods called on IO thread ----------------------------------------------
136
137  // Audio related IPC message handlers.
138
139  // For ChromeOS: Checks if the stream should contain keyboard mic, if so
140  // registers to AudioInputDeviceManager. Then calls DoCreateStream.
141  // For non-ChromeOS: Just calls DoCreateStream.
142  void OnCreateStream(int stream_id,
143                      int render_view_id,
144                      int session_id,
145                      const AudioInputHostMsg_CreateStream_Config& config);
146
147  // Creates an audio input stream with the specified format whose data is
148  // consumed by an entity in the render view referenced by |render_view_id|.
149  // |session_id| is used to find out which device to be used for the stream.
150  // Upon success/failure, the peer is notified via the
151  // NotifyStreamCreated message.
152  void DoCreateStream(int stream_id,
153                      int render_view_id,
154                      int session_id,
155                      const AudioInputHostMsg_CreateStream_Config& config);
156
157  // Record the audio input stream referenced by |stream_id|.
158  void OnRecordStream(int stream_id);
159
160  // Close the audio stream referenced by |stream_id|.
161  void OnCloseStream(int stream_id);
162
163  // Set the volume of the audio stream referenced by |stream_id|.
164  void OnSetVolume(int stream_id, double volume);
165
166  // Complete the process of creating an audio input stream. This will set up
167  // the shared memory or shared socket in low latency mode and send the
168  // NotifyStreamCreated message to the peer.
169  void DoCompleteCreation(media::AudioInputController* controller);
170
171  // Send a state change message to the renderer.
172  void DoSendRecordingMessage(media::AudioInputController* controller);
173
174  // Handle error coming from audio stream.
175  void DoHandleError(media::AudioInputController* controller,
176      media::AudioInputController::ErrorCode error_code);
177
178  // Log audio level of captured audio stream.
179  void DoLog(media::AudioInputController* controller,
180             const std::string& message);
181
182  // Send an error message to the renderer.
183  void SendErrorMessage(int stream_id, ErrorCode error_code);
184
185  // Delete all audio entry and all audio streams
186  void DeleteEntries();
187
188  // Closes the stream. The stream is then deleted in DeleteEntry() after it
189  // is closed.
190  void CloseAndDeleteStream(AudioEntry* entry);
191
192  // Delete an audio entry and close the related audio stream.
193  void DeleteEntry(AudioEntry* entry);
194
195  // Delete audio entry and close the related audio input stream.
196  void DeleteEntryOnError(AudioEntry* entry, ErrorCode error_code);
197
198  // A helper method to look up a AudioEntry identified by |stream_id|.
199  // Returns NULL if not found.
200  AudioEntry* LookupById(int stream_id);
201
202  // Search for a AudioEntry having the reference to |controller|.
203  // This method is used to look up an AudioEntry after a controller
204  // event is received.
205  AudioEntry* LookupByController(media::AudioInputController* controller);
206
207  // If ChromeOS and |config|'s layout has keyboard mic, unregister in
208  // AudioInputDeviceManager.
209  void MaybeUnregisterKeyboardMicStream(
210      const AudioInputHostMsg_CreateStream_Config& config);
211
212  // Used to create an AudioInputController.
213  media::AudioManager* audio_manager_;
214
215  // Used to access to AudioInputDeviceManager.
216  MediaStreamManager* media_stream_manager_;
217
218  AudioMirroringManager* audio_mirroring_manager_;
219
220  // A map of stream IDs to audio sources.
221  AudioEntryMap audio_entries_;
222
223  // Raw pointer of the UserInputMonitor.
224  media::UserInputMonitor* user_input_monitor_;
225
226  scoped_ptr<media::AudioLog> audio_log_;
227
228  DISALLOW_COPY_AND_ASSIGN(AudioInputRendererHost);
229};
230
231}  // namespace content
232
233#endif  // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_RENDERER_HOST_H_
234