123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- // 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_provider_win.h"
- #include <windows.media.faceanalysis.h>
- #include "base/bind.h"
- #include "base/logging.h"
- #include "base/scoped_generic.h"
- #include "base/win/core_winrt_util.h"
- #include "base/win/post_async_results.h"
- #include "base/win/scoped_hstring.h"
- #include "base/win/windows_version.h"
- #include "mojo/public/cpp/bindings/pending_receiver.h"
- #include "mojo/public/cpp/bindings/self_owned_receiver.h"
- namespace shape_detection {
- namespace {
- using ABI::Windows::Foundation::IAsyncOperation;
- using ABI::Windows::Graphics::Imaging::BitmapPixelFormat;
- using ABI::Windows::Graphics::Imaging::ISoftwareBitmapStatics;
- using ABI::Windows::Media::FaceAnalysis::FaceDetector;
- using ABI::Windows::Media::FaceAnalysis::IFaceDetector;
- using ABI::Windows::Media::FaceAnalysis::IFaceDetectorStatics;
- using base::win::GetActivationFactory;
- using base::win::ScopedHString;
- using Microsoft::WRL::ComPtr;
- BitmapPixelFormat GetPreferredPixelFormat(IFaceDetectorStatics* factory) {
- static constexpr BitmapPixelFormat kFormats[] = {
- ABI::Windows::Graphics::Imaging::BitmapPixelFormat_Gray8,
- ABI::Windows::Graphics::Imaging::BitmapPixelFormat_Nv12};
- for (const auto& format : kFormats) {
- boolean is_supported = false;
- factory->IsBitmapPixelFormatSupported(format, &is_supported);
- if (is_supported)
- return format;
- }
- return ABI::Windows::Graphics::Imaging::BitmapPixelFormat_Unknown;
- }
- } // namespace
- void FaceDetectionProviderWin::CreateFaceDetection(
- mojo::PendingReceiver<shape_detection::mojom::FaceDetection> receiver,
- shape_detection::mojom::FaceDetectorOptionsPtr options) {
- // FaceDetector class is only available in Win 10 onwards (v10.0.10240.0).
- if (base::win::GetVersion() < base::win::Version::WIN10) {
- DVLOG(1) << "FaceDetector not supported before Windows 10";
- return;
- }
- // Loads functions dynamically at runtime to prevent library dependencies.
- if (!(base::win::ResolveCoreWinRTDelayload() &&
- ScopedHString::ResolveCoreWinRTStringDelayload())) {
- DLOG(ERROR) << "Failed loading functions from combase.dll";
- return;
- }
- ComPtr<IFaceDetectorStatics> factory;
- HRESULT hr = GetActivationFactory<
- IFaceDetectorStatics,
- RuntimeClass_Windows_Media_FaceAnalysis_FaceDetector>(&factory);
- if (FAILED(hr)) {
- DLOG(ERROR) << "IFaceDetectorStatics factory failed: "
- << logging::SystemErrorCodeToString(hr);
- return;
- }
- boolean is_supported = false;
- factory->get_IsSupported(&is_supported);
- if (!is_supported)
- return;
- // In the current version, the FaceDetector class only supports images in
- // Gray8 or Nv12. Gray8 should be a good type but verify it against
- // FaceDetector’s supported formats.
- BitmapPixelFormat pixel_format = GetPreferredPixelFormat(factory.Get());
- if (pixel_format ==
- ABI::Windows::Graphics::Imaging::BitmapPixelFormat_Unknown) {
- return;
- }
- // Create an instance of FaceDetector asynchronously.
- ComPtr<IAsyncOperation<FaceDetector*>> async_op;
- hr = factory->CreateAsync(&async_op);
- if (FAILED(hr)) {
- DLOG(ERROR) << "Create FaceDetector failed: "
- << logging::SystemErrorCodeToString(hr);
- return;
- }
- // Use WeakPtr to bind the callback so that the once callback will not be run
- // if this object has been already destroyed.
- hr = base::win::PostAsyncResults(
- std::move(async_op),
- base::BindOnce(&FaceDetectionProviderWin::OnFaceDetectorCreated,
- weak_factory_.GetWeakPtr(), std::move(receiver),
- pixel_format));
- if (FAILED(hr)) {
- DLOG(ERROR) << "Begin async operation failed: "
- << logging::SystemErrorCodeToString(hr);
- return;
- }
- // When |provider| goes out of scope it will immediately close its end of
- // the message pipe, then the callback OnFaceDetectorCreated will be not
- // called. This prevents this object from being destroyed before the
- // AsyncOperation completes.
- receiver_->PauseIncomingMethodCallProcessing();
- }
- FaceDetectionProviderWin::FaceDetectionProviderWin() {}
- FaceDetectionProviderWin::~FaceDetectionProviderWin() = default;
- void FaceDetectionProviderWin::OnFaceDetectorCreated(
- mojo::PendingReceiver<shape_detection::mojom::FaceDetection> receiver,
- BitmapPixelFormat pixel_format,
- ComPtr<IFaceDetector> face_detector) {
- receiver_->ResumeIncomingMethodCallProcessing();
- if (!face_detector)
- return;
- ComPtr<ISoftwareBitmapStatics> bitmap_factory;
- const HRESULT hr = GetActivationFactory<
- ISoftwareBitmapStatics,
- RuntimeClass_Windows_Graphics_Imaging_SoftwareBitmap>(&bitmap_factory);
- if (FAILED(hr)) {
- DLOG(ERROR) << "ISoftwareBitmapStatics factory failed: "
- << logging::SystemErrorCodeToString(hr);
- return;
- }
- auto impl = std::make_unique<FaceDetectionImplWin>(
- std::move(face_detector), std::move(bitmap_factory), pixel_format);
- auto* impl_ptr = impl.get();
- impl_ptr->SetReceiver(
- mojo::MakeSelfOwnedReceiver(std::move(impl), std::move(receiver)));
- }
- } // namespace shape_detection
|