alsa_output.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright 2013 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.
  13. //
  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.
  16. //
  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.
  20. #ifndef MEDIA_AUDIO_ALSA_ALSA_OUTPUT_H_
  21. #define MEDIA_AUDIO_ALSA_ALSA_OUTPUT_H_
  22. #include <alsa/asoundlib.h>
  23. #include <stdint.h>
  24. #include <memory>
  25. #include <string>
  26. #include "base/compiler_specific.h"
  27. #include "base/gtest_prod_util.h"
  28. #include "base/memory/raw_ptr.h"
  29. #include "base/memory/ref_counted.h"
  30. #include "base/memory/weak_ptr.h"
  31. #include "base/sequence_checker.h"
  32. #include "base/task/single_thread_task_runner.h"
  33. #include "base/time/tick_clock.h"
  34. #include "base/time/time.h"
  35. #include "media/audio/audio_io.h"
  36. #include "media/base/audio_parameters.h"
  37. namespace media {
  38. class AlsaWrapper;
  39. class AudioManagerBase;
  40. class ChannelMixer;
  41. class SeekableBuffer;
  42. class MEDIA_EXPORT AlsaPcmOutputStream : public AudioOutputStream {
  43. public:
  44. // String for the generic "default" ALSA device that has the highest
  45. // compatibility and chance of working.
  46. static const char kDefaultDevice[];
  47. // Pass this to the AlsaPcmOutputStream if you want to attempt auto-selection
  48. // of the audio device.
  49. static const char kAutoSelectDevice[];
  50. // Prefix for device names to enable ALSA library resampling.
  51. static const char kPlugPrefix[];
  52. // The minimum latency that is accepted by the device.
  53. static const uint32_t kMinLatencyMicros;
  54. // Create a PCM Output stream for the ALSA device identified by
  55. // |device_name|. The AlsaPcmOutputStream uses |wrapper| to communicate with
  56. // the alsa libraries, allowing for dependency injection during testing. All
  57. // requesting of data, and writing to the alsa device will be done on
  58. // the current thread.
  59. //
  60. // If unsure of what to use for |device_name|, use |kAutoSelectDevice|.
  61. AlsaPcmOutputStream(const std::string& device_name,
  62. const AudioParameters& params,
  63. AlsaWrapper* wrapper,
  64. AudioManagerBase* manager);
  65. AlsaPcmOutputStream(const AlsaPcmOutputStream&) = delete;
  66. AlsaPcmOutputStream& operator=(const AlsaPcmOutputStream&) = delete;
  67. ~AlsaPcmOutputStream() override;
  68. // Implementation of AudioOutputStream.
  69. bool Open() override;
  70. void Close() override;
  71. void Start(AudioSourceCallback* callback) override;
  72. void Stop() override;
  73. void Flush() override;
  74. void SetVolume(double volume) override;
  75. void GetVolume(double* volume) override;
  76. void SetTickClockForTesting(const base::TickClock* tick_clock);
  77. private:
  78. friend class AlsaPcmOutputStreamTest;
  79. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest,
  80. AutoSelectDevice_DeviceSelect);
  81. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest,
  82. AutoSelectDevice_FallbackDevices);
  83. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, AutoSelectDevice_HintFail);
  84. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket);
  85. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_Negative);
  86. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_StopStream);
  87. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_Underrun);
  88. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, BufferPacket_FullBuffer);
  89. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, ConstructedState);
  90. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, LatencyFloor);
  91. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, OpenClose);
  92. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, PcmOpenFailed);
  93. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, PcmSetParamsFailed);
  94. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, ScheduleNextWrite);
  95. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest,
  96. ScheduleNextWrite_StopStream);
  97. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, StartStop);
  98. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_FinishedPacket);
  99. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_NormalPacket);
  100. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_StopStream);
  101. FRIEND_TEST_ALL_PREFIXES(AlsaPcmOutputStreamTest, WritePacket_WriteFails);
  102. // Flags indicating the state of the stream.
  103. enum InternalState {
  104. kInError = 0,
  105. kCreated,
  106. kIsOpened,
  107. kIsPlaying,
  108. kIsStopped,
  109. kIsClosed
  110. };
  111. friend std::ostream& operator<<(std::ostream& os, InternalState);
  112. // Functions to get another packet from the data source and write it into the
  113. // ALSA device.
  114. void BufferPacket(bool* source_exhausted);
  115. void WritePacket();
  116. void WriteTask();
  117. void ScheduleNextWrite(bool source_exhausted);
  118. // Utility functions for talking with the ALSA API.
  119. std::string FindDeviceForChannels(uint32_t channels);
  120. snd_pcm_sframes_t GetAvailableFrames();
  121. snd_pcm_sframes_t GetCurrentDelay();
  122. // Attempts to find the best matching linux audio device for the given number
  123. // of channels. This function will set |device_name_| and |channel_mixer_|.
  124. snd_pcm_t* AutoSelectDevice(uint32_t latency);
  125. // Functions to safeguard state transitions. All changes to the object state
  126. // should go through these functions.
  127. bool CanTransitionTo(InternalState to);
  128. InternalState TransitionTo(InternalState to);
  129. InternalState state();
  130. // API for Proxying calls to the AudioSourceCallback provided during
  131. // Start().
  132. //
  133. // TODO(ajwong): This is necessary because the ownership semantics for the
  134. // |source_callback_| object are incorrect in AudioRenderHost. The callback
  135. // is passed into the output stream, but ownership is not transfered which
  136. // requires a synchronization on access of the |source_callback_| to avoid
  137. // using a deleted callback.
  138. int RunDataCallback(base::TimeDelta delay,
  139. base::TimeTicks delay_timestamp,
  140. AudioBus* audio_bus);
  141. void RunErrorCallback(int code);
  142. // Changes the AudioSourceCallback to proxy calls to. Pass in nullptr to
  143. // release ownership of the currently registered callback.
  144. void set_source_callback(AudioSourceCallback* callback);
  145. // Configuration constants from the constructor. Referenceable by all threads
  146. // since they are constants.
  147. const std::string requested_device_name_;
  148. const snd_pcm_format_t pcm_format_;
  149. const uint32_t channels_;
  150. const ChannelLayout channel_layout_;
  151. const uint32_t sample_rate_;
  152. const uint32_t bytes_per_sample_;
  153. const uint32_t bytes_per_frame_;
  154. // Device configuration data. Populated after OpenTask() completes.
  155. std::string device_name_;
  156. uint32_t packet_size_;
  157. base::TimeDelta latency_;
  158. uint32_t bytes_per_output_frame_;
  159. uint32_t alsa_buffer_frames_;
  160. // Flag indicating the code should stop reading from the data source or
  161. // writing to the ALSA device. This is set because the device has entered
  162. // an unrecoverable error state, or the ClosedTask() has executed.
  163. bool stop_stream_;
  164. // Wrapper class to invoke all the ALSA functions.
  165. raw_ptr<AlsaWrapper> wrapper_;
  166. // Audio manager that created us. Used to report that we've been closed.
  167. raw_ptr<AudioManagerBase> manager_;
  168. // Task runner to use for polling.
  169. const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  170. // Handle to the actual PCM playback device.
  171. raw_ptr<snd_pcm_t> playback_handle_;
  172. std::unique_ptr<SeekableBuffer> buffer_;
  173. uint32_t frames_per_packet_;
  174. InternalState state_;
  175. float volume_; // Volume level from 0.0 to 1.0.
  176. raw_ptr<AudioSourceCallback> source_callback_;
  177. // Container for retrieving data from AudioSourceCallback::OnMoreData().
  178. std::unique_ptr<AudioBus> audio_bus_;
  179. // Channel mixer and temporary bus for the final mixed channel data.
  180. std::unique_ptr<ChannelMixer> channel_mixer_;
  181. std::unique_ptr<AudioBus> mixed_audio_bus_;
  182. raw_ptr<const base::TickClock> tick_clock_;
  183. SEQUENCE_CHECKER(sequence_checker_);
  184. // Allows us to run tasks on the AlsaPcmOutputStream instance which are
  185. // bound by its lifetime.
  186. // NOTE: Weak pointers must be invalidated before all other member variables.
  187. base::WeakPtrFactory<AlsaPcmOutputStream> weak_factory_{this};
  188. };
  189. MEDIA_EXPORT std::ostream& operator<<(std::ostream& os,
  190. AlsaPcmOutputStream::InternalState);
  191. } // namespace media
  192. #endif // MEDIA_AUDIO_ALSA_ALSA_OUTPUT_H_