audio_output_dispatcher_impl.h revision a02191e04bc25c4935f804f2c080ae28663d096d
1f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org// Use of this source code is governed by a BSD-style license that can be
3f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org// found in the LICENSE file.
4f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
5f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org// AudioOutputDispatcherImpl is an implementation of AudioOutputDispatcher.
6f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org//
7f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org// To avoid opening and closing audio devices more frequently than necessary,
8f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org// each dispatcher has a pool of inactive physical streams. A stream is closed
9f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org// only if it hasn't been used for a certain period of time (specified via the
10f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org// constructor).
118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org//
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#ifndef MEDIA_AUDIO_AUDIO_OUTPUT_DISPATCHER_IMPL_H_
148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#define MEDIA_AUDIO_AUDIO_OUTPUT_DISPATCHER_IMPL_H_
15300f562dedd02df2f41de443c8b58ab2ceaed0f0tomhudson@google.com
16cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#include <map>
17cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#include <vector>
18d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com
19b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "base/basictypes.h"
2030ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "base/memory/ref_counted.h"
21b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "base/timer/timer.h"
22b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "media/audio/audio_io.h"
23894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org#include "media/audio/audio_logging.h"
24894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org#include "media/audio/audio_manager.h"
25894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org#include "media/audio/audio_output_dispatcher.h"
26f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org#include "media/audio/audio_parameters.h"
27dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com
287510b224e52b9518a8ddf7418db0e9c258f79539kkinnunennamespace media {
29cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
30032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.comclass AudioOutputProxy;
31f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
32f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgclass MEDIA_EXPORT AudioOutputDispatcherImpl : public AudioOutputDispatcher {
33f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org public:
34f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  // |close_delay| specifies delay after the stream is idle until the audio
354b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org  // device is closed.
364b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org  AudioOutputDispatcherImpl(AudioManager* audio_manager,
37f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                            const AudioParameters& params,
38cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com                            const std::string& output_device_id,
39b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                            const base::TimeDelta& close_delay);
40b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
41b9119a6b563bf737e34d22f8bb96fc09a606c76fbsalomon@google.com  // Opens a new physical stream if there are no pending streams in
427510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen  // |idle_streams_|.  Do not call Close() or Stop() if this method fails.
43894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org  virtual bool OpenStream() OVERRIDE;
44894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
45b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt  // If there are pending streams in |idle_streams_| then it reuses one of
46b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt  // them, otherwise creates a new one.
477510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen  virtual bool StartStream(AudioOutputStream::AudioSourceCallback* callback,
48f4770d7e841a34d74d7f76a33312f4c5624da831senorblanco@chromium.org                           AudioOutputProxy* stream_proxy) OVERRIDE;
49cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
50f4770d7e841a34d74d7f76a33312f4c5624da831senorblanco@chromium.org  // Stops the stream assigned to the specified proxy and moves it into
51f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  // |idle_streams_| for reuse by other proxies.
52f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  virtual void StopStream(AudioOutputProxy* stream_proxy) OVERRIDE;
53f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
54f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  virtual void StreamVolumeSet(AudioOutputProxy* stream_proxy,
55f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                               double volume) OVERRIDE;
56f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
57f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  // Closes |idle_streams_| until the number of |idle_streams_| is equal to the
58f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  // |idle_proxies_| count.  If there are no |idle_proxies_| a single stream is
59f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  // kept alive until |close_timer_| fires.
60f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  virtual void CloseStream(AudioOutputProxy* stream_proxy) OVERRIDE;
61f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
62f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  virtual void Shutdown() OVERRIDE;
63f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
64f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org private:
65b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt  friend class base::RefCountedThreadSafe<AudioOutputDispatcherImpl>;
66b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt  virtual ~AudioOutputDispatcherImpl();
67f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
68f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  // Creates a new physical output stream, opens it and pushes to
69f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  // |idle_streams_|.  Returns false if the stream couldn't be created or
70f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  // opened.
71b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org  bool CreateAndOpenStream();
72b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org
73b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org  // Closes all |idle_streams_|.
74f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  void CloseAllIdleStreams();
75f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  // Similar to CloseAllIdleStreams(), but keeps |keep_alive| streams alive.
76f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  void CloseIdleStreams(size_t keep_alive);
77f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
78f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  size_t idle_proxies_;
79f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  std::vector<AudioOutputStream*> idle_streams_;
80f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
81f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  // When streams are stopped they're added to |idle_streams_|, if no stream is
82f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  // reused before |close_delay_| elapses |close_timer_| will run
83b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt  // CloseIdleStreams().
84b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt  base::DelayTimer<AudioOutputDispatcherImpl> close_timer_;
85f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
86f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  typedef std::map<AudioOutputProxy*, AudioOutputStream*> AudioStreamMap;
87f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  AudioStreamMap proxy_to_physical_map_;
88f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
89f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  scoped_ptr<AudioLog> audio_log_;
90f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  typedef std::map<AudioOutputStream*, int> AudioStreamIDMap;
91f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  AudioStreamIDMap audio_stream_ids_;
92b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org  int audio_stream_id_;
93b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org
94b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org  DISALLOW_COPY_AND_ASSIGN(AudioOutputDispatcherImpl);
95b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org};
96f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
97f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}  // namespace media
98f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
99f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org#endif  // MEDIA_AUDIO_AUDIO_OUTPUT_DISPATCHER_IMPL_H_
100f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org