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

Side by Side Diff: media/filters/video_decoder_selector_unittest.cc

Issue 2701203003: media: Prefer decrypting pipeline when CDM is attached (Closed)
Patch Set: comments addressed Created 3 years, 10 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
« no previous file with comments | « media/filters/decrypting_video_decoder.cc ('k') | media/filters/video_frame_stream_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <stddef.h> 5 #include <stddef.h>
6 #include <utility> 6 #include <utility>
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/macros.h" 10 #include "base/macros.h"
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 StrictMock<MockVideoDecoder>* decoder_2_; 157 StrictMock<MockVideoDecoder>* decoder_2_;
158 ScopedVector<VideoDecoder> all_decoders_; 158 ScopedVector<VideoDecoder> all_decoders_;
159 std::unique_ptr<VideoDecoder> selected_decoder_; 159 std::unique_ptr<VideoDecoder> selected_decoder_;
160 160
161 base::MessageLoop message_loop_; 161 base::MessageLoop message_loop_;
162 162
163 private: 163 private:
164 DISALLOW_COPY_AND_ASSIGN(VideoDecoderSelectorTest); 164 DISALLOW_COPY_AND_ASSIGN(VideoDecoderSelectorTest);
165 }; 165 };
166 166
167 // TODO(xhwang): Add kNoCdm tests for clear stream. 167 // Tests for clear streams.
168 168
169 // The stream is not encrypted but we have no clear decoder. No decoder can be
170 // selected.
171 TEST_F(VideoDecoderSelectorTest, ClearStream_NoDecryptor_NoClearDecoder) { 169 TEST_F(VideoDecoderSelectorTest, ClearStream_NoDecryptor_NoClearDecoder) {
172 UseClearStream(); 170 UseClearStream();
173 InitializeDecoderSelector(kNoDecryptor, 0); 171 InitializeDecoderSelector(kNoDecryptor, 0);
174 172
175 EXPECT_CALL(*this, OnDecoderSelected(IsNull(), IsNull())); 173 EXPECT_CALL(*this, OnDecoderSelected(IsNull(), IsNull()));
176 174
177 SelectDecoder(); 175 SelectDecoder();
178 } 176 }
179 177
180 // The stream is not encrypted and we have one clear decoder. The decoder 178 TEST_F(VideoDecoderSelectorTest, ClearStream_NoCdm_OneClearDecoder) {
181 // will be selected.
182 TEST_F(VideoDecoderSelectorTest, ClearStream_NoDecryptor_OneClearDecoder) {
183 UseClearStream(); 179 UseClearStream();
184 InitializeDecoderSelector(kNoDecryptor, 1); 180 InitializeDecoderSelector(kNoCdm, 1);
185 181
186 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _)) 182 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _))
187 .WillOnce(RunCallback<3>(true)); 183 .WillOnce(RunCallback<3>(true));
188 EXPECT_CALL(*this, OnDecoderSelected(decoder_1_, IsNull())); 184 EXPECT_CALL(*this, OnDecoderSelected(decoder_1_, IsNull()));
189 185
190 SelectDecoder(); 186 SelectDecoder();
191 } 187 }
192 188
189 TEST_F(VideoDecoderSelectorTest, Destroy_ClearStream_NoCdm_OneClearDecoder) {
190 UseClearStream();
191 InitializeDecoderSelector(kNoCdm, 1);
192
193 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _));
194
195 SelectDecoderAndDestroy();
196 }
197
198 TEST_F(VideoDecoderSelectorTest, ClearStream_NoCdm_MultipleClearDecoder) {
199 UseClearStream();
200 InitializeDecoderSelector(kNoCdm, 2);
201
202 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _))
203 .WillOnce(RunCallback<3>(false));
204 EXPECT_CALL(*decoder_2_, Initialize(ClearConfig(), _, _, _, _))
205 .WillOnce(RunCallback<3>(true));
206 EXPECT_CALL(*this, OnDecoderSelected(decoder_2_, IsNull()));
207
208 SelectDecoder();
209 }
210
211 TEST_F(VideoDecoderSelectorTest,
212 Destroy_ClearStream_NoCdm_MultipleClearDecoder) {
213 UseClearStream();
214 InitializeDecoderSelector(kNoCdm, 2);
215
216 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _))
217 .WillOnce(RunCallback<3>(false));
218 EXPECT_CALL(*decoder_2_, Initialize(ClearConfig(), _, _, _, _));
219
220 SelectDecoderAndDestroy();
221 }
222
223 TEST_F(VideoDecoderSelectorTest, ClearStream_NoDecryptor_OneClearDecoder) {
224 UseClearStream();
225 InitializeDecoderSelector(kNoDecryptor, 1);
226
227 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _))
228 .WillOnce(RunCallback<3>(false));
229 EXPECT_CALL(*this, OnDecoderSelected(IsNull(), IsNull()));
230
231 SelectDecoder();
232 }
233
193 TEST_F(VideoDecoderSelectorTest, 234 TEST_F(VideoDecoderSelectorTest,
194 Destroy_ClearStream_NoDecryptor_OneClearDecoder) { 235 Destroy_ClearStream_NoDecryptor_OneClearDecoder) {
195 UseClearStream(); 236 UseClearStream();
196 InitializeDecoderSelector(kNoDecryptor, 1); 237 InitializeDecoderSelector(kNoDecryptor, 1);
197 238
198 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _)); 239 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _));
199 240
200 SelectDecoderAndDestroy(); 241 SelectDecoderAndDestroy();
201 } 242 }
202 243
203 // The stream is not encrypted and we have multiple clear decoders. The first
204 // decoder that can decode the input stream will be selected.
205 TEST_F(VideoDecoderSelectorTest, ClearStream_NoDecryptor_MultipleClearDecoder) { 244 TEST_F(VideoDecoderSelectorTest, ClearStream_NoDecryptor_MultipleClearDecoder) {
206 UseClearStream(); 245 UseClearStream();
207 InitializeDecoderSelector(kNoDecryptor, 2); 246 InitializeDecoderSelector(kNoDecryptor, 2);
208 247
209 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _)) 248 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _))
210 .WillOnce(RunCallback<3>(false)); 249 .WillOnce(RunCallback<3>(false));
211 EXPECT_CALL(*decoder_2_, Initialize(ClearConfig(), _, _, _, _)) 250 EXPECT_CALL(*decoder_2_, Initialize(EncryptedConfig(), _, _, _, _))
212 .WillOnce(RunCallback<3>(true)); 251 .WillOnce(RunCallback<3>(true));
213 EXPECT_CALL(*this, OnDecoderSelected(decoder_2_, IsNull())); 252 EXPECT_CALL(*this, OnDecoderSelected(decoder_2_, IsNull()));
214 253
215 SelectDecoder(); 254 SelectDecoder();
216 } 255 }
217 256
218 TEST_F(VideoDecoderSelectorTest, 257 TEST_F(VideoDecoderSelectorTest,
219 Destroy_ClearStream_NoDecryptor_MultipleClearDecoder) { 258 Destroy_ClearStream_NoDecryptor_MultipleClearDecoder) {
220 UseClearStream(); 259 UseClearStream();
221 InitializeDecoderSelector(kNoDecryptor, 2); 260 InitializeDecoderSelector(kNoDecryptor, 2);
222 261
223 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _)) 262 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _))
224 .WillOnce(RunCallback<3>(false)); 263 .WillOnce(RunCallback<3>(false));
225 EXPECT_CALL(*decoder_2_, Initialize(ClearConfig(), _, _, _, _)); 264 EXPECT_CALL(*decoder_2_, Initialize(EncryptedConfig(), _, _, _, _));
226 265
227 SelectDecoderAndDestroy(); 266 SelectDecoderAndDestroy();
228 } 267 }
229 268
230 // There is a decryptor but the stream is not encrypted. The decoder will be 269 TEST_F(VideoDecoderSelectorTest, ClearStream_DecryptOnly) {
231 // selected.
232 TEST_F(VideoDecoderSelectorTest, ClearStream_HasDecryptor) {
233 UseClearStream(); 270 UseClearStream();
234 InitializeDecoderSelector(kDecryptOnly, 1); 271 InitializeDecoderSelector(kDecryptOnly, 1);
235 272
236 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _)) 273 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _))
237 .WillOnce(RunCallback<3>(true)); 274 .WillOnce(RunCallback<3>(true));
238 EXPECT_CALL(*this, OnDecoderSelected(decoder_1_, IsNull())); 275 EXPECT_CALL(*this, OnDecoderSelected(decoder_1_, NotNull()));
239 276
240 SelectDecoder(); 277 SelectDecoder();
241 } 278 }
242 279
243 TEST_F(VideoDecoderSelectorTest, Destroy_ClearStream_HasDecryptor) { 280 TEST_F(VideoDecoderSelectorTest, Destroy_ClearStream_DecryptOnly) {
244 UseClearStream(); 281 UseClearStream();
245 InitializeDecoderSelector(kDecryptOnly, 1); 282 InitializeDecoderSelector(kDecryptOnly, 1);
246 283
247 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _)); 284 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _));
248 285
249 SelectDecoderAndDestroy(); 286 SelectDecoderAndDestroy();
250 } 287 }
251 288
252 // The stream is encrypted and there's no decryptor. The decoder only supports 289 TEST_F(VideoDecoderSelectorTest, ClearStream_DecryptAndDecode) {
253 // clear streams so no decoder can be selected. 290 UseClearStream();
291 InitializeDecoderSelector(kDecryptAndDecode, 1);
292
293 #if !defined(OS_ANDROID)
294 // A DecryptingVideoDecoder will be created and selected. The clear decoder
295 // should not be touched at all. No DecryptingDemuxerStream should be
296 // created.
297 EXPECT_CALL(*this, OnDecoderSelected(NotNull(), IsNull()));
298 #else
299 // A DecryptingDemuxerStream will be created. The clear decoder will be
300 // initialized and returned.
301 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _))
302 .WillOnce(RunCallback<3>(true));
303 EXPECT_CALL(*this, OnDecoderSelected(NotNull(), NotNull()));
304 #endif
305
306 SelectDecoder();
307 }
308
309 // Tests for encrypted streams.
310
254 TEST_F(VideoDecoderSelectorTest, EncryptedStream_NoDecryptor_OneClearDecoder) { 311 TEST_F(VideoDecoderSelectorTest, EncryptedStream_NoDecryptor_OneClearDecoder) {
255 UseEncryptedStream(); 312 UseEncryptedStream();
256 InitializeDecoderSelector(kNoDecryptor, 1); 313 InitializeDecoderSelector(kNoDecryptor, 1);
257 314
258 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _)) 315 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _))
259 .WillOnce(RunCallback<3>(false)); 316 .WillOnce(RunCallback<3>(false));
260 EXPECT_CALL(*this, OnDecoderSelected(IsNull(), IsNull())); 317 EXPECT_CALL(*this, OnDecoderSelected(IsNull(), IsNull()));
261 318
262 SelectDecoder(); 319 SelectDecoder();
263 } 320 }
264 321
265 TEST_F(VideoDecoderSelectorTest, 322 TEST_F(VideoDecoderSelectorTest,
266 Destroy_EncryptedStream_NoDecryptor_OneClearDecoder) { 323 Destroy_EncryptedStream_NoDecryptor_OneClearDecoder) {
267 UseEncryptedStream(); 324 UseEncryptedStream();
268 InitializeDecoderSelector(kNoDecryptor, 1); 325 InitializeDecoderSelector(kNoDecryptor, 1);
269 326
270 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _)); 327 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _));
271 328
272 SelectDecoderAndDestroy(); 329 SelectDecoderAndDestroy();
273 } 330 }
274 331
275 // The stream is encrypted and there's no decryptor. There are multiple decoders
276 // and the first one that supports encrypted streams is selected.
277 TEST_F(VideoDecoderSelectorTest, EncryptedStream_NoDecryptor_MultipleDecoders) { 332 TEST_F(VideoDecoderSelectorTest, EncryptedStream_NoDecryptor_MultipleDecoders) {
278 UseEncryptedStream(); 333 UseEncryptedStream();
279 InitializeDecoderSelector(kNoDecryptor, 2); 334 InitializeDecoderSelector(kNoDecryptor, 2);
280 335
281 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _)) 336 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _))
282 .WillOnce(RunCallback<3>(false)); 337 .WillOnce(RunCallback<3>(false));
283 EXPECT_CALL(*decoder_2_, Initialize(EncryptedConfig(), _, _, _, _)) 338 EXPECT_CALL(*decoder_2_, Initialize(EncryptedConfig(), _, _, _, _))
284 .WillOnce(RunCallback<3>(true)); 339 .WillOnce(RunCallback<3>(true));
285 EXPECT_CALL(*this, OnDecoderSelected(decoder_2_, IsNull())); 340 EXPECT_CALL(*this, OnDecoderSelected(decoder_2_, IsNull()));
286 341
287 SelectDecoder(); 342 SelectDecoder();
288 } 343 }
289 344
290 TEST_F(VideoDecoderSelectorTest, 345 TEST_F(VideoDecoderSelectorTest,
291 Destroy_EncryptedStream_NoDecryptor_MultipleDecoders) { 346 Destroy_EncryptedStream_NoDecryptor_MultipleDecoders) {
292 UseEncryptedStream(); 347 UseEncryptedStream();
293 InitializeDecoderSelector(kNoDecryptor, 2); 348 InitializeDecoderSelector(kNoDecryptor, 2);
294 349
295 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _)) 350 EXPECT_CALL(*decoder_1_, Initialize(EncryptedConfig(), _, _, _, _))
296 .WillOnce(RunCallback<3>(false)); 351 .WillOnce(RunCallback<3>(false));
297 EXPECT_CALL(*decoder_2_, Initialize(EncryptedConfig(), _, _, _, _)); 352 EXPECT_CALL(*decoder_2_, Initialize(EncryptedConfig(), _, _, _, _));
298 353
299 SelectDecoderAndDestroy(); 354 SelectDecoderAndDestroy();
300 } 355 }
301 356
302 // Decryptor can only do decryption and there's no decoder available. No decoder
303 // can be selected.
304 TEST_F(VideoDecoderSelectorTest, EncryptedStream_DecryptOnly_NoDecoder) { 357 TEST_F(VideoDecoderSelectorTest, EncryptedStream_DecryptOnly_NoDecoder) {
305 UseEncryptedStream(); 358 UseEncryptedStream();
306 InitializeDecoderSelector(kDecryptOnly, 0); 359 InitializeDecoderSelector(kDecryptOnly, 0);
307 360
308 EXPECT_CALL(*this, OnDecoderSelected(IsNull(), IsNull())); 361 EXPECT_CALL(*this, OnDecoderSelected(IsNull(), IsNull()));
309 362
310 SelectDecoder(); 363 SelectDecoder();
311 } 364 }
312 365
313 // Decryptor can do decryption-only and there's a decoder available. The decoder
314 // will be selected and a DecryptingDemuxerStream will be created.
315 TEST_F(VideoDecoderSelectorTest, EncryptedStream_DecryptOnly_OneClearDecoder) { 366 TEST_F(VideoDecoderSelectorTest, EncryptedStream_DecryptOnly_OneClearDecoder) {
316 UseEncryptedStream(); 367 UseEncryptedStream();
317 InitializeDecoderSelector(kDecryptOnly, 1); 368 InitializeDecoderSelector(kDecryptOnly, 1);
318 369
319 // Since we use DecryptingDemuxerStream, the decoder will be initialized with 370 // Since we use DecryptingDemuxerStream, the decoder will be initialized with
320 // a clear config. 371 // a clear config.
321 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _)) 372 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _))
322 .WillOnce(RunCallback<3>(true)); 373 .WillOnce(RunCallback<3>(true));
323 EXPECT_CALL(*this, OnDecoderSelected(decoder_1_, NotNull())); 374 EXPECT_CALL(*this, OnDecoderSelected(decoder_1_, NotNull()));
324 375
325 SelectDecoder(); 376 SelectDecoder();
326 } 377 }
327 378
328 TEST_F(VideoDecoderSelectorTest, 379 TEST_F(VideoDecoderSelectorTest,
329 Destroy_EncryptedStream_DecryptOnly_OneClearDecoder) { 380 Destroy_EncryptedStream_DecryptOnly_OneClearDecoder) {
330 UseEncryptedStream(); 381 UseEncryptedStream();
331 InitializeDecoderSelector(kDecryptOnly, 1); 382 InitializeDecoderSelector(kDecryptOnly, 1);
332 383
333 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _)); 384 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _));
334 385
335 SelectDecoderAndDestroy(); 386 SelectDecoderAndDestroy();
336 } 387 }
337 388
338 // Decryptor can only do decryption and there are multiple decoders available.
339 // The first decoder that can decode the input stream will be selected and
340 // a DecryptingDemuxerStream will be created.
341 TEST_F(VideoDecoderSelectorTest, 389 TEST_F(VideoDecoderSelectorTest,
342 EncryptedStream_DecryptOnly_MultipleClearDecoder) { 390 EncryptedStream_DecryptOnly_MultipleClearDecoder) {
343 UseEncryptedStream(); 391 UseEncryptedStream();
344 InitializeDecoderSelector(kDecryptOnly, 2); 392 InitializeDecoderSelector(kDecryptOnly, 2);
345 393
346 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _)) 394 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _))
347 .WillOnce(RunCallback<3>(false)); 395 .WillOnce(RunCallback<3>(false));
348 EXPECT_CALL(*decoder_2_, Initialize(ClearConfig(), _, _, _, _)) 396 EXPECT_CALL(*decoder_2_, Initialize(ClearConfig(), _, _, _, _))
349 .WillOnce(RunCallback<3>(true)); 397 .WillOnce(RunCallback<3>(true));
350 EXPECT_CALL(*this, OnDecoderSelected(decoder_2_, NotNull())); 398 EXPECT_CALL(*this, OnDecoderSelected(decoder_2_, NotNull()));
351 399
352 SelectDecoder(); 400 SelectDecoder();
353 } 401 }
354 402
355 TEST_F(VideoDecoderSelectorTest, 403 TEST_F(VideoDecoderSelectorTest,
356 Destroy_EncryptedStream_DecryptOnly_MultipleClearDecoder) { 404 Destroy_EncryptedStream_DecryptOnly_MultipleClearDecoder) {
357 UseEncryptedStream(); 405 UseEncryptedStream();
358 InitializeDecoderSelector(kDecryptOnly, 2); 406 InitializeDecoderSelector(kDecryptOnly, 2);
359 407
360 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _)) 408 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _))
361 .WillOnce(RunCallback<3>(false)); 409 .WillOnce(RunCallback<3>(false));
362 EXPECT_CALL(*decoder_2_, Initialize(ClearConfig(), _, _, _, _)); 410 EXPECT_CALL(*decoder_2_, Initialize(ClearConfig(), _, _, _, _));
363 411
364 SelectDecoderAndDestroy(); 412 SelectDecoderAndDestroy();
365 } 413 }
366 414
367 // Decryptor can do decryption and decoding.
368 TEST_F(VideoDecoderSelectorTest, EncryptedStream_DecryptAndDecode) { 415 TEST_F(VideoDecoderSelectorTest, EncryptedStream_DecryptAndDecode) {
369 UseEncryptedStream(); 416 UseEncryptedStream();
370 InitializeDecoderSelector(kDecryptAndDecode, 1); 417 InitializeDecoderSelector(kDecryptAndDecode, 1);
371 418
372 #if !defined(OS_ANDROID) 419 #if !defined(OS_ANDROID)
373 // A DecryptingVideoDecoder will be created and selected. The clear decoder 420 // A DecryptingVideoDecoder will be created and selected. The clear decoder
374 // should not be touched at all. No DecryptingDemuxerStream should be 421 // should not be touched at all. No DecryptingDemuxerStream should be
375 // created. 422 // created.
376 EXPECT_CALL(*this, OnDecoderSelected(NotNull(), IsNull())); 423 EXPECT_CALL(*this, OnDecoderSelected(NotNull(), IsNull()));
377 #else 424 #else
378 // A DecryptingDemuxerStream will be created. The clear decoder will be 425 // A DecryptingDemuxerStream will be created. The clear decoder will be
379 // initialized and returned. 426 // initialized and returned.
380 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _)) 427 EXPECT_CALL(*decoder_1_, Initialize(ClearConfig(), _, _, _, _))
381 .WillOnce(RunCallback<3>(true)); 428 .WillOnce(RunCallback<3>(true));
382 EXPECT_CALL(*this, OnDecoderSelected(NotNull(), NotNull())); 429 EXPECT_CALL(*this, OnDecoderSelected(NotNull(), NotNull()));
383 #endif 430 #endif
384 431
385 SelectDecoder(); 432 SelectDecoder();
386 } 433 }
387 434
388 } // namespace media 435 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/decrypting_video_decoder.cc ('k') | media/filters/video_frame_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698