123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- // Copyright 2017 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "services/shape_detection/face_detection_impl_win.h"
- #include "base/bind.h"
- #include "base/logging.h"
- #include "base/win/post_async_results.h"
- #include "services/shape_detection/detection_utils_win.h"
- namespace shape_detection {
- namespace {
- using ABI::Windows::Foundation::IAsyncOperation;
- using ABI::Windows::Foundation::Collections::IVector;
- using ABI::Windows::Graphics::Imaging::BitmapPixelFormat;
- using ABI::Windows::Media::FaceAnalysis::DetectedFace;
- using ABI::Windows::Media::FaceAnalysis::IDetectedFace;
- using ABI::Windows::Media::FaceAnalysis::IFaceDetector;
- using Microsoft::WRL::ComPtr;
- } // namespace
- FaceDetectionImplWin::FaceDetectionImplWin(
- ComPtr<IFaceDetector> face_detector,
- ComPtr<ISoftwareBitmapStatics> bitmap_factory,
- BitmapPixelFormat pixel_format)
- : face_detector_(std::move(face_detector)),
- bitmap_factory_(std::move(bitmap_factory)),
- pixel_format_(pixel_format) {
- DCHECK(face_detector_);
- DCHECK(bitmap_factory_);
- }
- FaceDetectionImplWin::~FaceDetectionImplWin() = default;
- void FaceDetectionImplWin::Detect(const SkBitmap& bitmap,
- DetectCallback callback) {
- if (FAILED(BeginDetect(bitmap))) {
- // No detection taking place; run |callback| with an empty array of results.
- std::move(callback).Run(std::vector<mojom::FaceDetectionResultPtr>());
- return;
- }
- // Hold on the callback until AsyncOperation completes.
- detected_face_callback_ = std::move(callback);
- // This prevents the Detect function from being called before the
- // AsyncOperation completes.
- receiver_->PauseIncomingMethodCallProcessing();
- }
- HRESULT FaceDetectionImplWin::BeginDetect(const SkBitmap& bitmap) {
- ComPtr<ISoftwareBitmap> win_bitmap = CreateWinBitmapWithPixelFormat(
- bitmap, bitmap_factory_.Get(), pixel_format_);
- if (!win_bitmap)
- return E_FAIL;
- // Detect faces asynchronously.
- ComPtr<IAsyncOperation<IVector<DetectedFace*>*>> async_op;
- HRESULT hr = face_detector_->DetectFacesAsync(win_bitmap.Get(), &async_op);
- if (FAILED(hr)) {
- DLOG(ERROR) << "Detect faces asynchronously failed: "
- << logging::SystemErrorCodeToString(hr);
- return hr;
- }
- // Use WeakPtr to bind the callback so that the once callback will not be run
- // if this object has been already destroyed. |win_bitmap| needs to be kept
- // alive until OnFaceDetected().
- hr = base::win::PostAsyncResults(
- std::move(async_op),
- base::BindOnce(&FaceDetectionImplWin::OnFaceDetected,
- weak_factory_.GetWeakPtr(), std::move(win_bitmap)));
- if (FAILED(hr)) {
- DLOG(ERROR) << "PostAsyncResults failed: "
- << logging::SystemErrorCodeToString(hr);
- return hr;
- }
- return hr;
- }
- std::vector<mojom::FaceDetectionResultPtr>
- FaceDetectionImplWin::BuildFaceDetectionResult(
- ComPtr<IVector<DetectedFace*>> detected_face) {
- std::vector<mojom::FaceDetectionResultPtr> results;
- if (!detected_face)
- return results;
- uint32_t count;
- HRESULT hr = detected_face->get_Size(&count);
- if (FAILED(hr)) {
- DLOG(ERROR) << "get_Size failed: " << logging::SystemErrorCodeToString(hr);
- return results;
- }
- results.reserve(count);
- for (uint32_t i = 0; i < count; i++) {
- ComPtr<IDetectedFace> face;
- hr = detected_face->GetAt(i, &face);
- if (FAILED(hr))
- break;
- ABI::Windows::Graphics::Imaging::BitmapBounds bounds;
- hr = face->get_FaceBox(&bounds);
- if (FAILED(hr))
- break;
- auto result = shape_detection::mojom::FaceDetectionResult::New();
- result->bounding_box =
- gfx::RectF(bounds.X, bounds.Y, bounds.Width, bounds.Height);
- results.push_back(std::move(result));
- }
- return results;
- }
- // |win_bitmap| is passed here so that it is kept alive until the AsyncOperation
- // completes because DetectFacesAsync does not hold a reference.
- void FaceDetectionImplWin::OnFaceDetected(
- ComPtr<ISoftwareBitmap> /* win_bitmap */,
- ComPtr<IVector<DetectedFace*>> result) {
- std::move(detected_face_callback_)
- .Run(BuildFaceDetectionResult(std::move(result)));
- receiver_->ResumeIncomingMethodCallProcessing();
- }
- } // namespace shape_detection
|