// 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 "base/containers/circular_deque.h" #include "base/functional/callback.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 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 pushes that output via its |output_callback_|. class MEDIA_EXPORT ConvertingAudioFifo final : public AudioConverter::InputCallback { public: using OuputCallback = base::RepeatingCallback; ConvertingAudioFifo(const AudioParameters& input_params, const AudioParameters& converted_params, OuputCallback output_callback); 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 input_bus); // 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 EnsureExpectedChannelCount( std::unique_ptr audio_bus); // Callbacks through which converted frames are delivered. const OuputCallback output_callback_; 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 mixer_ GUARDED_BY_CONTEXT(sequence_checker_); AudioParameters mixer_input_params_ GUARDED_BY_CONTEXT(sequence_checker_); // Synchronously performs audio conversions. std::unique_ptr converter_ GUARDED_BY_CONTEXT(sequence_checker_); // Destination bus for the |converter_|. std::unique_ptr converted_audio_bus_ GUARDED_BY_CONTEXT(sequence_checker_); // All current input frames. base::circular_deque> inputs_ GUARDED_BY_CONTEXT(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_); }; } // namespace media #endif // MEDIA_BASE_CONVERTING_AUDIO_FIFO_H_