2 番目の AVCaptureSession を作成すると、最初の AVCaptureSession でオートフォーカスが機能しません。作成される 2 番目のセッションは、オートフォーカスが機能するセッションであり、最初に作成されたセッションはオートフォーカスではありません。
自動ホワイトバランスと自動露出が両方のセッションで機能するのと同じように、どちらのセッションも、もう一方のセッションが停止した後に開始するとオートフォーカスできると思います. 以下のサンプル コードでログ ウィンドウを観察すると、キー値を観察するメッセージが送信されていることがわかります。ただし、トップセッションの実行中にフォーカスメッセージが変更されることはありません。
補足: 残念ながら、使用しているサードパーティ ライブラリにバグがあり、セッションを切り替えるときにセッションを完全に再作成することができません (AVCaptureSessions がリークされ、最終的にアプリが強制終了されます)。完全な話は、このライブラリが私のためにキャプチャ セッションの 1 つを作成しているということです。セッションを開始および停止するためのパブリック API があり、別のセッションを作成したいと考えています。以下のコードは、サードパーティのライブラリを使用せずに問題を示しています。
以下にリストされたコードと、上下に 2 つのビューを持つ XIB ファイルと、問題を示す switchSessions メソッドに接続されたボタンを使用して、テスト アプリケーションを作成しました。
ここで説明されている問題、 Focus (Autofocus) not working in camera (AVFoundation AVCaptureSession)に関連している可能性がありますが、2 つのキャプチャ セッションについては言及されていません。
ヘッダー ファイル:
#import <UIKit/UIKit.h>
@class AVCaptureSession;
@class AVCaptureStillImageOutput;
@class AVCaptureVideoPreviewLayer;
@class AVCaptureDevice;
@class AVCaptureDeviceInput;
@interface AVCaptureSessionFocusBugViewController : UIViewController {
IBOutlet UIView *_topView;
IBOutlet UIView *_bottomView;
AVCaptureDevice *_device;
AVCaptureSession *_topSession;
AVCaptureStillImageOutput *_outputTopSession;
AVCaptureVideoPreviewLayer *_previewLayerTopSession;
AVCaptureDeviceInput *_inputTopSession;
AVCaptureSession *_bottomSession;
AVCaptureStillImageOutput *_outputBottomSession;
AVCaptureVideoPreviewLayer *_previewLayerBottomSession;
AVCaptureDeviceInput *_inputBottomSession;
}
- (IBAction)switchSessions:(id)sender;
@end
実装ファイル:
#import "AVCaptureSessionFocusBugViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface AVCaptureSessionFocusBugViewController ()
- (void)setupCaptureSession:(AVCaptureSession **)session
output:(AVCaptureStillImageOutput **)output
previewLayer:(AVCaptureVideoPreviewLayer **)previewLayer
input:(AVCaptureDeviceInput **)input
view:(UIView *)view;
- (void)tearDownSession:(AVCaptureSession **)session
output:(AVCaptureStillImageOutput **)output
previewLayer:(AVCaptureVideoPreviewLayer **)previewLayer
input:(AVCaptureDeviceInput **)input
view:(UIView *)view;
@end
@implementation AVCaptureSessionFocusBugViewController
- (IBAction)switchSessions:(id)sender
{
if ([_topSession isRunning]) {
[_topSession stopRunning];
[_bottomSession startRunning];
NSLog(@"Bottom session now running.");
}
else {
[_bottomSession stopRunning];
[_topSession startRunning];
NSLog(@"Top session now running.");
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
NSLog(@"Observed value for key at key path %@.", keyPath);
// Enable to confirm that the focusMode is set correctly.
//NSLog(@"Autofocus for the device is set to %d.", [_device focusMode]);
}
- (void)viewDidLoad {
[super viewDidLoad];
_device = [[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] retain];
[self setupCaptureSession:&_topSession
output:&_outputTopSession
previewLayer:&_previewLayerTopSession
input:&_inputTopSession
view:_topView];
[self setupCaptureSession:&_bottomSession
output:&_outputBottomSession
previewLayer:&_previewLayerBottomSession
input:&_inputBottomSession
view:_bottomView];
// NB: We only need to observe one device, since the top and bottom sessions use the same device.
[_device addObserver:self forKeyPath:@"adjustingFocus" options:NSKeyValueObservingOptionNew context:nil];
[_device addObserver:self forKeyPath:@"adjustingExposure" options:NSKeyValueObservingOptionNew context:nil];
[_device addObserver:self forKeyPath:@"adjustingWhiteBalance" options:NSKeyValueObservingOptionNew context:nil];
[_topSession startRunning];
NSLog(@"Starting top session.");
}
- (void)setupCaptureSession:(AVCaptureSession **)session
output:(AVCaptureStillImageOutput **)output
previewLayer:(AVCaptureVideoPreviewLayer **)previewLayer
input:(AVCaptureDeviceInput **)input
view:(UIView *)view
{
*session = [[AVCaptureSession alloc] init];
// Create the preview layer.
*previewLayer = [[AVCaptureVideoPreviewLayer layerWithSession:*session] retain];
[*previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[*previewLayer setFrame:[view bounds]];
[[view layer] addSublayer:*previewLayer];
// Configure the inputs and outputs.
[*session setSessionPreset:AVCaptureSessionPresetMedium];
NSError *error = nil;
*input = [[AVCaptureDeviceInput deviceInputWithDevice:_device error:&error] retain];
if (!*input) {
NSLog(@"Error creating input device:%@", [error localizedDescription]);
return;
}
[*session addInput:*input];
*output = [[AVCaptureStillImageOutput alloc] init];
[*session addOutput:*output];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG, AVVideoCodecKey, nil];
[*output setOutputSettings:outputSettings];
[outputSettings release];
}
- (void)viewDidUnload {
[_topView release];
_topView = nil;
[_bottomView release];
_bottomView = nil;
[_device release];
_device = nil;
[self tearDownSession:&_topSession
output:&_outputTopSession
previewLayer:&_previewLayerTopSession
input:&_inputTopSession
view:_topView];
[self tearDownSession:&_bottomSession
output:&_outputBottomSession
previewLayer:&_previewLayerBottomSession
input:&_inputBottomSession
view:_bottomView];
}
- (void)tearDownSession:(AVCaptureSession **)session
output:(AVCaptureStillImageOutput **)output
previewLayer:(AVCaptureVideoPreviewLayer **)previewLayer
input:(AVCaptureDeviceInput **)input
view:(UIView *)view
{
if ([*session isRunning]) {
[*session stopRunning];
}
[*session removeOutput:*output];
[*output release];
*output = nil;
[*session removeInput:*input];
[*input release];
*input = nil;
[*previewLayer removeFromSuperlayer];
[*previewLayer release];
*previewLayer = nil;
[*session release];
*session = nil;
}
@end