Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: media/audio/linux/alsa_output.h

Issue 2008010: Fixes in AlsaPcmOutputStream. (Closed)
Patch Set: - Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // Creates an output stream based on the ALSA PCM interface. 5 // Creates an output stream based on the ALSA PCM interface.
6 // 6 //
7 // On device write failure, the stream will move itself to an invalid state. 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. 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 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() 10 // error if possible. Specifically, If the stream is in an error state, Open()
(...skipping 21 matching lines...) Expand all
32 32
33 #include <string> 33 #include <string>
34 34
35 #include "base/lock.h" 35 #include "base/lock.h"
36 #include "base/ref_counted.h" 36 #include "base/ref_counted.h"
37 #include "base/scoped_ptr.h" 37 #include "base/scoped_ptr.h"
38 #include "base/thread.h" 38 #include "base/thread.h"
39 #include "media/audio/audio_output.h" 39 #include "media/audio/audio_output.h"
40 #include "testing/gtest/include/gtest/gtest_prod.h" 40 #include "testing/gtest/include/gtest/gtest_prod.h"
41 41
42 namespace media {
43 class SeekableBuffer;
44 }; // namespace media
45
42 class AlsaWrapper; 46 class AlsaWrapper;
43 class AudioManagerLinux; 47 class AudioManagerLinux;
44 48
45 class AlsaPcmOutputStream : 49 class AlsaPcmOutputStream :
46 public AudioOutputStream, 50 public AudioOutputStream,
47 public base::RefCountedThreadSafe<AlsaPcmOutputStream> { 51 public base::RefCountedThreadSafe<AlsaPcmOutputStream> {
48 public: 52 public:
49 // String for the generic "default" ALSA device that has the highest 53 // String for the generic "default" ALSA device that has the highest
50 // compatibility and chance of working. 54 // compatibility and chance of working.
51 static const char kDefaultDevice[]; 55 static const char kDefaultDevice[];
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 private: 91 private:
88 friend class base::RefCountedThreadSafe<AlsaPcmOutputStream>; 92 friend class base::RefCountedThreadSafe<AlsaPcmOutputStream>;
89 friend class AlsaPcmOutputStreamTest; 93 friend class AlsaPcmOutputStreamTest;
90 FRIEND_TEST(AlsaPcmOutputStreamTest, AutoSelectDevice_DeviceSelect); 94 FRIEND_TEST(AlsaPcmOutputStreamTest, AutoSelectDevice_DeviceSelect);
91 FRIEND_TEST(AlsaPcmOutputStreamTest, AutoSelectDevice_FallbackDevices); 95 FRIEND_TEST(AlsaPcmOutputStreamTest, AutoSelectDevice_FallbackDevices);
92 FRIEND_TEST(AlsaPcmOutputStreamTest, AutoSelectDevice_HintFail); 96 FRIEND_TEST(AlsaPcmOutputStreamTest, AutoSelectDevice_HintFail);
93 FRIEND_TEST(AlsaPcmOutputStreamTest, BufferPacket); 97 FRIEND_TEST(AlsaPcmOutputStreamTest, BufferPacket);
94 FRIEND_TEST(AlsaPcmOutputStreamTest, BufferPacket_Negative); 98 FRIEND_TEST(AlsaPcmOutputStreamTest, BufferPacket_Negative);
95 FRIEND_TEST(AlsaPcmOutputStreamTest, BufferPacket_StopStream); 99 FRIEND_TEST(AlsaPcmOutputStreamTest, BufferPacket_StopStream);
96 FRIEND_TEST(AlsaPcmOutputStreamTest, BufferPacket_Underrun); 100 FRIEND_TEST(AlsaPcmOutputStreamTest, BufferPacket_Underrun);
97 FRIEND_TEST(AlsaPcmOutputStreamTest, BufferPacket_UnfinishedPacket); 101 FRIEND_TEST(AlsaPcmOutputStreamTest, BufferPacket_FullBuffer);
98 FRIEND_TEST(AlsaPcmOutputStreamTest, ConstructedState); 102 FRIEND_TEST(AlsaPcmOutputStreamTest, ConstructedState);
99 FRIEND_TEST(AlsaPcmOutputStreamTest, LatencyFloor); 103 FRIEND_TEST(AlsaPcmOutputStreamTest, LatencyFloor);
100 FRIEND_TEST(AlsaPcmOutputStreamTest, OpenClose); 104 FRIEND_TEST(AlsaPcmOutputStreamTest, OpenClose);
101 FRIEND_TEST(AlsaPcmOutputStreamTest, PcmOpenFailed); 105 FRIEND_TEST(AlsaPcmOutputStreamTest, PcmOpenFailed);
102 FRIEND_TEST(AlsaPcmOutputStreamTest, PcmSetParamsFailed); 106 FRIEND_TEST(AlsaPcmOutputStreamTest, PcmSetParamsFailed);
103 FRIEND_TEST(AlsaPcmOutputStreamTest, ScheduleNextWrite); 107 FRIEND_TEST(AlsaPcmOutputStreamTest, ScheduleNextWrite);
104 FRIEND_TEST(AlsaPcmOutputStreamTest, ScheduleNextWrite_StopStream); 108 FRIEND_TEST(AlsaPcmOutputStreamTest, ScheduleNextWrite_StopStream);
105 FRIEND_TEST(AlsaPcmOutputStreamTest, StartStop); 109 FRIEND_TEST(AlsaPcmOutputStreamTest, StartStop);
106 FRIEND_TEST(AlsaPcmOutputStreamTest, WritePacket_FinishedPacket); 110 FRIEND_TEST(AlsaPcmOutputStreamTest, WritePacket_FinishedPacket);
107 FRIEND_TEST(AlsaPcmOutputStreamTest, WritePacket_NormalPacket); 111 FRIEND_TEST(AlsaPcmOutputStreamTest, WritePacket_NormalPacket);
108 FRIEND_TEST(AlsaPcmOutputStreamTest, WritePacket_StopStream); 112 FRIEND_TEST(AlsaPcmOutputStreamTest, WritePacket_StopStream);
109 FRIEND_TEST(AlsaPcmOutputStreamTest, WritePacket_WriteFails); 113 FRIEND_TEST(AlsaPcmOutputStreamTest, WritePacket_WriteFails);
110 114
111 virtual ~AlsaPcmOutputStream(); 115 virtual ~AlsaPcmOutputStream();
112 116
113 // In-memory buffer to hold sound samples before pushing to the sound device.
114 // TODO(ajwong): There are now about 3 buffer/packet implementations. Factor
115 // them out.
116 struct Packet {
117 explicit Packet(uint32 new_capacity)
118 : capacity(new_capacity),
119 size(0),
120 used(0),
121 buffer(new char[capacity]) {
122 }
123 uint32 capacity;
124 uint32 size;
125 uint32 used;
126 scoped_array<char> buffer;
127 };
128
129 // Flags indicating the state of the stream. 117 // Flags indicating the state of the stream.
130 enum InternalState { 118 enum InternalState {
131 kInError = 0, 119 kInError = 0,
132 kCreated, 120 kCreated,
133 kIsOpened, 121 kIsOpened,
134 kIsPlaying, 122 kIsPlaying,
135 kIsStopped, 123 kIsStopped,
136 kIsClosed 124 kIsClosed
137 }; 125 };
138 friend std::ostream& operator<<(std::ostream& os, InternalState); 126 friend std::ostream& operator<<(std::ostream& os, InternalState);
139 127
140 // Various tasks that complete actions started in the public API. 128 // Various tasks that complete actions started in the public API.
141 void OpenTask(uint32 packet_size); 129 void OpenTask(uint32 packet_size);
142 void StartTask(); 130 void StartTask();
143 void CloseTask(); 131 void CloseTask();
144 132
145 // Functions to get another packet from the data source and write it into the 133 // Functions to get another packet from the data source and write it into the
146 // ALSA device. 134 // ALSA device.
147 void BufferPacket(Packet* packet); 135 void BufferPacket();
148 void WritePacket(Packet* packet); 136 void WritePacket();
149 void WriteTask(); 137 void WriteTask();
150 void ScheduleNextWrite(Packet* current_packet); 138 void ScheduleNextWrite();
151 139
152 // Utility functions for talking with the ALSA API. 140 // Utility functions for talking with the ALSA API.
153 static uint32 FramesInPacket(const Packet& packet, uint32 bytes_per_frame);
154 static uint32 FramesToMicros(uint32 frames, uint32 sample_rate); 141 static uint32 FramesToMicros(uint32 frames, uint32 sample_rate);
155 static uint32 FramesToMillis(uint32 frames, uint32 sample_rate); 142 static uint32 FramesToMillis(uint32 frames, uint32 sample_rate);
156 std::string FindDeviceForChannels(uint32 channels); 143 std::string FindDeviceForChannels(uint32 channels);
157 snd_pcm_t* OpenDevice(const std::string& device_name, 144 snd_pcm_t* OpenDevice(const std::string& device_name,
158 uint32 channels, 145 uint32 channels,
159 uint32 latency); 146 uint32 latency);
160 bool CloseDevice(snd_pcm_t* handle); 147 bool CloseDevice(snd_pcm_t* handle);
161 snd_pcm_sframes_t GetAvailableFrames(); 148 snd_pcm_sframes_t GetAvailableFrames();
149 snd_pcm_sframes_t GetCurrentDelay();
162 150
163 // Attempts to find the best matching linux audio device for the given number 151 // Attempts to find the best matching linux audio device for the given number
164 // of channels. This function will set |device_name_| and |should_downmix_|. 152 // of channels. This function will set |device_name_| and |should_downmix_|.
165 snd_pcm_t* AutoSelectDevice(uint32 latency); 153 snd_pcm_t* AutoSelectDevice(uint32 latency);
166 154
167 // Thread-asserting accessors for member variables. 155 // Thread-asserting accessors for member variables.
168 AudioManagerLinux* manager(); 156 AudioManagerLinux* manager();
169 157
170 // Struct holding all mutable the data that must be shared by the 158 // Struct holding all mutable the data that must be shared by the
171 // message_loop() and the thread that created the object. 159 // message_loop() and the thread that created the object.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 const snd_pcm_format_t pcm_format_; 208 const snd_pcm_format_t pcm_format_;
221 const uint32 channels_; 209 const uint32 channels_;
222 const uint32 sample_rate_; 210 const uint32 sample_rate_;
223 const uint32 bytes_per_sample_; 211 const uint32 bytes_per_sample_;
224 const uint32 bytes_per_frame_; 212 const uint32 bytes_per_frame_;
225 213
226 // Device configuration data. Populated after OpenTask() completes. 214 // Device configuration data. Populated after OpenTask() completes.
227 std::string device_name_; 215 std::string device_name_;
228 bool should_downmix_; 216 bool should_downmix_;
229 uint32 latency_micros_; 217 uint32 latency_micros_;
218 uint32 packet_size_;
230 uint32 micros_per_packet_; 219 uint32 micros_per_packet_;
231 uint32 bytes_per_output_frame_; 220 uint32 bytes_per_output_frame_;
221 uint32 alsa_buffer_frames_;
232 222
233 // Flag indicating the code should stop reading from the data source or 223 // Flag indicating the code should stop reading from the data source or
234 // writing to the ALSA device. This is set because the device has entered 224 // writing to the ALSA device. This is set because the device has entered
235 // an unrecoverable error state, or the ClosedTask() has executed. 225 // an unrecoverable error state, or the ClosedTask() has executed.
236 bool stop_stream_; 226 bool stop_stream_;
237 227
238 // Wrapper class to invoke all the ALSA functions. 228 // Wrapper class to invoke all the ALSA functions.
239 AlsaWrapper* wrapper_; 229 AlsaWrapper* wrapper_;
240 230
241 // Audio manager that created us. Used to report that we've been closed. 231 // Audio manager that created us. Used to report that we've been closed.
242 // This should only be used on the |client_thread_loop_|. Access via 232 // This should only be used on the |client_thread_loop_|. Access via
243 // the manager() function. 233 // the manager() function.
244 AudioManagerLinux* manager_; 234 AudioManagerLinux* manager_;
245 235
246 // Handle to the actual PCM playback device. 236 // Handle to the actual PCM playback device.
247 snd_pcm_t* playback_handle_; 237 snd_pcm_t* playback_handle_;
248 238
249 scoped_ptr<Packet> packet_; 239 scoped_ptr<media::SeekableBuffer> buffer_;
250 uint32 frames_per_packet_; 240 uint32 frames_per_packet_;
251 241
252 // Used to check which message loop is allowed to call the public APIs. 242 // Used to check which message loop is allowed to call the public APIs.
253 MessageLoop* client_thread_loop_; 243 MessageLoop* client_thread_loop_;
254 244
255 // The message loop responsible for querying the data source, and writing to 245 // The message loop responsible for querying the data source, and writing to
256 // the output device. 246 // the output device.
257 MessageLoop* message_loop_; 247 MessageLoop* message_loop_;
258 248
259 DISALLOW_COPY_AND_ASSIGN(AlsaPcmOutputStream); 249 DISALLOW_COPY_AND_ASSIGN(AlsaPcmOutputStream);
260 }; 250 };
261 251
262 #endif // MEDIA_AUDIO_LINUX_ALSA_OUTPUT_H_ 252 #endif // MEDIA_AUDIO_LINUX_ALSA_OUTPUT_H_
OLDNEW
« no previous file with comments | « no previous file | media/audio/linux/alsa_output.cc » ('j') | media/audio/linux/alsa_output_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698