iOS WebRTC自定义MyVideoSourceFilter未触发didCaptureVideoFrame问题
问题分析与解决方案
错误原因
- 未遵守协议:
MyVideoSourceFilter未声明遵守RTCVideoCapturerDelegate协议,RTCCameraVideoCapturer仅会向实现该协议的代理发送回调消息。 - 对象被释放:
RTCCameraVideoCapturer的delegate是弱引用属性,你当前代码中的filter是局部变量,代码块执行完毕后会被ARC自动释放,导致代理失效。 - 未启动捕获流程:若未获取摄像头权限或未调用
startCapture方法启动视频采集,不会产生任何视频帧,自然触发不了didCaptureVideoFrame回调。
补充操作
1. 让自定义类遵守协议
修改MyVideoSourceFilter的头文件,明确声明遵守RTCVideoCapturerDelegate:
#import <WebRTC/WebRTC.h> @interface MyVideoSourceFilter : NSObject <RTCVideoCapturerDelegate> @property (nonatomic, strong) RTCVideoSource *videoSource; - (instancetype)initWithSource:(RTCVideoSource *)source; @end
2. 强引用自定义Filter对象
在当前类中添加强引用属性保存filter,避免其被释放:
// 在当前类的头文件或类扩展中添加 @property (nonatomic, strong) MyVideoSourceFilter *videoFilter; // 初始化代码修改为 self.videoFilter = [[MyVideoSourceFilter alloc] initWithSource:videoSource]; self.videoCapturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:self.videoFilter]; // 无需重复设置delegate,initWithDelegate已完成代理绑定
3. 启动摄像头捕获并处理权限
确保已获取摄像头权限,并启动视频采集:
// 检查并请求摄像头权限 AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; if (status == AVAuthorizationStatusAuthorized) { [self startVideoCapture]; } else if (status == AVAuthorizationStatusNotDetermined) { [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { if (granted) { dispatch_async(dispatch_get_main_queue(), ^{ [self startVideoCapture]; }); } }]; } // 启动视频采集的辅助方法 - (void)startVideoCapture { AVCaptureDevice *frontCamera = [self getFrontCamera]; AVCaptureDeviceFormat *preferredFormat = [self getPreferredCaptureFormatForDevice:frontCamera]; if (frontCamera && preferredFormat) { [self.videoCapturer startCaptureWithDevice:frontCamera format:preferredFormat fps:30]; } } // 获取前置摄像头 - (AVCaptureDevice *)getFrontCamera { for (AVCaptureDevice *device in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { if (device.position == AVCaptureDevicePositionFront) { return device; } } return nil; } // 获取合适的捕获格式(示例为1280x720) - (AVCaptureDeviceFormat *)getPreferredCaptureFormatForDevice:(AVCaptureDevice *)device { for (AVCaptureDeviceFormat *format in device.formats) { CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(format.formatDescription); if (dimensions.width == 1280 && dimensions.height == 720) { return format; } } return device.formats.firstObject; }
4. 验证代理有效性
初始化完成后可打印代理对象,确认其不为空:
NSLog(@"videoCapturer delegate: %@", self.videoCapturer.delegate);
内容的提问来源于stack exchange,提问作者Peter Li
相关产品推荐
相关产品推荐

