当我停止运行AVCaptureSession时,我的AVCaptureSession期间创建的线程不会关闭.
症状
通常我的dispatch_queue会立即开始从相机获取帧.但是打开和关闭打开/关闭AVCaptureSession的VIEwController大约四次后,dispatch_queue大约需要十秒钟才能启动.
预测
似乎与AVCaptureSession关联的线程未清除.
关闭AVCaptureSession后,我看到这些线程仍然存在:
com.apple.coremedia.capturesource.connections(serial) 1 Pending Blockcom.apple.coremedia.capturesession.connections(serial) 1 Pending Block<AVCMNotificationdispatcher: 0x16bce00> serial queue(serial) 4 Pending Blockscom.apple.avfoundation.vIDeocapturedevice.observed_propertIEs_queue(serial)com.apple.tcc.cache_queue(serial) 1 Pending Blockcom.apple.tcc.preflight.kTCCServiceCamera(serial) 1 Pending Block
在我使用AVCaptureSession打开/关闭VIEwController之后,仍保留相同的线程,但是这三个线程的Pending块数量增加了
<AVCMNotificationdispatcher: 0x17c441a0> serial queue (serial) 9 Pending Blockscom.apple.avfoundation.vIDeocapturedevice.observed_propertIEs_queue(serial)com.apple.tcc.preflight.kTCCServiceCamera(serial) 5 Pending Blocks
代码设置
VIDeoSource.h和VIDeoSource.mm
在我的VIEwController中,我将它初始化为:
self.vIDeoSource = [[VIDeoSource alloc] init];self.vIDeoSource.delegate = self;[self.vIDeoSource setResolution:AVCaptureSessionPreset352x288]; // was 640[self.vIDeoSource startWithDeviceposition:AVCaptureDevicepositionFront];
我开始和停止captureSession如下,它开始和停止非常好.实际的帧抓取效果非常好.
[self.vIDeoSource.captureSession startRunning]; [self.vIDeoSource.captureSession stopRunning];
VIDeoSource的相关部分,如果您需要了解更多,请告诉我.
来自VIDeoSource.mm
- (voID)dealloc {NSLog(@"Cleaning Up VIDeo Source");[_captureSession stopRunning];AVCaptureinput* input = [_captureSession.inputs objectAtIndex:0];[_captureSession removeinput:input];input = nil;AVCaptureVIDeoDataOutput* output = (AVCaptureVIDeoDataOutput*)[_captureSession.outputs objectAtIndex:0];[_captureSession removeOutput:output];output = nil;_captureSession = nil;_deviceinput = nil;_delegate = nil;// [super dealloc]; // compiler handles this for you with ARC}- (voID) addVIDeoDataOutput {// (1) Instantiate a new vIDeo data output objectAVCaptureVIDeoDataOutput * captureOutput = [[AVCaptureVIDeoDataOutput alloc] init ];// captureOutput.alwaysdiscardsLateVIDeoFrames = YES;NSLog(@"Create dispatch Queue");// (2) The sample buffer delegate requires a serial dispatch queuedispatch_queue_t queue;queue = dispatch_queue_create("com.name.test",disPATCH_QUEUE_SERIAL);[captureOutput setSampleBufferDelegate:self queue:queue];// dispatch_release(queue); // compiler handles this for you with ARC// (3) define the pixel format for the vIDeo data outputNsstring * key = (Nsstring*)kCVPixelBufferPixelFormatTypeKey;NSNumber * value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];NSDictionary * settings = @{key:value};NSLog(@"Set VIDeo Settings");[captureOutput setVIDeoSettings:settings];NSLog(@"Always discard Late VIDeo Frames");[captureOutput setAlwaysdiscardsLateVIDeoFrames:YES];// (4) Configure the output port on the captureSession property[self.captureSession addOutput:captureOutput];}
来自VIDeoSource.h
@interface VIDeoSource : NSObject@property (nonatomic,strong) AVCaptureSession * captureSession; @property (nonatomic,strong) AVCaptureDeviceinput * deviceinput;@property (nonatomic,weak) ID<VIDeoSourceDelegate> delegate;- (BOol)startWithDeviceposition:(AVCaptureDeviceposition)deviceposition;- (voID) setResolution:(Nsstring*)resolution;@end
请求
当我取消分配VIDeoSource时,如何确保这些线程关闭?
解决方法 解决了!解决方案:从与用于captureOutput的SampleBuffer队列相同的dispatch_queue调用startRunning和stopRunning.
这是我的新设置:
#import "VIDeoSource.h"@interface VIDeoSource () <AVCaptureVIDeoDataOutputSampleBufferDelegate>// Session management.@property (nonatomic) dispatch_queue_t sessionQueue;@property (nonatomic) AVCaptureSession *captureSession;@property (nonatomic) AVCaptureDeviceinput *deviceinput;/*@property (nonatomic,strong) AVCaptureSession * captureSession;@property (nonatomic,strong) AVCaptureDeviceinput * deviceinput; */@end@implementation VIDeoSource-(ID) init{ if(self = [super init]){ self.captureSession = [[AVCaptureSession alloc] init]; self.sessionQueue = dispatch_queue_create( "session queue",disPATCH_QUEUE_SERIAL ); } return self;}
然后为setSampleBufferDelegate队列使用相同的sessionQueue.
[captureOutput setSampleBufferDelegate:self queue:self.sessionQueue];
现在,对于最重要的部分,请确保从SAME队列中调用startRunning / stopRunning:
dispatch_async( self.sessionQueue,^{ [self.captureSession startRunning];});
同样,您可以创建一个很好的小函数来清理并停止captureSession:
-(voID)closeCaptureSession { dispatch_async(self.sessionQueue,^{ if([_captureSession isRunning])[_captureSession stopRunning]; [_captureSession stopRunning]; // Remove all inputs for(AVCaptureinput *input1 in _captureSession.inputs) { [_captureSession removeinput:input1]; } // Remove all outputs for(AVCaptureVIDeoDataOutput *output1 in _captureSession.outputs) { [output1 setSampleBufferDelegate:nil queue:NulL]; [_captureSession removeOutput:output1]; } // Set to Nil to make ARC's job a little easIEr self.captureSession = nil; self.deviceinput = nil; self.delegate = nil; self.sessionQueue=nil; });}总结
以上是内存溢出为你收集整理的AVCaptureSession和相机线程没有关闭[iOS]全部内容,希望文章能够帮你解决AVCaptureSession和相机线程没有关闭[iOS]所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)