274 lines
8.8 KiB
Objective-C
274 lines
8.8 KiB
Objective-C
//
|
|
// CameraManager.m
|
|
// Yoosee
|
|
//
|
|
// Created by guojunyi on 14-4-18.
|
|
// Copyright (c) 2014年 guojunyi. All rights reserved.
|
|
//
|
|
|
|
#import "CameraManager.h"
|
|
#import "Constants.h"
|
|
#import "config.h"
|
|
@interface CameraManager ()
|
|
|
|
@end
|
|
|
|
@implementation CameraManager
|
|
|
|
+ (id)sharedManager
|
|
{
|
|
|
|
static CameraManager *manager = nil;
|
|
@synchronized([self class]){
|
|
if(manager==nil){
|
|
DLog(@"Alloc CameraManager");
|
|
manager = [[CameraManager alloc] init];
|
|
}
|
|
}
|
|
return manager;
|
|
|
|
|
|
}
|
|
|
|
#pragma mark - 寻找前置摄像头,没有则返回空
|
|
- (AVCaptureDevice *)frontFacingCamera {
|
|
return [self cameraWithPosition:AVCaptureDevicePositionFront];
|
|
}
|
|
|
|
#pragma mark - 寻找背置摄像头,没有则返回空
|
|
- (AVCaptureDevice *)backFacingCamera {
|
|
return [self cameraWithPosition:AVCaptureDevicePositionBack];
|
|
}
|
|
|
|
#pragma mark - 从指定AVCaptureDevice的位置获取设置
|
|
- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition) position {
|
|
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
|
|
for (AVCaptureDevice *device in devices) {
|
|
if ([device position] == position) {
|
|
return device;
|
|
}
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
- (NSUInteger)cameraCount {
|
|
return [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];
|
|
}
|
|
|
|
#pragma mark - 前后摄像头切换
|
|
- (int)cameraChange {
|
|
|
|
if ([self cameraCount] > 1) {
|
|
|
|
NSError *error;
|
|
AVCaptureDevicePosition position = self.input.device.position;
|
|
[self.session beginConfiguration];
|
|
[self.session removeInput:self.input];
|
|
self.input = nil;
|
|
|
|
AVCaptureDeviceInput * newDeviceInput = nil;
|
|
if (position == AVCaptureDevicePositionBack) {
|
|
newDeviceInput =
|
|
[AVCaptureDeviceInput deviceInputWithDevice:[self frontFacingCamera] error:&error];
|
|
} else if (position == AVCaptureDevicePositionFront) {
|
|
newDeviceInput =
|
|
[AVCaptureDeviceInput deviceInputWithDevice:[self backFacingCamera] error:&error];
|
|
}
|
|
if (newDeviceInput != nil) {
|
|
if ([self.session canAddInput:newDeviceInput]) {
|
|
[self.session addInput:newDeviceInput];
|
|
self.input = newDeviceInput;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
position = self.input.device.position;
|
|
|
|
|
|
[self setFrontCameraChangeOrientationToLandscapeRight];
|
|
[self.session commitConfiguration];
|
|
|
|
}
|
|
//自动对焦
|
|
//[self autoFocusAtPoint:CGPointMake(.5f, .5f)];
|
|
|
|
return self.input.device.position;
|
|
}
|
|
|
|
#pragma mark - 自动对焦
|
|
- (void)autoFocusAtPoint:(CGPoint)point {
|
|
AVCaptureDevice *device = self.input.device;
|
|
if ([device isFocusPointOfInterestSupported] && [device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
|
|
NSError *error;
|
|
if ([device lockForConfiguration:&error]) {
|
|
[device setFocusPointOfInterest:point];
|
|
[device setFocusMode:AVCaptureFocusModeAutoFocus];
|
|
[device unlockForConfiguration];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)setFrontCameraChangeOrientationToLandscapeRight {
|
|
|
|
for (AVCaptureConnection *connection in self.output.connections)
|
|
if (connection.supportsVideoOrientation && connection.videoOrientation != AVCaptureVideoOrientationLandscapeRight)
|
|
[connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
|
|
}
|
|
|
|
- (void)setFrameRate:(NSInteger)fRate {
|
|
DLog(@"setFrameRate");
|
|
if (fRate > 0)
|
|
{
|
|
for (AVCaptureConnection *connection in self.output.connections)
|
|
{
|
|
|
|
if ([connection respondsToSelector:@selector(setVideoMinFrameDuration:)])
|
|
connection.videoMinFrameDuration = CMTimeMake(1, fRate);
|
|
|
|
if ([connection respondsToSelector:@selector(setVideoMaxFrameDuration:)])
|
|
if ( connection.isVideoMaxFrameDurationSupported ) {
|
|
connection.videoMaxFrameDuration = CMTimeMake(1, fRate);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (AVCaptureConnection *connection in self.output.connections)
|
|
{
|
|
if ([connection respondsToSelector:@selector(setVideoMinFrameDuration:)])
|
|
connection.videoMinFrameDuration = kCMTimeInvalid; // This sets videoMinFrameDuration back to default
|
|
|
|
if ([connection respondsToSelector:@selector(setVideoMaxFrameDuration:)])
|
|
connection.videoMaxFrameDuration = kCMTimeInvalid; // This sets videoMaxFrameDuration back to default
|
|
}
|
|
}
|
|
}
|
|
|
|
- (NSInteger)frameRate {
|
|
return self.frameRate;
|
|
}
|
|
|
|
|
|
- (void)addCameraView:(UIView *)view
|
|
{
|
|
UIView *bgView = [[UIView alloc] initWithFrame:view.bounds];
|
|
[bgView setBackgroundColor:[UIColor blackColor]];
|
|
[self.previewLayer setBackgroundColor:[UIColor blackColor].CGColor];
|
|
|
|
[self.previewLayer setFrame:view.bounds];
|
|
[bgView.layer addSublayer:self.previewLayer];
|
|
|
|
[view addSubview:bgView];
|
|
[view sendSubviewToBack:bgView];
|
|
[self.previewLayer setOrientation:AVCaptureVideoOrientationLandscapeRight];
|
|
}
|
|
|
|
-(void)startCamera:(BOOL)isFont{
|
|
AVCaptureSession *session = [[AVCaptureSession alloc] init];
|
|
[session beginConfiguration];
|
|
[session setSessionPreset:AVCaptureSessionPreset352x288];
|
|
|
|
|
|
AVCaptureVideoDataOutput * newVideoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
|
|
// 指定像素格式
|
|
newVideoDataOutput.videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
[NSNumber numberWithInt:kCVPixelFormatType_32BGRA],
|
|
kCVPixelBufferPixelFormatTypeKey,nil];
|
|
newVideoDataOutput.alwaysDiscardsLateVideoFrames = YES;
|
|
// 配置图像输出
|
|
if ([session canAddOutput:newVideoDataOutput]) {
|
|
[session addOutput:newVideoDataOutput];
|
|
dispatch_queue_t queue = dispatch_queue_create("com.yige.cameraProcessingQueue", NULL);
|
|
[newVideoDataOutput setSampleBufferDelegate:self queue:queue];
|
|
dispatch_release(queue);
|
|
self.output = newVideoDataOutput;
|
|
}
|
|
[newVideoDataOutput release];
|
|
|
|
// 设置预览祯率
|
|
self.frameRate = VIDEO_FRAME_RATE;
|
|
|
|
if(isFont){
|
|
AVCaptureDeviceInput * newDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:[self frontFacingCamera] error:nil];
|
|
if ([session canAddInput:newDeviceInput]) {
|
|
[session addInput:newDeviceInput];
|
|
self.input = newDeviceInput;
|
|
}
|
|
}else{
|
|
AVCaptureDeviceInput * newDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:[self backFacingCamera] error:nil];
|
|
if ([session canAddInput:newDeviceInput]) {
|
|
[session addInput:newDeviceInput];
|
|
self.input = newDeviceInput;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
AVCaptureVideoPreviewLayer * newPreviewLayer =
|
|
[[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
|
|
|
|
[newPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
|
|
self.previewLayer = newPreviewLayer;
|
|
[newPreviewLayer release];
|
|
|
|
for (AVCaptureConnection *connection in self.output.connections)
|
|
if (connection.supportsVideoOrientation && connection.videoOrientation != AVCaptureVideoOrientationLandscapeRight)
|
|
[connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
|
|
|
|
[session commitConfiguration];
|
|
[session startRunning];
|
|
self.session = session;
|
|
self.isRun = YES;
|
|
[session release];
|
|
}
|
|
|
|
-(void)stopCamera{
|
|
if([self session]){
|
|
|
|
self.isRun = NO;
|
|
|
|
[self.session stopRunning];
|
|
|
|
// [self.session release];
|
|
// [self.input release];
|
|
// [self.output release];
|
|
// [self.previewLayer release];
|
|
|
|
self.session = nil;
|
|
self.input = nil;
|
|
self.output = nil;
|
|
self.previewLayer = nil;
|
|
}
|
|
}
|
|
|
|
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
|
|
if(self.isRun){
|
|
@autoreleasepool {
|
|
self.isFinishCaptureOutput = NO;
|
|
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
|
|
CVPixelBufferLockBaseAddress(imageBuffer,0);
|
|
uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
|
|
|
|
DWORD dwSize = CVPixelBufferGetDataSize(imageBuffer);
|
|
DWORD dwWidth = CVPixelBufferGetWidth(imageBuffer);
|
|
DWORD dwHeight = CVPixelBufferGetHeight(imageBuffer);
|
|
|
|
//设备端生成视频
|
|
if (self.session.sessionPreset == AVCaptureSessionPreset352x288) {
|
|
fgFillVideoRawFrame(baseAddress, dwSize, dwWidth, dwHeight, 0);
|
|
}else {
|
|
fgFillVideoRawFrame(baseAddress, dwSize, dwWidth, dwHeight, 1);
|
|
}
|
|
|
|
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
|
|
|
|
self.isFinishCaptureOutput = YES;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
@end
|