Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(397)

Side by Side Diff: chromecast/media/cma/backend/alsa/stream_mixer_alsa_unittest.cc

Issue 2847673002: [Chromecast] Complete PostProcessingPipeline changes (Closed)
Patch Set: Fix deps Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
17 #include "base/strings/stringprintf.h"
16 #include "base/threading/thread_task_runner_handle.h" 18 #include "base/threading/thread_task_runner_handle.h"
19 #include "base/values.h"
17 #include "chromecast/media/cma/backend/alsa/mock_alsa_wrapper.h" 20 #include "chromecast/media/cma/backend/alsa/mock_alsa_wrapper.h"
21 #include "chromecast/media/cma/backend/alsa/post_processing_pipeline.h"
18 #include "media/audio/audio_device_description.h" 22 #include "media/audio/audio_device_description.h"
19 #include "media/base/audio_bus.h" 23 #include "media/base/audio_bus.h"
20 #include "media/base/vector_math.h" 24 #include "media/base/vector_math.h"
21 #include "testing/gmock/include/gmock/gmock.h" 25 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h" 26 #include "testing/gtest/include/gtest/gtest.h"
23 27
24 using testing::_; 28 using testing::_;
25 29
26 namespace chromecast { 30 namespace chromecast {
27 namespace media { 31 namespace media {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 1340850135, -1616803932, 117 1340850135, -1616803932,
114 -850779335, 1666492408, 118 -850779335, 1666492408,
115 1290349909, -492418001, 119 1290349909, -492418001,
116 659200170, -542374913, 120 659200170, -542374913,
117 -120005682, 1030923147, 121 -120005682, 1030923147,
118 -877887021, -870241979, 122 -877887021, -870241979,
119 1322678128, -344799975, 123 1322678128, -344799975,
120 } 124 }
121 }; 125 };
122 126
127 // Compensate for integer arithmatic errors.
128 const int kMaxDelayErrorUs = 2;
129
130 const char kDelayModuleSolib[] = "delay.so";
131
132 // Should match # of "processors" blocks below.
133 const int kNumPostProcessors = 5;
134 const char kTestPipelineJsonTemplate[] = R"json(
135 {
136 "output_streams": [{
137 "streams": [ "default" ],
138 "processors": [{
139 "processor": "%s",
140 "config": { "delay": %d }
141 }]
142 }, {
143 "streams": [ "assistant-tts" ],
144 "processors": [{
145 "processor": "%s",
146 "config": { "delay": %d }
147 }]
148 }, {
149 "streams": [ "communications" ],
150 "processors": []
151 }],
152 "mix": {
153 "processors": [{
154 "processor": "%s",
155 "config": { "delay": %d }
156 }]
157 },
158 "linearize": {
159 "processors": [{
160 "processor": "%s",
161 "config": { "delay": %d }
162 }]
163 }
164 }
165 )json";
166
167 const int kDefaultProcessorDelay = 10;
168 const int kTtsProcessorDelay = 100;
169 const int kMixProcessorDelay = 1000;
170 const int kLinearizeProcessorDelay = 10000;
171
123 // Return a scoped pointer filled with the data laid out at |index| above. 172 // Return a scoped pointer filled with the data laid out at |index| above.
124 std::unique_ptr<::media::AudioBus> GetTestData(size_t index) { 173 std::unique_ptr<::media::AudioBus> GetTestData(size_t index) {
125 CHECK_LT(index, NUM_DATA_SETS); 174 CHECK_LT(index, NUM_DATA_SETS);
126 int frames = NUM_SAMPLES / kNumChannels; 175 int frames = NUM_SAMPLES / kNumChannels;
127 auto data = ::media::AudioBus::Create(kNumChannels, frames); 176 auto data = ::media::AudioBus::Create(kNumChannels, frames);
128 data->FromInterleaved(kTestData[index], frames, kBytesPerSample); 177 data->FromInterleaved(kTestData[index], frames, kBytesPerSample);
129 return data; 178 return data;
130 } 179 }
131 180
132 class MockInputQueue : public StreamMixerAlsa::InputQueue { 181 class MockInputQueue : public StreamMixerAlsa::InputQueue {
133 public: 182 public:
134 explicit MockInputQueue(int samples_per_second, 183 MockInputQueue(int samples_per_second,
135 const std::string& device_id = 184 const std::string& device_id =
136 ::media::AudioDeviceDescription::kDefaultDeviceId) 185 ::media::AudioDeviceDescription::kDefaultDeviceId)
137 : paused_(true), 186 : paused_(true),
138 samples_per_second_(samples_per_second), 187 samples_per_second_(samples_per_second),
139 max_read_size_(kTestMaxReadSize), 188 max_read_size_(kTestMaxReadSize),
140 multiplier_(1.0), 189 multiplier_(1.0),
141 primary_(true), 190 primary_(true),
142 deleting_(false), 191 deleting_(false),
143 device_id_(device_id), 192 device_id_(device_id),
144 filter_group_(nullptr) { 193 filter_group_(nullptr) {
145 ON_CALL(*this, GetResampledData(_, _)).WillByDefault( 194 ON_CALL(*this, GetResampledData(_, _)).WillByDefault(
146 testing::Invoke(this, &MockInputQueue::DoGetResampledData)); 195 testing::Invoke(this, &MockInputQueue::DoGetResampledData));
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 bool primary_; 283 bool primary_;
235 bool deleting_; 284 bool deleting_;
236 const std::string device_id_; 285 const std::string device_id_;
237 FilterGroup* filter_group_; 286 FilterGroup* filter_group_;
238 287
239 std::unique_ptr<::media::AudioBus> data_; 288 std::unique_ptr<::media::AudioBus> data_;
240 289
241 DISALLOW_COPY_AND_ASSIGN(MockInputQueue); 290 DISALLOW_COPY_AND_ASSIGN(MockInputQueue);
242 }; 291 };
243 292
293 class MockPostProcessor : public PostProcessingPipeline {
294 public:
295 MockPostProcessor(const std::string& name,
296 const base::ListValue* filter_description_list,
297 int channels)
298 : name_(name) {
299 CHECK(instances_.insert({name_, this}).second);
300
301 if (!filter_description_list) {
302 // This happens for PostProcessingPipeline with no post-processors.
303 return;
304 }
305
306 // Parse |filter_description_list| for parameters.
307 for (size_t i = 0; i < filter_description_list->GetSize(); ++i) {
308 const base::DictionaryValue* description_dict;
309 CHECK(filter_description_list->GetDictionary(i, &description_dict));
310 std::string solib;
311 CHECK(description_dict->GetString("processor", &solib));
312 // This will initially be called with the actual pipeline on creation.
313 // Ignore and wait for the call to ResetPostProcessorsForTest.
314 if (solib == kDelayModuleSolib) {
315 const base::DictionaryValue* processor_config_dict;
316 CHECK(
317 description_dict->GetDictionary("config", &processor_config_dict));
318 int module_delay;
319 CHECK(processor_config_dict->GetInteger("delay", &module_delay));
320 rendering_delay_ += module_delay;
321 processor_config_dict->GetBoolean("ringing", &ringing_);
322 }
323 }
324 ON_CALL(*this, ProcessFrames(_, _, _, _))
325 .WillByDefault(
326 testing::Invoke(this, &MockPostProcessor::DoProcessFrames));
327 }
328 ~MockPostProcessor() override { instances_.erase(name_); }
329 MOCK_METHOD4(ProcessFrames,
330 int(const std::vector<float*>& data,
331 int num_frames,
332 float current_volume,
333 bool is_silence));
334 bool SetSampleRate(int sample_rate) override { return false; }
335 bool IsRinging() override { return ringing_; }
336 int delay() { return rendering_delay_; }
337 std::string name() const { return name_; }
338
339 static std::unordered_map<std::string, MockPostProcessor*>* instances() {
340 return &instances_;
341 }
342
343 private:
344 int DoProcessFrames(const std::vector<float*>& data,
345 int num_frames,
346 float current_volume,
347 bool is_sience) {
348 return rendering_delay_;
349 }
350
351 static std::unordered_map<std::string, MockPostProcessor*> instances_;
352 std::string name_;
353 int rendering_delay_ = 0;
354 bool ringing_ = false;
355
356 DISALLOW_COPY_AND_ASSIGN(MockPostProcessor);
357 };
358
359 std::unordered_map<std::string, MockPostProcessor*>
360 MockPostProcessor::instances_;
361
244 // Given |inputs|, returns mixed audio data according to the mixing method used 362 // Given |inputs|, returns mixed audio data according to the mixing method used
245 // by the mixer. 363 // by the mixer.
246 std::unique_ptr<::media::AudioBus> GetMixedAudioData( 364 std::unique_ptr<::media::AudioBus> GetMixedAudioData(
247 const std::vector<testing::StrictMock<MockInputQueue>*>& inputs) { 365 const std::vector<testing::StrictMock<MockInputQueue>*>& inputs) {
248 int read_size = std::numeric_limits<int>::max(); 366 int read_size = std::numeric_limits<int>::max();
249 for (auto* input : inputs) { 367 for (auto* input : inputs) {
250 CHECK(input); 368 CHECK(input);
251 read_size = std::min(input->MaxReadSize(), read_size); 369 read_size = std::min(input->MaxReadSize(), read_size);
252 } 370 }
253 371
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 ASSERT_EQ(expected.channels(), actual.channels()); 408 ASSERT_EQ(expected.channels(), actual.channels());
291 ASSERT_EQ(expected.frames(), actual.frames()); 409 ASSERT_EQ(expected.frames(), actual.frames());
292 for (int c = 0; c < expected.channels(); ++c) { 410 for (int c = 0; c < expected.channels(); ++c) {
293 const float* expected_data = expected.channel(c); 411 const float* expected_data = expected.channel(c);
294 const float* actual_data = actual.channel(c); 412 const float* actual_data = actual.channel(c);
295 for (int f = 0; f < expected.frames(); ++f) 413 for (int f = 0; f < expected.frames(); ++f)
296 ASSERT_FLOAT_EQ(*expected_data++, *actual_data++) << c << " " << f; 414 ASSERT_FLOAT_EQ(*expected_data++, *actual_data++) << c << " " << f;
297 } 415 }
298 } 416 }
299 417
418 // Check that MediaPipelineBackendAlsa::RenderingDelay.delay_microseconds is
419 // within kMaxDelayErrorUs of |delay|
420 MATCHER_P2(MatchDelay, delay, id, "") {
421 bool result = std::abs(arg.delay_microseconds - delay) < kMaxDelayErrorUs;
422 if (!result) {
423 LOG(ERROR) << "Expected delay_microseconds for " << id << " to be " << delay
424 << " but got " << arg.delay_microseconds;
425 }
426 return result;
427 }
428
429 // Convert a number of frames at kTestSamplesPerSecond to microseconds
430 int64_t FramesToDelayUs(int64_t frames) {
431 return frames * base::Time::kMicrosecondsPerSecond / kTestSamplesPerSecond;
432 }
433
300 } // namespace 434 } // namespace
301 435
436 std::unique_ptr<PostProcessingPipeline> PostProcessingPipeline::Create(
437 const std::string& name,
438 const base::ListValue* filter_description_list,
439 int channels) {
440 return base::MakeUnique<testing::NiceMock<MockPostProcessor>>(
441 name, filter_description_list, channels);
442 }
443
302 class StreamMixerAlsaTest : public testing::Test { 444 class StreamMixerAlsaTest : public testing::Test {
303 protected: 445 protected:
304 StreamMixerAlsaTest() 446 StreamMixerAlsaTest()
305 : message_loop_(new base::MessageLoop()), 447 : message_loop_(new base::MessageLoop()),
306 mock_alsa_(new testing::NiceMock<MockAlsaWrapper>()) { 448 mock_alsa_(new testing::NiceMock<MockAlsaWrapper>()) {
307 StreamMixerAlsa::MakeSingleThreadedForTest(); 449 StreamMixerAlsa::MakeSingleThreadedForTest();
308 StreamMixerAlsa::Get()->DisablePostProcessingForTest(); 450 std::string test_pipeline_json = base::StringPrintf(
451 kTestPipelineJsonTemplate, kDelayModuleSolib, kDefaultProcessorDelay,
452 kDelayModuleSolib, kTtsProcessorDelay, kDelayModuleSolib,
453 kMixProcessorDelay, kDelayModuleSolib, 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
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 std::string test_pipeline_json = base::StringPrintf(
1083 kTestPipelineJson, kDelayModuleSolib, kDelayModuleSolib);
1084 mixer->ResetPostProcessorsForTest(test_pipeline_json);
1085 mixer->AddInput(base::WrapUnique(input));
1086
1087 // "mix" + "linearize" should be automatic
1088 CHECK_EQ(MockPostProcessor::instances()->size(), 4u);
1089
1090 mock_alsa()->set_avail(4086);
1091
1092 auto* post_processors = MockPostProcessor::instances();
1093 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "default", 1,
1094 kNumFrames, false);
1095 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "mix", 1, kNumFrames,
1096 false);
1097 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "linearize", 1,
1098 kNumFrames, false);
1099 EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "assistant-tts", 1,
1100 kNumFrames, true);
1101
1102 mixer->WriteFramesForTest();
1103 }
1104
1105 TEST_F(StreamMixerAlsaTest, PostProcessorProvidesDefaultPipeline) {
1106 StreamMixerAlsa* mixer = StreamMixerAlsa::Get();
1107 mixer->ResetPostProcessorsForTest("{}");
1108
1109 auto* instances = MockPostProcessor::instances();
1110 CHECK(instances->find("default") != instances->end());
1111 CHECK(instances->find("mix") != instances->end());
1112 CHECK(instances->find("linearize") != instances->end());
1113 CHECK_EQ(MockPostProcessor::instances()->size(), 3u);
1114 }
1115
1116 TEST_F(StreamMixerAlsaTest, InvalidStreamTypeCrashes) {
1117 const char json[] = R"json(
1118 {
1119 "output_streams": [{
1120 "streams": [ "foobar" ],
1121 "processors": [{
1122 "processor": "dont_care.so",
1123 "config": { "delay": 0 }
1124 }]
1125 }]
1126 }
1127 )json";
1128
1129 EXPECT_DEATH(StreamMixerAlsa::Get()->ResetPostProcessorsForTest(json),
1130 "foobar is not a stream type");
1131 }
1132
1133 TEST_F(StreamMixerAlsaTest, BadJsonCrashes) {
1134 const std::string json("{{");
1135 EXPECT_DEATH(StreamMixerAlsa::Get()->ResetPostProcessorsForTest(json),
1136 "Invalid JSON");
1137 }
1138
1139 TEST_F(StreamMixerAlsaTest, MultiplePostProcessorsInOneStream) {
1140 const char kJsonTemplate[] = R"json(
1141 {
1142 "output_streams": [{
1143 "streams": [ "default" ],
1144 "processors": [{
1145 "processor": "%s",
1146 "config": { "delay": 10 }
1147 }, {
1148 "processor": "%s",
1149 "config": { "delay": 100 }
1150 }]
1151 }],
1152 "mix": {
1153 "processors": [{
1154 "processor": "%s",
1155 "config": { "delay": 1000 }
1156 }, {
1157 "processor": "%s",
1158 "config": { "delay": 10000 }
1159 }]
1160 }
1161 }
1162 )json";
1163
1164 std::string json =
1165 base::StringPrintf(kJsonTemplate, kDelayModuleSolib, kDelayModuleSolib,
1166 kDelayModuleSolib, kDelayModuleSolib);
1167
1168 StreamMixerAlsa* mixer = StreamMixerAlsa::Get();
1169 mixer->ResetPostProcessorsForTest(json);
1170
1171 // "mix" + "linearize" + "default"
1172 CHECK_EQ(MockPostProcessor::instances()->size(), 3u);
1173
1174 auto* post_processors = MockPostProcessor::instances();
1175 CHECK_EQ(post_processors->find("default")->second->delay(), 110);
1176 CHECK_EQ(post_processors->find("mix")->second->delay(), 11000);
1177 CHECK_EQ(post_processors->find("linearize")->second->delay(), 0);
1178 mixer->WriteFramesForTest();
1179 }
1180
806 } // namespace media 1181 } // namespace media
807 } // namespace chromecast 1182 } // namespace chromecast
OLDNEW
« no previous file with comments | « chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc ('k') | chromecast/public/media/audio_post_processor_shlib.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698