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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 #endif | 67 #endif |
68 #if defined(ARCH_CPU_X86_FAMILY) | 68 #if defined(ARCH_CPU_X86_FAMILY) |
69 #include "content/common/gpu/media/vaapi_video_decode_accelerator.h" | 69 #include "content/common/gpu/media/vaapi_video_decode_accelerator.h" |
70 #include "content/common/gpu/media/vaapi_wrapper.h" | 70 #include "content/common/gpu/media/vaapi_wrapper.h" |
71 #endif // defined(ARCH_CPU_X86_FAMILY) | 71 #endif // defined(ARCH_CPU_X86_FAMILY) |
72 #else | 72 #else |
73 #error The VideoAccelerator tests are not supported on this platform. | 73 #error The VideoAccelerator tests are not supported on this platform. |
74 #endif // OS_WIN | 74 #endif // OS_WIN |
75 | 75 |
76 #if defined(USE_OZONE) | 76 #if defined(USE_OZONE) |
| 77 #include "ui/ozone/public/native_pixmap.h" |
77 #include "ui/ozone/public/ozone_gpu_test_helper.h" | 78 #include "ui/ozone/public/ozone_gpu_test_helper.h" |
78 #include "ui/ozone/public/ozone_platform.h" | 79 #include "ui/ozone/public/ozone_platform.h" |
| 80 #include "ui/ozone/public/surface_factory_ozone.h" |
79 #endif // defined(USE_OZONE) | 81 #endif // defined(USE_OZONE) |
80 | 82 |
81 using media::VideoDecodeAccelerator; | 83 using media::VideoDecodeAccelerator; |
82 | 84 |
83 namespace content { | 85 namespace content { |
84 namespace { | 86 namespace { |
85 | 87 |
86 using base::MakeTuple; | 88 using base::MakeTuple; |
87 | 89 |
88 // Values optionally filled in from flags; see main() below. | 90 // Values optionally filled in from flags; see main() below. |
(...skipping 29 matching lines...) Expand all Loading... |
118 int g_rendering_warm_up = 0; | 120 int g_rendering_warm_up = 0; |
119 | 121 |
120 // The value is set by the switch "--num_play_throughs". The video will play | 122 // The value is set by the switch "--num_play_throughs". The video will play |
121 // the specified number of times. In different test cases, we have different | 123 // the specified number of times. In different test cases, we have different |
122 // values for |num_play_throughs|. This setting will override the value. A | 124 // values for |num_play_throughs|. This setting will override the value. A |
123 // special value "0" means no override. | 125 // special value "0" means no override. |
124 int g_num_play_throughs = 0; | 126 int g_num_play_throughs = 0; |
125 // Fake decode | 127 // Fake decode |
126 int g_fake_decoder = 0; | 128 int g_fake_decoder = 0; |
127 | 129 |
| 130 // Test buffer import into VDA, providing buffers allocated by us, instead of |
| 131 // requesting the VDA itself to allocate buffers. |
| 132 bool g_test_import = false; |
| 133 |
128 // Environment to store rendering thread. | 134 // Environment to store rendering thread. |
129 class VideoDecodeAcceleratorTestEnvironment; | 135 class VideoDecodeAcceleratorTestEnvironment; |
130 VideoDecodeAcceleratorTestEnvironment* g_env; | 136 VideoDecodeAcceleratorTestEnvironment* g_env; |
131 | 137 |
132 // Magic constants for differentiating the reasons for NotifyResetDone being | 138 // Magic constants for differentiating the reasons for NotifyResetDone being |
133 // called. | 139 // called. |
134 enum ResetPoint { | 140 enum ResetPoint { |
135 // Reset() just after calling Decode() with a fragment containing config info. | 141 // Reset() just after calling Decode() with a fragment containing config info. |
136 RESET_AFTER_FIRST_CONFIG_INFO = -4, | 142 RESET_AFTER_FIRST_CONFIG_INFO = -4, |
137 START_OF_STREAM_RESET = -3, | 143 START_OF_STREAM_RESET = -3, |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 | 268 |
263 private: | 269 private: |
264 base::Thread rendering_thread_; | 270 base::Thread rendering_thread_; |
265 #if defined(USE_OZONE) | 271 #if defined(USE_OZONE) |
266 std::unique_ptr<ui::OzoneGpuTestHelper> gpu_helper_; | 272 std::unique_ptr<ui::OzoneGpuTestHelper> gpu_helper_; |
267 #endif | 273 #endif |
268 | 274 |
269 DISALLOW_COPY_AND_ASSIGN(VideoDecodeAcceleratorTestEnvironment); | 275 DISALLOW_COPY_AND_ASSIGN(VideoDecodeAcceleratorTestEnvironment); |
270 }; | 276 }; |
271 | 277 |
272 // A helper class used to manage the lifetime of a Texture. | 278 // A helper class used to manage the lifetime of a Texture. Can be backed by |
| 279 // either a buffer allocated by the VDA, or by a preallocated pixmap. |
273 class TextureRef : public base::RefCounted<TextureRef> { | 280 class TextureRef : public base::RefCounted<TextureRef> { |
274 public: | 281 public: |
275 TextureRef(uint32_t texture_id, const base::Closure& no_longer_needed_cb) | 282 static scoped_refptr<TextureRef> Create( |
276 : texture_id_(texture_id), no_longer_needed_cb_(no_longer_needed_cb) {} | 283 uint32_t texture_id, |
| 284 const base::Closure& no_longer_needed_cb); |
| 285 |
| 286 static scoped_refptr<TextureRef> CreatePreallocated( |
| 287 uint32_t texture_id, |
| 288 const base::Closure& no_longer_needed_cb, |
| 289 media::VideoPixelFormat pixel_format, |
| 290 const gfx::Size& size); |
| 291 |
| 292 std::vector<gfx::GpuMemoryBufferHandle> ExportGpuMemoryBufferHandles() const; |
277 | 293 |
278 int32_t texture_id() const { return texture_id_; } | 294 int32_t texture_id() const { return texture_id_; } |
279 | 295 |
280 private: | 296 private: |
281 friend class base::RefCounted<TextureRef>; | 297 friend class base::RefCounted<TextureRef>; |
| 298 |
| 299 TextureRef(uint32_t texture_id, const base::Closure& no_longer_needed_cb) |
| 300 : texture_id_(texture_id), no_longer_needed_cb_(no_longer_needed_cb) {} |
| 301 |
282 ~TextureRef(); | 302 ~TextureRef(); |
283 | 303 |
284 uint32_t texture_id_; | 304 uint32_t texture_id_; |
285 base::Closure no_longer_needed_cb_; | 305 base::Closure no_longer_needed_cb_; |
| 306 #if defined(USE_OZONE) |
| 307 scoped_refptr<ui::NativePixmap> pixmap_; |
| 308 #endif |
286 }; | 309 }; |
287 | 310 |
288 TextureRef::~TextureRef() { | 311 TextureRef::~TextureRef() { |
289 base::ResetAndReturn(&no_longer_needed_cb_).Run(); | 312 base::ResetAndReturn(&no_longer_needed_cb_).Run(); |
290 } | 313 } |
291 | 314 |
| 315 // static |
| 316 scoped_refptr<TextureRef> TextureRef::Create( |
| 317 uint32_t texture_id, |
| 318 const base::Closure& no_longer_needed_cb) { |
| 319 return make_scoped_refptr(new TextureRef(texture_id, no_longer_needed_cb)); |
| 320 } |
| 321 |
| 322 #if defined(USE_OZONE) |
| 323 gfx::BufferFormat VideoPixelFormatToGfxBufferFormat( |
| 324 media::VideoPixelFormat pixel_format) { |
| 325 switch (pixel_format) { |
| 326 case media::VideoPixelFormat::PIXEL_FORMAT_ARGB: |
| 327 return gfx::BufferFormat::BGRA_8888; |
| 328 case media::VideoPixelFormat::PIXEL_FORMAT_XRGB: |
| 329 return gfx::BufferFormat::BGRX_8888; |
| 330 case media::VideoPixelFormat::PIXEL_FORMAT_NV12: |
| 331 return gfx::BufferFormat::YUV_420_BIPLANAR; |
| 332 default: |
| 333 LOG_ASSERT(false) << "Unknown VideoPixelFormat"; |
| 334 return gfx::BufferFormat::BGRX_8888; |
| 335 } |
| 336 } |
| 337 #endif |
| 338 |
| 339 // static |
| 340 scoped_refptr<TextureRef> TextureRef::CreatePreallocated( |
| 341 uint32_t texture_id, |
| 342 const base::Closure& no_longer_needed_cb, |
| 343 media::VideoPixelFormat pixel_format, |
| 344 const gfx::Size& size) { |
| 345 scoped_refptr<TextureRef> texture_ref; |
| 346 #if defined(USE_OZONE) |
| 347 texture_ref = TextureRef::Create(texture_id, no_longer_needed_cb); |
| 348 LOG_ASSERT(texture_ref); |
| 349 |
| 350 ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); |
| 351 ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); |
| 352 gfx::BufferFormat buffer_format = |
| 353 VideoPixelFormatToGfxBufferFormat(pixel_format); |
| 354 texture_ref->pixmap_ = |
| 355 factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size, |
| 356 buffer_format, gfx::BufferUsage::SCANOUT); |
| 357 LOG_ASSERT(texture_ref->pixmap_); |
| 358 #endif |
| 359 |
| 360 return texture_ref; |
| 361 } |
| 362 |
| 363 std::vector<gfx::GpuMemoryBufferHandle> |
| 364 TextureRef::ExportGpuMemoryBufferHandles() const { |
| 365 std::vector<gfx::GpuMemoryBufferHandle> handles; |
| 366 #if defined(USE_OZONE) |
| 367 CHECK(pixmap_); |
| 368 int duped_fd = HANDLE_EINTR(dup(pixmap_->GetDmaBufFd())); |
| 369 LOG_ASSERT(duped_fd != -1) << "Failed duplicating dmabuf fd"; |
| 370 gfx::GpuMemoryBufferHandle handle; |
| 371 handle.type = gfx::OZONE_NATIVE_PIXMAP; |
| 372 handle.native_pixmap_handle.fd = base::FileDescriptor(duped_fd, true); |
| 373 handles.push_back(handle); |
| 374 #endif |
| 375 return handles; |
| 376 } |
| 377 |
292 // Client that can accept callbacks from a VideoDecodeAccelerator and is used by | 378 // Client that can accept callbacks from a VideoDecodeAccelerator and is used by |
293 // the TESTs below. | 379 // the TESTs below. |
294 class GLRenderingVDAClient | 380 class GLRenderingVDAClient |
295 : public VideoDecodeAccelerator::Client, | 381 : public VideoDecodeAccelerator::Client, |
296 public base::SupportsWeakPtr<GLRenderingVDAClient> { | 382 public base::SupportsWeakPtr<GLRenderingVDAClient> { |
297 public: | 383 public: |
298 // |window_id| the window_id of the client, which is used to identify the | 384 // |window_id| the window_id of the client, which is used to identify the |
299 // rendering area in the |rendering_helper|. | 385 // rendering area in the |rendering_helper|. |
300 // Doesn't take ownership of |rendering_helper| or |note|, which must outlive | 386 // Doesn't take ownership of |rendering_helper| or |note|, which must outlive |
301 // |*this|. | 387 // |*this|. |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 } else { | 610 } else { |
525 if (!vda_factory_) { | 611 if (!vda_factory_) { |
526 vda_factory_ = GpuVideoDecodeAcceleratorFactoryImpl::Create( | 612 vda_factory_ = GpuVideoDecodeAcceleratorFactoryImpl::Create( |
527 base::Bind(&RenderingHelper::GetGLContext, | 613 base::Bind(&RenderingHelper::GetGLContext, |
528 base::Unretained(rendering_helper_)), | 614 base::Unretained(rendering_helper_)), |
529 base::Bind(&DoNothingReturnTrue), base::Bind(&DummyBindImage)); | 615 base::Bind(&DoNothingReturnTrue), base::Bind(&DummyBindImage)); |
530 LOG_ASSERT(vda_factory_); | 616 LOG_ASSERT(vda_factory_); |
531 } | 617 } |
532 | 618 |
533 VideoDecodeAccelerator::Config config(profile_); | 619 VideoDecodeAccelerator::Config config(profile_); |
| 620 if (g_test_import) { |
| 621 config.output_mode = |
| 622 media::VideoDecodeAccelerator::Config::OutputMode::IMPORT; |
| 623 } |
534 gpu::GpuPreferences gpu_preferences; | 624 gpu::GpuPreferences gpu_preferences; |
535 decoder_ = vda_factory_->CreateVDA(this, config, gpu_preferences); | 625 decoder_ = vda_factory_->CreateVDA(this, config, gpu_preferences); |
536 } | 626 } |
537 | 627 |
538 LOG_ASSERT(decoder_) << "Failed creating a VDA"; | 628 LOG_ASSERT(decoder_) << "Failed creating a VDA"; |
539 | 629 |
540 decoder_->TryToSetupDecodeOnSeparateThread( | 630 decoder_->TryToSetupDecodeOnSeparateThread( |
541 weak_this_, base::ThreadTaskRunnerHandle::Get()); | 631 weak_this_, base::ThreadTaskRunnerHandle::Get()); |
542 | 632 |
543 SetState(CS_DECODER_SET); | 633 SetState(CS_DECODER_SET); |
(...skipping 13 matching lines...) Expand all Loading... |
557 requested_num_of_buffers += kExtraPictureBuffers; | 647 requested_num_of_buffers += kExtraPictureBuffers; |
558 | 648 |
559 texture_target_ = texture_target; | 649 texture_target_ = texture_target; |
560 for (uint32_t i = 0; i < requested_num_of_buffers; ++i) { | 650 for (uint32_t i = 0; i < requested_num_of_buffers; ++i) { |
561 uint32_t texture_id; | 651 uint32_t texture_id; |
562 base::WaitableEvent done(false, false); | 652 base::WaitableEvent done(false, false); |
563 rendering_helper_->CreateTexture( | 653 rendering_helper_->CreateTexture( |
564 texture_target_, &texture_id, dimensions, &done); | 654 texture_target_, &texture_id, dimensions, &done); |
565 done.Wait(); | 655 done.Wait(); |
566 | 656 |
| 657 scoped_refptr<TextureRef> texture_ref; |
| 658 base::Closure delete_texture_cb = |
| 659 base::Bind(&RenderingHelper::DeleteTexture, |
| 660 base::Unretained(rendering_helper_), texture_id); |
| 661 |
| 662 if (g_test_import) { |
| 663 media::VideoPixelFormat pixel_format = decoder_->GetOutputFormat(); |
| 664 if (pixel_format == media::PIXEL_FORMAT_UNKNOWN) |
| 665 pixel_format = media::PIXEL_FORMAT_ARGB; |
| 666 texture_ref = TextureRef::CreatePreallocated( |
| 667 texture_id, delete_texture_cb, pixel_format, dimensions); |
| 668 } else { |
| 669 texture_ref = TextureRef::Create(texture_id, delete_texture_cb); |
| 670 } |
| 671 |
| 672 LOG_ASSERT(texture_ref); |
| 673 |
567 int32_t picture_buffer_id = next_picture_buffer_id_++; | 674 int32_t picture_buffer_id = next_picture_buffer_id_++; |
568 LOG_ASSERT(active_textures_ | 675 LOG_ASSERT( |
569 .insert(std::make_pair( | 676 active_textures_.insert(std::make_pair(picture_buffer_id, texture_ref)) |
570 picture_buffer_id, | 677 .second); |
571 new TextureRef(texture_id, | |
572 base::Bind(&RenderingHelper::DeleteTexture, | |
573 base::Unretained(rendering_helper_), | |
574 texture_id)))) | |
575 .second); | |
576 | 678 |
577 media::PictureBuffer::TextureIds ids; | 679 media::PictureBuffer::TextureIds ids; |
578 ids.push_back(texture_id); | 680 ids.push_back(texture_id); |
579 buffers.push_back(media::PictureBuffer(picture_buffer_id, dimensions, ids)); | 681 buffers.push_back(media::PictureBuffer(picture_buffer_id, dimensions, ids)); |
580 } | 682 } |
581 decoder_->AssignPictureBuffers(buffers); | 683 decoder_->AssignPictureBuffers(buffers); |
| 684 |
| 685 if (g_test_import) { |
| 686 for (const auto& buffer : buffers) { |
| 687 TextureRefMap::iterator texture_it = active_textures_.find(buffer.id()); |
| 688 ASSERT_NE(active_textures_.end(), texture_it); |
| 689 |
| 690 std::vector<gfx::GpuMemoryBufferHandle> handles = |
| 691 texture_it->second->ExportGpuMemoryBufferHandles(); |
| 692 LOG_ASSERT(!handles.empty()) << "Failed producing GMB handles"; |
| 693 |
| 694 decoder_->ImportBufferForPicture(buffer.id(), handles); |
| 695 } |
| 696 } |
582 } | 697 } |
583 | 698 |
584 void GLRenderingVDAClient::DismissPictureBuffer(int32_t picture_buffer_id) { | 699 void GLRenderingVDAClient::DismissPictureBuffer(int32_t picture_buffer_id) { |
585 LOG_ASSERT(1U == active_textures_.erase(picture_buffer_id)); | 700 LOG_ASSERT(1U == active_textures_.erase(picture_buffer_id)); |
586 } | 701 } |
587 | 702 |
588 void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { | 703 void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { |
589 // We shouldn't be getting pictures delivered after Reset has completed. | 704 // We shouldn't be getting pictures delivered after Reset has completed. |
590 LOG_ASSERT(state_ < CS_RESET); | 705 LOG_ASSERT(state_ < CS_RESET); |
591 | 706 |
(...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 continue; | 1665 continue; |
1551 } | 1666 } |
1552 if (it->first == "fake_decoder") { | 1667 if (it->first == "fake_decoder") { |
1553 content::g_fake_decoder = 1; | 1668 content::g_fake_decoder = 1; |
1554 continue; | 1669 continue; |
1555 } | 1670 } |
1556 if (it->first == "v" || it->first == "vmodule") | 1671 if (it->first == "v" || it->first == "vmodule") |
1557 continue; | 1672 continue; |
1558 if (it->first == "ozone-platform" || it->first == "ozone-use-surfaceless") | 1673 if (it->first == "ozone-platform" || it->first == "ozone-use-surfaceless") |
1559 continue; | 1674 continue; |
| 1675 if (it->first == "test_import") { |
| 1676 content::g_test_import = true; |
| 1677 continue; |
| 1678 } |
1560 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; | 1679 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; |
1561 } | 1680 } |
1562 | 1681 |
1563 base::ShadowingAtExitManager at_exit_manager; | 1682 base::ShadowingAtExitManager at_exit_manager; |
1564 #if defined(OS_WIN) || defined(USE_OZONE) | 1683 #if defined(OS_WIN) || defined(USE_OZONE) |
1565 // For windows the decoding thread initializes the media foundation decoder | 1684 // For windows the decoding thread initializes the media foundation decoder |
1566 // which uses COM. We need the thread to be a UI thread. | 1685 // which uses COM. We need the thread to be a UI thread. |
1567 // On Ozone, the backend initializes the event system using a UI | 1686 // On Ozone, the backend initializes the event system using a UI |
1568 // thread. | 1687 // thread. |
1569 base::MessageLoopForUI main_loop; | 1688 base::MessageLoopForUI main_loop; |
1570 #else | 1689 #else |
1571 base::MessageLoop main_loop; | 1690 base::MessageLoop main_loop; |
1572 #endif // OS_WIN || USE_OZONE | 1691 #endif // OS_WIN || USE_OZONE |
1573 | 1692 |
1574 #if defined(USE_OZONE) | 1693 #if defined(USE_OZONE) |
1575 ui::OzonePlatform::InitializeForUI(); | 1694 ui::OzonePlatform::InitializeForUI(); |
1576 #endif | 1695 #endif |
1577 | 1696 |
1578 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) | 1697 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
1579 content::VaapiWrapper::PreSandboxInitialization(); | 1698 content::VaapiWrapper::PreSandboxInitialization(); |
1580 #endif | 1699 #endif |
1581 | 1700 |
1582 content::g_env = | 1701 content::g_env = |
1583 reinterpret_cast<content::VideoDecodeAcceleratorTestEnvironment*>( | 1702 reinterpret_cast<content::VideoDecodeAcceleratorTestEnvironment*>( |
1584 testing::AddGlobalTestEnvironment( | 1703 testing::AddGlobalTestEnvironment( |
1585 new content::VideoDecodeAcceleratorTestEnvironment())); | 1704 new content::VideoDecodeAcceleratorTestEnvironment())); |
1586 | 1705 |
1587 return RUN_ALL_TESTS(); | 1706 return RUN_ALL_TESTS(); |
1588 } | 1707 } |
OLD | NEW |