converting_audio_fifo.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/base/converting_audio_fifo.h"
  5. #include "media/base/audio_bus.h"
  6. #include "media/base/audio_converter.h"
  7. #include "media/base/channel_mixer.h"
  8. namespace media {
  9. ConvertingAudioFifo::ConvertingAudioFifo(
  10. const AudioParameters& input_params,
  11. const AudioParameters& converted_params,
  12. ConvertingAudioFifo::OuputCallback output_callback)
  13. : output_callback_(std::move(output_callback)),
  14. input_params_(input_params),
  15. converted_params_(converted_params),
  16. converter_(std::make_unique<AudioConverter>(input_params,
  17. converted_params,
  18. /*disable_fifo=*/true)) {
  19. converter_->AddInput(this);
  20. converter_->PrimeWithSilence();
  21. min_input_frames_needed_ = converter_->GetMaxInputFramesRequested(
  22. converted_params_.frames_per_buffer());
  23. converted_audio_bus_ = AudioBus::Create(
  24. converted_params_.channels(), converted_params_.frames_per_buffer());
  25. }
  26. ConvertingAudioFifo::~ConvertingAudioFifo() {
  27. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  28. converter_->RemoveInput(this);
  29. }
  30. void ConvertingAudioFifo::Push(std::unique_ptr<AudioBus> input_bus) {
  31. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  32. DCHECK(!is_flushing_);
  33. total_frames_ += input_bus->frames();
  34. inputs_.emplace_back(EnsureExpectedChannelCount(std::move(input_bus)));
  35. // Immediately convert frames if we have enough.
  36. while (total_frames_ >= min_input_frames_needed_)
  37. Convert();
  38. }
  39. void ConvertingAudioFifo::Convert() {
  40. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  41. DCHECK(total_frames_ >= min_input_frames_needed_ || is_flushing_)
  42. << "total_frames_=" << total_frames_
  43. << ",min_input_frames_needed_=" << min_input_frames_needed_
  44. << ",is_flushing_=" << is_flushing_;
  45. converter_->Convert(converted_audio_bus_.get());
  46. output_callback_.Run(converted_audio_bus_.get());
  47. }
  48. void ConvertingAudioFifo::Flush() {
  49. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  50. is_flushing_ = true;
  51. // Convert all remaining frames.
  52. while (total_frames_)
  53. Convert();
  54. converter_->Reset();
  55. converter_->PrimeWithSilence();
  56. inputs_.clear();
  57. total_frames_ = 0;
  58. front_frame_index_ = 0;
  59. is_flushing_ = false;
  60. }
  61. double ConvertingAudioFifo::ProvideInput(AudioBus* audio_bus,
  62. uint32_t frames_delayed) {
  63. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  64. int frames_needed = audio_bus->frames();
  65. int frames_written = 0;
  66. // If we aren't flushing, this should only be called if we have enough
  67. // frames to completey satisfy the request.
  68. DCHECK(is_flushing_ || total_frames_ >= frames_needed)
  69. << "is_flushing_=" << is_flushing_ << ",total_frames_=" << total_frames_
  70. << ",frames_needed=" << frames_needed;
  71. // Write until we've fulfilled the request or run out of frames.
  72. while (frames_written < frames_needed && total_frames_) {
  73. const AudioBus* front = inputs_.front().get();
  74. int frames_in_front = front->frames() - front_frame_index_;
  75. int frames_to_write =
  76. std::min(frames_needed - frames_written, frames_in_front);
  77. front->CopyPartialFramesTo(front_frame_index_, frames_to_write,
  78. frames_written, audio_bus);
  79. frames_written += frames_to_write;
  80. front_frame_index_ += frames_to_write;
  81. total_frames_ -= frames_to_write;
  82. if (front_frame_index_ == front->frames()) {
  83. // We exhausted all frames in the front buffer, remove it.
  84. inputs_.pop_front();
  85. front_frame_index_ = 0;
  86. }
  87. }
  88. // We should only run out of frames if we're flushing.
  89. if (frames_written != frames_needed) {
  90. DCHECK(is_flushing_);
  91. DCHECK(!total_frames_);
  92. DCHECK(!inputs_.size());
  93. audio_bus->ZeroFramesPartial(frames_written,
  94. frames_needed - frames_written);
  95. }
  96. return 1.0f;
  97. }
  98. std::unique_ptr<AudioBus> ConvertingAudioFifo::EnsureExpectedChannelCount(
  99. std::unique_ptr<AudioBus> audio_bus) {
  100. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  101. // No mixing required.
  102. if (audio_bus->channels() == input_params_.channels())
  103. return audio_bus;
  104. const int& incoming_channels = audio_bus->channels();
  105. if (!mixer_ || mixer_input_params_.channels() != incoming_channels) {
  106. // Both the format and the sample rate are unused for mixing, but we still
  107. // need to pass a value below.
  108. mixer_input_params_.Reset(input_params_.format(),
  109. GuessChannelLayout(incoming_channels),
  110. incoming_channels, input_params_.sample_rate());
  111. mixer_ = std::make_unique<ChannelMixer>(mixer_input_params_, input_params_);
  112. }
  113. auto mixed_bus =
  114. AudioBus::Create(input_params_.channels(), audio_bus->frames());
  115. mixer_->Transform(audio_bus.get(), mixed_bus.get());
  116. return mixed_bus;
  117. }
  118. } // namespace media