summaryrefslogtreecommitdiffstats
path: root/media/audio/audio_output_controller.h
blob: 2077c9bb2dadb60c47f13affae2a282f2a4317c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_
#define MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_

#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "base/time.h"
#include "media/audio/audio_buffers_state.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_manager.h"
#include "media/audio/simple_sources.h"

namespace base {
class WaitableEvent;
}  // namespace base

class MessageLoop;

// An AudioOutputController controls an AudioOutputStream and provides data
// to this output stream. It has an important function that it executes
// audio operations like play, pause, stop, etc. on a separate thread,
// namely the audio manager thread.
//
// All the public methods of AudioOutputController are non-blocking.
// The actual operations are performed on the audio manager thread.
//
// Here is a state diagram for the AudioOutputController:
//
//             .----------------------->  [ Closed / Error ]  <------.
//             |                                   ^                 |
//             |                                   |                 |
//        [ Created ]  -->  [ Starting ]  -->  [ Playing ]  -->  [ Paused ]
//             ^                 |                 ^                |  ^
//             |                 |                 |                |  |
//             |                 |                 `----------------'  |
//             |                 V                                     |
//             |        [ PausedWhenStarting ] ------------------------'
//             |
//       *[  Empty  ]
//
// * Initial state
//
// The AudioOutputStream can request data from the AudioOutputController via the
// AudioSourceCallback interface. AudioOutputController uses the SyncReader
// passed to it via construction to synchronously fulfill this read request.
//
// The audio manager thread is owned by the AudioManager that the
// AudioOutputController holds a reference to.  When performing tasks on this
// thread, the controller must not add or release references to the
// AudioManager or itself (since it in turn holds a reference to the manager),
// for delayed tasks as it can slow down or even prevent normal shut down.
// So, for tasks on the audio thread, the controller uses WeakPtr which enables
// us to safely cancel pending polling tasks.
//
// AudioManager will take care of properly shutting down the audio manager
// thread.
//
#include "media/base/media_export.h"

namespace media {

class MEDIA_EXPORT AudioOutputController
    : public base::RefCountedThreadSafe<AudioOutputController>,
      public AudioOutputStream::AudioSourceCallback {
 public:
  // Value sent by the controller to the renderer in low-latency mode
  // indicating that the stream is paused.
  static const int kPauseMark;

  // An event handler that receives events from the AudioOutputController. The
  // following methods are called on the audio manager thread.
  class MEDIA_EXPORT EventHandler {
   public:
    virtual ~EventHandler() {}
    virtual void OnCreated(AudioOutputController* controller) = 0;
    virtual void OnPlaying(AudioOutputController* controller) = 0;
    virtual void OnPaused(AudioOutputController* controller) = 0;
    virtual void OnError(AudioOutputController* controller, int error_code) = 0;
  };

  // A synchronous reader interface used by AudioOutputController for
  // synchronous reading.
  class SyncReader {
   public:
    virtual ~SyncReader() {}

    // Notify the synchronous reader the number of bytes in the
    // AudioOutputController not yet played. This is used by SyncReader to
    // prepare more data and perform synchronization.
    virtual void UpdatePendingBytes(uint32 bytes) = 0;

    // Read certain amount of data into |data|. This method returns if some
    // data is available.
    virtual uint32 Read(void* data, uint32 size) = 0;

    // Close this synchronous reader.
    virtual void Close() = 0;

    // Poll if data is ready.
    // Not reliable, as there is no guarantee that renderer is "new-style"
    // renderer that writes metadata into buffer. After several unsuccessful
    // attempts caller should assume the data is ready even if that function
    // returns false.
    virtual bool DataReady() = 0;
  };

  // Factory method for creating an AudioOutputController.
  // This also creates and opens an AudioOutputStream on the audio manager
  // thread, and if this is successful, the |event_handler| will receive an
  // OnCreated() call from the same audio manager thread.
  static scoped_refptr<AudioOutputController> Create(
      AudioManager* audio_manager,
      EventHandler* event_handler,
      const AudioParameters& params,
      // External synchronous reader for audio controller.
      SyncReader* sync_reader);

  // Methods to control playback of the stream.

  // Starts the playback of this audio output stream.
  void Play();

  // Pause this audio output stream.
  void Pause();

  // Discard all audio data buffered in this output stream. This method only
  // has effect when the stream is paused.
  void Flush();

  // Closes the audio output stream. The state is changed and the resources
  // are freed on the audio manager thread. closed_task is executed after that.
  // Callbacks (EventHandler and SyncReader) must exist until closed_task is
  // called.
  //
  // It is safe to call this method more than once. Calls after the first one
  // will have no effect.
  void Close(const base::Closure& closed_task);

  // Sets the volume of the audio output stream.
  void SetVolume(double volume);

  ///////////////////////////////////////////////////////////////////////////
  // AudioSourceCallback methods.
  virtual uint32 OnMoreData(uint8* dest,
                            uint32 max_size,
                            AudioBuffersState buffers_state) OVERRIDE;
  virtual void OnError(AudioOutputStream* stream, int code) OVERRIDE;
  virtual void WaitTillDataReady() OVERRIDE;

 protected:
    // Internal state of the source.
  enum State {
    kEmpty,
    kCreated,
    kPlaying,
    kStarting,
    kPausedWhenStarting,
    kPaused,
    kClosed,
    kError,
  };

  friend class base::RefCountedThreadSafe<AudioOutputController>;
  virtual ~AudioOutputController();

 private:
  // We are polling sync reader if data became available.
  static const int kPollNumAttempts;
  static const int kPollPauseInMilliseconds;

  AudioOutputController(EventHandler* handler,
                        SyncReader* sync_reader);

  // The following methods are executed on the audio manager thread.
  void DoCreate(AudioManager* audio_manager, const AudioParameters& params);
  void DoPlay();
  void PollAndStartIfDataReady();
  void DoPause();
  void DoFlush();
  void DoClose();
  void DoSetVolume(double volume);
  void DoReportError(int code);

  // Helper method that starts physical stream.
  void StartStream();

  // Helper method that stops, closes, and NULLs |*stream_|.
  // Signals event when done if it is not NULL.
  void DoStopCloseAndClearStream(base::WaitableEvent *done);

  // |handler_| may be called only if |state_| is not kClosed.
  EventHandler* handler_;
  AudioOutputStream* stream_;

  // The current volume of the audio stream.
  double volume_;

  // |state_| is written on the audio manager thread and is read on the
  // hardware audio thread. These operations need to be locked. But lock
  // is not required for reading on the audio manager thread.
  State state_;

  // The |lock_| must be acquired whenever we access |state_| from a thread
  // other than the audio manager thread.
  base::Lock lock_;

  // SyncReader is used only in low latency mode for synchronous reading.
  SyncReader* sync_reader_;

  // The message loop of audio manager thread that this object runs on.
  scoped_refptr<base::MessageLoopProxy> message_loop_;

  // When starting stream we wait for data to become available.
  // Number of times left.
  int number_polling_attempts_left_;

  // Used to post delayed tasks to ourselves that we can cancel.
  // We don't want the tasks to hold onto a reference as it will slow down
  // shutdown and force it to wait for the most delayed task.
  // Also, if we're shutting down, we do not want to poll for more data.
  base::WeakPtrFactory<AudioOutputController> weak_this_;

  // Workaround for Mac OS X bug, see crbug.com/128128.
  base::Time previous_stop_time_;

  DISALLOW_COPY_AND_ASSIGN(AudioOutputController);
};

}  // namespace media

#endif  // MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_