AudioInputSource.h (5777B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 6 7 #ifndef DOM_MEDIA_AudioInputSource_H_ 8 #define DOM_MEDIA_AudioInputSource_H_ 9 10 #include "AudioDriftCorrection.h" 11 #include "AudioSegment.h" 12 #include "CubebInputStream.h" 13 #include "CubebUtils.h" 14 #include "TimeUnits.h" 15 #include "mozilla/MozPromise.h" 16 #include "mozilla/ProfilerUtils.h" 17 #include "mozilla/RefPtr.h" 18 #include "mozilla/SPSCQueue.h" 19 #include "mozilla/SharedThreadPool.h" 20 #include "mozilla/Variant.h" 21 22 namespace mozilla { 23 24 // This is an interface to operate an input-only audio stream within a 25 // cubeb-task thread on a specific thread. Once the class instance is created, 26 // all its operations must be called on the same thread. 27 // 28 // The audio data is periodically produced by the underlying audio stream on the 29 // stream's callback thread, and can be safely read by GetAudioSegment() on a 30 // specific thread. 31 class AudioInputSource : public CubebInputStream::Listener { 32 public: 33 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AudioInputSource, override); 34 35 using Id = uint32_t; 36 37 class EventListener { 38 public: 39 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING; 40 41 // This two events will be fired on main thread. 42 virtual void AudioDeviceChanged(Id aId) = 0; 43 enum class State { Started, Stopped, Drained, Error }; 44 virtual void AudioStateCallback(Id aId, State aState) = 0; 45 46 protected: 47 EventListener() = default; 48 virtual ~EventListener() = default; 49 }; 50 51 AudioInputSource(RefPtr<EventListener>&& aListener, Id aSourceId, 52 CubebUtils::AudioDeviceID aDeviceId, uint32_t aChannelCount, 53 bool aIsVoice, const PrincipalHandle& aPrincipalHandle, 54 TrackRate aSourceRate, TrackRate aTargetRate); 55 56 // The following functions should always be called in the same thread: They 57 // are always run on MediaTrackGraph's graph thread. 58 // Sets up mStream. 59 void Init(); 60 // Starts producing audio data. 61 void Start(); 62 // Stops producing audio data. 63 void Stop(); 64 // Set the params to be applied in the platform for this source. 65 using SetRequestedProcessingParamsPromise = 66 MozPromise<cubeb_input_processing_params, int, true>; 67 RefPtr<SetRequestedProcessingParamsPromise> SetRequestedProcessingParams( 68 cubeb_input_processing_params aParams); 69 // Returns the AudioSegment with aDuration of data inside. 70 // The graph thread can change behind the scene, e.g., cubeb stream reinit due 71 // to default output device changed). When this happens, we need to notify 72 // mSPSCQueue to change its data consumer. 73 enum class Consumer { Same, Changed }; 74 AudioSegment GetAudioSegment(TrackTime aDuration, Consumer aConsumer); 75 76 // CubebInputStream::Listener interface: These are used only for the 77 // underlying audio stream. No user should call these APIs. 78 // This will be fired on audio callback thread. 79 long DataCallback(const void* aBuffer, long aFrames) override; 80 // This can be fired on any thread. 81 void StateCallback(cubeb_state aState) override; 82 // This can be fired on any thread. 83 void DeviceChangedCallback() override; 84 85 // Any threads: 86 // The unique id of this source. 87 const Id mId; 88 // The id of this audio device producing the data. 89 const CubebUtils::AudioDeviceID mDeviceId; 90 // The channel count of audio data produced. 91 const uint32_t mChannelCount; 92 // The sample rate of the audio data produced. 93 const TrackRate mRate; 94 // Indicate whether the audio stream is for voice or not. 95 const bool mIsVoice; 96 // The principal of the audio data produced. 97 const PrincipalHandle mPrincipalHandle; 98 99 protected: 100 ~AudioInputSource() = default; 101 102 private: 103 // Underlying audio thread only. 104 bool CheckThreadIdChanged(); 105 106 // Any thread. 107 const bool mSandboxed; 108 109 // Thread id of the underlying audio thread. Underlying audio thread only. 110 std::atomic<ProfilerThreadId> mAudioThreadId; 111 112 // Forward the underlying event from main thread. 113 const RefPtr<EventListener> mEventListener; 114 115 // Shared thread pool containing only one thread for cubeb operations. 116 // The cubeb operations: Start() and Stop() will be called on 117 // MediaTrackGraph's graph thread, which can be the cubeb stream's callback 118 // thread. Running cubeb operations within cubeb stream callback thread can 119 // cause the deadlock on Linux, so we dispatch those operations to the task 120 // thread. 121 const RefPtr<SharedThreadPool> mTaskThread; 122 123 // Correct the drift between the underlying audio stream and its reader. 124 AudioDriftCorrection mDriftCorrector; 125 126 // An input-only cubeb stream operated within mTaskThread. 127 UniquePtr<CubebInputStream> mStream; 128 129 // The params configured on the cubeb stream, after filtering away unsupported 130 // params. mTaskThread only. 131 cubeb_input_processing_params mConfiguredProcessingParams = 132 CUBEB_INPUT_PROCESSING_PARAM_NONE; 133 134 struct Empty {}; 135 136 struct LatencyChangeData { 137 media::TimeUnit mLatency; 138 }; 139 140 struct Data : public Variant<AudioChunk, LatencyChangeData, Empty> { 141 Data() : Variant(AsVariant(Empty())) {} 142 explicit Data(AudioChunk&& aChunk) 143 : Variant(AsVariant(std::move(aChunk))) {} 144 explicit Data(LatencyChangeData aLatencyChangeData) 145 : Variant(AsVariant(std::move(aLatencyChangeData))) {} 146 }; 147 148 // A single-producer-single-consumer lock-free queue whose data is produced by 149 // the audio callback thread and consumed by AudioInputSource's data reader. 150 SPSCQueue<Data> mSPSCQueue{30}; 151 }; 152 153 } // namespace mozilla 154 155 #endif // DOM_MEDIA_AudioInputSource_H_