2026-07-23 15:48:01 +08:00
|
|
|
|
#import <AVFoundation/AVFoundation.h>
|
|
|
|
|
|
#import <UIKit/UIKit.h>
|
|
|
|
|
|
|
|
|
|
|
|
/// 获取当前正在使用的后置摄像头设备
|
|
|
|
|
|
static AVCaptureDevice *GetActiveRearCamera(void)
|
|
|
|
|
|
{
|
2026-09-01 15:47:57 +08:00
|
|
|
|
// 遍历所有 AVCaptureDevice,找到后置摄像头
|
|
|
|
|
|
// 注意:Unity WebCamTexture 内部的 AVCaptureSession 不会暴露给原生代码,
|
|
|
|
|
|
// 但 AVCaptureDevice 本身可以独立 lockForConfiguration 设置对焦模式,
|
|
|
|
|
|
// 不需要成为当前 session 的输入设备。
|
2026-07-23 15:48:01 +08:00
|
|
|
|
if (@available(iOS 10.0, *)) {
|
|
|
|
|
|
AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession
|
2026-09-01 15:47:57 +08:00
|
|
|
|
discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera,
|
|
|
|
|
|
AVCaptureDeviceTypeBuiltInTelephotoCamera,
|
|
|
|
|
|
AVCaptureDeviceTypeBuiltInDualCamera,
|
|
|
|
|
|
AVCaptureDeviceTypeBuiltInDualWideCamera,
|
|
|
|
|
|
AVCaptureDeviceTypeBuiltInTripleCamera]
|
2026-07-23 15:48:01 +08:00
|
|
|
|
mediaType:AVMediaTypeVideo
|
|
|
|
|
|
position:AVCaptureDevicePositionBack];
|
|
|
|
|
|
for (AVCaptureDevice *d in session.devices) {
|
2026-09-01 15:47:57 +08:00
|
|
|
|
return d; // 拿到任意后置摄像头即可
|
2026-07-23 15:48:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
|
|
|
|
/// 开启连续自动对焦
|
|
|
|
|
|
void _EnableContinuousAutoFocus(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
AVCaptureDevice *device = GetActiveRearCamera();
|
|
|
|
|
|
if (!device) return;
|
|
|
|
|
|
|
|
|
|
|
|
NSError *error = nil;
|
|
|
|
|
|
if ([device lockForConfiguration:&error]) {
|
|
|
|
|
|
if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
|
|
|
|
|
|
device.focusMode = AVCaptureFocusModeContinuousAutoFocus;
|
|
|
|
|
|
NSLog(@"[CameraFocusHelper] 已开启连续自动对焦");
|
|
|
|
|
|
}
|
|
|
|
|
|
if ([device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) {
|
|
|
|
|
|
device.exposureMode = AVCaptureExposureModeContinuousAutoExposure;
|
|
|
|
|
|
}
|
|
|
|
|
|
[device unlockForConfiguration];
|
|
|
|
|
|
} else {
|
|
|
|
|
|
NSLog(@"[CameraFocusHelper] 配置失败: %@", error.localizedDescription);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 触发单次自动对焦(点击对焦用)
|
|
|
|
|
|
void _TriggerAutoFocus(float normalizedX, float normalizedY)
|
|
|
|
|
|
{
|
|
|
|
|
|
AVCaptureDevice *device = GetActiveRearCamera();
|
|
|
|
|
|
if (!device) return;
|
|
|
|
|
|
|
|
|
|
|
|
NSError *error = nil;
|
|
|
|
|
|
if ([device lockForConfiguration:&error]) {
|
|
|
|
|
|
if ([device isFocusPointOfInterestSupported]) {
|
|
|
|
|
|
device.focusPointOfInterest = CGPointMake(normalizedX, normalizedY);
|
|
|
|
|
|
device.focusMode = AVCaptureFocusModeAutoFocus;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ([device isExposurePointOfInterestSupported]) {
|
|
|
|
|
|
device.exposurePointOfInterest = CGPointMake(normalizedX, normalizedY);
|
|
|
|
|
|
device.exposureMode = AVCaptureExposureModeAutoExpose;
|
|
|
|
|
|
}
|
|
|
|
|
|
[device unlockForConfiguration];
|
|
|
|
|
|
|
|
|
|
|
|
// 1.5秒后恢复连续对焦
|
|
|
|
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)),
|
|
|
|
|
|
dispatch_get_main_queue(), ^{
|
|
|
|
|
|
_EnableContinuousAutoFocus();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-01 15:47:57 +08:00
|
|
|
|
/// 周期性重新触发对焦(与 Android softTrigger 思路一致)
|
|
|
|
|
|
/// 通过"点对焦 → 1.5s 后恢复连续对焦"的方式让镜头做一次完整对焦循环,无黑屏
|
|
|
|
|
|
void _TriggerContinuousRefocus(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
_TriggerAutoFocus(0.5f, 0.5f);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-23 15:48:01 +08:00
|
|
|
|
}
|