2014 snapchat source code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
4.2 KiB

  1. //
  2. // SCManagedCaptureDeviceFaceDetectionAutoExposureHandler.m
  3. // Snapchat
  4. //
  5. // Created by Jiyang Zhu on 3/6/18.
  6. // Copyright © 2018 Snapchat, Inc. All rights reserved.
  7. //
  8. #import "SCManagedCaptureDeviceFaceDetectionAutoExposureHandler.h"
  9. #import "AVCaptureDevice+ConfigurationLock.h"
  10. #import "SCCameraTweaks.h"
  11. #import "SCManagedCaptureDeviceExposureHandler.h"
  12. #import "SCManagedCaptureFaceDetectionAdjustingPOIResource.h"
  13. #import "SCManagedCapturer.h"
  14. #import "SCManagedCapturerListener.h"
  15. #import <SCFoundation/SCAssertWrapper.h>
  16. #import <SCFoundation/SCTrace.h>
  17. #import <SCFoundation/SCTraceODPCompatible.h>
  18. @import AVFoundation;
  19. @interface SCManagedCaptureDeviceFaceDetectionAutoExposureHandler () <SCManagedCapturerListener>
  20. @property (nonatomic, strong) AVCaptureDevice *device;
  21. @property (nonatomic, weak) id<SCCapturer> managedCapturer;
  22. @property (nonatomic, assign) CGPoint exposurePointOfInterest;
  23. @property (nonatomic, assign) BOOL isVisible;
  24. @property (nonatomic, copy) NSDictionary<NSNumber *, NSValue *> *faceBoundsByFaceID;
  25. @property (nonatomic, strong) SCManagedCaptureFaceDetectionAdjustingPOIResource *resource;
  26. @end
  27. @implementation SCManagedCaptureDeviceFaceDetectionAutoExposureHandler
  28. - (instancetype)initWithDevice:(AVCaptureDevice *)device
  29. pointOfInterest:(CGPoint)pointOfInterest
  30. managedCapturer:(id<SCCapturer>)managedCapturer
  31. {
  32. if (self = [super init]) {
  33. SCAssert(device, @"AVCaptureDevice should not be nil.");
  34. SCAssert(managedCapturer, @"id<SCCapturer> should not be nil.");
  35. _device = device;
  36. _exposurePointOfInterest = pointOfInterest;
  37. SCManagedCaptureDevicePosition position =
  38. (device.position == AVCaptureDevicePositionFront ? SCManagedCaptureDevicePositionFront
  39. : SCManagedCaptureDevicePositionBack);
  40. _resource = [[SCManagedCaptureFaceDetectionAdjustingPOIResource alloc]
  41. initWithDefaultPointOfInterest:pointOfInterest
  42. shouldTargetOnFaceAutomatically:SCCameraTweaksTurnOnFaceDetectionFocusByDefault(position)];
  43. _managedCapturer = managedCapturer;
  44. }
  45. return self;
  46. }
  47. - (void)dealloc
  48. {
  49. [_managedCapturer removeListener:self];
  50. }
  51. - (CGPoint)getExposurePointOfInterest
  52. {
  53. return self.exposurePointOfInterest;
  54. }
  55. - (void)setExposurePointOfInterest:(CGPoint)pointOfInterest fromUser:(BOOL)fromUser
  56. {
  57. SCTraceODPCompatibleStart(2);
  58. pointOfInterest = [self.resource updateWithNewProposedPointOfInterest:pointOfInterest fromUser:fromUser];
  59. [self _actuallySetExposurePointOfInterestIfNeeded:pointOfInterest];
  60. }
  61. - (void)_actuallySetExposurePointOfInterestIfNeeded:(CGPoint)pointOfInterest
  62. {
  63. SCTraceODPCompatibleStart(2);
  64. SC_GUARD_ELSE_RETURN(!CGPointEqualToPoint(pointOfInterest, self.exposurePointOfInterest));
  65. if ([self.device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure] &&
  66. [self.device isExposurePointOfInterestSupported]) {
  67. [self.device runTask:@"set exposure"
  68. withLockedConfiguration:^() {
  69. // Set exposure point before changing exposure mode
  70. // Be noticed that order does matter
  71. self.device.exposurePointOfInterest = pointOfInterest;
  72. self.device.exposureMode = AVCaptureExposureModeContinuousAutoExposure;
  73. }];
  74. }
  75. self.exposurePointOfInterest = pointOfInterest;
  76. }
  77. - (void)setStableExposure:(BOOL)stableExposure
  78. {
  79. }
  80. - (void)setVisible:(BOOL)visible
  81. {
  82. SCTraceODPCompatibleStart(2);
  83. SC_GUARD_ELSE_RETURN(_isVisible != visible);
  84. _isVisible = visible;
  85. if (visible) {
  86. [self.managedCapturer addListener:self];
  87. } else {
  88. [self.managedCapturer removeListener:self];
  89. [self.resource reset];
  90. }
  91. }
  92. #pragma mark - SCManagedCapturerListener
  93. - (void)managedCapturer:(id<SCCapturer>)managedCapturer
  94. didDetectFaceBounds:(NSDictionary<NSNumber *, NSValue *> *)faceBoundsByFaceID
  95. {
  96. SCTraceODPCompatibleStart(2);
  97. SC_GUARD_ELSE_RETURN(self.isVisible);
  98. CGPoint pointOfInterest = [self.resource updateWithNewDetectedFaceBounds:faceBoundsByFaceID];
  99. [self _actuallySetExposurePointOfInterestIfNeeded:pointOfInterest];
  100. }
  101. @end