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