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