15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Audio rendering unit utilizing audio output stream provided by browser 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// process through IPC. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Relationship of classes. 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AudioOutputController AudioOutputDevice 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ^ ^ 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | | 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// v IPC v 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AudioRendererHost <---------> AudioOutputIPC (AudioMessageFilter) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Transportation of audio samples from the render to the browser process 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is done by using shared memory in combination with a sync socket pair 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to generate a low latency transport. The AudioOutputDevice user registers an 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AudioOutputDevice::RenderCallback at construction and will be polled by the 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AudioOutputDevice for audio to be played out by the underlying audio layers. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// State sequences. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Task [IO thread] IPC [IO thread] 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start -> CreateStreamOnIOThread -----> CreateStream ------> 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// <- OnStreamCreated <- AudioMsg_NotifyStreamCreated <- 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---> PlayOnIOThread -----------> PlayStream --------> 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Optionally Play() / Pause() sequences may occur: 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Play -> PlayOnIOThread --------------> PlayStream ---------> 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pause -> PauseOnIOThread ------------> PauseStream --------> 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (note that Play() / Pause() sequences before OnStreamCreated are 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deferred until OnStreamCreated, with the last valid state being used) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AudioOutputDevice::Render => audio transport on audio thread => 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// | 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stop --> ShutDownOnIOThread --------> CloseStream -> Close 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class utilizes several threads during its lifetime, namely: 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. Creating thread. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Must be the main render thread. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. Control thread (may be the main render thread or another thread). 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The methods: Start(), Stop(), Play(), Pause(), SetVolume() 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// must be called on the same thread. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. IO thread (internal implementation detail - not exposed to public API) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The thread within which this class receives all the IPC messages and 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IPC communications can only happen in this thread. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4. Audio transport thread (See AudioDeviceThread). 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Responsible for calling the AudioThreadCallback implementation that in 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// turn calls AudioRendererSink::RenderCallback which feeds audio samples to 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the audio layer in the browser process using sync sockets and shared 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memory. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation notes: 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The user must call Stop() before deleting the class instance. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MEDIA_AUDIO_AUDIO_OUTPUT_DEVICE_H_ 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_AUDIO_AUDIO_OUTPUT_DEVICE_H_ 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/memory/shared_memory.h" 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_device_thread.h" 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_output_ipc.h" 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_parameters.h" 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/audio/scoped_task_runner_observer.h" 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/audio_renderer_sink.h" 709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "media/base/media_export.h" 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MEDIA_EXPORT AudioOutputDevice 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : NON_EXPORTED_BASE(public AudioRendererSink), 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NON_EXPORTED_BASE(public AudioOutputIPCDelegate), 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NON_EXPORTED_BASE(public ScopedTaskRunnerObserver) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // NOTE: Clients must call Initialize() before using. 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioOutputDevice( 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<AudioOutputIPC> ipc, 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner); 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Initialize the stream using |session_id|, which is used for the browser 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // to select the correct input device. 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void InitializeWithSessionId(const AudioParameters& params, 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RenderCallback* callback, 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int session_id); 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioRendererSink implementation. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Initialize(const AudioParameters& params, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderCallback* callback) OVERRIDE; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Start() OVERRIDE; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Stop() OVERRIDE; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Play() OVERRIDE; 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void Pause() OVERRIDE; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool SetVolume(double volume) OVERRIDE; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Methods called on IO thread ---------------------------------------------- 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioOutputIPCDelegate methods. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnStateChanged(AudioOutputIPCDelegate::State state) OVERRIDE; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnStreamCreated(base::SharedMemoryHandle handle, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SyncSocket::Handle socket_handle, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int length) OVERRIDE; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnIPCClosed() OVERRIDE; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Magic required by ref_counted.h to avoid any code deleting the object 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // accidentally while there are references to it. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<AudioOutputDevice>; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~AudioOutputDevice(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note: The ordering of members in this enum is critical to correct behavior! 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enum State { 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_CLOSED, // No more IPCs can take place. 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IDLE, // Not started. 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CREATING_STREAM, // Waiting for OnStreamCreated() to be called back. 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PAUSED, // Paused. OnStreamCreated() has been called. Can Play()/Stop(). 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLAYING, // Playing back. Can Pause()/Stop(). 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Methods called on IO thread ---------------------------------------------- 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The following methods are tasks posted on the IO thread that need to 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // be executed on that thread. They use AudioOutputIPC to send IPC messages 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // upon state changes. 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void CreateStreamOnIOThread(const AudioParameters& params); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PlayOnIOThread(); 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void PauseOnIOThread(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ShutDownOnIOThread(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetVolumeOnIOThread(double volume); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // base::MessageLoop::DestructionObserver implementation for the IO loop. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the IO loop dies before we do, we shut down the audio thread from here. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void WillDestroyCurrentMessageLoop() OVERRIDE; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters audio_parameters_; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderCallback* callback_; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A pointer to the IPC layer that takes care of sending requests over to 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the AudioRendererHost. Only valid when state_ != IPC_CLOSED and must only 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // be accessed on the IO thread. 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<AudioOutputIPC> ipc_; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Current state (must only be accessed from the IO thread). See comments for 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // State enum above. 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) State state_; 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // State of Play() / Pause() calls before OnStreamCreated() is called. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool play_on_start_; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // The media session ID used to identify which input device to be started. 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Only used by Unified IO. 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int session_id_; 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our audio thread callback class. See source file for details. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class AudioThreadCallback; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In order to avoid a race between OnStreamCreated and Stop(), we use this 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // guard to control stopping and starting the audio thread. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock audio_thread_lock_; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioDeviceThread audio_thread_; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioOutputDevice::AudioThreadCallback> audio_callback_; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Temporary hack to ignore OnStreamCreated() due to the user calling Stop() 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so we don't start the audio thread pointing to a potentially freed 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |callback_|. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(scherkus): Replace this by changing AudioRendererSink to either accept 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the callback via Start(). See http://crbug.com/151051 for details. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool stopping_hack_; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AudioOutputDevice); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // MEDIA_AUDIO_AUDIO_OUTPUT_DEVICE_H_ 180