face_detection_provider_win.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright 2017 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 "services/shape_detection/face_detection_provider_win.h"
  5. #include <windows.media.faceanalysis.h>
  6. #include "base/bind.h"
  7. #include "base/logging.h"
  8. #include "base/scoped_generic.h"
  9. #include "base/win/core_winrt_util.h"
  10. #include "base/win/post_async_results.h"
  11. #include "base/win/scoped_hstring.h"
  12. #include "base/win/windows_version.h"
  13. #include "mojo/public/cpp/bindings/pending_receiver.h"
  14. #include "mojo/public/cpp/bindings/self_owned_receiver.h"
  15. namespace shape_detection {
  16. namespace {
  17. using ABI::Windows::Foundation::IAsyncOperation;
  18. using ABI::Windows::Graphics::Imaging::BitmapPixelFormat;
  19. using ABI::Windows::Graphics::Imaging::ISoftwareBitmapStatics;
  20. using ABI::Windows::Media::FaceAnalysis::FaceDetector;
  21. using ABI::Windows::Media::FaceAnalysis::IFaceDetector;
  22. using ABI::Windows::Media::FaceAnalysis::IFaceDetectorStatics;
  23. using base::win::GetActivationFactory;
  24. using base::win::ScopedHString;
  25. using Microsoft::WRL::ComPtr;
  26. BitmapPixelFormat GetPreferredPixelFormat(IFaceDetectorStatics* factory) {
  27. static constexpr BitmapPixelFormat kFormats[] = {
  28. ABI::Windows::Graphics::Imaging::BitmapPixelFormat_Gray8,
  29. ABI::Windows::Graphics::Imaging::BitmapPixelFormat_Nv12};
  30. for (const auto& format : kFormats) {
  31. boolean is_supported = false;
  32. factory->IsBitmapPixelFormatSupported(format, &is_supported);
  33. if (is_supported)
  34. return format;
  35. }
  36. return ABI::Windows::Graphics::Imaging::BitmapPixelFormat_Unknown;
  37. }
  38. } // namespace
  39. void FaceDetectionProviderWin::CreateFaceDetection(
  40. mojo::PendingReceiver<shape_detection::mojom::FaceDetection> receiver,
  41. shape_detection::mojom::FaceDetectorOptionsPtr options) {
  42. // FaceDetector class is only available in Win 10 onwards (v10.0.10240.0).
  43. if (base::win::GetVersion() < base::win::Version::WIN10) {
  44. DVLOG(1) << "FaceDetector not supported before Windows 10";
  45. return;
  46. }
  47. // Loads functions dynamically at runtime to prevent library dependencies.
  48. if (!(base::win::ResolveCoreWinRTDelayload() &&
  49. ScopedHString::ResolveCoreWinRTStringDelayload())) {
  50. DLOG(ERROR) << "Failed loading functions from combase.dll";
  51. return;
  52. }
  53. ComPtr<IFaceDetectorStatics> factory;
  54. HRESULT hr = GetActivationFactory<
  55. IFaceDetectorStatics,
  56. RuntimeClass_Windows_Media_FaceAnalysis_FaceDetector>(&factory);
  57. if (FAILED(hr)) {
  58. DLOG(ERROR) << "IFaceDetectorStatics factory failed: "
  59. << logging::SystemErrorCodeToString(hr);
  60. return;
  61. }
  62. boolean is_supported = false;
  63. factory->get_IsSupported(&is_supported);
  64. if (!is_supported)
  65. return;
  66. // In the current version, the FaceDetector class only supports images in
  67. // Gray8 or Nv12. Gray8 should be a good type but verify it against
  68. // FaceDetector’s supported formats.
  69. BitmapPixelFormat pixel_format = GetPreferredPixelFormat(factory.Get());
  70. if (pixel_format ==
  71. ABI::Windows::Graphics::Imaging::BitmapPixelFormat_Unknown) {
  72. return;
  73. }
  74. // Create an instance of FaceDetector asynchronously.
  75. ComPtr<IAsyncOperation<FaceDetector*>> async_op;
  76. hr = factory->CreateAsync(&async_op);
  77. if (FAILED(hr)) {
  78. DLOG(ERROR) << "Create FaceDetector failed: "
  79. << logging::SystemErrorCodeToString(hr);
  80. return;
  81. }
  82. // Use WeakPtr to bind the callback so that the once callback will not be run
  83. // if this object has been already destroyed.
  84. hr = base::win::PostAsyncResults(
  85. std::move(async_op),
  86. base::BindOnce(&FaceDetectionProviderWin::OnFaceDetectorCreated,
  87. weak_factory_.GetWeakPtr(), std::move(receiver),
  88. pixel_format));
  89. if (FAILED(hr)) {
  90. DLOG(ERROR) << "Begin async operation failed: "
  91. << logging::SystemErrorCodeToString(hr);
  92. return;
  93. }
  94. // When |provider| goes out of scope it will immediately close its end of
  95. // the message pipe, then the callback OnFaceDetectorCreated will be not
  96. // called. This prevents this object from being destroyed before the
  97. // AsyncOperation completes.
  98. receiver_->PauseIncomingMethodCallProcessing();
  99. }
  100. FaceDetectionProviderWin::FaceDetectionProviderWin() {}
  101. FaceDetectionProviderWin::~FaceDetectionProviderWin() = default;
  102. void FaceDetectionProviderWin::OnFaceDetectorCreated(
  103. mojo::PendingReceiver<shape_detection::mojom::FaceDetection> receiver,
  104. BitmapPixelFormat pixel_format,
  105. ComPtr<IFaceDetector> face_detector) {
  106. receiver_->ResumeIncomingMethodCallProcessing();
  107. if (!face_detector)
  108. return;
  109. ComPtr<ISoftwareBitmapStatics> bitmap_factory;
  110. const HRESULT hr = GetActivationFactory<
  111. ISoftwareBitmapStatics,
  112. RuntimeClass_Windows_Graphics_Imaging_SoftwareBitmap>(&bitmap_factory);
  113. if (FAILED(hr)) {
  114. DLOG(ERROR) << "ISoftwareBitmapStatics factory failed: "
  115. << logging::SystemErrorCodeToString(hr);
  116. return;
  117. }
  118. auto impl = std::make_unique<FaceDetectionImplWin>(
  119. std::move(face_detector), std::move(bitmap_factory), pixel_format);
  120. auto* impl_ptr = impl.get();
  121. impl_ptr->SetReceiver(
  122. mojo::MakeSelfOwnedReceiver(std::move(impl), std::move(receiver)));
  123. }
  124. } // namespace shape_detection