| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 // Unit test for VideoCaptureBufferPool. | 5 // Unit test for VideoCaptureBufferPool. |
| 6 | 6 |
| 7 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" | 7 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" |
| 8 | 8 |
| 9 #include <stddef.h> | 9 #include <stddef.h> |
| 10 #include <stdint.h> | 10 #include <stdint.h> |
| 11 #include <string.h> | 11 #include <string.h> |
| 12 |
| 12 #include <utility> | 13 #include <utility> |
| 14 #include <vector> |
| 13 | 15 |
| 14 #include "base/bind.h" | 16 #include "base/bind.h" |
| 15 #include "base/macros.h" | 17 #include "base/macros.h" |
| 16 #include "base/memory/ref_counted.h" | 18 #include "base/memory/ref_counted.h" |
| 17 #include "base/memory/scoped_ptr.h" | 19 #include "base/memory/scoped_ptr.h" |
| 18 #include "base/message_loop/message_loop.h" | 20 #include "base/message_loop/message_loop.h" |
| 19 #include "build/build_config.h" | 21 #include "build/build_config.h" |
| 20 #include "cc/test/test_context_provider.h" | 22 #include "cc/test/test_context_provider.h" |
| 21 #include "cc/test/test_web_graphics_context_3d.h" | 23 #include "cc/test/test_web_graphics_context_3d.h" |
| 22 #include "content/browser/compositor/buffer_queue.h" | 24 #include "content/browser/compositor/buffer_queue.h" |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 scoped_ptr<Buffer> ReserveBuffer(const gfx::Size& dimensions, | 170 scoped_ptr<Buffer> ReserveBuffer(const gfx::Size& dimensions, |
| 169 PixelFormatAndStorage format_and_storage) { | 171 PixelFormatAndStorage format_and_storage) { |
| 170 // To verify that ReserveBuffer always sets |buffer_id_to_drop|, | 172 // To verify that ReserveBuffer always sets |buffer_id_to_drop|, |
| 171 // initialize it to something different than the expected value. | 173 // initialize it to something different than the expected value. |
| 172 int buffer_id_to_drop = ~expected_dropped_id_; | 174 int buffer_id_to_drop = ~expected_dropped_id_; |
| 173 DVLOG(1) << media::VideoCaptureFormat::PixelStorageToString( | 175 DVLOG(1) << media::VideoCaptureFormat::PixelStorageToString( |
| 174 format_and_storage.pixel_storage) << " " | 176 format_and_storage.pixel_storage) << " " |
| 175 << media::VideoPixelFormatToString(format_and_storage.pixel_format) | 177 << media::VideoPixelFormatToString(format_and_storage.pixel_format) |
| 176 << " " << dimensions.ToString(); | 178 << " " << dimensions.ToString(); |
| 177 const int buffer_id = pool_->ReserveForProducer( | 179 const int buffer_id = pool_->ReserveForProducer( |
| 178 format_and_storage.pixel_format, format_and_storage.pixel_storage, | 180 dimensions, format_and_storage.pixel_format, |
| 179 dimensions, &buffer_id_to_drop); | 181 format_and_storage.pixel_storage, &buffer_id_to_drop); |
| 180 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 182 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
| 181 return scoped_ptr<Buffer>(); | 183 return scoped_ptr<Buffer>(); |
| 182 EXPECT_EQ(expected_dropped_id_, buffer_id_to_drop); | 184 EXPECT_EQ(expected_dropped_id_, buffer_id_to_drop); |
| 183 | 185 |
| 184 scoped_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle = | 186 scoped_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle = |
| 185 pool_->GetBufferHandle(buffer_id); | 187 pool_->GetBufferHandle(buffer_id); |
| 186 return scoped_ptr<Buffer>( | 188 return scoped_ptr<Buffer>( |
| 187 new Buffer(pool_, std::move(buffer_handle), buffer_id)); | 189 new Buffer(pool_, std::move(buffer_handle), buffer_id)); |
| 188 } | 190 } |
| 189 | 191 |
| 192 scoped_ptr<Buffer> ResurrectLastBuffer( |
| 193 const gfx::Size& dimensions, |
| 194 PixelFormatAndStorage format_and_storage) { |
| 195 const int buffer_id = pool_->ResurrectLastForProducer( |
| 196 dimensions, format_and_storage.pixel_format, |
| 197 format_and_storage.pixel_storage); |
| 198 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
| 199 return scoped_ptr<Buffer>(); |
| 200 return scoped_ptr<Buffer>( |
| 201 new Buffer(pool_, pool_->GetBufferHandle(buffer_id), buffer_id)); |
| 202 } |
| 203 |
| 190 base::MessageLoop loop_; | 204 base::MessageLoop loop_; |
| 191 int expected_dropped_id_; | 205 int expected_dropped_id_; |
| 192 scoped_refptr<VideoCaptureBufferPool> pool_; | 206 scoped_refptr<VideoCaptureBufferPool> pool_; |
| 193 | 207 |
| 194 private: | 208 private: |
| 195 #if !defined(OS_ANDROID) | 209 #if !defined(OS_ANDROID) |
| 196 scoped_ptr<StubBrowserGpuMemoryBufferManager> gpu_memory_buffer_manager_; | 210 scoped_ptr<StubBrowserGpuMemoryBufferManager> gpu_memory_buffer_manager_; |
| 197 scoped_ptr<MockBufferQueue> output_surface_; | 211 scoped_ptr<MockBufferQueue> output_surface_; |
| 198 #endif | 212 #endif |
| 199 | 213 |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 memset(buffer2->data(), 0x22, buffer2->mapped_size()); | 378 memset(buffer2->data(), 0x22, buffer2->mapped_size()); |
| 365 if (buffer4->data() != nullptr) | 379 if (buffer4->data() != nullptr) |
| 366 memset(buffer4->data(), 0x55, buffer4->mapped_size()); | 380 memset(buffer4->data(), 0x55, buffer4->mapped_size()); |
| 367 buffer2.reset(); | 381 buffer2.reset(); |
| 368 | 382 |
| 369 if (buffer4->data() != nullptr) | 383 if (buffer4->data() != nullptr) |
| 370 memset(buffer4->data(), 0x77, buffer4->mapped_size()); | 384 memset(buffer4->data(), 0x77, buffer4->mapped_size()); |
| 371 buffer4.reset(); | 385 buffer4.reset(); |
| 372 } | 386 } |
| 373 | 387 |
| 388 // Tests that a previously-released buffer can be immediately resurrected under |
| 389 // normal conditions. |
| 390 TEST_P(VideoCaptureBufferPoolTest, ResurrectsLastBuffer) { |
| 391 ExpectDroppedId(VideoCaptureBufferPool::kInvalidId); |
| 392 |
| 393 // At the start, there should be nothing to resurrect. |
| 394 scoped_ptr<Buffer> resurrected = |
| 395 ResurrectLastBuffer(gfx::Size(10, 10), GetParam()); |
| 396 ASSERT_EQ(nullptr, resurrected.get()); |
| 397 |
| 398 // Reserve a 10x10 buffer and fill it with 0xab values. |
| 399 scoped_ptr<Buffer> original = ReserveBuffer(gfx::Size(10, 10), GetParam()); |
| 400 ASSERT_NE(nullptr, original.get()); |
| 401 const size_t original_mapped_size = original->mapped_size(); |
| 402 memset(original->data(), 0xab, original_mapped_size); |
| 403 |
| 404 // Try to resurrect a buffer BEFORE releasing |original|. This should fail. |
| 405 resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam()); |
| 406 ASSERT_EQ(nullptr, resurrected.get()); |
| 407 |
| 408 // Release |original| and then try to resurrect it. Confirm the content of |
| 409 // the resurrected buffer is a fill of 0xab values. |
| 410 original.reset(); |
| 411 resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam()); |
| 412 ASSERT_NE(nullptr, resurrected.get()); |
| 413 ASSERT_EQ(original_mapped_size, resurrected->mapped_size()); |
| 414 uint8_t* resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data()); |
| 415 for (size_t i = 0; i < original_mapped_size; ++i) |
| 416 EXPECT_EQ(0xab, resurrected_memory[i]) << "Mismatch at byte offset: " << i; |
| 417 |
| 418 // Now, fill the resurrected buffer with 0xbc values and release it. |
| 419 memset(resurrected_memory, 0xbc, original_mapped_size); |
| 420 resurrected.reset(); |
| 421 |
| 422 // Finally, resurrect the buffer again, and confirm it contains a fill of 0xbc |
| 423 // values. |
| 424 resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam()); |
| 425 ASSERT_NE(nullptr, resurrected.get()); |
| 426 ASSERT_EQ(original_mapped_size, resurrected->mapped_size()); |
| 427 resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data()); |
| 428 for (size_t i = 0; i < original_mapped_size; ++i) |
| 429 EXPECT_EQ(0xbc, resurrected_memory[i]) << "Mismatch at byte offset: " << i; |
| 430 } |
| 431 |
| 432 // Tests that a buffer cannot be resurrected if its properties do not match. |
| 433 TEST_P(VideoCaptureBufferPoolTest, DoesNotResurrectIfPropertiesNotMatched) { |
| 434 ExpectDroppedId(VideoCaptureBufferPool::kInvalidId); |
| 435 |
| 436 // Reserve a 10x10 buffer, fill it with 0xcd values, and release it. |
| 437 scoped_ptr<Buffer> original = ReserveBuffer(gfx::Size(10, 10), GetParam()); |
| 438 ASSERT_NE(nullptr, original.get()); |
| 439 const size_t original_mapped_size = original->mapped_size(); |
| 440 memset(original->data(), 0xcd, original_mapped_size); |
| 441 original.reset(); |
| 442 |
| 443 // Expect that the buffer cannot be resurrected if the dimensions do not |
| 444 // match. |
| 445 scoped_ptr<Buffer> resurrected = |
| 446 ResurrectLastBuffer(gfx::Size(8, 8), GetParam()); |
| 447 ASSERT_EQ(nullptr, resurrected.get()); |
| 448 |
| 449 // Expect that the buffer cannot be resurrected if the pixel format does not |
| 450 // match. |
| 451 PixelFormatAndStorage altered_format_or_storage = GetParam(); |
| 452 altered_format_or_storage.pixel_format = |
| 453 (altered_format_or_storage.pixel_format == media::PIXEL_FORMAT_I420 |
| 454 ? media::PIXEL_FORMAT_ARGB |
| 455 : media::PIXEL_FORMAT_I420); |
| 456 resurrected = |
| 457 ResurrectLastBuffer(gfx::Size(10, 10), altered_format_or_storage); |
| 458 ASSERT_EQ(nullptr, resurrected.get()); |
| 459 |
| 460 // Expect that the buffer cannot be resurrected if the pixel storage does not |
| 461 // match. |
| 462 altered_format_or_storage = GetParam(); |
| 463 altered_format_or_storage.pixel_storage = |
| 464 (altered_format_or_storage.pixel_storage == media::PIXEL_STORAGE_CPU) |
| 465 ? media::PIXEL_STORAGE_GPUMEMORYBUFFER |
| 466 : media::PIXEL_STORAGE_CPU; |
| 467 resurrected = |
| 468 ResurrectLastBuffer(gfx::Size(10, 10), altered_format_or_storage); |
| 469 ASSERT_EQ(nullptr, resurrected.get()); |
| 470 |
| 471 // Finally, check that the buffer CAN be resurrected if all properties match. |
| 472 resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam()); |
| 473 ASSERT_NE(nullptr, resurrected.get()); |
| 474 ASSERT_EQ(original_mapped_size, resurrected->mapped_size()); |
| 475 uint8_t* resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data()); |
| 476 for (size_t i = 0; i < original_mapped_size; ++i) |
| 477 EXPECT_EQ(0xcd, resurrected_memory[i]) << "Mismatch at byte offset: " << i; |
| 478 } |
| 479 |
| 480 // Tests that the buffers are managed by the pool such that the last-released |
| 481 // buffer is kept around as long as possible (for successful resurrection). |
| 482 TEST_P(VideoCaptureBufferPoolTest, AvoidsClobberingForResurrectingLastBuffer) { |
| 483 ExpectDroppedId(VideoCaptureBufferPool::kInvalidId); |
| 484 |
| 485 // Reserve a 10x10 buffer, fill it with 0xde values, and release it. |
| 486 scoped_ptr<Buffer> original = ReserveBuffer(gfx::Size(10, 10), GetParam()); |
| 487 ASSERT_NE(nullptr, original.get()); |
| 488 const size_t original_mapped_size = original->mapped_size(); |
| 489 memset(original->data(), 0xde, original_mapped_size); |
| 490 original.reset(); |
| 491 |
| 492 // Reserve all but one of the pool's buffers. |
| 493 std::vector<scoped_ptr<Buffer>> held_buffers; |
| 494 for (int i = 0; i < kTestBufferPoolSize - 1; ++i) { |
| 495 held_buffers.push_back(ReserveBuffer(gfx::Size(10, 10), GetParam())); |
| 496 ASSERT_NE(nullptr, held_buffers.back().get()); |
| 497 } |
| 498 |
| 499 // Now, attempt to resurrect the original buffer. This should succeed. |
| 500 scoped_ptr<Buffer> resurrected = |
| 501 ResurrectLastBuffer(gfx::Size(10, 10), GetParam()); |
| 502 ASSERT_NE(nullptr, resurrected.get()); |
| 503 ASSERT_EQ(original_mapped_size, resurrected->mapped_size()); |
| 504 uint8_t* resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data()); |
| 505 for (size_t i = 0; i < original_mapped_size; ++i) |
| 506 EXPECT_EQ(0xde, resurrected_memory[i]) << "Mismatch at byte offset: " << i; |
| 507 resurrected.reset(); |
| 508 |
| 509 // Reserve the final buffer in the pool, and then confirm resurrection does |
| 510 // not succeed. |
| 511 held_buffers.push_back(ReserveBuffer(gfx::Size(10, 10), GetParam())); |
| 512 ASSERT_NE(nullptr, held_buffers.back().get()); |
| 513 resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam()); |
| 514 ASSERT_EQ(nullptr, resurrected.get()); |
| 515 } |
| 516 |
| 374 INSTANTIATE_TEST_CASE_P(, | 517 INSTANTIATE_TEST_CASE_P(, |
| 375 VideoCaptureBufferPoolTest, | 518 VideoCaptureBufferPoolTest, |
| 376 testing::ValuesIn(kCapturePixelFormatAndStorages)); | 519 testing::ValuesIn(kCapturePixelFormatAndStorages)); |
| 377 | 520 |
| 378 } // namespace content | 521 } // namespace content |
| OLD | NEW |