Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(380)

Side by Side Diff: services/shape_detection/face_detection_impl_mac.mm

Issue 2528743002: Shape Detection: Implement FaceDetection on Mac as out-of-process service (Closed)
Patch Set: Use media::ScopedResultCallback Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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
5 #include "services/shape_detection/face_detection_impl_mac.h"
6
7 #include "base/mac/scoped_cftyperef.h"
8 #include "base/mac/scoped_nsobject.h"
9 #include "base/memory/shared_memory.h"
10 #include "media/capture/video/scoped_result_callback.h"
11 #include "mojo/public/cpp/bindings/strong_binding.h"
12 #include "mojo/public/cpp/system/platform_handle.h"
13
14 namespace shape_detection {
15
16 // kCIFormatRGBA8 is not exposed to public until Mac 10.11. So we define the
17 // same constant to support RGBA8 format in earlier versions.
18
19 #if !defined(MAC_OS_X_VERSION_10_11) || \
20 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_11
21 namespace {
22
23 const int kCIFormatRGBA8 = 24;
24
25 } // anonymous namespace
26 #endif
27
28 void FaceDetectionImpl::Create(blink::mojom::FaceDetectionRequest request) {
29 mojo::MakeStrongBinding(base::MakeUnique<FaceDetectionImplMac>(),
30 std::move(request));
31 }
32
33 FaceDetectionImplMac::FaceDetectionImplMac() {
34 context_.reset([[CIContext alloc] init]);
35 NSDictionary* const opts = @{CIDetectorAccuracy : CIDetectorAccuracyHigh};
36 detector_.reset([[CIDetector detectorOfType:CIDetectorTypeFace
37 context:context_
38 options:opts] retain]);
39 }
40
41 FaceDetectionImplMac::~FaceDetectionImplMac() {}
42
43 void FaceDetectionImplMac::Detect(mojo::ScopedSharedBufferHandle frame_data,
44 uint32_t width,
45 uint32_t height,
46 blink::mojom::FaceDetectorOptionsPtr options,
47 const DetectCallback& callback) {
48 media::ScopedResultCallback<DetectCallback> scoped_callback(
49 base::Bind(&FaceDetectionImplMac::RunCallbackWithFaces, callback),
50 base::Bind(&FaceDetectionImplMac::RunCallbackWithNoFaces));
51
52 base::CheckedNumeric<uint32_t> num_pixels =
53 base::CheckedNumeric<uint32_t>(width) * height;
54 base::CheckedNumeric<uint32_t> num_bytes = num_pixels * 4;
55 if (!num_bytes.IsValid()) {
56 DLOG(ERROR) << "Data overflow";
57 return;
58 }
59
60 base::SharedMemoryHandle memory_handle;
61 size_t memory_size = 0;
62 bool read_only_flag = false;
63 const MojoResult result = mojo::UnwrapSharedMemoryHandle(
64 std::move(frame_data), &memory_handle, &memory_size, &read_only_flag);
65 DCHECK_EQ(MOJO_RESULT_OK, result) << "Failed to unwrap SharedBufferHandle";
66 if (!memory_size || memory_size != num_bytes.ValueOrDie()) {
67 DLOG(ERROR) << "Invalid image size";
68 return;
69 }
70
71 std::unique_ptr<base::SharedMemory> shared_memory(
72 new base::SharedMemory(memory_handle, true /* read_only */));
Avi (use Gerrit) 2016/12/06 05:44:21 Can we do auto shared_memory = base::MakeUnique<b
xianglu 2016/12/08 01:20:54 Done.
73 if (!shared_memory->Map(memory_size)) {
74 DLOG(ERROR) << "Failed to map bytes from shared memory";
75 return;
76 }
77
78 NSData* byte_data = [NSData dataWithBytesNoCopy:shared_memory->memory()
79 length:num_bytes.ValueOrDie()
80 freeWhenDone:NO];
81
82 base::ScopedCFTypeRef<CGColorSpaceRef> colorspace(
83 CGColorSpaceCreateWithName(kCGColorSpaceSRGB));
84
85 // CIImage will return nil when RGBA8 is not supported in a certain sion.
Avi (use Gerrit) 2016/12/06 05:44:21 "sion"? Do you mean version? Have you actually te
xianglu 2016/12/08 01:20:54 Yes. The format is supported since 10.4.
86 base::scoped_nsobject<CIImage> ci_image([[CIImage alloc]
87 initWithBitmapData:byte_data
88 bytesPerRow:width * 4
89 size:CGSizeMake(width, height)
90 format:kCIFormatRGBA8
91 colorSpace:colorspace]);
92 if (!ci_image) {
93 DLOG(ERROR) << "Failed to create CIImage";
94 return;
95 }
96
97 NSArray* const features = [detector_ featuresInImage:ci_image];
98
99 blink::mojom::FaceDetectionResultPtr faces =
100 blink::mojom::FaceDetectionResult::New();
101 for (CIFaceFeature* const f in features) {
102 // In the default Core Graphics coordinate space, the origin is located
103 // in the lower-left corner, and thus |ci_image| is flipped vertically.
104 // We need to adjust |y| coordinate of bounding box before sending it .
Avi (use Gerrit) 2016/12/06 05:44:21 no space before the .
xianglu 2016/12/08 01:20:54 Done.
105 gfx::RectF boundingbox(f.bounds.origin.x,
106 height - f.bounds.origin.y - f.bounds.size.height,
107 f.bounds.size.width, f.bounds.size.height);
108 faces->bounding_boxes.push_back(boundingbox);
109 }
110 scoped_callback.Run(std::move(faces));
111 }
112
113 void FaceDetectionImplMac::RunCallbackWithFaces(
114 const DetectCallback& callback,
115 blink::mojom::FaceDetectionResultPtr faces) {
116 callback.Run(std::move(faces));
117 }
118
119 void FaceDetectionImplMac::RunCallbackWithNoFaces(
120 const DetectCallback& callback) {
121 callback.Run(blink::mojom::FaceDetectionResult::New());
122 }
123
124 } // namespace shape_detection
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698