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 |