1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
media / audio / cras / cras_input.h [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_AUDIO_CRAS_CRAS_INPUT_H_
#define MEDIA_AUDIO_CRAS_CRAS_INPUT_H_
#include <cras_client.h>
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>
#include "base/compiler_specific.h"
#include "media/audio/aecdump_recording_manager.h"
#include "media/audio/agc_audio_stream.h"
#include "media/audio/audio_debug_recording_helper.h"
#include "media/audio/audio_io.h"
#include "media/audio/cras/audio_manager_cras_base.h"
#include "media/audio/system_glitch_reporter.h"
#include "media/base/amplitude_peak_detector.h"
#include "media/base/audio_glitch_info.h"
#include "media/base/audio_parameters.h"
#include "media/base/media_export.h"
namespace media {
class AudioManagerCrasBase;
// Provides an input stream for audio capture based on CRAS, the ChromeOS Audio
// Server. This object is not thread safe and all methods should be invoked in
// the thread that created the object.
class MEDIA_EXPORT CrasInputStream : public AgcAudioStream<AudioInputStream>,
public AecdumpRecordingSource {
public:
// The ctor takes all the usual parameters, plus |manager| which is the
// audio manager who is creating this object.
CrasInputStream(const AudioParameters& params,
AudioManagerCrasBase* manager,
const std::string& device_id,
const AudioManager::LogCallback& log_callback);
CrasInputStream(const CrasInputStream&) = delete;
CrasInputStream& operator=(const CrasInputStream&) = delete;
// The dtor is typically called by the AudioManager only and it is usually
// triggered by calling AudioOutputStream::Close().
~CrasInputStream() override;
// Implementation of AudioInputStream.
AudioInputStream::OpenOutcome Open() override;
void Start(AudioInputCallback* callback) override;
void Stop() override;
void Close() override;
double GetMaxVolume() override;
void SetVolume(double volume) override;
double GetVolume() override;
bool IsMuted() override;
void SetOutputDeviceForAec(const std::string& output_device_id) override;
// Implementation of AecdumpRecordingSource
void StartAecdump(base::File aecdump_file) override;
void StopAecdump() override;
private:
// Handles requests to get samples from the provided buffer. This will be
// called by the audio server when it has samples ready.
static int SamplesReady(struct libcras_stream_cb_data* data);
// Handles notification that there was an error with the playback stream.
static int StreamError(cras_client* client,
cras_stream_id_t stream_id,
int err,
void* arg);
// Reads one or more buffers of audio from the device, passes on to the
// registered callback. Called from SamplesReady().
void ReadAudio(size_t frames, uint8_t* buffer, const timespec* latency_ts);
// Deals with an error that occurred in the stream. Called from
// StreamError().
void NotifyStreamError(int err);
// Convert from dB * 100 to a volume ratio.
double GetVolumeRatioFromDecibels(double dB) const;
// Convert from a volume ratio to dB.
double GetDecibelsFromVolumeRatio(double volume_ratio) const;
// Return true to use AEC in CRAS for this input stream.
inline bool UseCrasAec() const;
// Return true to use NS in CRAS for this input stream.
inline bool UseCrasNs() const;
// Return true to use AGC in CRAS for this input stream.
inline bool UseCrasAgc() const;
// Return true to use client controlled voice isolation in CRAS for this
// input stream.
inline bool UseClientControlledVoiceIsolation() const;
// Return true to use voice isolation in CRAS for this input stream.
inline bool UseCrasVoiceIsolation() const;
// Return true to allow AEC on DSP for this input stream.
inline bool DspBasedAecIsAllowed() const;
// Return true to allow NS on DSP for this input stream.
inline bool DspBasedNsIsAllowed() const;
// Return true to allow AGC on DSP for this input stream.
inline bool DspBasedAgcIsAllowed() const;
// Return true if UI Gains should be ignored for this input stream.
inline bool IgnoreUiGains() const;
// Called from the dtor and when the stream is reset.
void ReportAndResetStats();
// There are 2 main reasons for input audio glitches.
// 1. Audio frames are overwritten in the shared memory due to client being
// too slow at taking them out, and shared memory overrun occurs.
// The overwritten frames are calculated using |overrun_frames|.
// 2. Audio samples are dropped from the input device hardware buffer due to
// there being too many unhandled samples. The duration of the dropped
// audio samples calculated using |dropped_samples_duration|.
// Check if the input audio glitches of these 2 types happen this callback.
// The total duration of the audio glitch for this callback is the
// combination of the glitch duration from both types of input audio
// glitches.
void CalculateAudioGlitches(uint32_t overrun_frames,
base::TimeDelta dropped_samples_duration);
// Non-refcounted pointer back to the audio manager.
// The AudioManager indirectly holds on to stream objects, so we don't
// want circular references. Additionally, stream objects live on the
// audio thread, which is owned by the audio manager and we don't want to
// addref the manager from that thread.
AudioManagerCrasBase* const audio_manager_;
// Callback to pass audio samples too, valid while recording.
AudioInputCallback* callback_ = NULL;
// The client used to communicate with the audio server.
struct libcras_client* client_ = NULL;
// PCM parameters for the stream.
const AudioParameters params_;
// True if the stream has been started.
bool started_ = false;
// ID of the playing stream.
cras_stream_id_t stream_id_ = 0;
// Direction of the stream.
const CRAS_STREAM_DIRECTION stream_direction_ = CRAS_STREAM_INPUT;
// Index of the CRAS device to stream input from.
int pin_device_ = NO_DEVICE;
// True if the stream is a system-wide loopback stream.
const bool is_loopback_;
// True if the loopback stream does not contain chrome audio.
const bool is_loopback_without_chrome_;
// True if we want to mute system audio during capturing.
const bool mute_system_audio_;
bool mute_done_ = false;
#if DCHECK_IS_ON()
// Flag to indicate if recording has been enabled or not.
bool recording_enabled_;
#endif
// Value of input stream volume, between 0.0 - 1.0.
double input_volume_ = 1.0f;
std::unique_ptr<AudioBus> audio_bus_;
// Used to aggregate and report glitch metrics to UMA (periodically) and to
// text logs (when a stream ends).
SystemGlitchReporter glitch_reporter_;
AudioGlitchInfo::Accumulator glitch_info_accumulator_;
// Callback to send statistics info.
const AudioManager::LogCallback log_callback_;
// Contains the amount of overrun frames passed in from the previous callback.
// Overrun frames are audio frames that are overwrittten in the shared memory
// due to client delay.
uint32_t last_overrun_frames_ = 0;
// Contains the duration of dropped samples passed in from the previous
// callback.
// Dropped data are samples dropped from the input device's hardware buffer
// due to too many samples.
base::TimeDelta last_dropped_samples_duration_;
AmplitudePeakDetector peak_detector_;
base::WeakPtrFactory<CrasInputStream> weak_factory_{this};
};
} // namespace media
#endif // MEDIA_AUDIO_CRAS_CRAS_INPUT_H_