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
media / base / converting_audio_fifo.h [blame]
// Copyright 2022 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_BASE_CONVERTING_AUDIO_FIFO_H_
#define MEDIA_BASE_CONVERTING_AUDIO_FIFO_H_
#include <memory>
#include "base/containers/circular_deque.h"
#include "base/sequence_checker.h"
#include "media/base/audio_converter.h"
#include "media/base/audio_parameters.h"
#include "media/base/media_export.h"
namespace media {
class AudioBus;
class AudioBusPool;
class ChannelMixer;
// FIFO which uses an AudioConverter to convert input frames into an output
// format. When enough input frames are pushed into the FIFO, it converts them
// synchronously, and notifies the availability of that output via its
// |output_ready_callback_|.
class MEDIA_EXPORT ConvertingAudioFifo final
: public AudioConverter::InputCallback {
public:
ConvertingAudioFifo(const AudioParameters& input_params,
const AudioParameters& converted_params);
ConvertingAudioFifo(const ConvertingAudioFifo&) = delete;
ConvertingAudioFifo& operator=(const ConvertingAudioFifo&) = delete;
~ConvertingAudioFifo() override;
// Adds inputs into the FIFO. `input_bus` must have the same sample rate as
// |input_params_|, but the number of channels or frames can be different.
void Push(std::unique_ptr<AudioBus> input_bus);
// Returns whether there is any available converted output.
bool HasOutput();
// Gets the current output.
const AudioBus* PeekOutput();
// Releases the current output.
void PopOutput();
// Forces all remaining frames to be converted, ouputing silence in case there
// isn't enough data. Noop if there aren't any available frames.
void Flush();
int min_number_input_frames_needed_for_testing() {
return min_input_frames_needed_;
}
private:
friend class ConvertingAudioFifoTest;
// AudioConverter::InputCallback implementation.
double ProvideInput(AudioBus* audio_bus,
uint32_t frames_delayed,
const AudioGlitchInfo& glitch_info) override;
// Consumes frames from |inputs_|, converts them to match
// |output_params_| fills |dest|.
void Convert();
// Returns an AudioBus with the same number of channels as |input_params_|,
// mixing |audio_bus| if necessary.
std::unique_ptr<AudioBus> EnsureExpectedChannelCount(
std::unique_ptr<AudioBus> audio_bus);
const AudioParameters input_params_;
const AudioParameters converted_params_;
bool is_flushing_ = false;
// Index to the first unused frame in |inputs_.front()|.
int front_frame_index_ = 0;
// Total number of input frames currently in the FIFO.
int total_frames_ = 0;
// Number of input frames needed to fully fulfill one Convert() call.
int min_input_frames_needed_;
// Used to mix incoming Push()'ed buffers to match the |input_params_|'s
// channel count. This is needed because we can receive multiple inputs with
// varying channel counts before having the |min_input_frames_needed_|
// to satisfy one round of conversions. If we created a new |converter_| each
// time the input channel changes, we would risk introducing silence when
// flushing (or losing data if we didn't flush).
std::unique_ptr<ChannelMixer> mixer_ GUARDED_BY_CONTEXT(sequence_checker_);
AudioParameters mixer_input_params_ GUARDED_BY_CONTEXT(sequence_checker_);
// Synchronously performs audio conversions.
std::unique_ptr<AudioConverter> converter_
GUARDED_BY_CONTEXT(sequence_checker_);
base::circular_deque<std::unique_ptr<AudioBus>> pending_outputs_
GUARDED_BY_CONTEXT(sequence_checker_);
std::unique_ptr<AudioBusPool> output_pool_
GUARDED_BY_CONTEXT(sequence_checker_);
// All current input frames.
base::circular_deque<std::unique_ptr<AudioBus>> inputs_
GUARDED_BY_CONTEXT(sequence_checker_);
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace media
#endif // MEDIA_BASE_CONVERTING_AUDIO_FIFO_H_