media_foundation_texture_pool.cc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // Copyright 2021 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.
  4. #include <dxgi1_2.h>
  5. #include "media/base/win/mf_helpers.h"
  6. #include "media/renderers/win/media_foundation_texture_pool.h"
  7. namespace {
  8. using Microsoft::WRL::ComPtr;
  9. // The Texture Count was determined empirically initially having a count of 30
  10. // and running many different video presentations in frame server mode and
  11. // recording the number of textures in use and the count never exceeded 3.
  12. // Therefore for a max of 3 in flight with the 3 being written requires that
  13. // we allocate 4 textures.
  14. constexpr int kTexturePoolCount = 4;
  15. } // namespace
  16. namespace media {
  17. MediaFoundationFrameInfo::MediaFoundationFrameInfo() = default;
  18. MediaFoundationFrameInfo::~MediaFoundationFrameInfo() = default;
  19. MediaFoundationFrameInfo::MediaFoundationFrameInfo(
  20. MediaFoundationFrameInfo&& other) = default;
  21. MediaFoundationTexturePool::TextureInfo::TextureInfo()
  22. : texture_in_use_(false) {}
  23. MediaFoundationTexturePool::TextureInfo::~TextureInfo() = default;
  24. MediaFoundationTexturePool::TextureInfo::TextureInfo(const TextureInfo& other) =
  25. default;
  26. MediaFoundationTexturePool::TextureInfo&
  27. MediaFoundationTexturePool::TextureInfo::operator=(
  28. const MediaFoundationTexturePool::TextureInfo& other) = default;
  29. MediaFoundationTexturePool::MediaFoundationTexturePool() = default;
  30. MediaFoundationTexturePool::~MediaFoundationTexturePool() = default;
  31. // TODO(crbug.com/1278157): The pool should release the textures when the media
  32. // engine is idling to save resources.
  33. HRESULT MediaFoundationTexturePool::Initialize(
  34. ID3D11Device* device,
  35. FramePoolInitializedCallback frame_pool_cb,
  36. const gfx::Size& frame_size) {
  37. D3D11_TEXTURE2D_DESC desc{
  38. static_cast<UINT>(frame_size.width()),
  39. static_cast<UINT>(frame_size.height()),
  40. 1,
  41. 1,
  42. // TODO(crbug.com/1276134): Need to handle higher bit-depths like HDR.
  43. DXGI_FORMAT_R8G8B8A8_UNORM,
  44. {1, 0},
  45. D3D11_USAGE_DEFAULT,
  46. D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
  47. 0,
  48. D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
  49. D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX};
  50. std::vector<MediaFoundationFrameInfo> frame_infos;
  51. bool callback_is_valid = !frame_pool_cb.is_null();
  52. if (callback_is_valid) {
  53. frame_infos.reserve(kTexturePoolCount);
  54. }
  55. // We can be reinitialized so remove all the previous textures from our
  56. // pool.
  57. texture_pool_.clear();
  58. for (int i = 0; i < kTexturePoolCount; ++i) {
  59. auto texture_info_element = std::make_unique<TextureInfo>();
  60. auto texture_token = base::UnguessableToken::Create();
  61. ComPtr<ID3D11Texture2D> d3d11_video_frame;
  62. RETURN_IF_FAILED(
  63. device->CreateTexture2D(&desc, nullptr, &d3d11_video_frame));
  64. SetDebugName(d3d11_video_frame.Get(), "Media_MFFrameServerMode_Pool");
  65. ComPtr<IDXGIResource1> d3d11_video_frame_resource;
  66. RETURN_IF_FAILED(d3d11_video_frame.As(&d3d11_video_frame_resource));
  67. HANDLE shared_texture_handle;
  68. RETURN_IF_FAILED(d3d11_video_frame_resource->CreateSharedHandle(
  69. nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
  70. nullptr, &shared_texture_handle));
  71. base::win::ScopedHandle scoped_shared_texture_handle;
  72. scoped_shared_texture_handle.Set(shared_texture_handle);
  73. shared_texture_handle = nullptr;
  74. texture_pool_[texture_token].texture_ = std::move(d3d11_video_frame);
  75. texture_pool_[texture_token].texture_in_use_ = false;
  76. if (callback_is_valid) {
  77. MediaFoundationFrameInfo frame_info;
  78. frame_info.dxgi_handle = std::move(scoped_shared_texture_handle);
  79. frame_info.token = texture_token;
  80. frame_infos.emplace_back(std::move(frame_info));
  81. }
  82. }
  83. if (callback_is_valid) {
  84. frame_pool_cb.Run(std::move(frame_infos), frame_size);
  85. }
  86. return S_OK;
  87. }
  88. ComPtr<ID3D11Texture2D> MediaFoundationTexturePool::AcquireTexture(
  89. base::UnguessableToken* texture_token) {
  90. for (auto& texture_item : texture_pool_) {
  91. if (!texture_item.second.texture_in_use_) {
  92. *texture_token = texture_item.first;
  93. texture_item.second.texture_in_use_ = true;
  94. return texture_item.second.texture_;
  95. }
  96. }
  97. return nullptr;
  98. }
  99. void MediaFoundationTexturePool::ReleaseTexture(
  100. const base::UnguessableToken& texture_token) {
  101. auto it = texture_pool_.find(texture_token);
  102. if (it != texture_pool_.end()) {
  103. it->second.texture_in_use_ = false;
  104. }
  105. }
  106. } // namespace media