@capacitor-community/camera-preview 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/CapacitorCommunityCameraPreview.podspec +3 -2
  2. package/LICENSE +21 -0
  3. package/README.md +61 -57
  4. package/android/.gradle/4.10.1/fileChanges/last-build.bin +0 -0
  5. package/android/.gradle/4.10.1/fileHashes/fileHashes.bin +0 -0
  6. package/android/.gradle/4.10.1/fileHashes/fileHashes.lock +0 -0
  7. package/android/.gradle/4.10.1/gc.properties +0 -0
  8. package/android/.gradle/vcs-1/gc.properties +0 -0
  9. package/android/.idea/compiler.xml +6 -0
  10. package/android/.idea/gradle.xml +20 -0
  11. package/android/.idea/jarRepositories.xml +45 -0
  12. package/android/.idea/libraries/Gradle__androidx_activity_activity_1_2_0_aar.xml +14 -0
  13. package/android/.idea/libraries/Gradle__androidx_activity_activity_1_2_3_aar.xml +14 -0
  14. package/android/.idea/libraries/Gradle__androidx_annotation_annotation_1_1_0.xml +9 -0
  15. package/android/.idea/libraries/Gradle__androidx_annotation_annotation_1_2_0.xml +9 -0
  16. package/android/.idea/libraries/Gradle__androidx_annotation_annotation_experimental_1_0_0_aar.xml +11 -0
  17. package/android/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_2_0_aar.xml +14 -0
  18. package/android/.idea/libraries/Gradle__androidx_appcompat_appcompat_1_3_0_aar.xml +14 -0
  19. package/android/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_2_0_aar.xml +11 -0
  20. package/android/.idea/libraries/Gradle__androidx_appcompat_appcompat_resources_1_3_0_aar.xml +11 -0
  21. package/android/.idea/libraries/Gradle__androidx_arch_core_core_common_2_1_0.xml +9 -0
  22. package/android/.idea/libraries/Gradle__androidx_arch_core_core_runtime_2_1_0_aar.xml +11 -0
  23. package/android/.idea/libraries/Gradle__androidx_collection_collection_1_1_0.xml +9 -0
  24. package/android/.idea/libraries/Gradle__androidx_coordinatorlayout_coordinatorlayout_1_1_0_aar.xml +14 -0
  25. package/android/.idea/libraries/Gradle__androidx_core_core_1_3_2_aar.xml +14 -0
  26. package/android/.idea/libraries/Gradle__androidx_core_core_1_5_0_aar.xml +14 -0
  27. package/android/.idea/libraries/Gradle__androidx_cursoradapter_cursoradapter_1_0_0_aar.xml +11 -0
  28. package/android/.idea/libraries/Gradle__androidx_customview_customview_1_0_0_aar.xml +11 -0
  29. package/android/.idea/libraries/Gradle__androidx_drawerlayout_drawerlayout_1_0_0_aar.xml +14 -0
  30. package/android/.idea/libraries/Gradle__androidx_exifinterface_exifinterface_1_3_2_aar.xml +14 -0
  31. package/android/.idea/libraries/Gradle__androidx_fragment_fragment_1_3_0_aar.xml +14 -0
  32. package/android/.idea/libraries/Gradle__androidx_fragment_fragment_1_3_4_aar.xml +14 -0
  33. package/android/.idea/libraries/Gradle__androidx_interpolator_interpolator_1_0_0_aar.xml +11 -0
  34. package/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_3_0.xml +9 -0
  35. package/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_common_2_3_1.xml +9 -0
  36. package/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_2_0_0_aar.xml +11 -0
  37. package/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_3_0_aar.xml +11 -0
  38. package/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_livedata_core_2_3_1_aar.xml +11 -0
  39. package/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_3_0_aar.xml +11 -0
  40. package/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_runtime_2_3_1_aar.xml +11 -0
  41. package/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_3_0_aar.xml +11 -0
  42. package/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_2_3_1_aar.xml +11 -0
  43. package/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_2_3_0_aar.xml +11 -0
  44. package/android/.idea/libraries/Gradle__androidx_lifecycle_lifecycle_viewmodel_savedstate_2_3_1_aar.xml +11 -0
  45. package/android/.idea/libraries/Gradle__androidx_loader_loader_1_0_0_aar.xml +11 -0
  46. package/android/.idea/libraries/Gradle__androidx_savedstate_savedstate_1_1_0_aar.xml +11 -0
  47. package/android/.idea/libraries/Gradle__androidx_test_core_1_3_0_aar.xml +11 -0
  48. package/android/.idea/libraries/Gradle__androidx_test_espresso_espresso_core_3_1_0_alpha3_aar.xml +11 -0
  49. package/android/.idea/libraries/Gradle__androidx_test_espresso_espresso_core_3_3_0_aar.xml +11 -0
  50. package/android/.idea/libraries/Gradle__androidx_test_espresso_espresso_idling_resource_3_1_0_alpha3_aar.xml +11 -0
  51. package/android/.idea/libraries/Gradle__androidx_test_espresso_espresso_idling_resource_3_3_0_aar.xml +11 -0
  52. package/android/.idea/libraries/Gradle__androidx_test_ext_junit_1_1_2_aar.xml +11 -0
  53. package/android/.idea/libraries/Gradle__androidx_test_monitor_1_1_0_alpha3_aar.xml +11 -0
  54. package/android/.idea/libraries/Gradle__androidx_test_monitor_1_3_0_aar.xml +11 -0
  55. package/android/.idea/libraries/Gradle__androidx_test_runner_1_1_0_alpha3_aar.xml +11 -0
  56. package/android/.idea/libraries/Gradle__androidx_test_runner_1_3_0_aar.xml +11 -0
  57. package/android/.idea/libraries/Gradle__androidx_tracing_tracing_1_0_0_aar.xml +11 -0
  58. package/android/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_1_1_0_aar.xml +11 -0
  59. package/android/.idea/libraries/Gradle__androidx_vectordrawable_vectordrawable_animated_1_1_0_aar.xml +11 -0
  60. package/android/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_0_aar.xml +11 -0
  61. package/android/.idea/libraries/Gradle__androidx_versionedparcelable_versionedparcelable_1_1_1_aar.xml +11 -0
  62. package/android/.idea/libraries/Gradle__androidx_viewpager_viewpager_1_0_0_aar.xml +11 -0
  63. package/android/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_2_0_1.xml +9 -0
  64. package/android/.idea/libraries/Gradle__com_squareup_javawriter_2_1_1.xml +9 -0
  65. package/android/.idea/libraries/Gradle__javax_inject_javax_inject_1.xml +9 -0
  66. package/android/.idea/libraries/Gradle__junit_junit_4_12.xml +9 -0
  67. package/android/.idea/libraries/Gradle__junit_junit_4_13_1.xml +9 -0
  68. package/android/.idea/libraries/Gradle__net_bytebuddy_byte_buddy_1_10_18.xml +9 -0
  69. package/android/.idea/libraries/Gradle__net_bytebuddy_byte_buddy_agent_1_10_18.xml +9 -0
  70. package/android/.idea/libraries/Gradle__net_sf_kxml_kxml2_2_3_0.xml +9 -0
  71. package/android/.idea/libraries/Gradle__org_apache_cordova_framework_7_0_0_aar.xml +11 -0
  72. package/android/.idea/libraries/Gradle__org_hamcrest_hamcrest_core_1_3.xml +9 -0
  73. package/android/.idea/libraries/Gradle__org_hamcrest_hamcrest_integration_1_3.xml +9 -0
  74. package/android/.idea/libraries/Gradle__org_hamcrest_hamcrest_library_1_3.xml +9 -0
  75. package/android/.idea/libraries/Gradle__org_json_json_20140107.xml +9 -0
  76. package/android/.idea/libraries/Gradle__org_mockito_mockito_core_3_6_28.xml +9 -0
  77. package/android/.idea/libraries/Gradle__org_mockito_mockito_inline_3_6_28.xml +9 -0
  78. package/android/.idea/libraries/Gradle__org_objenesis_objenesis_3_1.xml +9 -0
  79. package/android/.idea/misc.xml +9 -0
  80. package/android/.idea/modules/1419750366/android.capacitor-android.iml +92 -0
  81. package/android/.idea/modules/android.iml +87 -0
  82. package/android/.idea/modules.xml +9 -0
  83. package/android/.idea/vcs.xml +6 -0
  84. package/android/build.gradle +4 -4
  85. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraActivity.java +128 -70
  86. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +163 -118
  87. package/android/src/main/java/com/ahm/capacitor/camera/preview/CustomTextureView.java +31 -0
  88. package/android/src/main/java/com/ahm/capacitor/camera/preview/Preview.java +96 -19
  89. package/dist/esm/definitions.d.ts +18 -5
  90. package/dist/esm/definitions.js +1 -0
  91. package/dist/esm/index.d.ts +3 -1
  92. package/dist/esm/index.js +5 -1
  93. package/dist/esm/index.js.map +1 -1
  94. package/dist/esm/web.d.ts +8 -1
  95. package/dist/esm/web.js +95 -77
  96. package/dist/esm/web.js.map +1 -1
  97. package/ios/Plugin/CameraController.swift +155 -48
  98. package/ios/Plugin/Plugin.m +3 -0
  99. package/ios/Plugin/Plugin.swift +126 -47
  100. package/ios/Plugin.xcodeproj/project.pbxproj +4 -8
  101. package/ios/Podfile +2 -2
  102. package/ios/Podfile.lock +5 -5
  103. package/package.json +4 -3
  104. package/android/local.properties +0 -8
  105. package/ios/Plugin.xcodeproj/xcuserdata/nielsvanharen.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  106. package/ios/Plugin.xcworkspace/xcuserdata/arielhernandezmusa.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  107. package/ios/Plugin.xcworkspace/xcuserdata/nielsvanharen.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
@@ -17,6 +17,7 @@ class CameraController: NSObject {
17
17
  var frontCamera: AVCaptureDevice?
18
18
  var frontCameraInput: AVCaptureDeviceInput?
19
19
 
20
+ var dataOutput: AVCaptureVideoDataOutput?
20
21
  var photoOutput: AVCapturePhotoOutput?
21
22
 
22
23
  var rearCamera: AVCaptureDevice?
@@ -27,7 +28,12 @@ class CameraController: NSObject {
27
28
  var flashMode = AVCaptureDevice.FlashMode.off
28
29
  var photoCaptureCompletionBlock: ((UIImage?, Error?) -> Void)?
29
30
 
31
+ var sampleBufferCaptureCompletionBlock: ((UIImage?, Error?) -> Void)?
32
+
30
33
  var highResolutionOutput: Bool = false
34
+
35
+ var audioDevice: AVCaptureDevice?
36
+ var audioInput: AVCaptureDeviceInput?
31
37
  }
32
38
 
33
39
  extension CameraController {
@@ -56,6 +62,7 @@ extension CameraController {
56
62
  camera.unlockForConfiguration()
57
63
  }
58
64
  }
65
+ self.audioDevice = AVCaptureDevice.default(for: AVMediaType.audio)
59
66
  }
60
67
 
61
68
  func configureDeviceInputs() throws {
@@ -79,6 +86,16 @@ extension CameraController {
79
86
  self.currentCameraPosition = .front
80
87
  }
81
88
  } else { throw CameraControllerError.noCamerasAvailable }
89
+
90
+ // Add audio input
91
+ if let audioDevice = self.audioDevice {
92
+ self.audioInput = try AVCaptureDeviceInput(device: audioDevice)
93
+ if captureSession.canAddInput(self.audioInput!) {
94
+ captureSession.addInput(self.audioInput!)
95
+ } else {
96
+ throw CameraControllerError.inputsAreInvalid
97
+ }
98
+ }
82
99
  }
83
100
 
84
101
  func configurePhotoOutput() throws {
@@ -91,12 +108,32 @@ extension CameraController {
91
108
  captureSession.startRunning()
92
109
  }
93
110
 
111
+ func configureDataOutput() throws {
112
+ guard let captureSession = self.captureSession else { throw CameraControllerError.captureSessionIsMissing }
113
+
114
+ self.dataOutput = AVCaptureVideoDataOutput()
115
+ self.dataOutput?.videoSettings = [
116
+ (kCVPixelBufferPixelFormatTypeKey as String): NSNumber(value: kCVPixelFormatType_32BGRA as UInt32)
117
+ ]
118
+ self.dataOutput?.alwaysDiscardsLateVideoFrames = true
119
+ if captureSession.canAddOutput(self.dataOutput!) {
120
+ captureSession.addOutput(self.dataOutput!)
121
+ }
122
+
123
+ captureSession.commitConfiguration()
124
+
125
+ let queue = DispatchQueue(label: "DataOutput", attributes: [])
126
+ self.dataOutput?.setSampleBufferDelegate(self, queue: queue)
127
+ }
128
+
94
129
  DispatchQueue(label: "prepare").async {
95
130
  do {
96
131
  createCaptureSession()
97
132
  try configureCaptureDevices()
98
133
  try configureDeviceInputs()
99
134
  try configurePhotoOutput()
135
+ try configureDataOutput()
136
+ //try configureVideoOutput()
100
137
  }
101
138
 
102
139
  catch {
@@ -108,6 +145,8 @@ extension CameraController {
108
145
  }
109
146
 
110
147
  DispatchQueue.main.async {
148
+ self.updateVideoOrientation()
149
+
111
150
  completionHandler(nil)
112
151
  }
113
152
  }
@@ -119,36 +158,44 @@ extension CameraController {
119
158
  self.previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
120
159
  self.previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
121
160
 
122
- let orientation: UIDeviceOrientation = UIDevice.current.orientation
123
- let statusBarOrientation = UIApplication.shared.statusBarOrientation
124
- switch (orientation) {
161
+ view.layer.insertSublayer(self.previewLayer!, at: 0)
162
+ self.previewLayer?.frame = view.frame
163
+ }
164
+
165
+ func updateVideoOrientation() {
166
+ assert(Thread.isMainThread) // UIApplication.statusBarOrientation requires the main thread.
167
+
168
+ let videoOrientation: AVCaptureVideoOrientation
169
+ switch UIDevice.current.orientation {
125
170
  case .portrait:
126
- self.previewLayer?.connection?.videoOrientation = .portrait
127
- case .landscapeRight:
128
- self.previewLayer?.connection?.videoOrientation = .landscapeLeft
171
+ videoOrientation = .portrait
129
172
  case .landscapeLeft:
130
- self.previewLayer?.connection?.videoOrientation = .landscapeRight
173
+ videoOrientation = .landscapeRight
174
+ case .landscapeRight:
175
+ videoOrientation = .landscapeLeft
131
176
  case .portraitUpsideDown:
132
- self.previewLayer?.connection?.videoOrientation = .portraitUpsideDown
133
- case .faceUp, .faceDown:
134
- switch (statusBarOrientation) {
177
+ videoOrientation = .portraitUpsideDown
178
+ case .faceUp, .faceDown, .unknown:
179
+ fallthrough
180
+ @unknown default:
181
+ switch UIApplication.shared.statusBarOrientation {
135
182
  case .portrait:
136
- self.previewLayer?.connection?.videoOrientation = .portrait
137
- case .landscapeRight:
138
- self.previewLayer?.connection?.videoOrientation = .landscapeRight
183
+ videoOrientation = .portrait
139
184
  case .landscapeLeft:
140
- self.previewLayer?.connection?.videoOrientation = .landscapeLeft
185
+ videoOrientation = .landscapeLeft
186
+ case .landscapeRight:
187
+ videoOrientation = .landscapeRight
141
188
  case .portraitUpsideDown:
142
- self.previewLayer?.connection?.videoOrientation = .portraitUpsideDown
143
- default:
144
- self.previewLayer?.connection?.videoOrientation = .portrait
189
+ videoOrientation = .portraitUpsideDown
190
+ case .unknown:
191
+ fallthrough
192
+ @unknown default:
193
+ videoOrientation = .portrait
145
194
  }
146
- default:
147
- self.previewLayer?.connection?.videoOrientation = .portrait
148
195
  }
149
196
 
150
- view.layer.insertSublayer(self.previewLayer!, at: 0)
151
- self.previewLayer?.frame = view.frame
197
+ previewLayer?.connection?.videoOrientation = videoOrientation
198
+ dataOutput?.connections.forEach { $0.videoOrientation = videoOrientation }
152
199
  }
153
200
 
154
201
  func switchCameras() throws {
@@ -212,36 +259,19 @@ extension CameraController {
212
259
  settings.flashMode = self.flashMode
213
260
  settings.isHighResolutionPhotoEnabled = self.highResolutionOutput;
214
261
 
215
- let currentDevice: UIDevice = .current
216
- let deviceOrientation: UIDeviceOrientation = currentDevice.orientation
217
- let statusBarOrientation = UIApplication.shared.statusBarOrientation
218
- if deviceOrientation == .portrait {
219
- self.photoOutput?.connection(with: AVMediaType.video)?.videoOrientation = AVCaptureVideoOrientation.portrait
220
- }else if (deviceOrientation == .landscapeLeft){
221
- self.photoOutput?.connection(with: AVMediaType.video)?.videoOrientation = AVCaptureVideoOrientation.landscapeRight
222
- }else if (deviceOrientation == .landscapeRight){
223
- self.photoOutput?.connection(with: AVMediaType.video)?.videoOrientation = AVCaptureVideoOrientation.landscapeLeft
224
- }else if (deviceOrientation == .portraitUpsideDown){
225
- self.photoOutput?.connection(with: AVMediaType.video)?.videoOrientation = AVCaptureVideoOrientation.portraitUpsideDown
226
- }else if (deviceOrientation == .faceUp || deviceOrientation == .faceDown){
227
- switch (statusBarOrientation) {
228
- case .portrait:
229
- self.photoOutput?.connection(with: AVMediaType.video)?.videoOrientation = AVCaptureVideoOrientation.portrait
230
- case .landscapeRight:
231
- self.photoOutput?.connection(with: AVMediaType.video)?.videoOrientation = AVCaptureVideoOrientation.landscapeRight
232
- case .landscapeLeft:
233
- self.photoOutput?.connection(with: AVMediaType.video)?.videoOrientation = AVCaptureVideoOrientation.landscapeLeft
234
- case .portraitUpsideDown:
235
- self.photoOutput?.connection(with: AVMediaType.video)?.videoOrientation = AVCaptureVideoOrientation.portraitUpsideDown
236
- default:
237
- self.photoOutput?.connection(with: AVMediaType.video)?.videoOrientation = AVCaptureVideoOrientation.portrait
238
- }
239
- }else {
240
- self.photoOutput?.connection(with: AVMediaType.video)?.videoOrientation = AVCaptureVideoOrientation.portrait
241
- }
242
262
  self.photoOutput?.capturePhoto(with: settings, delegate: self)
243
263
  self.photoCaptureCompletionBlock = completion
244
264
  }
265
+
266
+ func captureSample(completion: @escaping (UIImage?, Error?) -> Void) {
267
+ guard let captureSession = captureSession,
268
+ captureSession.isRunning else {
269
+ completion(nil, CameraControllerError.captureSessionIsMissing)
270
+ return
271
+ }
272
+
273
+ self.sampleBufferCaptureCompletionBlock = completion
274
+ }
245
275
 
246
276
  func getSupportedFlashModes() throws -> [String] {
247
277
  var currentCamera: AVCaptureDevice?
@@ -359,6 +389,31 @@ extension CameraController {
359
389
  }
360
390
 
361
391
  }
392
+
393
+ func captureVideo(completion: @escaping (URL?, Error?) -> Void) {
394
+ guard let captureSession = self.captureSession, captureSession.isRunning else {
395
+ completion(nil, CameraControllerError.captureSessionIsMissing)
396
+ return
397
+ }
398
+ let path = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
399
+ let identifier = UUID()
400
+ let randomIdentifier = identifier.uuidString.replacingOccurrences(of: "-", with: "")
401
+ let finalIdentifier = String(randomIdentifier.prefix(8))
402
+ let fileName="cpcp_video_"+finalIdentifier+".mp4"
403
+
404
+ let fileUrl = path.appendingPathComponent(fileName)
405
+ try? FileManager.default.removeItem(at: fileUrl)
406
+ /*videoOutput!.startRecording(to: fileUrl, recordingDelegate: self)
407
+ self.videoRecordCompletionBlock = completion*/
408
+ }
409
+
410
+ func stopRecording(completion: @escaping (Error?) -> Void) {
411
+ guard let captureSession = self.captureSession, captureSession.isRunning else {
412
+ completion(CameraControllerError.captureSessionIsMissing)
413
+ return
414
+ }
415
+ //self.videoOutput?.stopRecording()
416
+ }
362
417
  }
363
418
 
364
419
  extension CameraController: AVCapturePhotoCaptureDelegate {
@@ -377,6 +432,48 @@ extension CameraController: AVCapturePhotoCaptureDelegate {
377
432
  }
378
433
  }
379
434
 
435
+ extension CameraController: AVCaptureVideoDataOutputSampleBufferDelegate {
436
+ func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
437
+ guard let completion = sampleBufferCaptureCompletionBlock else { return }
438
+
439
+ guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
440
+ completion(nil, CameraControllerError.unknown)
441
+ return
442
+ }
443
+
444
+ CVPixelBufferLockBaseAddress(imageBuffer, .readOnly)
445
+ defer { CVPixelBufferUnlockBaseAddress(imageBuffer, .readOnly) }
446
+
447
+ let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)
448
+ let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)
449
+ let width = CVPixelBufferGetWidth(imageBuffer)
450
+ let height = CVPixelBufferGetHeight(imageBuffer)
451
+ let colorSpace = CGColorSpaceCreateDeviceRGB()
452
+ let bitmapInfo: UInt32 = CGBitmapInfo.byteOrder32Little.rawValue |
453
+ CGImageAlphaInfo.premultipliedFirst.rawValue
454
+
455
+ let context = CGContext(
456
+ data: baseAddress,
457
+ width: width,
458
+ height: height,
459
+ bitsPerComponent: 8,
460
+ bytesPerRow: bytesPerRow,
461
+ space: colorSpace,
462
+ bitmapInfo: bitmapInfo
463
+ )
464
+
465
+ guard let cgImage = context?.makeImage() else {
466
+ completion(nil, CameraControllerError.unknown)
467
+ return
468
+ }
469
+
470
+ let image = UIImage(cgImage: cgImage)
471
+ completion(image.fixedOrientation(), nil)
472
+
473
+ sampleBufferCaptureCompletionBlock = nil
474
+ }
475
+ }
476
+
380
477
 
381
478
 
382
479
 
@@ -479,3 +576,13 @@ extension UIImage {
479
576
  return UIImage.init(cgImage: newCGImage, scale: 1, orientation: .up)
480
577
  }
481
578
  }
579
+
580
+ extension CameraController: AVCaptureFileOutputRecordingDelegate {
581
+ func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
582
+ /*if error == nil {
583
+ self.videoRecordCompletionBlock?(outputFileURL, nil)
584
+ } else {
585
+ self.videoRecordCompletionBlock?(nil, error)
586
+ }*/
587
+ }
588
+ }
@@ -7,7 +7,10 @@ CAP_PLUGIN(CameraPreview, "CameraPreview",
7
7
  CAP_PLUGIN_METHOD(start, CAPPluginReturnPromise);
8
8
  CAP_PLUGIN_METHOD(stop, CAPPluginReturnPromise);
9
9
  CAP_PLUGIN_METHOD(capture, CAPPluginReturnPromise);
10
+ CAP_PLUGIN_METHOD(captureSample, CAPPluginReturnPromise);
10
11
  CAP_PLUGIN_METHOD(flip, CAPPluginReturnPromise);
11
12
  CAP_PLUGIN_METHOD(getSupportedFlashModes, CAPPluginReturnPromise);
12
13
  CAP_PLUGIN_METHOD(setFlashMode, CAPPluginReturnPromise);
14
+ CAP_PLUGIN_METHOD(startRecordVideo, CAPPluginReturnPromise);
15
+ CAP_PLUGIN_METHOD(stopRecordVideo, CAPPluginReturnPromise);
13
16
  )
@@ -23,27 +23,35 @@ public class CameraPreview: CAPPlugin {
23
23
 
24
24
  @objc func rotated() {
25
25
 
26
- let height = self.paddingBottom != nil ? self.height! - self.paddingBottom!: self.height!;
27
-
28
26
  if UIDevice.current.orientation.isLandscape {
29
-
30
- self.previewView.frame = CGRect(x: self.y!, y: self.x!, width: height, height: self.width!)
31
- self.cameraController.previewLayer?.frame = self.previewView.frame
32
-
33
- if (UIDevice.current.orientation == UIDeviceOrientation.landscapeLeft) {
34
- self.cameraController.previewLayer?.connection?.videoOrientation = .landscapeRight
35
- }
36
-
37
- if (UIDevice.current.orientation == UIDeviceOrientation.landscapeRight) {
38
- self.cameraController.previewLayer?.connection?.videoOrientation = .landscapeLeft
27
+ if(self.width! > self.height!) {
28
+ // we started in landscape
29
+ let height = self.paddingBottom != nil ? self.height! - self.paddingBottom!: self.height!;
30
+ self.previewView.frame = CGRect(x: self.x!, y: self.y!, width: self.width!, height: height)
31
+ } else {
32
+ // we started in portrait
33
+ let width = self.paddingBottom != nil ? self.width! - self.paddingBottom!: self.width!;
34
+ self.previewView.frame = CGRect(x: self.y!, y: self.x!, width: self.height!, height: width)
39
35
  }
36
+ self.cameraController.previewLayer?.frame = self.previewView.frame
40
37
  }
41
38
 
42
39
  if UIDevice.current.orientation.isPortrait {
43
- self.previewView.frame = CGRect(x: self.x!, y: self.y!, width: self.width!, height: self.height!)
40
+ if (self.previewView != nil && self.x != nil && self.y != nil && self.width != nil && self.height != nil) {
41
+ if(self.height! > self.width!) {
42
+ // we started in portrait
43
+ let height = self.paddingBottom != nil ? self.height! - self.paddingBottom!: self.height!;
44
+ self.previewView.frame = CGRect(x: self.x!, y: self.y!, width: self.width!, height: height)
45
+ } else {
46
+ // we started in landscape
47
+ let width = self.paddingBottom != nil ? self.width! - self.paddingBottom!: self.width!;
48
+ self.previewView.frame = CGRect(x: self.y!, y: self.x!, width: self.height!, height: width)
49
+ }
50
+ }
44
51
  self.cameraController.previewLayer?.frame = self.previewView.frame
45
- self.cameraController.previewLayer?.connection?.videoOrientation = .portrait
46
52
  }
53
+
54
+ cameraController.updateVideoOrientation()
47
55
  }
48
56
 
49
57
  @objc func start(_ call: CAPPluginCall) {
@@ -67,44 +75,48 @@ public class CameraPreview: CAPPlugin {
67
75
  self.paddingBottom = CGFloat(call.getInt("paddingBottom")!)
68
76
  }
69
77
 
70
- AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) in
71
- if (!granted) {
72
- call.reject("permission failed");
73
- }
74
- });
75
-
76
78
  self.rotateWhenOrientationChanged = call.getBool("rotateWhenOrientationChanged") ?? true
77
79
  self.toBack = call.getBool("toBack") ?? false
78
80
  self.storeToFile = call.getBool("storeToFile") ?? false
79
81
 
80
- if (self.rotateWhenOrientationChanged == true) {
81
- NotificationCenter.default.addObserver(self, selector: #selector(CameraPreview.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
82
- }
83
-
84
- DispatchQueue.main.async {
85
- if (self.cameraController.captureSession?.isRunning ?? false) {
86
- call.reject("camera already started")
87
- } else {
88
- self.cameraController.prepare(cameraPosition: self.cameraPosition){error in
89
- if let error = error {
90
- print(error)
91
- call.reject(error.localizedDescription)
92
- return
93
- }
94
- self.previewView = UIView(frame: CGRect(x: self.x!, y: self.y!, width: self.width!, height: self.height!))
95
- self.webView.isOpaque = false
96
- self.webView.backgroundColor = UIColor.clear
97
- self.webView.scrollView.backgroundColor = UIColor.clear
98
- self.webView.superview?.addSubview(self.previewView)
99
- if (self.toBack!) {
100
- self.webView.superview?.bringSubviewToFront(self.webView)
101
- }
102
- try? self.cameraController.displayPreview(on: self.previewView)
103
- call.resolve()
82
+ AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) in
83
+ guard granted else {
84
+ call.reject("permission failed");
85
+ return
86
+ }
87
+
88
+ DispatchQueue.main.async {
89
+ if (self.cameraController.captureSession?.isRunning ?? false) {
90
+ call.reject("camera already started")
91
+ } else {
92
+ self.cameraController.prepare(cameraPosition: self.cameraPosition){error in
93
+ if let error = error {
94
+ print(error)
95
+ call.reject(error.localizedDescription)
96
+ return
97
+ }
98
+ let height = self.paddingBottom != nil ? self.height! - self.paddingBottom!: self.height!;
99
+ self.previewView = UIView(frame: CGRect(x: self.x ?? 0, y: self.y ?? 0, width: self.width!, height: height))
100
+ self.webView?.isOpaque = false
101
+ self.webView?.backgroundColor = UIColor.clear
102
+ self.webView?.scrollView.backgroundColor = UIColor.clear
103
+ self.webView?.superview?.addSubview(self.previewView)
104
+ if (self.toBack!) {
105
+ self.webView?.superview?.bringSubviewToFront(self.webView!)
106
+ }
107
+ try? self.cameraController.displayPreview(on: self.previewView)
108
+
109
+ if (self.rotateWhenOrientationChanged == true) {
110
+ NotificationCenter.default.addObserver(self, selector: #selector(CameraPreview.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
111
+ }
112
+
113
+ call.resolve()
104
114
 
115
+ }
105
116
  }
106
117
  }
107
- }
118
+ });
119
+
108
120
  }
109
121
 
110
122
  @objc func flip(_ call: CAPPluginCall) {
@@ -121,7 +133,7 @@ public class CameraPreview: CAPPlugin {
121
133
  if (self.cameraController.captureSession?.isRunning ?? false) {
122
134
  self.cameraController.captureSession?.stopRunning()
123
135
  self.previewView.removeFromSuperview()
124
- self.webView.isOpaque = true
136
+ self.webView?.isOpaque = true
125
137
  call.resolve()
126
138
  } else {
127
139
  call.reject("camera already stopped")
@@ -156,7 +168,7 @@ public class CameraPreview: CAPPlugin {
156
168
  return
157
169
  }
158
170
  let imageData: Data?
159
- if (self.cameraPosition == "front") {
171
+ if (self.cameraController.currentCameraPosition == .front) {
160
172
  let flippedImage = image.withHorizontallyFlippedOrientation()
161
173
  imageData = flippedImage.jpegData(compressionQuality: CGFloat(quality!/100))
162
174
  } else {
@@ -178,6 +190,41 @@ public class CameraPreview: CAPPlugin {
178
190
  }
179
191
  }
180
192
  }
193
+
194
+ @objc func captureSample(_ call: CAPPluginCall) {
195
+ DispatchQueue.main.async {
196
+ let quality: Int? = call.getInt("quality", 85)
197
+
198
+ self.cameraController.captureSample { image, error in
199
+ guard let image = image else {
200
+ print("Image capture error: \(String(describing: error))")
201
+ call.reject("Image capture error: \(String(describing: error))")
202
+ return
203
+ }
204
+
205
+ let imageData: Data?
206
+ if (self.cameraPosition == "front") {
207
+ let flippedImage = image.withHorizontallyFlippedOrientation()
208
+ imageData = flippedImage.jpegData(compressionQuality: CGFloat(quality!/100))
209
+ } else {
210
+ imageData = image.jpegData(compressionQuality: CGFloat(quality!/100))
211
+ }
212
+
213
+ if (self.storeToFile == false){
214
+ let imageBase64 = imageData?.base64EncodedString()
215
+ call.resolve(["value": imageBase64!])
216
+ } else {
217
+ do {
218
+ let fileUrl = self.getTempFilePath()
219
+ try imageData?.write(to:fileUrl)
220
+ call.resolve(["value": fileUrl.absoluteString])
221
+ } catch {
222
+ call.reject("Error writing image to file")
223
+ }
224
+ }
225
+ }
226
+ }
227
+ }
181
228
 
182
229
  @objc func getSupportedFlashModes(_ call: CAPPluginCall) {
183
230
  do {
@@ -217,5 +264,37 @@ public class CameraPreview: CAPPlugin {
217
264
  call.reject("failed to set flash mode")
218
265
  }
219
266
  }
267
+
268
+ @objc func startRecordVideo(_ call: CAPPluginCall) {
269
+ DispatchQueue.main.async {
270
+
271
+ let quality: Int? = call.getInt("quality", 85)
272
+
273
+ self.cameraController.captureVideo { (image, error) in
274
+
275
+ guard let image = image else {
276
+ print(error ?? "Image capture error")
277
+ guard let error = error else {
278
+ call.reject("Image capture error")
279
+ return
280
+ }
281
+ call.reject(error.localizedDescription)
282
+ return
283
+ }
284
+
285
+ //self.videoUrl = image
286
+
287
+ call.resolve(["value":image.absoluteString])
288
+ }
289
+ }
290
+ }
291
+
292
+
293
+ @objc func stopRecordVideo(_ call: CAPPluginCall) {
294
+
295
+ self.cameraController.stopRecording { (error) in
296
+
297
+ }
298
+ }
220
299
 
221
300
  }
@@ -14,8 +14,6 @@
14
14
  4C2070D622DA87B100D1AD33 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2070D522DA87B100D1AD33 /* CoreImage.framework */; };
15
15
  4C2070D822DA87C600D1AD33 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2070D722DA87C500D1AD33 /* QuartzCore.framework */; };
16
16
  4C2070DA22DA87CE00D1AD33 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2070D922DA87CE00D1AD33 /* CoreVideo.framework */; };
17
- 4C2070DC22DA87D700D1AD33 /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2070DB22DA87D700D1AD33 /* GLKit.framework */; };
18
- 4C2070DE22DA87E700D1AD33 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2070DD22DA87E700D1AD33 /* OpenGLES.framework */; };
19
17
  4C2070E022DA87F500D1AD33 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2070DF22DA87F500D1AD33 /* CoreGraphics.framework */; };
20
18
  4C2070E222DA87FB00D1AD33 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2070E122DA87FB00D1AD33 /* AssetsLibrary.framework */; };
21
19
  4C2070E422DA881600D1AD33 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2070E322DA881600D1AD33 /* CoreLocation.framework */; };
@@ -77,8 +75,6 @@
77
75
  4C2070E422DA881600D1AD33 /* CoreLocation.framework in Frameworks */,
78
76
  4C2070E222DA87FB00D1AD33 /* AssetsLibrary.framework in Frameworks */,
79
77
  4C2070E022DA87F500D1AD33 /* CoreGraphics.framework in Frameworks */,
80
- 4C2070DE22DA87E700D1AD33 /* OpenGLES.framework in Frameworks */,
81
- 4C2070DC22DA87D700D1AD33 /* GLKit.framework in Frameworks */,
82
78
  4C2070D822DA87C600D1AD33 /* QuartzCore.framework in Frameworks */,
83
79
  4C2070D622DA87B100D1AD33 /* CoreImage.framework in Frameworks */,
84
80
  4C2070D222DA878E00D1AD33 /* ImageIO.framework in Frameworks */,
@@ -418,7 +414,7 @@
418
414
  GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
419
415
  GCC_WARN_UNUSED_FUNCTION = YES;
420
416
  GCC_WARN_UNUSED_VARIABLE = YES;
421
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
417
+ IPHONEOS_DEPLOYMENT_TARGET = 12.1;
422
418
  MTL_ENABLE_DEBUG_INFO = YES;
423
419
  ONLY_ACTIVE_ARCH = YES;
424
420
  SDKROOT = iphoneos;
@@ -473,7 +469,7 @@
473
469
  GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
474
470
  GCC_WARN_UNUSED_FUNCTION = YES;
475
471
  GCC_WARN_UNUSED_VARIABLE = YES;
476
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
472
+ IPHONEOS_DEPLOYMENT_TARGET = 12.1;
477
473
  MTL_ENABLE_DEBUG_INFO = NO;
478
474
  SDKROOT = iphoneos;
479
475
  SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
@@ -497,7 +493,7 @@
497
493
  DYLIB_INSTALL_NAME_BASE = "@rpath";
498
494
  INFOPLIST_FILE = Plugin/Info.plist;
499
495
  INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
500
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
496
+ IPHONEOS_DEPLOYMENT_TARGET = 12.1;
501
497
  LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(FRAMEWORK_SEARCH_PATHS)\n$(FRAMEWORK_SEARCH_PATHS)\n$(FRAMEWORK_SEARCH_PATHS)";
502
498
  ONLY_ACTIVE_ARCH = YES;
503
499
  PRODUCT_BUNDLE_IDENTIFIER = com.getcapacitor.Plugin;
@@ -522,7 +518,7 @@
522
518
  DYLIB_INSTALL_NAME_BASE = "@rpath";
523
519
  INFOPLIST_FILE = Plugin/Info.plist;
524
520
  INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
525
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
521
+ IPHONEOS_DEPLOYMENT_TARGET = 12.1;
526
522
  LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(FRAMEWORK_SEARCH_PATHS)";
527
523
  ONLY_ACTIVE_ARCH = NO;
528
524
  PRODUCT_BUNDLE_IDENTIFIER = com.getcapacitor.Plugin;
package/ios/Podfile CHANGED
@@ -1,4 +1,4 @@
1
- platform :ios, '11.0'
1
+ platform :ios, '12.1'
2
2
 
3
3
  target 'Plugin' do
4
4
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
@@ -10,4 +10,4 @@ target 'PluginTests' do
10
10
  use_frameworks!
11
11
 
12
12
  pod 'Capacitor', :path => '../node_modules/@capacitor/ios'
13
- end
13
+ end
package/ios/Podfile.lock CHANGED
@@ -1,6 +1,6 @@
1
1
  PODS:
2
- - Capacitor (2.0.1):
3
- - CapacitorCordova (= 2.0.1)
2
+ - Capacitor (3.0.0):
3
+ - CapacitorCordova
4
4
  - CapacitorCordova (2.0.1)
5
5
 
6
6
  DEPENDENCIES:
@@ -15,9 +15,9 @@ EXTERNAL SOURCES:
15
15
  :path: "../node_modules/@capacitor/ios"
16
16
 
17
17
  SPEC CHECKSUMS:
18
- Capacitor: 893baa42b33635ddf23d29d23d2a7f33f7c08bc7
18
+ Capacitor: 06cd8cd01340f5b162e9528bf5569d87a6f29009
19
19
  CapacitorCordova: 9fee2eb6780331b6ff09710d6a7d1f2e4707f1b9
20
20
 
21
- PODFILE CHECKSUM: 38d083712967e4c216faff8d0b7c5eb7faa2b523
21
+ PODFILE CHECKSUM: d3e2703a3105a8e75e11dfc45c25f5cbf9801486
22
22
 
23
- COCOAPODS: 1.9.1
23
+ COCOAPODS: 1.9.3
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@capacitor-community/camera-preview",
3
- "version": "1.2.0",
3
+ "version": "2.0.0",
4
4
  "description": "Camera preview",
5
5
  "main": "dist/esm/index.js",
6
6
  "types": "dist/esm/index.d.ts",
7
7
  "scripts": {
8
8
  "build": "npm run clean && tsc",
9
- "clean": "rm -rf ./dist",
9
+ "clean": "rimraf './dist'",
10
10
  "watch": "tsc --watch",
11
11
  "prepublishOnly": "npm run build",
12
12
  "prepare": "npm run build"
@@ -19,7 +19,8 @@
19
19
  "devDependencies": {
20
20
  "@capacitor/android": "latest",
21
21
  "@capacitor/ios": "latest",
22
- "typescript": "^3.2.4"
22
+ "rimraf": "^3.0.2",
23
+ "typescript": "^4.3.2"
23
24
  },
24
25
  "files": [
25
26
  "dist/",
@@ -1,8 +0,0 @@
1
- ## This file must *NOT* be checked into Version Control Systems,
2
- # as it contains information specific to your local configuration.
3
- #
4
- # Location of the SDK. This is only used by Gradle.
5
- # For customization when using a Version Control System, please read the
6
- # header note.
7
- #Sun Jul 14 21:09:11 UYT 2019
8
- sdk.dir=/Users/arielhernandezmusa/Library/Android/sdk
@@ -1,14 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>SchemeUserState</key>
6
- <dict>
7
- <key>Plugin.xcscheme_^#shared#^_</key>
8
- <dict>
9
- <key>orderHint</key>
10
- <integer>4</integer>
11
- </dict>
12
- </dict>
13
- </dict>
14
- </plist>