OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromecast/media/cma/backend/alsa/post_processing_pipeline.h" | 5 #include "chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
11 #include "base/scoped_native_library.h" | 11 #include "base/scoped_native_library.h" |
12 #include "base/values.h" | 12 #include "base/values.h" |
13 #include "chromecast/base/serializers.h" | 13 #include "chromecast/base/serializers.h" |
14 #include "chromecast/public/media/audio_post_processor_shlib.h" | 14 #include "chromecast/public/media/audio_post_processor_shlib.h" |
| 15 #include "chromecast/public/volume_control.h" |
15 | 16 |
16 namespace chromecast { | 17 namespace chromecast { |
17 namespace media { | 18 namespace media { |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 const int kNoSampleRate = -1; | 22 const int kNoSampleRate = -1; |
22 const char kSoCreateFunction[] = "AudioPostProcessorShlib_Create"; | 23 const char kSoCreateFunction[] = "AudioPostProcessorShlib_Create"; |
| 24 const char kProcessorKey[] = "processor"; |
23 | 25 |
24 } // namespace | 26 } // namespace |
25 | 27 |
26 using CreatePostProcessor = AudioPostProcessor* (*)(const std::string&, int); | 28 using CreatePostProcessor = AudioPostProcessor* (*)(const std::string&, int); |
27 | 29 |
28 PostProcessingPipeline::PostProcessingPipeline( | 30 std::unique_ptr<PostProcessingPipeline> PostProcessingPipeline::Create( |
| 31 const std::string& name, |
| 32 const base::ListValue* filter_description_list, |
| 33 int num_channels) { |
| 34 return base::MakeUnique<PostProcessingPipelineImpl>( |
| 35 name, filter_description_list, num_channels); |
| 36 } |
| 37 |
| 38 PostProcessingPipelineImpl::PostProcessingPipelineImpl( |
| 39 const std::string& name, |
29 const base::ListValue* filter_description_list, | 40 const base::ListValue* filter_description_list, |
30 int channels) | 41 int channels) |
31 : sample_rate_(kNoSampleRate) { | 42 : name_(name), sample_rate_(kNoSampleRate) { |
32 if (!filter_description_list) { | 43 if (!filter_description_list) { |
33 return; // Warning logged. | 44 return; // Warning logged. |
34 } | 45 } |
35 for (size_t i = 0; i < filter_description_list->GetSize(); ++i) { | 46 for (size_t i = 0; i < filter_description_list->GetSize(); ++i) { |
36 const base::DictionaryValue* processor_description_dict; | 47 const base::DictionaryValue* processor_description_dict; |
37 CHECK( | 48 CHECK( |
38 filter_description_list->GetDictionary(i, &processor_description_dict)); | 49 filter_description_list->GetDictionary(i, &processor_description_dict)); |
39 std::string library_path; | 50 std::string library_path; |
40 CHECK(processor_description_dict->GetString("processor", &library_path)); | 51 CHECK(processor_description_dict->GetString(kProcessorKey, &library_path)); |
41 if (library_path == "null" || library_path == "none") { | 52 if (library_path == "null" || library_path == "none") { |
42 continue; | 53 continue; |
43 } | 54 } |
44 const base::Value* processor_config_val; | 55 const base::Value* processor_config_val; |
45 CHECK(processor_description_dict->Get("config", &processor_config_val)); | 56 CHECK(processor_description_dict->Get("config", &processor_config_val)); |
46 CHECK(processor_config_val->is_dict() || processor_config_val->is_string()); | 57 CHECK(processor_config_val->is_dict() || processor_config_val->is_string()); |
47 auto processor_config_string = SerializeToJson(*processor_config_val); | 58 auto processor_config_string = SerializeToJson(*processor_config_val); |
48 | 59 |
49 LOG(INFO) << "Creating an instance of " << library_path << "(" | 60 LOG(INFO) << "Creating an instance of " << library_path << "(" |
50 << *processor_config_string << ")"; | 61 << *processor_config_string << ")"; |
51 libraries_.push_back(base::MakeUnique<base::ScopedNativeLibrary>( | 62 libraries_.push_back(base::MakeUnique<base::ScopedNativeLibrary>( |
52 base::FilePath(library_path))); | 63 base::FilePath(library_path))); |
53 CHECK(libraries_.back()->is_valid()) | 64 CHECK(libraries_.back()->is_valid()) |
54 << "Could not open post processing library " << library_path; | 65 << "Could not open post processing library " << library_path; |
55 CreatePostProcessor create = reinterpret_cast<CreatePostProcessor>( | 66 CreatePostProcessor create = reinterpret_cast<CreatePostProcessor>( |
56 libraries_.back()->GetFunctionPointer(kSoCreateFunction)); | 67 libraries_.back()->GetFunctionPointer(kSoCreateFunction)); |
57 | 68 |
58 CHECK(create) << "Could not find " << kSoCreateFunction << "() in " | 69 CHECK(create) << "Could not find " << kSoCreateFunction << "() in " |
59 << library_path; | 70 << library_path; |
60 processors_.push_back( | 71 processors_.push_back( |
61 base::WrapUnique(create(*processor_config_string, channels))); | 72 base::WrapUnique(create(*processor_config_string, channels))); |
62 } | 73 } |
63 } | 74 } |
64 | 75 |
65 PostProcessingPipeline::~PostProcessingPipeline() = default; | 76 PostProcessingPipelineImpl::~PostProcessingPipelineImpl() = default; |
66 | 77 |
67 int PostProcessingPipeline::ProcessFrames(const std::vector<float*>& data, | 78 int PostProcessingPipelineImpl::ProcessFrames(const std::vector<float*>& data, |
68 int num_frames, | 79 int num_frames, |
69 float current_volume, | 80 float current_multiplier, |
70 bool is_silence) { | 81 bool is_silence) { |
71 DCHECK_NE(sample_rate_, kNoSampleRate); | 82 DCHECK_NE(sample_rate_, kNoSampleRate); |
72 if (is_silence) { | 83 if (is_silence) { |
73 if (!IsRinging()) { | 84 if (!IsRinging()) { |
74 return total_delay_frames_; // Output will be silence. | 85 return total_delay_frames_; // Output will be silence. |
75 } | 86 } |
76 silence_frames_processed_ += num_frames; | 87 silence_frames_processed_ += num_frames; |
77 } else { | 88 } else { |
78 silence_frames_processed_ = 0; | 89 silence_frames_processed_ = 0; |
79 } | 90 } |
80 | 91 |
| 92 UpdateCastVolume(current_multiplier); |
| 93 |
81 total_delay_frames_ = 0; | 94 total_delay_frames_ = 0; |
82 for (auto& processor : processors_) { | 95 for (auto& processor : processors_) { |
83 total_delay_frames_ += | 96 total_delay_frames_ += |
84 processor->ProcessFrames(data, num_frames, current_volume); | 97 processor->ProcessFrames(data, num_frames, cast_volume_); |
85 } | 98 } |
86 return total_delay_frames_; | 99 return total_delay_frames_; |
87 } | 100 } |
88 | 101 |
89 bool PostProcessingPipeline::SetSampleRate(int sample_rate) { | 102 bool PostProcessingPipelineImpl::SetSampleRate(int sample_rate) { |
90 sample_rate_ = sample_rate; | 103 sample_rate_ = sample_rate; |
91 bool result = true; | 104 bool result = true; |
92 for (auto& processor : processors_) { | 105 for (auto& processor : processors_) { |
93 result &= processor->SetSampleRate(sample_rate_); | 106 result &= processor->SetSampleRate(sample_rate_); |
94 } | 107 } |
95 ringing_time_in_frames_ = GetRingingTimeInFrames(); | 108 ringing_time_in_frames_ = GetRingingTimeInFrames(); |
96 silence_frames_processed_ = 0; | 109 silence_frames_processed_ = 0; |
97 return result; | 110 return result; |
98 } | 111 } |
99 | 112 |
100 bool PostProcessingPipeline::IsRinging() { | 113 bool PostProcessingPipelineImpl::IsRinging() { |
101 return silence_frames_processed_ < ringing_time_in_frames_; | 114 return silence_frames_processed_ < ringing_time_in_frames_; |
102 } | 115 } |
103 | 116 |
104 int PostProcessingPipeline::GetRingingTimeInFrames() { | 117 int PostProcessingPipelineImpl::GetRingingTimeInFrames() { |
105 int memory_frames = 0; | 118 int memory_frames = 0; |
106 for (auto& processor : processors_) { | 119 for (auto& processor : processors_) { |
107 memory_frames += processor->GetRingingTimeInFrames(); | 120 memory_frames += processor->GetRingingTimeInFrames(); |
108 } | 121 } |
109 return memory_frames; | 122 return memory_frames; |
110 } | 123 } |
111 | 124 |
| 125 void PostProcessingPipelineImpl::UpdateCastVolume(float multiplier) { |
| 126 DCHECK_GE(multiplier, 0.0); |
| 127 |
| 128 if (multiplier == current_multiplier_) { |
| 129 return; |
| 130 } |
| 131 current_multiplier_ = multiplier; |
| 132 float dbfs = std::log10(multiplier) * 20; |
| 133 DCHECK(chromecast::media::VolumeControl::DbFSToVolume); |
| 134 cast_volume_ = chromecast::media::VolumeControl::DbFSToVolume(dbfs); |
| 135 } |
| 136 |
112 } // namespace media | 137 } // namespace media |
113 } // namespace chromecast | 138 } // namespace chromecast |
OLD | NEW |