iOS中AVCaptureVideoDataOutputSampleBufferDelegate未触发captureOutput求助
问题分析与解决方案
你的摄像头画面正常显示,但captureOutput代理方法不触发,主要有以下几个常见原因及对应的修复方案:
1. AVCaptureVideoDataOutput 未被强引用
你在setupCamera方法中创建的AVCaptureVideoDataOutput是局部变量,虽然已添加到captureSession,但系统对输出对象的引用可能不足以维持其生命周期,导致输出对象被提前释放,代理回调自然无法触发。
修复:在类中添加强引用属性保存视频输出对象:
在.h文件中添加:
@property (nonatomic, strong) AVCaptureVideoDataOutput *videoDataOutput;
然后在setupCamera中修改创建逻辑:
self.videoDataOutput = [[AVCaptureVideoDataOutput alloc] init]; [self.videoDataOutput setSampleBufferDelegate:self queue:self.videoDataOutputQueue]; [self.captureSession addOutput:self.videoDataOutput];
2. 未指定兼容的像素格式
AVCaptureVideoDataOutput默认的像素格式可能不被当前设备支持,导致无法输出采样缓冲区。
修复:添加像素格式设置,使用通用的32位BGRA格式:
self.videoDataOutput = [[AVCaptureVideoDataOutput alloc] init]; // 设置兼容的像素格式 NSDictionary *outputSettings = @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}; self.videoDataOutput.videoSettings = outputSettings; [self.videoDataOutput setSampleBufferDelegate:self queue:self.videoDataOutputQueue]; [self.captureSession addOutput:self.videoDataOutput];
3. 检查AVCaptureConnection的启用状态
添加视频输出后,对应的AVCaptureConnection可能处于未启用状态,需要手动确认并启用。
修复:在添加输出后,获取连接并启用:
[self.captureSession addOutput:self.videoDataOutput]; // 获取视频连接并启用 AVCaptureConnection *connection = [self.videoDataOutput connectionWithMediaType:AVMediaTypeVideo]; if (connection.isEnabled == NO) { connection.enabled = YES; }
4. 确保代理对象(Trying实例)的生命周期
如果你的Trying类实例是临时创建的(比如在某个方法中局部声明,方法结束后被释放),那么代理对象不存在,回调也不会触发。要确保Trying实例被其他对象(比如ViewController)强引用持有。
修改后的完整代码示例
.h 文件
#import <AVFoundation/AVFoundation.h> #import <UIKit/UIKit.h> @interface Trying : NSObject <AVCaptureVideoDataOutputSampleBufferDelegate> @property (nonatomic, strong) AVCaptureSession *captureSession; @property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer; @property (nonatomic, strong) dispatch_queue_t videoDataOutputQueue; @property (nonatomic, strong) UIView *view; @property (nonatomic, strong) AVCaptureVideoDataOutput *videoDataOutput; // 新增属性 - (void)setupCamera; @end
.m 文件
#import <Foundation/Foundation.h> #import <AVFoundation/AVFoundation.h> #import "Trying.h" @interface Trying () @end @implementation Trying - (void)setupCamera { self.captureSession = [[AVCaptureSession alloc] init]; AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; NSError *error; AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error]; if (deviceInput) { [self.captureSession addInput:deviceInput]; AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession]; previewLayer.frame = self.view.bounds; previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; [self.view.layer addSublayer:previewLayer]; self.previewLayer = previewLayer; // Create a video data output and set the delegate self.videoDataOutputQueue = dispatch_queue_create("VideoDataOutputQueue", DISPATCH_QUEUE_SERIAL); self.videoDataOutput = [[AVCaptureVideoDataOutput alloc] init]; // 设置像素格式 NSDictionary *outputSettings = @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}; self.videoDataOutput.videoSettings = outputSettings; [self.videoDataOutput setSampleBufferDelegate:self queue:self.videoDataOutputQueue]; [self.captureSession addOutput:self.videoDataOutput]; // 检查并启用连接 AVCaptureConnection *connection = [self.videoDataOutput connectionWithMediaType:AVMediaTypeVideo]; if (!connection.isEnabled) { connection.enabled = YES; } // Start the session [self.captureSession startRunning]; } else { NSLog(@"Error setting up camera: %@", error.localizedDescription); } } - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { // Process the live sample buffer here NSLog(@"Got a live sample buffer"); // You can use the sampleBuffer for further processing, such as image recognition or analysis } - (void)captureOutput:(AVCaptureOutput *)output didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { NSLog(@"Dropped a sample buffer"); // Handle dropped frames if needed } @end
内容的提问来源于stack exchange,提问作者Tanishq Gupta
相关产品推荐
相关产品推荐

