【问题标题】:Camera feed slow to load with AVCaptureSession on iOS - How can I speed it up?在 iOS 上使用 AVCaptureSession 加载相机馈送速度很慢 - 如何加快速度?
【发布时间】:2014-02-22 03:05:23
【问题描述】:

现在我正在尝试允许用户在我的应用程序中拍照而不使用 UIImagePickerController。我正在使用 AVCaptureSession 和所有相关类将相机源作为子层加载到我的一个视图控制器上的全屏视图上。该代码有效,但不幸的是相机加载速度很慢。通常需要 2-3 秒。这是我的代码:

session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetMedium;

if ([session canSetSessionPreset:AVCaptureSessionPresetHigh])
    //Check size based configs are supported before setting them
    [session setSessionPreset:AVCaptureSessionPresetHigh];

[session setSessionPreset:AVCaptureSessionPreset1280x720];

CALayer *viewLayer = self.liveCameraFeed.layer;
//NSLog(@"viewLayer = %@", viewLayer);

AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];

captureVideoPreviewLayer.frame = viewLayer.bounds;
[viewLayer addSublayer:captureVideoPreviewLayer];

AVCaptureDevice *device;

if(isFront)
{
    device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
}
else
{
    device = [self frontCamera];
}

AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
AVCaptureDeviceInput * audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil];
[session addInput:audioInput];

NSError *error = nil;
input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
    // Handle the error appropriately.
    //NSLog(@"ERROR: trying to open camera: %@", error);
}

[session addInput:input];
[session startRunning];

stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[stillImageOutput setOutputSettings:outputSettings];
[session addOutput:stillImageOutput];

有什么方法可以加快速度吗?我已经尝试使用 Grand Central Dispatch 和 NSThread 将其加载到另一个线程上,尽管这阻止了应用程序冻结,但它使相机的加载时间更长。任何帮助表示赞赏。

【问题讨论】:

    标签: ios camera photo avcapturesession


    【解决方案1】:

    就我而言,我需要等待session 开始运行

    dispatch_async(queue) {
      self.session.startRunning()
    
      dispatch_async(dispatch_get_main_queue()) {
        self.delegate?.cameraManDidStart(self)
    
        let layer = AVCaptureVideoPreviewLayer(session: self.session)
      }
    }
    

    【讨论】:

    • 非常感谢!在网络上的大多数教程中,AVCaptureVideoPreviewLayer 在调用 startRunning() 之前附加到会话,但实际上如果在会话启动后异步附加它,预览会更快!
    • 无论出于何种原因,在会话开始后将会话附加到预览层会延迟初始的captureOutput... 调用,所以要小心!
    【解决方案2】:

    等待 AVCaptureSessionstartRunning 函数也是我的解决方案。您可以在全局异步中运行 startRunning,然后在主线程中添加您的 AVCaptureVideoPreviewLayer

    Swift 4示例

    DispatchQueue.global().async {
        self.captureSession.startRunning()
        DispatchQueue.main.async {
            let videoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以在viewWillAppear 时加载 AVCaptureSession。这个对我有用。当我从其他视图切换到带有AVCaptureSession 的视图时,我看到相机立即运行。

      【讨论】:

      • 实际上这对我有帮助。通过放置以下代码,我可以看到 2-3 秒的改进:[viewLayer addSublayer:captureVideoPreviewLayer];viewDidAppearviewWillAppear。不知道为什么这么快,但您可以自己测试并确认...
      【解决方案4】:

      对于任何感兴趣的人,我想出的解决方案是在不同的线程上预加载相机并保持打开状态。

      【讨论】:

      • 是的,我很感兴趣!所以你一直保持 AVCaptureSession (带输入)?这对性能有什么影响?谢谢。
      • 它很重。但我还没有找到更好的解决方案。捕获会话保持打开状态,但在我的相机视图中反复添加和删除提要层。因此,如果用户尝试打开相机,则捕获会话提要子层将添加到我的相机视图中,并且当用户退出相机时,提要子层将被删除。
      • 这是不久前,所以我需要检查代码以准确记住我所做的,但如果我没记错的话,我的解决方案是将相机加载到不同的线程上并保持打开状态,但只显示子层当用户想要使用相机时。否则,仍然保持相机在后台打开,但删除子图层。
      • 编辑:这是上面的修改版本。
      【解决方案5】:

      我尝试了以上所有方法,但效果不如 Instagram 或 Facebook,所以我在父屏幕中加载了 AVCaptureDevice、AVCaptureVideoPreviewLayer、AVCaptureSession,并将其作为参数传递给子屏幕。加载速度非常快。

      【讨论】:

        猜你喜欢
        • 2010-11-12
        • 1970-01-01
        • 2015-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-08
        • 1970-01-01
        相关资源
        最近更新 更多