47-[AVCaptureVideoDataOutput _updateRemoteQueue:] 偶尔会出现崩溃

(void)captureOutput:(AVCaptureOutput )captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection )connection

调用这个代理方法 偶尔会崩溃 bugly显示如下

8 AVFoundation -[AVCaptureVideoDataOutput _handleRemoteQueueOperation:] + 344
9 AVFoundation ___47-[AVCaptureVideoDataOutput _updateRemoteQueue:]_block_invoke + 100
10 CoreMedia ___FigRemoteOperationReceiverCreateMessageReceiver_block_invoke + 272
11 CoreMedia ___FigRemoteQueueReceiverSetHandler_block_invoke.2 + 224
12 libdispatch.dylib __dispatch_client_callout + 16### 问题描述

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)

pragma mark 相机相关

  • (AVCaptureSession *)captureSession {
    if (!_captureSession) {

    //创建会话层
    _captureSession = [[AVCaptureSession alloc] init];
    [_captureSession setSessionPreset:AVCaptureSessionPreset1920x1080];

    }
    return _captureSession;

}

  • (AVCaptureDeviceInput *)captureInput {
    if (!_captureInput) {

    _captureInput = [AVCaptureDeviceInput deviceInputWithDevice:self.captureDevice error:nil];

    }
    return _captureInput;

}

  • (AVCaptureStillImageOutput *)captureOutput {
    if (!_captureOutput) {

    //创建、配置输出
    _captureOutput = [[AVCaptureStillImageOutput alloc] init];
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey,nil];
    [_captureOutput setOutputSettings:outputSettings];

    }
    return _captureOutput;

}

  • (AVCaptureVideoDataOutput *)captureDataOutput {
    if (!_captureDataOutput) {

    _captureDataOutput = [[AVCaptureVideoDataOutput alloc] init];
    _captureDataOutput.alwaysDiscardsLateVideoFrames = YES;
    dispatch_queue_t queue = dispatch_queue_create("cameraQueue", NULL);
    [_captureDataOutput setSampleBufferDelegate:self queue:queue];
    NSString* formatKey = (NSString*)kCVPixelBufferPixelFormatTypeKey;
    NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
    NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:formatKey];
    [_captureDataOutput setVideoSettings:videoSettings];

    }
    return _captureDataOutput;

}

  • (AVCaptureVideoPreviewLayer *)capturePreviewLayer {
    if (!_capturePreviewLayer) {

    _capturePreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession: self.captureSession];
    _capturePreviewLayer.frame = CGRectMake(0,0, ScreenW, ScreenH);
    _capturePreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

    }
    return _capturePreviewLayer;

}

  • (AVCaptureDevice *)captureDevice {
    if (!_captureDevice) {

    NSArray *deviceArr = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *device in deviceArr)
    {
        if (device.position == AVCaptureDevicePositionBack){
            _captureDevice = device;
            _captureInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
        }
    }

    }
    return _captureDevice;

}
//输入设备

if ([self.captureSession canAddInput:self.captureInput]) {
    [self.captureSession addInput:self.captureInput];
}
//输出设备
if ([self.captureSession canAddOutput:self.captureDataOutput]) {
    [self.captureSession addOutput:self.captureDataOutput];
}
//输出设备
if ([self.captureSession canAddOutput:self.captureOutput]) {
    [self.captureSession addOutput:self.captureOutput];
}
//添加预览层
[self.view.layer addSublayer:self.capturePreviewLayer];

 [self.view.layer addSublayer:self.detectLayer];
 self.view.layer.masksToBounds = YES;
 [self.view addSubview:self.squareView];
阅读 3.6k
1 个回答

这个 queue 放在作为函数的局部变量,不合适。

dispatch_queue_t queue = dispatch_queue_create("cameraQueue", NULL);
[_captureDataOutput setSampleBufferDelegate:self queue:queue];

系统的代理回调在一个创建的局部的队列变量中执行,
然后如果碰巧这个 queue 没被系统回收,代理就调用有效。
如果这个 queue 被系统回收了,代理调用有崩




这个肯定不能放在函数内创建,dispatch_queue_t queue

看到就怪怪的

你可以用系统提供的队列。

如果要用你自定制的,

苹果是这么做的

@property (nonatomic) dispatch_queue_t sessionQueue;

使用 AVFoundation, 苹果的实例代码, 你应该看一下。

AFN 用的是单例。


static dispatch_queue_t url_session_manager_processing_queue() {
    static dispatch_queue_t af_url_session_manager_processing_queue;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        af_url_session_manager_processing_queue = dispatch_queue_create("com.alamofire.networking.session.manager.processing", DISPATCH_QUEUE_CONCURRENT);
    });

    return af_url_session_manager_processing_queue;
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题