Linux: Depend on liberation-fonts package for RPMs.
[chromium-blink-merge.git] / content / browser / media / media_internals_unittest.cc
blob37ac3e050df257eb76ff01e8049d43ba20b87d2f
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/media/media_internals.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/json/json_reader.h"
10 #include "base/run_loop.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/public/test/test_browser_thread_bundle.h"
14 #include "media/audio/audio_parameters.h"
15 #include "media/base/channel_layout.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/gfx/geometry/size.h"
19 namespace {
20 const int kTestComponentID = 0;
21 const char kTestDeviceID[] = "test-device-id";
23 // This class encapsulates a MediaInternals reference. It also has some useful
24 // methods to receive a callback, deserialize its associated data and expect
25 // integer/string values.
26 class MediaInternalsTestBase {
27 public:
28 MediaInternalsTestBase()
29 : media_internals_(content::MediaInternals::GetInstance()) {
31 virtual ~MediaInternalsTestBase() {}
33 protected:
34 // Extracts and deserializes the JSON update data; merges into |update_data_|.
35 void UpdateCallbackImpl(const base::string16& update) {
36 // Each update string looks like "<JavaScript Function Name>({<JSON>});"
37 // or for video capabilities: "<JavaScript Function Name>([{<JSON>}]);".
38 // In the second case we will be able to extract the dictionary if it is the
39 // only member of the list.
40 // To use the JSON reader we need to strip out the JS function name and ().
41 std::string utf8_update = base::UTF16ToUTF8(update);
42 const std::string::size_type first_brace = utf8_update.find('{');
43 const std::string::size_type last_brace = utf8_update.rfind('}');
44 scoped_ptr<base::Value> output_value = base::JSONReader::Read(
45 utf8_update.substr(first_brace, last_brace - first_brace + 1));
46 CHECK(output_value);
48 base::DictionaryValue* output_dict = NULL;
49 CHECK(output_value->GetAsDictionary(&output_dict));
50 update_data_.MergeDictionary(output_dict);
53 void ExpectInt(const std::string& key, int expected_value) const {
54 int actual_value = 0;
55 ASSERT_TRUE(update_data_.GetInteger(key, &actual_value));
56 EXPECT_EQ(expected_value, actual_value);
59 void ExpectString(const std::string& key,
60 const std::string& expected_value) const {
61 std::string actual_value;
62 ASSERT_TRUE(update_data_.GetString(key, &actual_value));
63 EXPECT_EQ(expected_value, actual_value);
66 void ExpectStatus(const std::string& expected_value) const {
67 ExpectString("status", expected_value);
70 void ExpectListOfStrings(const std::string& key,
71 const base::ListValue& expected_list) const {
72 const base::ListValue* actual_list;
73 ASSERT_TRUE(update_data_.GetList(key, &actual_list));
74 const size_t expected_size = expected_list.GetSize();
75 const size_t actual_size = actual_list->GetSize();
76 ASSERT_EQ(expected_size, actual_size);
77 for (size_t i = 0; i < expected_size; ++i) {
78 std::string expected_value, actual_value;
79 ASSERT_TRUE(expected_list.GetString(i, &expected_value));
80 ASSERT_TRUE(actual_list->GetString(i, &actual_value));
81 EXPECT_EQ(expected_value, actual_value);
85 const content::TestBrowserThreadBundle thread_bundle_;
86 base::DictionaryValue update_data_;
87 content::MediaInternals* const media_internals_;
90 } // namespace
92 namespace content {
94 class MediaInternalsVideoCaptureDeviceTest : public testing::Test,
95 public MediaInternalsTestBase {
96 public:
97 MediaInternalsVideoCaptureDeviceTest()
98 : update_cb_(base::Bind(
99 &MediaInternalsVideoCaptureDeviceTest::UpdateCallbackImpl,
100 base::Unretained(this))) {
101 media_internals_->AddUpdateCallback(update_cb_);
104 ~MediaInternalsVideoCaptureDeviceTest() override {
105 media_internals_->RemoveUpdateCallback(update_cb_);
108 protected:
109 MediaInternals::UpdateCallback update_cb_;
112 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
113 defined(OS_ANDROID)
114 TEST_F(MediaInternalsVideoCaptureDeviceTest,
115 AllCaptureApiTypesHaveProperStringRepresentation) {
116 typedef media::VideoCaptureDevice::Name VideoCaptureDeviceName;
117 typedef std::map<VideoCaptureDeviceName::CaptureApiType, std::string>
118 CaptureApiTypeStringMap;
119 CaptureApiTypeStringMap m;
120 #if defined(OS_LINUX)
121 m[VideoCaptureDeviceName::V4L2_SINGLE_PLANE] = "V4L2 SPLANE";
122 m[VideoCaptureDeviceName::V4L2_MULTI_PLANE] = "V4L2 MPLANE";
123 #elif defined(OS_WIN)
124 m[VideoCaptureDeviceName::MEDIA_FOUNDATION] = "Media Foundation";
125 m[VideoCaptureDeviceName::DIRECT_SHOW] = "Direct Show";
126 #elif defined(OS_MACOSX)
127 m[VideoCaptureDeviceName::AVFOUNDATION] = "AV Foundation";
128 m[VideoCaptureDeviceName::QTKIT] = "QTKit";
129 m[VideoCaptureDeviceName::DECKLINK] = "DeckLink";
130 #elif defined(OS_ANDROID)
131 m[VideoCaptureDeviceName::API1] = "Camera API1";
132 m[VideoCaptureDeviceName::API2_LEGACY] = "Camera API2 Legacy";
133 m[VideoCaptureDeviceName::API2_FULL] = "Camera API2 Full";
134 m[VideoCaptureDeviceName::API2_LIMITED] = "Camera API2 Limited";
135 m[VideoCaptureDeviceName::TANGO] = "Tango API";
136 #endif
137 EXPECT_EQ(media::VideoCaptureDevice::Name::API_TYPE_UNKNOWN, m.size());
138 for (CaptureApiTypeStringMap::iterator it = m.begin(); it != m.end(); ++it) {
139 const VideoCaptureDeviceName device_name("dummy", "dummy", it->first);
140 EXPECT_EQ(it->second, device_name.GetCaptureApiTypeString());
143 #endif
145 TEST_F(MediaInternalsVideoCaptureDeviceTest,
146 VideoCaptureFormatStringIsInExpectedFormat) {
147 // Since media internals will send video capture capabilities to JavaScript in
148 // an expected format and there are no public methods for accessing the
149 // resolutions, frame rates or pixel formats, this test checks that the format
150 // has not changed. If the test fails because of the changed format, it should
151 // be updated at the same time as the media internals JS files.
152 const float kFrameRate = 30.0f;
153 const gfx::Size kFrameSize(1280, 720);
154 const media::VideoPixelFormat kPixelFormat =
155 media::PIXEL_FORMAT_I420;
156 const media::VideoPixelStorage kPixelStorage = media::PIXEL_STORAGE_CPU;
157 const media::VideoCaptureFormat capture_format(kFrameSize, kFrameRate,
158 kPixelFormat, kPixelStorage);
159 const std::string expected_string = base::StringPrintf(
160 "(%s)@%.3ffps, pixel format: %s storage: %s.",
161 kFrameSize.ToString().c_str(), kFrameRate,
162 media::VideoPixelFormatToString(kPixelFormat).c_str(),
163 media::VideoCaptureFormat::PixelStorageToString(kPixelStorage).c_str());
164 EXPECT_EQ(expected_string,
165 media::VideoCaptureFormat::ToString(capture_format));
168 TEST_F(MediaInternalsVideoCaptureDeviceTest,
169 NotifyVideoCaptureDeviceCapabilitiesEnumerated) {
170 const int kWidth = 1280;
171 const int kHeight = 720;
172 const float kFrameRate = 30.0f;
173 const media::VideoPixelFormat kPixelFormat =
174 media::PIXEL_FORMAT_I420;
175 const media::VideoCaptureFormat format_hd({kWidth, kHeight},
176 kFrameRate, kPixelFormat);
177 media::VideoCaptureFormats formats{};
178 formats.push_back(format_hd);
179 const media::VideoCaptureDeviceInfo device_info(
180 #if defined(OS_MACOSX)
181 media::VideoCaptureDevice::Name("dummy", "dummy",
182 media::VideoCaptureDevice::Name::QTKIT),
183 #elif defined(OS_WIN)
184 media::VideoCaptureDevice::Name("dummy", "dummy",
185 media::VideoCaptureDevice::Name::DIRECT_SHOW),
186 #elif defined(OS_LINUX)
187 media::VideoCaptureDevice::Name(
188 "dummy", "/dev/dummy",
189 media::VideoCaptureDevice::Name::V4L2_SINGLE_PLANE),
190 #elif defined(OS_ANDROID)
191 media::VideoCaptureDevice::Name("dummy", "dummy",
192 media::VideoCaptureDevice::Name::API2_LEGACY),
193 #else
194 media::VideoCaptureDevice::Name("dummy", "dummy"),
195 #endif
196 formats);
197 media::VideoCaptureDeviceInfos device_infos{};
198 device_infos.push_back(device_info);
200 // When updating video capture capabilities, the update will serialize
201 // a JSON array of objects to string. So here, the |UpdateCallbackImpl| will
202 // deserialize the first object in the array. This means we have to have
203 // exactly one device_info in the |device_infos|.
204 media_internals_->UpdateVideoCaptureDeviceCapabilities(device_infos);
206 #if defined(OS_LINUX)
207 ExpectString("id", "/dev/dummy");
208 #else
209 ExpectString("id", "dummy");
210 #endif
211 ExpectString("name", "dummy");
212 base::ListValue expected_list;
213 expected_list.AppendString(media::VideoCaptureFormat::ToString(format_hd));
214 ExpectListOfStrings("formats", expected_list);
215 #if defined(OS_LINUX)
216 ExpectString("captureApi", "V4L2 SPLANE");
217 #elif defined(OS_WIN)
218 ExpectString("captureApi", "Direct Show");
219 #elif defined(OS_MACOSX)
220 ExpectString("captureApi", "QTKit");
221 #elif defined(OS_ANDROID)
222 ExpectString("captureApi", "Camera API2 Legacy");
223 #endif
226 class MediaInternalsAudioLogTest
227 : public MediaInternalsTestBase,
228 public testing::TestWithParam<media::AudioLogFactory::AudioComponent> {
229 public:
230 MediaInternalsAudioLogTest()
231 : update_cb_(base::Bind(&MediaInternalsAudioLogTest::UpdateCallbackImpl,
232 base::Unretained(this))),
233 test_params_(MakeAudioParams()),
234 test_component_(GetParam()),
235 audio_log_(media_internals_->CreateAudioLog(test_component_)) {
236 media_internals_->AddUpdateCallback(update_cb_);
239 virtual ~MediaInternalsAudioLogTest() {
240 media_internals_->RemoveUpdateCallback(update_cb_);
243 protected:
244 MediaInternals::UpdateCallback update_cb_;
245 const media::AudioParameters test_params_;
246 const media::AudioLogFactory::AudioComponent test_component_;
247 scoped_ptr<media::AudioLog> audio_log_;
249 private:
250 static media::AudioParameters MakeAudioParams() {
251 media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LINEAR,
252 media::CHANNEL_LAYOUT_MONO, 48000, 16, 128);
253 params.set_effects(media::AudioParameters::ECHO_CANCELLER |
254 media::AudioParameters::DUCKING);
255 return params;
259 TEST_P(MediaInternalsAudioLogTest, AudioLogCreateStartStopErrorClose) {
260 audio_log_->OnCreated(kTestComponentID, test_params_, kTestDeviceID);
261 base::RunLoop().RunUntilIdle();
263 ExpectString("channel_layout",
264 media::ChannelLayoutToString(test_params_.channel_layout()));
265 ExpectInt("sample_rate", test_params_.sample_rate());
266 ExpectInt("frames_per_buffer", test_params_.frames_per_buffer());
267 ExpectInt("channels", test_params_.channels());
268 ExpectString("effects", "ECHO_CANCELLER | DUCKING");
269 ExpectString("device_id", kTestDeviceID);
270 ExpectInt("component_id", kTestComponentID);
271 ExpectInt("component_type", test_component_);
272 ExpectStatus("created");
274 // Verify OnStarted().
275 audio_log_->OnStarted(kTestComponentID);
276 base::RunLoop().RunUntilIdle();
277 ExpectStatus("started");
279 // Verify OnStopped().
280 audio_log_->OnStopped(kTestComponentID);
281 base::RunLoop().RunUntilIdle();
282 ExpectStatus("stopped");
284 // Verify OnError().
285 const char kErrorKey[] = "error_occurred";
286 std::string no_value;
287 ASSERT_FALSE(update_data_.GetString(kErrorKey, &no_value));
288 audio_log_->OnError(kTestComponentID);
289 base::RunLoop().RunUntilIdle();
290 ExpectString(kErrorKey, "true");
292 // Verify OnClosed().
293 audio_log_->OnClosed(kTestComponentID);
294 base::RunLoop().RunUntilIdle();
295 ExpectStatus("closed");
298 TEST_P(MediaInternalsAudioLogTest, AudioLogCreateClose) {
299 audio_log_->OnCreated(kTestComponentID, test_params_, kTestDeviceID);
300 base::RunLoop().RunUntilIdle();
301 ExpectStatus("created");
303 audio_log_->OnClosed(kTestComponentID);
304 base::RunLoop().RunUntilIdle();
305 ExpectStatus("closed");
308 INSTANTIATE_TEST_CASE_P(
309 MediaInternalsAudioLogTest, MediaInternalsAudioLogTest, testing::Values(
310 media::AudioLogFactory::AUDIO_INPUT_CONTROLLER,
311 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER,
312 media::AudioLogFactory::AUDIO_OUTPUT_STREAM));
314 } // namespace content