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 // Low-latency audio capturing class utilizing audio input stream provided
6 // by a server process by use of an IPC interface.
7 //
8 // Relationship of classes:
9 //
10 //  AudioInputController                 AudioInputDevice
11 //           ^                                  ^
12 //           |                                  |
13 //           v                  IPC             v
14 // MojoAudioInputStream    <----------->  AudioInputIPC
15 //           ^                            (MojoAudioInputIPC)
16 //           |
17 //           v
18 // AudioInputDeviceManager
19 //
20 // Transportation of audio samples from the browser to the render process
21 // is done by using shared memory in combination with a SyncSocket.
22 // The AudioInputDevice user registers an AudioInputDevice::CaptureCallback by
23 // calling Initialize().  The callback will be called with recorded audio from
24 // the underlying audio layers.
25 // The session ID is used by the RenderFrameAudioInputStreamFactory to start
26 // the device referenced by this ID.
27 //
28 // State sequences:
29 //
30 // Start -> CreateStream ->
31 //       <- OnStreamCreated <-
32 //       -> RecordStream ->
33 //
34 // AudioInputDevice::Capture => low latency audio transport on audio thread =>
35 //
36 // Stop ->  CloseStream -> Close
37 //
38 // This class depends on the audio transport thread. That thread is responsible
39 // for calling the CaptureCallback and feeding it audio samples from the server
40 // side audio layer using a socket and shared memory.
41 //
42 // Implementation notes:
43 // - The user must call Stop() before deleting the class instance.
44 
45 #ifndef MEDIA_AUDIO_AUDIO_INPUT_DEVICE_H_
46 #define MEDIA_AUDIO_AUDIO_INPUT_DEVICE_H_
47 
48 #include <memory>
49 #include <string>
50 
51 #include "base/compiler_specific.h"
52 #include "base/macros.h"
53 #include "base/memory/read_only_shared_memory_region.h"
54 #include "base/optional.h"
55 #include "base/sequence_checker.h"
56 #include "base/threading/platform_thread.h"
57 #include "base/time/time.h"
58 #include "media/audio/alive_checker.h"
59 #include "media/audio/audio_device_thread.h"
60 #include "media/audio/audio_input_ipc.h"
61 #include "media/base/audio_capturer_source.h"
62 #include "media/base/audio_parameters.h"
63 #include "media/base/media_export.h"
64 
65 namespace media {
66 
67 class MEDIA_EXPORT AudioInputDevice : public AudioCapturerSource,
68                                       public AudioInputIPCDelegate {
69  public:
70   enum Purpose : int8_t { kUserInput, kLoopback };
71 
72   // NOTE: Clients must call Initialize() before using.
73   // |enable_uma| controls logging of UMA stats. It is used to ensure that
74   // stats are not logged for mirroring service streams.
75   AudioInputDevice(std::unique_ptr<AudioInputIPC> ipc, Purpose purpose);
76 
77   // AudioCapturerSource implementation.
78   void Initialize(const AudioParameters& params,
79                   CaptureCallback* callback) override;
80   void Start() override;
81   void Stop() override;
82   void SetVolume(double volume) override;
83   void SetAutomaticGainControl(bool enabled) override;
84   void SetOutputDeviceForAec(const std::string& output_device_id) override;
85 
86  private:
87   friend class base::RefCountedThreadSafe<AudioInputDevice>;
88 
89   // Our audio thread callback class.  See source file for details.
90   class AudioThreadCallback;
91 
92   // Note: The ordering of members in this enum is critical to correct behavior!
93   enum State {
94     IPC_CLOSED,       // No more IPCs can take place.
95     IDLE,             // Not started.
96     CREATING_STREAM,  // Waiting for OnStreamCreated() to be called back.
97     RECORDING,        // Receiving audio data.
98   };
99 
100   // This enum is used for UMA, so the only allowed operation on this definition
101   // is to add new states to the bottom, update kMaxValue, and update the
102   // histogram "Media.Audio.Capture.StreamCallbackError2".
103   enum Error {
104     kNoError = 0,
105     kErrorDuringCreation = 1,
106     kErrorDuringCapture = 2,
107     kMaxValue = kErrorDuringCapture
108   };
109 
110   ~AudioInputDevice() override;
111 
112   // AudioInputIPCDelegate implementation.
113   void OnStreamCreated(base::ReadOnlySharedMemoryRegion shared_memory_region,
114                        base::SyncSocket::ScopedHandle socket_handle,
115                        bool initially_muted) override;
116   void OnError() override;
117   void OnMuted(bool is_muted) override;
118   void OnIPCClosed() override;
119 
120   // This is called by |alive_checker_| if it detects that the input stream is
121   // dead.
122   void DetectedDeadInputStream();
123 
124   AudioParameters audio_parameters_;
125 
126   const base::ThreadPriority thread_priority_;
127 
128   const bool enable_uma_;
129 
130   CaptureCallback* callback_;
131 
132   // A pointer to the IPC layer that takes care of sending requests over to
133   // the stream implementation.  Only valid when state_ != IPC_CLOSED.
134   std::unique_ptr<AudioInputIPC> ipc_;
135 
136   // Current state. See comments for State enum above.
137   State state_;
138 
139   // For UMA stats. May only be accessed on the IO thread.
140   Error had_error_ = kNoError;
141 
142   // Stores the Automatic Gain Control state. Default is false.
143   bool agc_is_enabled_;
144 
145   // Checks regularly that the input stream is alive and notifies us if it
146   // isn't by calling DetectedDeadInputStream(). Must outlive |audio_callback_|.
147   std::unique_ptr<AliveChecker> alive_checker_;
148 
149   std::unique_ptr<AudioInputDevice::AudioThreadCallback> audio_callback_;
150   std::unique_ptr<AudioDeviceThread> audio_thread_;
151 
152   SEQUENCE_CHECKER(sequence_checker_);
153 
154   // Cache the output device used for AEC in case it's called before the stream
155   // is created.
156   base::Optional<std::string> output_device_id_for_aec_;
157 
158   DISALLOW_IMPLICIT_CONSTRUCTORS(AudioInputDevice);
159 };
160 
161 }  // namespace media
162 
163 #endif  // MEDIA_AUDIO_AUDIO_INPUT_DEVICE_H_
164