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.

147 lines
5.0 KiB

  1. //
  2. // SCCaptureDeviceResolver.m
  3. // Snapchat
  4. //
  5. // Created by Lin Jia on 11/8/17.
  6. //
  7. //
  8. #import "SCCaptureDeviceResolver.h"
  9. #import "SCCameraTweaks.h"
  10. #import <SCBase/SCAvailability.h>
  11. #import <SCFoundation/SCAssertWrapper.h>
  12. @interface SCCaptureDeviceResolver () {
  13. AVCaptureDeviceDiscoverySession *_discoverySession;
  14. }
  15. @end
  16. @implementation SCCaptureDeviceResolver
  17. + (instancetype)sharedInstance
  18. {
  19. static SCCaptureDeviceResolver *resolver;
  20. static dispatch_once_t onceToken;
  21. dispatch_once(&onceToken, ^{
  22. resolver = [[SCCaptureDeviceResolver alloc] init];
  23. });
  24. return resolver;
  25. }
  26. - (instancetype)init
  27. {
  28. self = [super init];
  29. if (self) {
  30. NSMutableArray *deviceTypes = [[NSMutableArray alloc] init];
  31. [deviceTypes addObject:AVCaptureDeviceTypeBuiltInWideAngleCamera];
  32. if (SC_AT_LEAST_IOS_10_2) {
  33. [deviceTypes addObject:AVCaptureDeviceTypeBuiltInDualCamera];
  34. }
  35. // TODO: we should KVO _discoverySession.devices.
  36. _discoverySession =
  37. [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:deviceTypes
  38. mediaType:AVMediaTypeVideo
  39. position:AVCaptureDevicePositionUnspecified];
  40. }
  41. return self;
  42. }
  43. - (AVCaptureDevice *)findAVCaptureDevice:(AVCaptureDevicePosition)position
  44. {
  45. SCAssert(position == AVCaptureDevicePositionFront || position == AVCaptureDevicePositionBack, @"");
  46. AVCaptureDevice *captureDevice;
  47. if (position == AVCaptureDevicePositionFront) {
  48. captureDevice = [self _pickBestFrontCamera:[_discoverySession.devices copy]];
  49. } else if (position == AVCaptureDevicePositionBack) {
  50. captureDevice = [self _pickBestBackCamera:[_discoverySession.devices copy]];
  51. }
  52. if (captureDevice) {
  53. return captureDevice;
  54. }
  55. if (SC_AT_LEAST_IOS_10_2 && SCCameraTweaksEnableDualCamera()) {
  56. captureDevice = [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInDualCamera
  57. mediaType:AVMediaTypeVideo
  58. position:position];
  59. if (captureDevice) {
  60. return captureDevice;
  61. }
  62. }
  63. // if code still execute, discoverSession failed, then we keep searching.
  64. captureDevice = [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera
  65. mediaType:AVMediaTypeVideo
  66. position:position];
  67. if (captureDevice) {
  68. return captureDevice;
  69. }
  70. #if !TARGET_IPHONE_SIMULATOR
  71. // We do not return nil at the beginning of the function for simulator, because simulators of different IOS
  72. // versions can check whether or not our camera device API access is correct.
  73. SCAssertFail(@"No camera is found.");
  74. #endif
  75. return nil;
  76. }
  77. - (AVCaptureDevice *)_pickBestFrontCamera:(NSArray<AVCaptureDevice *> *)devices
  78. {
  79. for (AVCaptureDevice *device in devices) {
  80. if (device.position == AVCaptureDevicePositionFront) {
  81. return device;
  82. }
  83. }
  84. return nil;
  85. }
  86. - (AVCaptureDevice *)_pickBestBackCamera:(NSArray<AVCaptureDevice *> *)devices
  87. {
  88. // Look for dual camera first if needed. If dual camera not found, continue to look for wide angle camera.
  89. if (SC_AT_LEAST_IOS_10_2 && SCCameraTweaksEnableDualCamera()) {
  90. for (AVCaptureDevice *device in devices) {
  91. if (device.position == AVCaptureDevicePositionBack &&
  92. device.deviceType == AVCaptureDeviceTypeBuiltInDualCamera) {
  93. return device;
  94. }
  95. }
  96. }
  97. for (AVCaptureDevice *device in devices) {
  98. if (device.position == AVCaptureDevicePositionBack &&
  99. device.deviceType == AVCaptureDeviceTypeBuiltInWideAngleCamera) {
  100. return device;
  101. }
  102. }
  103. return nil;
  104. }
  105. - (AVCaptureDevice *)findDualCamera
  106. {
  107. if (SC_AT_LEAST_IOS_10_2) {
  108. for (AVCaptureDevice *device in [_discoverySession.devices copy]) {
  109. if (device.position == AVCaptureDevicePositionBack &&
  110. device.deviceType == AVCaptureDeviceTypeBuiltInDualCamera) {
  111. return device;
  112. }
  113. }
  114. }
  115. AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInDualCamera
  116. mediaType:AVMediaTypeVideo
  117. position:AVCaptureDevicePositionBack];
  118. if (captureDevice) {
  119. return captureDevice;
  120. }
  121. #if !TARGET_IPHONE_SIMULATOR
  122. // We do not return nil at the beginning of the function for simulator, because simulators of different IOS
  123. // versions can check whether or not our camera device API access is correct.
  124. SCAssertFail(@"No camera is found.");
  125. #endif
  126. return nil;
  127. }
  128. @end