OLD | NEW |
---|---|
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 // The bulk of this file is support code; sorry about that. Here's an overview | 5 // The bulk of this file is support code; sorry about that. Here's an overview |
6 // to hopefully help readers of this code: | 6 // to hopefully help readers of this code: |
7 // - RenderingHelper is charged with interacting with X11/{EGL/GLES2,GLX/GL} or | 7 // - RenderingHelper is charged with interacting with X11/{EGL/GLES2,GLX/GL} or |
8 // Win/EGL. | 8 // Win/EGL. |
9 // - ClientState is an enum for the state of the decode client used by the test. | 9 // - ClientState is an enum for the state of the decode client used by the test. |
10 // - ClientStateNotification is a barrier abstraction that allows the test code | 10 // - ClientStateNotification is a barrier abstraction that allows the test code |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
199 base::SPLIT_WANT_ALL); | 199 base::SPLIT_WANT_ALL); |
200 // Check these are legitimate MD5s. | 200 // Check these are legitimate MD5s. |
201 for (const std::string& md5_string : *md5_strings) { | 201 for (const std::string& md5_string : *md5_strings) { |
202 // Ignore the empty string added by SplitString | 202 // Ignore the empty string added by SplitString |
203 if (!md5_string.length()) | 203 if (!md5_string.length()) |
204 continue; | 204 continue; |
205 // Ignore comments | 205 // Ignore comments |
206 if (md5_string.at(0) == '#') | 206 if (md5_string.at(0) == '#') |
207 continue; | 207 continue; |
208 | 208 |
209 LOG_ASSERT(static_cast<int>(md5_string.length()) == kMD5StringLength) | 209 LOG_IF(WARNING, static_cast<int>(md5_string.length()) != kMD5StringLength) |
210 << md5_string; | 210 << "MD5 length error: " << md5_string; |
211 bool hex_only = std::count_if(md5_string.begin(), md5_string.end(), | 211 bool hex_only = std::count_if(md5_string.begin(), md5_string.end(), |
212 isxdigit) == kMD5StringLength; | 212 isxdigit) == kMD5StringLength; |
213 LOG_ASSERT(hex_only) << md5_string; | 213 LOG_IF(WARNING, !hex_only) << "MD5 includes non-hex char: " << md5_string; |
214 } | 214 } |
215 LOG_ASSERT(md5_strings->size() >= 1U) << " MD5 checksum file (" | 215 LOG_IF(ERROR, md5_strings->size() < 1U) << " MD5 checksum file (" |
Owen Lin
2016/12/27 07:32:44
== 0
Why this one is error and others are just war
johnylin1
2016/12/27 14:02:06
My opinion is "missing file" will definitely make
wuchengli
2017/01/03 09:10:11
+1. Use LOG_IF(ERROR, for consistency because it's
johnylin1
2017/01/04 15:34:36
Done.
| |
216 << filepath.MaybeAsASCII() | 216 << filepath.MaybeAsASCII() |
217 << ") missing or empty."; | 217 << ") missing or empty."; |
218 } | 218 } |
219 | 219 |
220 // State of the GLRenderingVDAClient below. Order matters here as the test | 220 // State of the GLRenderingVDAClient below. Order matters here as the test |
221 // makes assumptions about it. | 221 // makes assumptions about it. |
222 enum ClientState { | 222 enum ClientState { |
223 CS_CREATED = 0, | 223 CS_CREATED = 0, |
224 CS_DECODER_SET = 1, | 224 CS_DECODER_SET = 1, |
225 CS_INITIALIZED = 2, | 225 CS_INITIALIZED = 2, |
226 CS_FLUSHING = 3, | 226 CS_FLUSHING = 3, |
227 CS_FLUSHED = 4, | 227 CS_FLUSHED = 4, |
(...skipping 1045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1273 // instantiated. | 1273 // instantiated. |
1274 // - Number of concurrent in-flight Decode() calls per decoder. | 1274 // - Number of concurrent in-flight Decode() calls per decoder. |
1275 // - Number of play-throughs. | 1275 // - Number of play-throughs. |
1276 // - reset_after_frame_num: see GLRenderingVDAClient ctor. | 1276 // - reset_after_frame_num: see GLRenderingVDAClient ctor. |
1277 // - delete_decoder_phase: see GLRenderingVDAClient ctor. | 1277 // - delete_decoder_phase: see GLRenderingVDAClient ctor. |
1278 // - whether to test slow rendering by delaying ReusePictureBuffer(). | 1278 // - whether to test slow rendering by delaying ReusePictureBuffer(). |
1279 // - whether the video frames are rendered as thumbnails. | 1279 // - whether the video frames are rendered as thumbnails. |
1280 class VideoDecodeAcceleratorParamTest | 1280 class VideoDecodeAcceleratorParamTest |
1281 : public VideoDecodeAcceleratorTest, | 1281 : public VideoDecodeAcceleratorTest, |
1282 public ::testing::WithParamInterface< | 1282 public ::testing::WithParamInterface< |
1283 std::tuple<int, int, int, ResetPoint, ClientState, bool, bool>> {}; | 1283 std::tuple<int, int, int, ResetPoint, ClientState, bool, bool>> { |
1284 protected: | |
1285 using NotesVector = | |
1286 std::vector<std::unique_ptr<ClientStateNotification<ClientState>>>; | |
1287 using ClientsVector = std::vector<std::unique_ptr<GLRenderingVDAClient>>; | |
1288 | |
1289 // Delete all GLRenderingClient objects in their own thread. | |
1290 void DeleteClientsAndNotes(ClientsVector clients, NotesVector notes); | |
1291 }; | |
1292 | |
1293 void VideoDecodeAcceleratorParamTest::DeleteClientsAndNotes( | |
wuchengli
2017/01/03 09:10:12
This can be renamed to VideoDecodeAcceleratorParam
johnylin1
2017/01/04 15:34:36
Sounds great. I override TearDown() in VideoDecode
| |
1294 ClientsVector clients, | |
1295 NotesVector notes) { | |
1296 std::unique_ptr<ClientsVector> clients2(new ClientsVector); | |
1297 clients2->swap(clients); | |
1298 std::unique_ptr<NotesVector> notes2(new NotesVector); | |
1299 notes2->swap(notes); | |
1300 | |
1301 // |clients| must be deleted first because |clients| use |notes2|. | |
1302 g_env->GetRenderingTaskRunner()->PostTask( | |
1303 FROM_HERE, base::Bind(&Delete<ClientsVector>, base::Passed(&clients2))); | |
1304 | |
1305 g_env->GetRenderingTaskRunner()->PostTask( | |
1306 FROM_HERE, base::Bind(&Delete<NotesVector>, base::Passed(¬es2))); | |
1307 | |
1308 WaitUntilIdle(); | |
1309 } | |
1284 | 1310 |
1285 // Wait for |note| to report a state and if it's not |expected_state| then | 1311 // Wait for |note| to report a state and if it's not |expected_state| then |
1286 // assert |client| has deleted its decoder. | 1312 // expect |client| has deleted its decoder and set terminate_ealy. |
1287 static void AssertWaitForStateOrDeleted( | 1313 static void AssertWaitForStateOrDeleted( |
1288 ClientStateNotification<ClientState>* note, | 1314 ClientStateNotification<ClientState>* note, |
1289 GLRenderingVDAClient* client, | 1315 GLRenderingVDAClient* client, |
1316 bool* terminate_early, | |
1290 ClientState expected_state) { | 1317 ClientState expected_state) { |
1318 // If terminate_early is true it means something is already wrong of decoder, | |
1319 // we should bypass all latter state checks. | |
1320 if (*terminate_early) | |
1321 return; | |
1291 ClientState state = note->Wait(); | 1322 ClientState state = note->Wait(); |
1292 if (state == expected_state) | 1323 if (state == expected_state) |
1293 return; | 1324 return; |
1294 ASSERT_TRUE(client->decoder_deleted()) | 1325 if (!client->decoder_deleted()) { |
1295 << "Decoder not deleted but Wait() returned " << state | 1326 LOG(ERROR) << "Decoder not deleted but Wait() returned " << state |
1296 << ", instead of " << expected_state; | 1327 << ", instead of " << expected_state; |
1328 *terminate_early = true; | |
1329 } | |
1297 } | 1330 } |
1298 | 1331 |
1299 // We assert a minimal number of concurrent decoders we expect to succeed. | 1332 // We assert a minimal number of concurrent decoders we expect to succeed. |
1300 // Different platforms can support more concurrent decoders, so we don't assert | 1333 // Different platforms can support more concurrent decoders, so we don't assert |
1301 // failure above this. | 1334 // failure above this. |
1302 enum { kMinSupportedNumConcurrentDecoders = 3 }; | 1335 enum { kMinSupportedNumConcurrentDecoders = 3 }; |
1303 | 1336 |
1304 // Test the most straightforward case possible: data is decoded from a single | 1337 // Test the most straightforward case possible: data is decoded from a single |
1305 // chunk and rendered to the screen. | 1338 // chunk and rendered to the screen. |
1306 TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { | 1339 TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
(...skipping 10 matching lines...) Expand all Loading... | |
1317 | 1350 |
1318 if (g_num_play_throughs > 0) | 1351 if (g_num_play_throughs > 0) |
1319 num_play_throughs = g_num_play_throughs; | 1352 num_play_throughs = g_num_play_throughs; |
1320 | 1353 |
1321 UpdateTestVideoFileParams(num_concurrent_decoders, reset_point, | 1354 UpdateTestVideoFileParams(num_concurrent_decoders, reset_point, |
1322 &test_video_files_); | 1355 &test_video_files_); |
1323 | 1356 |
1324 // Suppress GL rendering for all tests when the "--rendering_fps" is 0. | 1357 // Suppress GL rendering for all tests when the "--rendering_fps" is 0. |
1325 const bool suppress_rendering = g_rendering_fps == 0; | 1358 const bool suppress_rendering = g_rendering_fps == 0; |
1326 | 1359 |
1327 using NotesVector = | |
1328 std::vector<std::unique_ptr<ClientStateNotification<ClientState>>>; | |
1329 using ClientsVector = std::vector<std::unique_ptr<GLRenderingVDAClient>>; | |
1330 NotesVector notes(num_concurrent_decoders); | 1360 NotesVector notes(num_concurrent_decoders); |
1331 ClientsVector clients(num_concurrent_decoders); | 1361 ClientsVector clients(num_concurrent_decoders); |
1332 | 1362 |
1333 RenderingHelperParams helper_params; | 1363 RenderingHelperParams helper_params; |
1334 helper_params.rendering_fps = g_rendering_fps; | 1364 helper_params.rendering_fps = g_rendering_fps; |
1335 helper_params.warm_up_iterations = g_rendering_warm_up; | 1365 helper_params.warm_up_iterations = g_rendering_warm_up; |
1336 helper_params.render_as_thumbnails = render_as_thumbnails; | 1366 helper_params.render_as_thumbnails = render_as_thumbnails; |
1337 if (render_as_thumbnails) { | 1367 if (render_as_thumbnails) { |
1338 // Only one decoder is supported with thumbnail rendering | 1368 // Only one decoder is supported with thumbnail rendering |
1339 LOG_ASSERT(num_concurrent_decoders == 1U); | 1369 LOG_ASSERT(num_concurrent_decoders == 1U); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1373 | 1403 |
1374 InitializeRenderingHelper(helper_params); | 1404 InitializeRenderingHelper(helper_params); |
1375 | 1405 |
1376 for (size_t index = 0; index < num_concurrent_decoders; ++index) { | 1406 for (size_t index = 0; index < num_concurrent_decoders; ++index) { |
1377 CreateAndStartDecoder(clients[index].get(), notes[index].get()); | 1407 CreateAndStartDecoder(clients[index].get(), notes[index].get()); |
1378 } | 1408 } |
1379 | 1409 |
1380 // Then wait for all the decodes to finish. | 1410 // Then wait for all the decodes to finish. |
1381 // Only check performance & correctness later if we play through only once. | 1411 // Only check performance & correctness later if we play through only once. |
1382 bool skip_performance_and_correctness_checks = num_play_throughs > 1; | 1412 bool skip_performance_and_correctness_checks = num_play_throughs > 1; |
1413 bool terminate_early = false; | |
Owen Lin
2016/12/27 07:32:44
Instead, can we have a helper function which retur
johnylin1
2017/01/04 15:34:36
This is no longer needed since we gonna delete cli
| |
1383 for (size_t i = 0; i < num_concurrent_decoders; ++i) { | 1414 for (size_t i = 0; i < num_concurrent_decoders; ++i) { |
1384 ClientStateNotification<ClientState>* note = notes[i].get(); | 1415 ClientStateNotification<ClientState>* note = notes[i].get(); |
1385 ClientState state = note->Wait(); | 1416 ClientState state = note->Wait(); |
1386 if (state != CS_INITIALIZED) { | 1417 if (state != CS_INITIALIZED) { |
1387 skip_performance_and_correctness_checks = true; | 1418 skip_performance_and_correctness_checks = true; |
1388 // We expect initialization to fail only when more than the supported | 1419 // We expect initialization to fail only when more than the supported |
1389 // number of decoders is instantiated. Assert here that something else | 1420 // number of decoders is instantiated. Break the loop and then terminate |
1390 // didn't trigger failure. | 1421 // test gracefully that something else didn't trigger failure. Do not use |
1391 ASSERT_GT(num_concurrent_decoders, | 1422 // assertion otherwise clients won't be deleted in the correct thread. |
1392 static_cast<size_t>(kMinSupportedNumConcurrentDecoders)); | 1423 if (num_concurrent_decoders <= |
1424 static_cast<size_t>(kMinSupportedNumConcurrentDecoders)) { | |
1425 LOG(ERROR) << "Initialization failed while the number of decoders " | |
1426 << "is still supportable. num_concurrent_decoders = " | |
1427 << num_concurrent_decoders; | |
1428 terminate_early = true; | |
1429 break; | |
1430 } | |
1393 continue; | 1431 continue; |
1394 } | 1432 } |
1395 ASSERT_EQ(state, CS_INITIALIZED); | |
1396 for (int n = 0; n < num_play_throughs; ++n) { | 1433 for (int n = 0; n < num_play_throughs; ++n) { |
1397 // For play-throughs other than the first, we expect initialization to | 1434 // For play-throughs other than the first, we expect initialization to |
1398 // succeed unconditionally. | 1435 // succeed unconditionally. |
1399 if (n > 0) { | 1436 if (n > 0) { |
1400 ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( | 1437 ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
1401 note, clients[i].get(), CS_INITIALIZED)); | 1438 note, clients[i].get(), &terminate_early, CS_INITIALIZED)); |
1402 } | 1439 } |
1403 // InitializeDone kicks off decoding inside the client, so we just need to | 1440 // InitializeDone kicks off decoding inside the client, so we just need to |
1404 // wait for Flush. | 1441 // wait for Flush. |
1405 ASSERT_NO_FATAL_FAILURE( | 1442 ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
1406 AssertWaitForStateOrDeleted(note, clients[i].get(), CS_FLUSHING)); | 1443 note, clients[i].get(), &terminate_early, CS_FLUSHING)); |
1407 ASSERT_NO_FATAL_FAILURE( | 1444 ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
1408 AssertWaitForStateOrDeleted(note, clients[i].get(), CS_FLUSHED)); | 1445 note, clients[i].get(), &terminate_early, CS_FLUSHED)); |
1409 // FlushDone requests Reset(). | 1446 // FlushDone requests Reset(). |
1410 ASSERT_NO_FATAL_FAILURE( | 1447 ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
1411 AssertWaitForStateOrDeleted(note, clients[i].get(), CS_RESETTING)); | 1448 note, clients[i].get(), &terminate_early, CS_RESETTING)); |
1412 } | 1449 } |
1413 ASSERT_NO_FATAL_FAILURE( | 1450 ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
1414 AssertWaitForStateOrDeleted(note, clients[i].get(), CS_RESET)); | 1451 note, clients[i].get(), &terminate_early, CS_RESET)); |
1415 // ResetDone requests Destroy(). | 1452 // ResetDone requests Destroy(). |
1416 ASSERT_NO_FATAL_FAILURE( | 1453 ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
1417 AssertWaitForStateOrDeleted(note, clients[i].get(), CS_DESTROYED)); | 1454 note, clients[i].get(), &terminate_early, CS_DESTROYED)); |
1455 // Break the loop and terminate test gracefully if there is already | |
1456 // something wrong. | |
1457 if (terminate_early) | |
1458 break; | |
1418 } | 1459 } |
1460 // There is already something wrong and should delete clients and then stop | |
1461 // testing. | |
1462 if (terminate_early) { | |
1463 DeleteClientsAndNotes(std::move(clients), std::move(notes)); | |
Owen Lin
2016/12/27 07:32:44
To me, it looks like the main issue here is to cal
johnylin1
2016/12/30 12:38:37
I got another idea is to delete clients and notes
johnylin1
2017/01/04 15:34:36
Override TearDown() is even better and also makes
| |
1464 } | |
1465 ASSERT_FALSE(terminate_early) << "Test is terminated due to failure above."; | |
1466 | |
1419 // Finally assert that decoding went as expected. | 1467 // Finally assert that decoding went as expected. |
1420 for (size_t i = 0; | 1468 for (size_t i = 0; |
1421 i < num_concurrent_decoders && !skip_performance_and_correctness_checks; | 1469 i < num_concurrent_decoders && !skip_performance_and_correctness_checks; |
1422 ++i) { | 1470 ++i) { |
1423 // We can only make performance/correctness assertions if the decoder was | 1471 // We can only make performance/correctness assertions if the decoder was |
1424 // allowed to finish. | 1472 // allowed to finish. |
1425 if (delete_decoder_state < CS_FLUSHED) | 1473 if (delete_decoder_state < CS_FLUSHED) |
1426 continue; | 1474 continue; |
1427 GLRenderingVDAClient* client = clients[i].get(); | 1475 GLRenderingVDAClient* client = clients[i].get(); |
1428 TestVideoFile* video_file = | 1476 TestVideoFile* video_file = |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1478 std::vector<gfx::PNGCodec::Comment>(), | 1526 std::vector<gfx::PNGCodec::Comment>(), |
1479 &png); | 1527 &png); |
1480 | 1528 |
1481 LOG(ERROR) << "Unknown thumbnails MD5: " << md5_string; | 1529 LOG(ERROR) << "Unknown thumbnails MD5: " << md5_string; |
1482 | 1530 |
1483 base::FilePath filepath(test_video_files_[0]->file_name); | 1531 base::FilePath filepath(test_video_files_[0]->file_name); |
1484 filepath = filepath.AddExtension(FILE_PATH_LITERAL(".bad_thumbnails")); | 1532 filepath = filepath.AddExtension(FILE_PATH_LITERAL(".bad_thumbnails")); |
1485 filepath = filepath.AddExtension(FILE_PATH_LITERAL(".png")); | 1533 filepath = filepath.AddExtension(FILE_PATH_LITERAL(".png")); |
1486 int num_bytes = base::WriteFile( | 1534 int num_bytes = base::WriteFile( |
1487 filepath, reinterpret_cast<char*>(&png[0]), png.size()); | 1535 filepath, reinterpret_cast<char*>(&png[0]), png.size()); |
1488 ASSERT_EQ(num_bytes, static_cast<int>(png.size())); | 1536 EXPECT_EQ(num_bytes, static_cast<int>(png.size())); |
1489 } | 1537 } |
1490 ASSERT_NE(match, golden_md5s.end()); | 1538 EXPECT_NE(match, golden_md5s.end()); |
1491 EXPECT_EQ(alpha_solid, true) << "RGBA frame had incorrect alpha"; | 1539 EXPECT_EQ(alpha_solid, true) << "RGBA frame had incorrect alpha"; |
1492 } | 1540 } |
1493 | 1541 |
1494 // Output the frame delivery time to file | 1542 // Output the frame delivery time to file |
1495 // We can only make performance/correctness assertions if the decoder was | 1543 // We can only make performance/correctness assertions if the decoder was |
1496 // allowed to finish. | 1544 // allowed to finish. |
1497 if (g_output_log != NULL && delete_decoder_state >= CS_FLUSHED) { | 1545 if (g_output_log != NULL && delete_decoder_state >= CS_FLUSHED) { |
1498 base::File output_file( | 1546 base::File output_file( |
1499 base::FilePath(g_output_log), | 1547 base::FilePath(g_output_log), |
1500 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); | 1548 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); |
1501 for (size_t i = 0; i < num_concurrent_decoders; ++i) { | 1549 for (size_t i = 0; i < num_concurrent_decoders; ++i) { |
1502 clients[i]->OutputFrameDeliveryTimes(&output_file); | 1550 clients[i]->OutputFrameDeliveryTimes(&output_file); |
1503 } | 1551 } |
1504 } | 1552 } |
1505 | 1553 |
1506 std::unique_ptr<ClientsVector> clients2(new ClientsVector); | 1554 DeleteClientsAndNotes(std::move(clients), std::move(notes)); |
1507 clients2->swap(clients); | |
1508 std::unique_ptr<NotesVector> notes2(new NotesVector); | |
1509 notes2->swap(notes); | |
1510 | |
1511 // |clients| must be deleted first because |clients| use |notes2|. | |
1512 g_env->GetRenderingTaskRunner()->PostTask( | |
1513 FROM_HERE, base::Bind(&Delete<ClientsVector>, base::Passed(&clients2))); | |
1514 | |
1515 g_env->GetRenderingTaskRunner()->PostTask( | |
1516 FROM_HERE, base::Bind(&Delete<NotesVector>, base::Passed(¬es2))); | |
1517 | |
1518 WaitUntilIdle(); | |
1519 }; | 1555 }; |
1520 | 1556 |
1521 // Test that replay after EOS works fine. | 1557 // Test that replay after EOS works fine. |
1522 INSTANTIATE_TEST_CASE_P( | 1558 INSTANTIATE_TEST_CASE_P( |
1523 ReplayAfterEOS, | 1559 ReplayAfterEOS, |
1524 VideoDecodeAcceleratorParamTest, | 1560 VideoDecodeAcceleratorParamTest, |
1525 ::testing::Values( | 1561 ::testing::Values( |
1526 std::make_tuple(1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false, false))); | 1562 std::make_tuple(1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false, false))); |
1527 | 1563 |
1528 // Test that Reset() before the first Decode() works fine. | 1564 // Test that Reset() before the first Decode() works fine. |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1825 | 1861 |
1826 media::g_env = | 1862 media::g_env = |
1827 reinterpret_cast<media::VideoDecodeAcceleratorTestEnvironment*>( | 1863 reinterpret_cast<media::VideoDecodeAcceleratorTestEnvironment*>( |
1828 testing::AddGlobalTestEnvironment( | 1864 testing::AddGlobalTestEnvironment( |
1829 new media::VideoDecodeAcceleratorTestEnvironment())); | 1865 new media::VideoDecodeAcceleratorTestEnvironment())); |
1830 | 1866 |
1831 return base::LaunchUnitTestsSerially( | 1867 return base::LaunchUnitTestsSerially( |
1832 argc, argv, | 1868 argc, argv, |
1833 base::Bind(&media::VDATestSuite::Run, base::Unretained(&test_suite))); | 1869 base::Bind(&media::VDATestSuite::Run, base::Unretained(&test_suite))); |
1834 } | 1870 } |
OLD | NEW |