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 // Audio rendering unit utilizing audio output stream provided by browser
6 // process through IPC.
7 //
8 // Relationship of classes.
9 //
10 //  AudioOutputController                AudioOutputDevice
11 //           ^                                  ^
12 //           |                                  |
13 //           v                 IPC              v
14 //  MojoAudioOutputStream  <---------> AudioOutputIPC (MojoAudioOutputIPC)
15 //
16 // Transportation of audio samples from the render to the browser process
17 // is done by using shared memory in combination with a sync socket pair
18 // to generate a low latency transport. The AudioOutputDevice user registers an
19 // AudioOutputDevice::RenderCallback at construction and will be polled by the
20 // AudioOutputController for audio to be played out by the underlying audio
21 // layers.
22 //
23 // State sequences.
24 //
25 //            Task [IO thread]                  IPC [IO thread]
26 // RequestDeviceAuthorization -> RequestDeviceAuthorizationOnIOThread ------>
27 // RequestDeviceAuthorization ->
28 //             <- OnDeviceAuthorized <- AudioMsg_NotifyDeviceAuthorized <-
29 //
30 // Start -> CreateStreamOnIOThread -----> CreateStream ------>
31 //       <- OnStreamCreated <- AudioMsg_NotifyStreamCreated <-
32 //       ---> PlayOnIOThread -----------> PlayStream -------->
33 //
34 // Optionally Play() / Pause() sequences may occur:
35 // Play -> PlayOnIOThread --------------> PlayStream --------->
36 // Pause -> PauseOnIOThread ------------> PauseStream -------->
37 // (note that Play() / Pause() sequences before
38 // OnStreamCreated are deferred until OnStreamCreated, with the last valid
39 // state being used)
40 //
41 // AudioOutputDevice::Render => audio transport on audio thread =>
42 //                               |
43 // Stop --> ShutDownOnIOThread -------->  CloseStream -> Close
44 //
45 // This class utilizes several threads during its lifetime, namely:
46 // 1. Creating thread.
47 //    Must be the main render thread.
48 // 2. Control thread (may be the main render thread or another thread).
49 //    The methods: Start(), Stop(), Play(), Pause(), SetVolume()
50 //    must be called on the same thread.
51 // 3. IO thread (internal implementation detail - not exposed to public API)
52 //    The thread within which this class receives all the IPC messages and
53 //    IPC communications can only happen in this thread.
54 // 4. Audio transport thread (See AudioDeviceThread).
55 //    Responsible for calling the AudioOutputDeviceThreadCallback
56 //    implementation that in turn calls AudioRendererSink::RenderCallback
57 //    which feeds audio samples to the audio layer in the browser process using
58 //    sync sockets and shared memory.
59 //
60 // Implementation notes:
61 // - The user must call Stop() before deleting the class instance.
62 
63 #ifndef MEDIA_AUDIO_AUDIO_OUTPUT_DEVICE_H_
64 #define MEDIA_AUDIO_AUDIO_OUTPUT_DEVICE_H_
65 
66 #include <memory>
67 #include <string>
68 
69 #include "base/bind.h"
70 #include "base/macros.h"
71 #include "base/memory/unsafe_shared_memory_region.h"
72 #include "base/synchronization/waitable_event.h"
73 #include "base/thread_annotations.h"
74 #include "base/time/time.h"
75 #include "media/audio/audio_device_thread.h"
76 #include "media/audio/audio_output_ipc.h"
77 #include "media/audio/audio_sink_parameters.h"
78 #include "media/base/audio_parameters.h"
79 #include "media/base/audio_renderer_sink.h"
80 #include "media/base/media_export.h"
81 #include "media/base/output_device_info.h"
82 
83 namespace base {
84 class OneShotTimer;
85 class SingleThreadTaskRunner;
86 }
87 
88 namespace media {
89 class AudioOutputDeviceThreadCallback;
90 
91 class MEDIA_EXPORT AudioOutputDevice : public AudioRendererSink,
92                                        public AudioOutputIPCDelegate {
93  public:
94   // NOTE: Clients must call Initialize() before using.
95   AudioOutputDevice(
96       std::unique_ptr<AudioOutputIPC> ipc,
97       const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
98       const AudioSinkParameters& sink_params,
99       base::TimeDelta authorization_timeout);
100 
101   // Request authorization to use the device specified in the constructor.
102   void RequestDeviceAuthorization();
103 
104   // AudioRendererSink implementation.
105   void Initialize(const AudioParameters& params,
106                   RenderCallback* callback) override;
107   void Start() override;
108   void Stop() override;
109   void Play() override;
110   void Pause() override;
111   void Flush() override;
112   bool SetVolume(double volume) override;
113   OutputDeviceInfo GetOutputDeviceInfo() override;
114   void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override;
115   bool IsOptimizedForHardwareParameters() override;
116   bool CurrentThreadIsRenderingThread() override;
117 
118   // Methods called on IO thread ----------------------------------------------
119   // AudioOutputIPCDelegate methods.
120   void OnError() override;
121   void OnDeviceAuthorized(OutputDeviceStatus device_status,
122                           const AudioParameters& output_params,
123                           const std::string& matched_device_id) override;
124   void OnStreamCreated(base::UnsafeSharedMemoryRegion shared_memory_region,
125                        base::SyncSocket::ScopedHandle socket_handle,
126                        bool play_automatically) override;
127   void OnIPCClosed() override;
128 
129  protected:
130   // Magic required by ref_counted.h to avoid any code deleting the object
131   // accidentally while there are references to it.
132   friend class base::RefCountedThreadSafe<AudioOutputDevice>;
133   ~AudioOutputDevice() override;
134 
135  private:
136   enum StartupState {
137     IDLE,                       // Authorization not requested.
138     AUTHORIZATION_REQUESTED,    // Sent (possibly completed) device
139                                 // authorization request.
140     STREAM_CREATION_REQUESTED,  // Sent (possibly completed) device creation
141                                 // request. Can Play()/Pause()/Stop().
142   };
143 
144   // This enum is used for UMA, so the only allowed operation on this definition
145   // is to add new states to the bottom, update kMaxValue, and update the
146   // histogram "Media.Audio.Render.StreamCallbackError2".
147   enum Error {
148     kNoError = 0,
149     kErrorDuringCreation = 1,
150     kErrorDuringRendering = 2,
151     kMaxValue = kErrorDuringRendering
152   };
153 
154   // Methods called on IO thread ----------------------------------------------
155   // The following methods are tasks posted on the IO thread that need to
156   // be executed on that thread.  They use AudioOutputIPC to send IPC messages
157   // upon state changes.
158   void RequestDeviceAuthorizationOnIOThread();
159   void InitializeOnIOThread(const AudioParameters& params,
160                             RenderCallback* callback);
161   void CreateStreamOnIOThread();
162   void PlayOnIOThread();
163   void PauseOnIOThread();
164   void FlushOnIOThread();
165   void ShutDownOnIOThread();
166   void SetVolumeOnIOThread(double volume);
167 
168   // Process device authorization result on the IO thread.
169   void ProcessDeviceAuthorizationOnIOThread(
170       OutputDeviceStatus device_status,
171       const AudioParameters& output_params,
172       const std::string& matched_device_id,
173       bool timed_out);
174 
175   void NotifyRenderCallbackOfError();
176 
177   OutputDeviceInfo GetOutputDeviceInfo_Signaled();
178   void OnAuthSignal();
179 
180   const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
181 
182   AudioParameters audio_parameters_;
183 
184   RenderCallback* callback_;
185 
186   // A pointer to the IPC layer that takes care of sending requests over to
187   // the implementation. May be set to nullptr after errors.
188   std::unique_ptr<AudioOutputIPC> ipc_;
189 
190   // Current state (must only be accessed from the IO thread).  See comments for
191   // State enum above.
192   StartupState state_;
193 
194   // For UMA stats. May only be accessed on the IO thread.
195   Error had_error_ = kNoError;
196 
197   // Last set volume.
198   double volume_ = 1.0;
199 
200   // The media session ID used to identify which input device to be started.
201   // Only used by Unified IO.
202   base::UnguessableToken session_id_;
203 
204   // ID of hardware output device to be used (provided |session_id_| is zero)
205   const std::string device_id_;
206 
207   // If |device_id_| is empty and |session_id_| is not, |matched_device_id_| is
208   // received in OnDeviceAuthorized().
209   std::string matched_device_id_;
210 
211   base::Optional<base::UnguessableToken> processing_id_;
212 
213   // In order to avoid a race between OnStreamCreated and Stop(), we use this
214   // guard to control stopping and starting the audio thread.
215   base::Lock audio_thread_lock_;
216   std::unique_ptr<AudioOutputDeviceThreadCallback> audio_callback_;
217   std::unique_ptr<AudioDeviceThread> audio_thread_
218       GUARDED_BY(audio_thread_lock_);
219 
220   // Temporary hack to ignore OnStreamCreated() due to the user calling Stop()
221   // so we don't start the audio thread pointing to a potentially freed
222   // |callback_|.
223   //
224   // TODO(scherkus): Replace this by changing AudioRendererSink to either accept
225   // the callback via Start(). See http://crbug.com/151051 for details.
226   bool stopping_hack_ GUARDED_BY(audio_thread_lock_);
227 
228   base::WaitableEvent did_receive_auth_;
229   AudioParameters output_params_;
230   OutputDeviceStatus device_status_;
231 
232   const base::TimeDelta auth_timeout_;
233   std::unique_ptr<base::OneShotTimer> auth_timeout_action_;
234 
235   // Pending callback for OutputDeviceInfo if it has not been received by the
236   // time a call to GetGetOutputDeviceInfoAsync() is called.
237   //
238   // Lock for use ONLY with |pending_device_info_cb_| and |did_receive_auth_|,
239   // if you add more usage of this lock ensure you have not added a deadlock.
240   base::Lock device_info_lock_;
241   OutputDeviceInfoCB pending_device_info_cb_ GUARDED_BY(device_info_lock_);
242 
243   DISALLOW_COPY_AND_ASSIGN(AudioOutputDevice);
244 };
245 
246 }  // namespace media
247 
248 #endif  // MEDIA_AUDIO_AUDIO_OUTPUT_DEVICE_H_
249