OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/stream_mixer_alsa.h" | 5 #include "chromecast/media/cma/backend/alsa/stream_mixer_alsa.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <limits> | 9 #include <limits> |
10 #include <unordered_map> | |
10 #include <utility> | 11 #include <utility> |
11 | 12 |
12 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
13 #include "base/memory/scoped_vector.h" | 14 #include "base/memory/scoped_vector.h" |
14 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
15 #include "base/run_loop.h" | 16 #include "base/run_loop.h" |
16 #include "base/threading/thread_task_runner_handle.h" | 17 #include "base/threading/thread_task_runner_handle.h" |
18 #include "base/values.h" | |
17 #include "chromecast/media/cma/backend/alsa/mock_alsa_wrapper.h" | 19 #include "chromecast/media/cma/backend/alsa/mock_alsa_wrapper.h" |
20 #include "chromecast/media/cma/backend/alsa/post_processing_pipeline.h" | |
18 #include "media/audio/audio_device_description.h" | 21 #include "media/audio/audio_device_description.h" |
19 #include "media/base/audio_bus.h" | 22 #include "media/base/audio_bus.h" |
20 #include "media/base/vector_math.h" | 23 #include "media/base/vector_math.h" |
21 #include "testing/gmock/include/gmock/gmock.h" | 24 #include "testing/gmock/include/gmock/gmock.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 25 #include "testing/gtest/include/gtest/gtest.h" |
23 | 26 |
24 using testing::_; | 27 using testing::_; |
25 | 28 |
26 namespace chromecast { | 29 namespace chromecast { |
27 namespace media { | 30 namespace media { |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 1340850135, -1616803932, | 116 1340850135, -1616803932, |
114 -850779335, 1666492408, | 117 -850779335, 1666492408, |
115 1290349909, -492418001, | 118 1290349909, -492418001, |
116 659200170, -542374913, | 119 659200170, -542374913, |
117 -120005682, 1030923147, | 120 -120005682, 1030923147, |
118 -877887021, -870241979, | 121 -877887021, -870241979, |
119 1322678128, -344799975, | 122 1322678128, -344799975, |
120 } | 123 } |
121 }; | 124 }; |
122 | 125 |
126 // Compensate for integer arithmatic errors. | |
127 const int kMaxDelayErrorUs = 2; | |
128 | |
129 const char kDelayModuleSolib[] = "delay.so"; | |
130 | |
131 // Should match # of "processors" blocks below. | |
132 const int kNumPostProcessors = 5; | |
133 const char kTestPipelineJsonTemplate[] = R"json( | |
134 { | |
135 "output_streams": [{ | |
136 "streams": [ "default" ], | |
137 "processors": [{ | |
138 "processor": "%s", | |
139 "config": { "delay": %d } | |
140 }] | |
141 }, { | |
142 "streams": [ "assistant-tts" ], | |
143 "processors": [{ | |
144 "processor": "%s", | |
145 "config": { "delay": %d } | |
146 }] | |
147 }, { | |
148 "streams": [ "communications" ], | |
149 "processors": [] | |
150 }], | |
151 "mix": { | |
152 "processors": [{ | |
153 "processor": "%s", | |
154 "config": { "delay": %d } | |
155 }] | |
156 }, | |
157 "linearize": { | |
158 "processors": [{ | |
159 "processor": "%s", | |
160 "config": { "delay": %d } | |
161 }] | |
162 } | |
163 } | |
164 )json"; | |
kmackay
2017/04/28 21:20:08
There should be a test with multiple processors fo
bshaya
2017/04/28 22:59:30
Done.
| |
165 | |
166 const int kDefaultProcessorDelay = 10; | |
167 const int kTtsProcessorDelay = 100; | |
168 const int kMixProcessorDelay = 1000; | |
169 const int kLinearizeProcessorDelay = 10000; | |
170 | |
123 // Return a scoped pointer filled with the data laid out at |index| above. | 171 // Return a scoped pointer filled with the data laid out at |index| above. |
124 std::unique_ptr<::media::AudioBus> GetTestData(size_t index) { | 172 std::unique_ptr<::media::AudioBus> GetTestData(size_t index) { |
125 CHECK_LT(index, NUM_DATA_SETS); | 173 CHECK_LT(index, NUM_DATA_SETS); |
126 int frames = NUM_SAMPLES / kNumChannels; | 174 int frames = NUM_SAMPLES / kNumChannels; |
127 auto data = ::media::AudioBus::Create(kNumChannels, frames); | 175 auto data = ::media::AudioBus::Create(kNumChannels, frames); |
128 data->FromInterleaved(kTestData[index], frames, kBytesPerSample); | 176 data->FromInterleaved(kTestData[index], frames, kBytesPerSample); |
129 return data; | 177 return data; |
130 } | 178 } |
131 | 179 |
132 class MockInputQueue : public StreamMixerAlsa::InputQueue { | 180 class MockInputQueue : public StreamMixerAlsa::InputQueue { |
133 public: | 181 public: |
134 explicit MockInputQueue(int samples_per_second, | 182 MockInputQueue(int samples_per_second, |
135 const std::string& device_id = | 183 const std::string& device_id = |
136 ::media::AudioDeviceDescription::kDefaultDeviceId) | 184 ::media::AudioDeviceDescription::kDefaultDeviceId) |
137 : paused_(true), | 185 : paused_(true), |
138 samples_per_second_(samples_per_second), | 186 samples_per_second_(samples_per_second), |
139 max_read_size_(kTestMaxReadSize), | 187 max_read_size_(kTestMaxReadSize), |
140 multiplier_(1.0), | 188 multiplier_(1.0), |
141 primary_(true), | 189 primary_(true), |
142 deleting_(false), | 190 deleting_(false), |
143 device_id_(device_id), | 191 device_id_(device_id), |
144 filter_group_(nullptr) { | 192 filter_group_(nullptr) { |
145 ON_CALL(*this, GetResampledData(_, _)).WillByDefault( | 193 ON_CALL(*this, GetResampledData(_, _)).WillByDefault( |
146 testing::Invoke(this, &MockInputQueue::DoGetResampledData)); | 194 testing::Invoke(this, &MockInputQueue::DoGetResampledData)); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 bool primary_; | 282 bool primary_; |
235 bool deleting_; | 283 bool deleting_; |
236 const std::string device_id_; | 284 const std::string device_id_; |
237 FilterGroup* filter_group_; | 285 FilterGroup* filter_group_; |
238 | 286 |
239 std::unique_ptr<::media::AudioBus> data_; | 287 std::unique_ptr<::media::AudioBus> data_; |
240 | 288 |
241 DISALLOW_COPY_AND_ASSIGN(MockInputQueue); | 289 DISALLOW_COPY_AND_ASSIGN(MockInputQueue); |
242 }; | 290 }; |
243 | 291 |
292 class MockPostProcessor : public PostProcessingPipeline { | |
293 public: | |
294 MockPostProcessor(const std::string& name, | |
295 const base::ListValue* filter_description_list, | |
296 int channels) | |
297 : name_(name) { | |
298 CHECK(instances_.insert({name_, this}).second); | |
299 | |
300 if (!filter_description_list) { | |
301 // This happens for PostProcessingPipeline with no post-processors. | |
302 return; | |
303 } | |
304 | |
305 // Parse |filter_description_list| for parameters. | |
306 for (size_t i = 0; i < filter_description_list->GetSize(); ++i) { | |
307 const base::DictionaryValue* description_dict; | |
308 CHECK(filter_description_list->GetDictionary(i, &description_dict)); | |
309 std::string solib; | |
310 CHECK(description_dict->GetString("processor", &solib)); | |
311 // This will initially be called with the actual pipeline on creation. | |
312 // Ignore and wait for the call to ResetPostProcessorsForTest. | |
313 if (solib == kDelayModuleSolib) { | |
314 const base::DictionaryValue* processor_config_dict; | |
315 CHECK( | |
316 description_dict->GetDictionary("config", &processor_config_dict)); | |
317 int module_delay; | |
318 CHECK(processor_config_dict->GetInteger("delay", &module_delay)); | |
319 rendering_delay_ += module_delay; | |
320 processor_config_dict->GetBoolean("ringing", &ringing_); | |
321 } | |
322 } | |
323 ON_CALL(*this, ProcessFrames(_, _, _, _)) | |
324 .WillByDefault( | |
325 testing::Invoke(this, &MockPostProcessor::DoProcessFrames)); | |
326 } | |
327 ~MockPostProcessor() override { instances_.erase(name_); } | |
328 MOCK_METHOD4(ProcessFrames, | |
329 int(const std::vector<float*>& data, | |
330 int num_frames, | |
331 float current_volume, | |
332 bool is_silence)); | |
333 bool SetSampleRate(int sample_rate) override { return false; } | |
334 bool IsRinging() override { return ringing_; } | |
335 std::string name() const { return name_; } | |
336 | |
337 static std::unordered_map<std::string, MockPostProcessor*>* instances() { | |
338 return &instances_; | |
339 } | |
340 | |
341 private: | |
342 int DoProcessFrames(const std::vector<float*>& data, | |
343 int num_frames, | |
344 float current_volume, | |
345 bool is_sience) { | |
346 return rendering_delay_; | |
347 } | |
348 | |
349 static std::unordered_map<std::string, MockPostProcessor*> instances_; | |
350 std::string name_; | |
351 int rendering_delay_ = 0; | |
352 bool ringing_ = false; | |
353 | |
354 DISALLOW_COPY_AND_ASSIGN(MockPostProcessor); | |
355 }; | |
356 | |
357 std::unordered_map<std::string, MockPostProcessor*> | |
358 MockPostProcessor::instances_; | |
359 | |
244 // Given |inputs|, returns mixed audio data according to the mixing method used | 360 // Given |inputs|, returns mixed audio data according to the mixing method used |
245 // by the mixer. | 361 // by the mixer. |
246 std::unique_ptr<::media::AudioBus> GetMixedAudioData( | 362 std::unique_ptr<::media::AudioBus> GetMixedAudioData( |
247 const std::vector<testing::StrictMock<MockInputQueue>*>& inputs) { | 363 const std::vector<testing::StrictMock<MockInputQueue>*>& inputs) { |
248 int read_size = std::numeric_limits<int>::max(); | 364 int read_size = std::numeric_limits<int>::max(); |
249 for (auto* input : inputs) { | 365 for (auto* input : inputs) { |
250 CHECK(input); | 366 CHECK(input); |
251 read_size = std::min(input->MaxReadSize(), read_size); | 367 read_size = std::min(input->MaxReadSize(), read_size); |
252 } | 368 } |
253 | 369 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
290 ASSERT_EQ(expected.channels(), actual.channels()); | 406 ASSERT_EQ(expected.channels(), actual.channels()); |
291 ASSERT_EQ(expected.frames(), actual.frames()); | 407 ASSERT_EQ(expected.frames(), actual.frames()); |
292 for (int c = 0; c < expected.channels(); ++c) { | 408 for (int c = 0; c < expected.channels(); ++c) { |
293 const float* expected_data = expected.channel(c); | 409 const float* expected_data = expected.channel(c); |
294 const float* actual_data = actual.channel(c); | 410 const float* actual_data = actual.channel(c); |
295 for (int f = 0; f < expected.frames(); ++f) | 411 for (int f = 0; f < expected.frames(); ++f) |
296 ASSERT_FLOAT_EQ(*expected_data++, *actual_data++) << c << " " << f; | 412 ASSERT_FLOAT_EQ(*expected_data++, *actual_data++) << c << " " << f; |
297 } | 413 } |
298 } | 414 } |
299 | 415 |
416 // Check that MediaPipelineBackendAlsa::RenderingDelay.delay_microseconds is | |
417 // within kMaxDelayErrorUs of |delay| | |
418 MATCHER_P2(MatchDelay, delay, id, "") { | |
419 bool result = std::abs(arg.delay_microseconds - delay) < kMaxDelayErrorUs; | |
420 if (!result) { | |
421 LOG(ERROR) << "Expected delay_microseconds for " << id << " to be " << delay | |
422 << " but got " << arg.delay_microseconds; | |
423 } | |
424 return result; | |
425 } | |
426 | |
427 // Convert a number of frames at kTestSamplesPerSecond to microseconds | |
428 int64_t FramesToDelayUs(int64_t frames) { | |
429 return frames * base::Time::kMicrosecondsPerSecond / kTestSamplesPerSecond; | |
430 } | |
431 | |
300 } // namespace | 432 } // namespace |
301 | 433 |
434 std::unique_ptr<PostProcessingPipeline> PostProcessingPipeline::Create( | |
435 const std::string& name, | |
436 const base::ListValue* filter_description_list, | |
437 int channels) { | |
438 return base::MakeUnique<testing::NiceMock<MockPostProcessor>>( | |
439 name, filter_description_list, channels); | |
440 } | |
441 | |
302 class StreamMixerAlsaTest : public testing::Test { | 442 class StreamMixerAlsaTest : public testing::Test { |
303 protected: | 443 protected: |
304 StreamMixerAlsaTest() | 444 StreamMixerAlsaTest() |
305 : message_loop_(new base::MessageLoop()), | 445 : message_loop_(new base::MessageLoop()), |
306 mock_alsa_(new testing::NiceMock<MockAlsaWrapper>()) { | 446 mock_alsa_(new testing::NiceMock<MockAlsaWrapper>()) { |
307 StreamMixerAlsa::MakeSingleThreadedForTest(); | 447 StreamMixerAlsa::MakeSingleThreadedForTest(); |
308 StreamMixerAlsa::Get()->DisablePostProcessingForTest(); | 448 char test_pipeline_json[sizeof(kTestPipelineJsonTemplate) * 2]; |
kmackay
2017/04/28 21:20:08
The size calculation here seems a bit ad-hoc. Why
bshaya
2017/04/28 22:59:30
Done.
| |
449 snprintf(test_pipeline_json, sizeof(test_pipeline_json), | |
450 kTestPipelineJsonTemplate, kDelayModuleSolib, | |
451 kDefaultProcessorDelay, kDelayModuleSolib, kTtsProcessorDelay, | |
452 kDelayModuleSolib, kMixProcessorDelay, kDelayModuleSolib, | |
453 kLinearizeProcessorDelay); | |
454 StreamMixerAlsa::Get()->ResetPostProcessorsForTest(test_pipeline_json); | |
455 CHECK_EQ(MockPostProcessor::instances()->size(), | |
456 static_cast<size_t>(kNumPostProcessors)); | |
309 StreamMixerAlsa::Get()->SetAlsaWrapperForTest(base::WrapUnique(mock_alsa_)); | 457 StreamMixerAlsa::Get()->SetAlsaWrapperForTest(base::WrapUnique(mock_alsa_)); |
310 } | 458 } |
311 | 459 |
312 ~StreamMixerAlsaTest() override { | 460 ~StreamMixerAlsaTest() override { |
313 StreamMixerAlsa::Get()->ClearInputsForTest(); | 461 StreamMixerAlsa::Get()->ClearInputsForTest(); |
314 StreamMixerAlsa::Get()->SetAlsaWrapperForTest(nullptr); | 462 StreamMixerAlsa::Get()->SetAlsaWrapperForTest(nullptr); |
315 } | 463 } |
316 | 464 |
317 MockAlsaWrapper* mock_alsa() { return mock_alsa_; } | 465 MockAlsaWrapper* mock_alsa() { return mock_alsa_; } |
318 | 466 |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
796 EXPECT_CALL(*inputs[0], AfterWriteFrames(_)); | 944 EXPECT_CALL(*inputs[0], AfterWriteFrames(_)); |
797 EXPECT_CALL(*inputs[1], GetResampledData(_, _)).Times(0); | 945 EXPECT_CALL(*inputs[1], GetResampledData(_, _)).Times(0); |
798 EXPECT_CALL(*inputs[1], VolumeScaleAccumulate(_, _, _, _)).Times(0); | 946 EXPECT_CALL(*inputs[1], VolumeScaleAccumulate(_, _, _, _)).Times(0); |
799 EXPECT_CALL(*inputs[1], OnSkipped()); | 947 EXPECT_CALL(*inputs[1], OnSkipped()); |
800 EXPECT_CALL(*inputs[1], AfterWriteFrames(_)); | 948 EXPECT_CALL(*inputs[1], AfterWriteFrames(_)); |
801 | 949 |
802 EXPECT_CALL(*mock_alsa(), PcmWritei(_, _, kNumFrames)).Times(1); | 950 EXPECT_CALL(*mock_alsa(), PcmWritei(_, _, kNumFrames)).Times(1); |
803 mixer->WriteFramesForTest(); | 951 mixer->WriteFramesForTest(); |
804 } | 952 } |
805 | 953 |
954 #define EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(map, name, times, frames, \ | |
955 silence) \ | |
956 do { \ | |
957 auto itr = map->find(name); \ | |
958 CHECK(itr != map->end()) << "Could not find processor for " << name; \ | |
959 EXPECT_CALL(*(itr->second), ProcessFrames(_, frames, _, silence)) \ | |
960 .Times(times); \ | |
961 } while (0); | |
962 | |
963 TEST_F(StreamMixerAlsaTest, PostProcessorDelayListedDeviceId) { | |
964 int common_delay = kMixProcessorDelay + kLinearizeProcessorDelay; | |
965 std::vector<testing::StrictMock<MockInputQueue>*> inputs; | |
966 std::vector<int64_t> delays; | |
967 inputs.push_back(new testing::StrictMock<MockInputQueue>( | |
968 kTestSamplesPerSecond, "default")); | |
969 delays.push_back(common_delay + kDefaultProcessorDelay); | |
970 | |
971 inputs.push_back(new testing::StrictMock<MockInputQueue>( | |
972 kTestSamplesPerSecond, "communications")); | |
973 delays.push_back(common_delay); | |
974 | |
975 inputs.push_back(new testing::StrictMock<MockInputQueue>( | |
976 kTestSamplesPerSecond, "assistant-tts")); | |
977 delays.push_back(common_delay + kTtsProcessorDelay); | |
978 | |
979 // Convert delay from frames to microseconds. | |
980 std::transform(delays.begin(), delays.end(), delays.begin(), | |
981 &FramesToDelayUs); | |
982 | |
983 const int kNumFrames = 10; | |
984 for (auto* input : inputs) { | |
985 input->SetMaxReadSize(kNumFrames); | |
986 input->SetPaused(false); | |
987 } | |
988 | |
989 StreamMixerAlsa* mixer = StreamMixerAlsa::Get(); | |
990 for (size_t i = 0; i < inputs.size(); ++i) { | |
991 EXPECT_CALL(*inputs[i], Initialize(_)).Times(1); | |
992 mixer->AddInput(base::WrapUnique(inputs[i])); | |
993 } | |
994 | |
995 mock_alsa()->set_avail(4086); | |
996 | |
997 auto* post_processors = MockPostProcessor::instances(); | |
998 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "default", 1, | |
999 kNumFrames, false); | |
1000 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "mix", 1, kNumFrames, | |
1001 false); | |
1002 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "linearize", 1, | |
1003 kNumFrames, false); | |
1004 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "communications", 1, | |
1005 kNumFrames, false); | |
1006 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "assistant-tts", 1, | |
1007 kNumFrames, false); | |
1008 | |
1009 // Poll the inputs for data. Each input will get a different | |
1010 // rendering delay based on their device type. | |
1011 for (size_t i = 0; i < inputs.size(); ++i) { | |
1012 EXPECT_CALL(*inputs[i], GetResampledData(_, kNumFrames)); | |
1013 EXPECT_CALL(*inputs[i], VolumeScaleAccumulate(_, _, kNumFrames, _)) | |
1014 .Times(kNumChannels); | |
1015 EXPECT_CALL(*inputs[i], AfterWriteFrames( | |
1016 MatchDelay(delays[i], inputs[i]->device_id()))); | |
1017 } | |
1018 mixer->WriteFramesForTest(); | |
1019 } | |
1020 | |
1021 TEST_F(StreamMixerAlsaTest, PostProcessorDelayUnlistedDevice) { | |
1022 const std::string device_id = "not-a-device-id"; | |
1023 testing::StrictMock<MockInputQueue>* input = | |
1024 new testing::StrictMock<MockInputQueue>(kTestSamplesPerSecond, device_id); | |
1025 | |
1026 // Delay should be based on default processor | |
1027 int64_t delay = FramesToDelayUs( | |
1028 kDefaultProcessorDelay + kLinearizeProcessorDelay + kMixProcessorDelay); | |
1029 const int kNumFrames = 10; | |
1030 input->SetMaxReadSize(kNumFrames); | |
1031 input->SetPaused(false); | |
1032 | |
1033 auto* post_processors = MockPostProcessor::instances(); | |
1034 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "default", 1, | |
1035 kNumFrames, false); | |
1036 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "mix", 1, kNumFrames, | |
1037 false); | |
1038 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "linearize", 1, | |
1039 kNumFrames, false); | |
1040 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "communications", 0, | |
1041 _, _); | |
1042 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "assistant-tts", 0, | |
1043 _, _); | |
1044 | |
1045 StreamMixerAlsa* mixer = StreamMixerAlsa::Get(); | |
1046 EXPECT_CALL(*input, Initialize(_)); | |
1047 mixer->AddInput(base::WrapUnique(input)); | |
1048 | |
1049 EXPECT_CALL(*input, GetResampledData(_, kNumFrames)); | |
1050 EXPECT_CALL(*input, VolumeScaleAccumulate(_, _, kNumFrames, _)) | |
1051 .Times(kNumChannels); | |
1052 EXPECT_CALL(*input, AfterWriteFrames(MatchDelay(delay, device_id))); | |
1053 mixer->WriteFramesForTest(); | |
1054 } | |
1055 | |
1056 TEST_F(StreamMixerAlsaTest, PostProcessorRingingWithoutInput) { | |
1057 const char kTestPipelineJson[] = R"json( | |
1058 { | |
1059 "output_streams": [{ | |
1060 "streams": [ "default" ], | |
1061 "processors": [{ | |
1062 "processor": "%s", | |
1063 "config": { "delay": 0, "ringing": true} | |
1064 }] | |
1065 }, { | |
1066 "streams": [ "assistant-tts" ], | |
1067 "processors": [{ | |
1068 "processor": "%s", | |
1069 "config": { "delay": 0, "ringing": true} | |
1070 }] | |
1071 }] | |
1072 } | |
1073 )json"; | |
1074 | |
1075 const int kNumFrames = 32; | |
1076 testing::NiceMock<MockInputQueue>* input = | |
1077 new testing::NiceMock<MockInputQueue>(kTestSamplesPerSecond, "default"); | |
1078 input->SetMaxReadSize(kNumFrames); | |
1079 input->SetPaused(false); | |
1080 | |
1081 StreamMixerAlsa* mixer = StreamMixerAlsa::Get(); | |
1082 char test_pipeline_json[sizeof(kTestPipelineJson) * 2]; | |
kmackay
2017/04/28 21:20:08
base::StringPrintf()?
bshaya
2017/04/28 22:59:30
Done.
| |
1083 snprintf(test_pipeline_json, sizeof(test_pipeline_json), kTestPipelineJson, | |
1084 kDelayModuleSolib, kDelayModuleSolib); | |
1085 mixer->ResetPostProcessorsForTest(test_pipeline_json); | |
1086 mixer->AddInput(base::WrapUnique(input)); | |
1087 | |
1088 // "mix" + "linearize" should be automatic | |
1089 CHECK_EQ(MockPostProcessor::instances()->size(), 4u); | |
1090 | |
1091 mock_alsa()->set_avail(4086); | |
1092 | |
1093 auto* post_processors = MockPostProcessor::instances(); | |
1094 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "default", 1, | |
1095 kNumFrames, false); | |
1096 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "mix", 1, kNumFrames, | |
1097 false); | |
1098 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "linearize", 1, | |
1099 kNumFrames, false); | |
1100 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "assistant-tts", 1, | |
1101 kNumFrames, true); | |
1102 | |
1103 mixer->WriteFramesForTest(); | |
1104 } | |
1105 | |
1106 TEST_F(StreamMixerAlsaTest, PostProcessorProvidesDefaultPipeline) { | |
1107 StreamMixerAlsa* mixer = StreamMixerAlsa::Get(); | |
1108 mixer->ResetPostProcessorsForTest(""); | |
1109 | |
1110 auto* instances = MockPostProcessor::instances(); | |
1111 CHECK(instances->find("default") != instances->end()); | |
1112 CHECK(instances->find("mix") != instances->end()); | |
1113 CHECK(instances->find("linearize") != instances->end()); | |
1114 CHECK_EQ(MockPostProcessor::instances()->size(), 3u); | |
1115 } | |
1116 | |
1117 TEST_F(StreamMixerAlsaTest, InvalidStreamTypeCrashes) { | |
1118 const char json[] = R"json( | |
1119 { | |
1120 "output_streams": [{ | |
1121 "streams": [ "foobar" ], | |
1122 "processors": [{ | |
1123 "processor": "%s", | |
1124 "config": { "delay": 0 } | |
1125 }] | |
1126 }] | |
1127 } | |
1128 )json"; | |
1129 | |
1130 EXPECT_DEATH(StreamMixerAlsa::Get()->ResetPostProcessorsForTest(json), | |
1131 "foobar is not a stream type"); | |
1132 } | |
1133 | |
806 } // namespace media | 1134 } // namespace media |
807 } // namespace chromecast | 1135 } // namespace chromecast |
OLD | NEW |