Chromium Code Reviews| Index: chromecast/media/cma/backend/alsa/filter_group.cc |
| diff --git a/chromecast/media/cma/backend/alsa/filter_group.cc b/chromecast/media/cma/backend/alsa/filter_group.cc |
| index e041b7e9b8ef6c6ea5a07d1985896d1cfbdab37a..de0e6b66dfa6258ff6955905fc93df3f35b7ee76 100644 |
| --- a/chromecast/media/cma/backend/alsa/filter_group.cc |
| +++ b/chromecast/media/cma/backend/alsa/filter_group.cc |
| @@ -7,24 +7,47 @@ |
| #include <algorithm> |
| #include "base/memory/ptr_util.h" |
| +#include "base/time/time.h" |
| #include "base/values.h" |
| #include "chromecast/media/cma/backend/alsa/post_processing_pipeline.h" |
| #include "media/base/audio_bus.h" |
| +#include "media/base/vector_math.h" |
| namespace chromecast { |
| namespace media { |
| -FilterGroup::FilterGroup(const std::unordered_set<std::string>& input_types, |
| - AudioContentType content_type, |
| - int num_channels, |
| - const base::ListValue* filter_list) |
| - : input_types_(input_types), |
| - content_type_(content_type), |
| - num_channels_(num_channels), |
| +FilterGroup::FilterGroup(int num_channels, |
| + const std::string& name, |
| + const base::ListValue* filter_list, |
| + const std::unordered_set<std::string>& input_types, |
| + const std::vector<FilterGroup*>& mixed_inputs) |
| + : num_channels_(num_channels), |
| + name_(name), |
| + input_types_(input_types), |
| + mixed_inputs_(mixed_inputs), |
| output_samples_per_second_(0), |
| channels_(num_channels_), |
| post_processing_pipeline_( |
| - base::MakeUnique<PostProcessingPipeline>(filter_list, |
| - num_channels_)) {} |
| + PostProcessingPipeline::Create(name_, filter_list, num_channels_)) {} |
| + |
| +FilterGroup::FilterGroup(int num_channels, |
| + const std::string& name, |
| + const base::ListValue* filter_list, |
| + const std::unordered_set<std::string>& input_types) |
| + : FilterGroup(num_channels, |
| + name, |
| + filter_list, |
| + input_types, |
| + std::vector<FilterGroup*>()) {} |
| + |
| +FilterGroup::FilterGroup(int num_channels, |
| + const std::string& name, |
| + const base::ListValue* filter_list, |
| + const std::vector<FilterGroup*>& mixed_inputs) |
| + : FilterGroup(num_channels, |
| + name, |
| + filter_list, |
| + std::unordered_set<std::string>(), |
| + mixed_inputs) {} |
| FilterGroup::~FilterGroup() = default; |
| @@ -41,20 +64,33 @@ void FilterGroup::AddActiveInput(StreamMixerAlsa::InputQueue* input) { |
| active_inputs_.push_back(input); |
| } |
| -std::vector<uint8_t>* FilterGroup::GetInterleaved() { |
| - return &interleaved_; |
| -} |
| - |
| -bool FilterGroup::MixAndFilter(int chunk_size) { |
| +float FilterGroup::MixAndFilter(int chunk_size) { |
| DCHECK_NE(output_samples_per_second_, 0); |
| - if (active_inputs_.empty() && !post_processing_pipeline_->IsRinging()) { |
| - return false; // Output will be silence, no need to mix. |
| - } |
| ResizeBuffersIfNecessary(chunk_size); |
| - mixed_->ZeroFramesPartial(0, chunk_size); |
| float volume = 0.0f; |
| + |
| + // Recursively mix inputs. |
| + for (auto* filter_group : mixed_inputs_) { |
| + volume = std::max(volume, filter_group->MixAndFilter(chunk_size)); |
| + } |
| + |
| + if (active_inputs_.empty() && volume == 0.0f && |
|
kmackay
2017/04/28 00:31:41
The volume == 0 check is a bit subtle, please add
bshaya
2017/04/28 01:37:36
Done.
|
| + !post_processing_pipeline_->IsRinging()) { |
| + if (frames_zeroed_ < chunk_size) { |
| + // ensure mixed_ is zeros. This is necessary if |
| + // our data is read laster. |
|
kmackay
2017/04/28 00:31:42
Fix comment formatting and 'laster'
bshaya
2017/04/28 01:37:36
Done.
|
| + mixed_->ZeroFramesPartial(0, chunk_size); |
| + frames_zeroed_ = chunk_size; |
| + } |
| + return 0.0f; // Output will be silence, no need to mix. |
| + } |
| + |
| + frames_zeroed_ = 0; |
| + |
| + // Mix InputQueue's |
|
kmackay
2017/04/28 00:31:41
nit: no apostrophe
bshaya
2017/04/28 01:37:36
Done.
|
| + mixed_->ZeroFramesPartial(0, chunk_size); |
| for (StreamMixerAlsa::InputQueue* input : active_inputs_) { |
| input->GetResampledData(temp_.get(), chunk_size); |
| for (int c = 0; c < num_channels_; ++c) { |
| @@ -65,18 +101,32 @@ bool FilterGroup::MixAndFilter(int chunk_size) { |
| volume = std::max(volume, input->EffectiveVolume()); |
| } |
| - post_processing_pipeline_->ProcessFrames(channels_, chunk_size, volume, |
| - active_inputs_.empty()); |
| - mixed_->ToInterleaved(chunk_size, BytesPerOutputFormatSample(), |
| - interleaved_.data()); |
| - return true; |
| + // Mix FilterGroup's |
|
kmackay
2017/04/28 00:31:41
nit: no apostrophe
bshaya
2017/04/28 01:37:36
Done.
|
| + for (FilterGroup* group : mixed_inputs_) { |
| + if (group->last_volume() > 0.0f) { |
| + for (int c = 0; c < num_channels_; ++c) { |
| + ::media::vector_math::FMAC(group->data()->channel(c), 1.0f, chunk_size, |
| + channels_[c]); |
| + } |
| + } |
| + } |
| + |
| + if (volume != 0.0f) { |
|
kmackay
2017/04/28 00:31:42
Why the if check? seems like last_volume_ should b
bshaya
2017/04/28 01:37:36
I need to hold on to last_volume_ until ringing is
|
| + last_volume_ = volume; |
| + } |
| + |
| + delay_frames_ = post_processing_pipeline_->ProcessFrames( |
| + channels_, chunk_size, volume, volume == 0.0f); |
| + return volume; |
| } |
| -void FilterGroup::ClearInterleaved(int chunk_size) { |
| - ResizeBuffersIfNecessary(chunk_size); |
| - memset(interleaved_.data(), 0, |
| - static_cast<size_t>(chunk_size) * num_channels_ * |
| - BytesPerOutputFormatSample()); |
| +int64_t FilterGroup::GetRenderingDelayMicroseconds() { |
| + return delay_frames_ * base::Time::kMicrosecondsPerSecond / |
| + output_samples_per_second_; |
| +} |
| + |
| +void FilterGroup::ClearActiveInputs() { |
| + active_inputs_.clear(); |
| } |
| void FilterGroup::ResizeBuffersIfNecessary(int chunk_size) { |
| @@ -89,26 +139,6 @@ void FilterGroup::ResizeBuffersIfNecessary(int chunk_size) { |
| if (!temp_ || temp_->frames() < chunk_size) { |
| temp_ = ::media::AudioBus::Create(num_channels_, chunk_size); |
| } |
| - |
| - size_t interleaved_size = static_cast<size_t>(chunk_size) * num_channels_ * |
| - BytesPerOutputFormatSample(); |
| - |
| - if (interleaved_.size() < interleaved_size) { |
| - interleaved_.resize(interleaved_size); |
| - } |
| -} |
| - |
| -int FilterGroup::BytesPerOutputFormatSample() { |
| - return sizeof(int32_t); |
| -} |
| - |
| -void FilterGroup::ClearActiveInputs() { |
| - active_inputs_.clear(); |
| -} |
| - |
| -void FilterGroup::DisablePostProcessingForTest() { |
| - post_processing_pipeline_ = |
| - base::MakeUnique<PostProcessingPipeline>(nullptr, num_channels_); |
| } |
| } // namespace media |