face_detection_impl_win.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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_impl_win.h"
  5. #include "base/bind.h"
  6. #include "base/logging.h"
  7. #include "base/win/post_async_results.h"
  8. #include "services/shape_detection/detection_utils_win.h"
  9. namespace shape_detection {
  10. namespace {
  11. using ABI::Windows::Foundation::IAsyncOperation;
  12. using ABI::Windows::Foundation::Collections::IVector;
  13. using ABI::Windows::Graphics::Imaging::BitmapPixelFormat;
  14. using ABI::Windows::Media::FaceAnalysis::DetectedFace;
  15. using ABI::Windows::Media::FaceAnalysis::IDetectedFace;
  16. using ABI::Windows::Media::FaceAnalysis::IFaceDetector;
  17. using Microsoft::WRL::ComPtr;
  18. } // namespace
  19. FaceDetectionImplWin::FaceDetectionImplWin(
  20. ComPtr<IFaceDetector> face_detector,
  21. ComPtr<ISoftwareBitmapStatics> bitmap_factory,
  22. BitmapPixelFormat pixel_format)
  23. : face_detector_(std::move(face_detector)),
  24. bitmap_factory_(std::move(bitmap_factory)),
  25. pixel_format_(pixel_format) {
  26. DCHECK(face_detector_);
  27. DCHECK(bitmap_factory_);
  28. }
  29. FaceDetectionImplWin::~FaceDetectionImplWin() = default;
  30. void FaceDetectionImplWin::Detect(const SkBitmap& bitmap,
  31. DetectCallback callback) {
  32. if (FAILED(BeginDetect(bitmap))) {
  33. // No detection taking place; run |callback| with an empty array of results.
  34. std::move(callback).Run(std::vector<mojom::FaceDetectionResultPtr>());
  35. return;
  36. }
  37. // Hold on the callback until AsyncOperation completes.
  38. detected_face_callback_ = std::move(callback);
  39. // This prevents the Detect function from being called before the
  40. // AsyncOperation completes.
  41. receiver_->PauseIncomingMethodCallProcessing();
  42. }
  43. HRESULT FaceDetectionImplWin::BeginDetect(const SkBitmap& bitmap) {
  44. ComPtr<ISoftwareBitmap> win_bitmap = CreateWinBitmapWithPixelFormat(
  45. bitmap, bitmap_factory_.Get(), pixel_format_);
  46. if (!win_bitmap)
  47. return E_FAIL;
  48. // Detect faces asynchronously.
  49. ComPtr<IAsyncOperation<IVector<DetectedFace*>*>> async_op;
  50. HRESULT hr = face_detector_->DetectFacesAsync(win_bitmap.Get(), &async_op);
  51. if (FAILED(hr)) {
  52. DLOG(ERROR) << "Detect faces asynchronously failed: "
  53. << logging::SystemErrorCodeToString(hr);
  54. return hr;
  55. }
  56. // Use WeakPtr to bind the callback so that the once callback will not be run
  57. // if this object has been already destroyed. |win_bitmap| needs to be kept
  58. // alive until OnFaceDetected().
  59. hr = base::win::PostAsyncResults(
  60. std::move(async_op),
  61. base::BindOnce(&FaceDetectionImplWin::OnFaceDetected,
  62. weak_factory_.GetWeakPtr(), std::move(win_bitmap)));
  63. if (FAILED(hr)) {
  64. DLOG(ERROR) << "PostAsyncResults failed: "
  65. << logging::SystemErrorCodeToString(hr);
  66. return hr;
  67. }
  68. return hr;
  69. }
  70. std::vector<mojom::FaceDetectionResultPtr>
  71. FaceDetectionImplWin::BuildFaceDetectionResult(
  72. ComPtr<IVector<DetectedFace*>> detected_face) {
  73. std::vector<mojom::FaceDetectionResultPtr> results;
  74. if (!detected_face)
  75. return results;
  76. uint32_t count;
  77. HRESULT hr = detected_face->get_Size(&count);
  78. if (FAILED(hr)) {
  79. DLOG(ERROR) << "get_Size failed: " << logging::SystemErrorCodeToString(hr);
  80. return results;
  81. }
  82. results.reserve(count);
  83. for (uint32_t i = 0; i < count; i++) {
  84. ComPtr<IDetectedFace> face;
  85. hr = detected_face->GetAt(i, &face);
  86. if (FAILED(hr))
  87. break;
  88. ABI::Windows::Graphics::Imaging::BitmapBounds bounds;
  89. hr = face->get_FaceBox(&bounds);
  90. if (FAILED(hr))
  91. break;
  92. auto result = shape_detection::mojom::FaceDetectionResult::New();
  93. result->bounding_box =
  94. gfx::RectF(bounds.X, bounds.Y, bounds.Width, bounds.Height);
  95. results.push_back(std::move(result));
  96. }
  97. return results;
  98. }
  99. // |win_bitmap| is passed here so that it is kept alive until the AsyncOperation
  100. // completes because DetectFacesAsync does not hold a reference.
  101. void FaceDetectionImplWin::OnFaceDetected(
  102. ComPtr<ISoftwareBitmap> /* win_bitmap */,
  103. ComPtr<IVector<DetectedFace*>> result) {
  104. std::move(detected_face_callback_)
  105. .Run(BuildFaceDetectionResult(std::move(result)));
  106. receiver_->ResumeIncomingMethodCallProcessing();
  107. }
  108. } // namespace shape_detection