Report errors from ChromiumEnv::GetChildren in Posix.
[chromium-blink-merge.git] / media / audio / linux / alsa_output.h
blob841615d9d3f5e11ffe89aa177b82741d60748c28
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 // Creates an output stream based on the ALSA PCM interface.
6 //
7 // On device write failure, the stream will move itself to an invalid state.
8 // No more data will be pulled from the data source, or written to the device.
9 // All calls to public API functions will either no-op themselves, or return an
10 // error if possible. Specifically, If the stream is in an error state, Open()
11 // will return false, and Start() will call OnError() immediately on the
12 // provided callback.
14 // If the stream is successfully opened, Close() must be called. After Close
15 // has been called, the object should be regarded as deleted and not touched.
17 // AlsaPcmOutputStream is a single threaded class that should only be used from
18 // the audio thread. When modifying the code in this class, please read the
19 // threading assumptions at the top of the implementation.
21 #ifndef MEDIA_AUDIO_LINUX_ALSA_OUTPUT_H_
22 #define MEDIA_AUDIO_LINUX_ALSA_OUTPUT_H_
24 #include <alsa/asoundlib.h>
26 #include <string>
28 #include "base/compiler_specific.h"
29 #include "base/gtest_prod_util.h"
30 #include "base/memory/scoped_ptr.h"
31 #include "base/memory/weak_ptr.h"
32 #include "base/time/time.h"
33 #include "media/audio/audio_io.h"
34 #include "media/audio/audio_parameters.h"
36 namespace base {
37 class MessageLoop;
40 namespace media {
42 class AlsaWrapper;
43 class AudioManagerLinux;
44 class ChannelMixer;
45 class SeekableBuffer;
47 class MEDIA_EXPORT AlsaPcmOutputStream : public AudioOutputStream {
48 public:
49 // String for the generic "default" ALSA device that has the highest
50 // compatibility and chance of working.
51 static const char kDefaultDevice[];
53 // Pass this to the AlsaPcmOutputStream if you want to attempt auto-selection
54 // of the audio device.
55 static const char kAutoSelectDevice[];
57 // Prefix for device names to enable ALSA library resampling.
58 static const char kPlugPrefix[];
60 // The minimum latency that is accepted by the device.
61 static const uint32 kMinLatencyMicros;
63 // Create a PCM Output stream for the ALSA device identified by
64 // |device_name|. The AlsaPcmOutputStream uses |wrapper| to communicate with
65 // the alsa libraries, allowing for dependency injection during testing. All
66 // requesting of data, and writing to the alsa device will be done on
67 // |message_loop|.
69 // If unsure of what to use for |device_name|, use |kAutoSelectDevice|.
70 AlsaPcmOutputStream(const std::string& device_name,
71 const AudioParameters& params,
72 AlsaWrapper* wrapper,
73 AudioManagerLinux* manager);
75 virtual ~AlsaPcmOutputStream();
77 // Implementation of AudioOutputStream.
78 virtual bool Open() OVERRIDE;
79 virtual void Close() OVERRIDE;
80 virtual void Start(AudioSourceCallback* callback) OVERRIDE;
81 virtual void Stop() OVERRIDE;
82 virtual void SetVolume(double volume) OVERRIDE;
83 virtual void GetVolume(double* volume) OVERRIDE;
85 private:
86 friend class AlsaPcmOutputStreamTest;
87 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest,
88 AutoSelectDevice_DeviceSelect);
89 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest,
90 AutoSelectDevice_FallbackDevices);
91 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, AutoSelectDevice_HintFail);
92 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket);
93 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_Negative);
94 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_StopStream);
95 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_Underrun);
96 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_FullBuffer);
97 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, ConstructedState);
98 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, LatencyFloor);
99 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, OpenClose);
100 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, PcmOpenFailed);
101 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, PcmSetParamsFailed);
102 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, ScheduleNextWrite);
103 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest,
104 ScheduleNextWrite_StopStream);
105 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, StartStop);
106 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_FinishedPacket);
107 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_NormalPacket);
108 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_StopStream);
109 FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_WriteFails);
111 // Flags indicating the state of the stream.
112 enum InternalState {
113 kInError = 0,
114 kCreated,
115 kIsOpened,
116 kIsPlaying,
117 kIsStopped,
118 kIsClosed
120 friend std::ostream& operator<<(std::ostream& os, InternalState);
122 // Functions to get another packet from the data source and write it into the
123 // ALSA device.
124 void BufferPacket(bool* source_exhausted);
125 void WritePacket();
126 void WriteTask();
127 void ScheduleNextWrite(bool source_exhausted);
129 // Utility functions for talking with the ALSA API.
130 static base::TimeDelta FramesToTimeDelta(int frames, double sample_rate);
131 std::string FindDeviceForChannels(uint32 channels);
132 snd_pcm_sframes_t GetAvailableFrames();
133 snd_pcm_sframes_t GetCurrentDelay();
135 // Attempts to find the best matching linux audio device for the given number
136 // of channels. This function will set |device_name_| and |channel_mixer_|.
137 snd_pcm_t* AutoSelectDevice(uint32 latency);
139 // Functions to safeguard state transitions. All changes to the object state
140 // should go through these functions.
141 bool CanTransitionTo(InternalState to);
142 InternalState TransitionTo(InternalState to);
143 InternalState state();
145 // Returns true when we're on the audio thread or if the audio thread's
146 // message loop is NULL (which will happen during shutdown).
147 bool IsOnAudioThread() const;
149 // API for Proxying calls to the AudioSourceCallback provided during
150 // Start().
152 // TODO(ajwong): This is necessary because the ownership semantics for the
153 // |source_callback_| object are incorrect in AudioRenderHost. The callback
154 // is passed into the output stream, but ownership is not transfered which
155 // requires a synchronization on access of the |source_callback_| to avoid
156 // using a deleted callback.
157 int RunDataCallback(AudioBus* audio_bus, AudioBuffersState buffers_state);
158 void RunErrorCallback(int code);
160 // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to
161 // release ownership of the currently registered callback.
162 void set_source_callback(AudioSourceCallback* callback);
164 // Configuration constants from the constructor. Referenceable by all threads
165 // since they are constants.
166 const std::string requested_device_name_;
167 const snd_pcm_format_t pcm_format_;
168 const uint32 channels_;
169 const ChannelLayout channel_layout_;
170 const uint32 sample_rate_;
171 const uint32 bytes_per_sample_;
172 const uint32 bytes_per_frame_;
174 // Device configuration data. Populated after OpenTask() completes.
175 std::string device_name_;
176 uint32 packet_size_;
177 base::TimeDelta latency_;
178 uint32 bytes_per_output_frame_;
179 uint32 alsa_buffer_frames_;
181 // Flag indicating the code should stop reading from the data source or
182 // writing to the ALSA device. This is set because the device has entered
183 // an unrecoverable error state, or the ClosedTask() has executed.
184 bool stop_stream_;
186 // Wrapper class to invoke all the ALSA functions.
187 AlsaWrapper* wrapper_;
189 // Audio manager that created us. Used to report that we've been closed.
190 AudioManagerLinux* manager_;
192 // Message loop to use for polling. The object is owned by the AudioManager.
193 // We hold a reference to the audio thread message loop since
194 // AudioManagerBase::ShutDown() can invalidate the message loop pointer
195 // before the stream gets deleted.
196 base::MessageLoop* message_loop_;
198 // Handle to the actual PCM playback device.
199 snd_pcm_t* playback_handle_;
201 scoped_ptr<media::SeekableBuffer> buffer_;
202 uint32 frames_per_packet_;
204 // Allows us to run tasks on the AlsaPcmOutputStream instance which are
205 // bound by its lifetime.
206 base::WeakPtrFactory<AlsaPcmOutputStream> weak_factory_;
208 InternalState state_;
209 float volume_; // Volume level from 0.0 to 1.0.
211 AudioSourceCallback* source_callback_;
213 // Container for retrieving data from AudioSourceCallback::OnMoreData().
214 scoped_ptr<AudioBus> audio_bus_;
216 // Channel mixer and temporary bus for the final mixed channel data.
217 scoped_ptr<ChannelMixer> channel_mixer_;
218 scoped_ptr<AudioBus> mixed_audio_bus_;
220 DISALLOW_COPY_AND_ASSIGN(AlsaPcmOutputStream);
223 MEDIA_EXPORT std::ostream& operator<<(std::ostream& os,
224 AlsaPcmOutputStream::InternalState);
226 }; // namespace media
228 #endif // MEDIA_AUDIO_LINUX_ALSA_OUTPUT_H_