• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef SDK_ANDROID_SRC_JNI_AUDIO_DEVICE_AAUDIO_PLAYER_H_
12 #define SDK_ANDROID_SRC_JNI_AUDIO_DEVICE_AAUDIO_PLAYER_H_
13 
14 #include <aaudio/AAudio.h>
15 #include <memory>
16 
17 #include "absl/types/optional.h"
18 #include "modules/audio_device/audio_device_buffer.h"
19 #include "modules/audio_device/include/audio_device_defines.h"
20 #include "rtc_base/message_handler.h"
21 #include "rtc_base/thread.h"
22 #include "rtc_base/thread_annotations.h"
23 #include "rtc_base/thread_checker.h"
24 #include "sdk/android/src/jni/audio_device/aaudio_wrapper.h"
25 #include "sdk/android/src/jni/audio_device/audio_device_module.h"
26 
27 namespace webrtc {
28 
29 class AudioDeviceBuffer;
30 class FineAudioBuffer;
31 
32 namespace jni {
33 
34 // Implements low-latency 16-bit mono PCM audio output support for Android
35 // using the C based AAudio API.
36 //
37 // An instance must be created and destroyed on one and the same thread.
38 // All public methods must also be called on the same thread. A thread checker
39 // will DCHECK if any method is called on an invalid thread. Audio buffers
40 // are requested on a dedicated high-priority thread owned by AAudio.
41 //
42 // The existing design forces the user to call InitPlayout() after StopPlayout()
43 // to be able to call StartPlayout() again. This is in line with how the Java-
44 // based implementation works.
45 //
46 // An audio stream can be disconnected, e.g. when an audio device is removed.
47 // This implementation will restart the audio stream using the new preferred
48 // device if such an event happens.
49 //
50 // Also supports automatic buffer-size adjustment based on underrun detections
51 // where the internal AAudio buffer can be increased when needed. It will
52 // reduce the risk of underruns (~glitches) at the expense of an increased
53 // latency.
54 class AAudioPlayer final : public AudioOutput,
55                            public AAudioObserverInterface,
56                            public rtc::MessageHandler {
57  public:
58   explicit AAudioPlayer(const AudioParameters& audio_parameters);
59   ~AAudioPlayer() override;
60 
61   int Init() override;
62   int Terminate() override;
63 
64   int InitPlayout() override;
65   bool PlayoutIsInitialized() const override;
66 
67   int StartPlayout() override;
68   int StopPlayout() override;
69   bool Playing() const override;
70 
71   void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override;
72 
73   // Not implemented in AAudio.
74   bool SpeakerVolumeIsAvailable() override;
75   int SetSpeakerVolume(uint32_t volume) override;
76   absl::optional<uint32_t> SpeakerVolume() const override;
77   absl::optional<uint32_t> MaxSpeakerVolume() const override;
78   absl::optional<uint32_t> MinSpeakerVolume() const override;
79 
80  protected:
81   // AAudioObserverInterface implementation.
82 
83   // For an output stream, this function should render and write |num_frames|
84   // of data in the streams current data format to the |audio_data| buffer.
85   // Called on a real-time thread owned by AAudio.
86   aaudio_data_callback_result_t OnDataCallback(void* audio_data,
87                                                int32_t num_frames) override;
88   // AAudio calls this functions if any error occurs on a callback thread.
89   // Called on a real-time thread owned by AAudio.
90   void OnErrorCallback(aaudio_result_t error) override;
91 
92   // rtc::MessageHandler used for restart messages from the error-callback
93   // thread to the main (creating) thread.
94   void OnMessage(rtc::Message* msg) override;
95 
96  private:
97   // Closes the existing stream and starts a new stream.
98   void HandleStreamDisconnected();
99 
100   // Ensures that methods are called from the same thread as this object is
101   // created on.
102   rtc::ThreadChecker main_thread_checker_;
103 
104   // Stores thread ID in first call to AAudioPlayer::OnDataCallback from a
105   // real-time thread owned by AAudio. Detached during construction of this
106   // object.
107   rtc::ThreadChecker thread_checker_aaudio_;
108 
109   // The thread on which this object is created on.
110   rtc::Thread* main_thread_;
111 
112   // Wraps all AAudio resources. Contains an output stream using the default
113   // output audio device. Can be accessed on both the main thread and the
114   // real-time thread owned by AAudio. See separate AAudio documentation about
115   // thread safety.
116   AAudioWrapper aaudio_;
117 
118   // FineAudioBuffer takes an AudioDeviceBuffer which delivers audio data
119   // in chunks of 10ms. It then allows for this data to be pulled in
120   // a finer or coarser granularity. I.e. interacting with this class instead
121   // of directly with the AudioDeviceBuffer one can ask for any number of
122   // audio data samples.
123   // Example: native buffer size can be 192 audio frames at 48kHz sample rate.
124   // WebRTC will provide 480 audio frames per 10ms but AAudio asks for 192
125   // in each callback (once every 4th ms). This class can then ask for 192 and
126   // the FineAudioBuffer will ask WebRTC for new data approximately only every
127   // second callback and also cache non-utilized audio.
128   std::unique_ptr<FineAudioBuffer> fine_audio_buffer_;
129 
130   // Counts number of detected underrun events reported by AAudio.
131   int32_t underrun_count_ = 0;
132 
133   // True only for the first data callback in each audio session.
134   bool first_data_callback_ = true;
135 
136   // Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the
137   // AudioDeviceModuleImpl class and set by AudioDeviceModule::Create().
138   AudioDeviceBuffer* audio_device_buffer_ RTC_GUARDED_BY(main_thread_checker_) =
139       nullptr;
140 
141   bool initialized_ RTC_GUARDED_BY(main_thread_checker_) = false;
142   bool playing_ RTC_GUARDED_BY(main_thread_checker_) = false;
143 
144   // Estimated latency between writing an audio frame to the output stream and
145   // the time that same frame is played out on the output audio device.
146   double latency_millis_ RTC_GUARDED_BY(thread_checker_aaudio_) = 0;
147 };
148 
149 }  // namespace jni
150 
151 }  // namespace webrtc
152 
153 #endif  // SDK_ANDROID_SRC_JNI_AUDIO_DEVICE_AAUDIO_PLAYER_H_
154