美文网首页
iOS-摄像头切换,并获取录制数据(封装)

iOS-摄像头切换,并获取录制数据(封装)

作者: 温柔vs先生 | 来源:发表于2023-03-28 20:06 被阅读0次
//
//  CameraSessionManager.h
//  test
//
//  Created by wbb on 2023/3/24.
//

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN

@interface CameraSessionManager : NSObject <AVCaptureVideoDataOutputSampleBufferDelegate>

@property (nonatomic, strong) AVCaptureSession *session;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;
@property (nonatomic, strong) AVCaptureDeviceInput *videoInput;
@property (nonatomic, strong) AVCaptureVideoDataOutput *videoOutput;
@property (nonatomic, weak) UIView *previewView;

- (instancetype)initWithPreviewView:(UIView *)previewView;
- (void)startRunning;
- (void)stopRunning;
- (void)toggleCamera;
- (AVCaptureVideoPreviewLayer *)getPreviewLayer;

@end


NS_ASSUME_NONNULL_END

//
//  CameraSessionManager.m
//  test
//
//  Created by wbb on 2023/3/24.
//

#import "CameraSessionManager.h"

@implementation CameraSessionManager
- (instancetype)initWithPreviewView:(UIView *)previewView {
    self = [super init];
    if (self) {
        _previewView = previewView;
        _session = [[AVCaptureSession alloc] init];
        [self setupVideoInput];
        [self setupVideoOutput];
        [self setupPreviewLayer];
    }
    return self;
}

- (void)setupVideoInput {
    AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    NSError *error;
    _videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
    if (error) {
        // 错误处理
        return;
    }
    if ([self.session canAddInput:self.videoInput]) {
        [self.session addInput:self.videoInput];
    }
}

- (void)setupVideoOutput {
    _videoOutput = [[AVCaptureVideoDataOutput alloc] init];
    _videoOutput.videoSettings = @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)};
    _videoOutput.alwaysDiscardsLateVideoFrames = YES;
    dispatch_queue_t videoQueue = dispatch_queue_create("videoQueue", DISPATCH_QUEUE_SERIAL);
    [_videoOutput setSampleBufferDelegate:self queue:videoQueue];
    if ([self.session canAddOutput:self.videoOutput]) {
        [self.session addOutput:self.videoOutput];
    }
}

- (void)setupPreviewLayer {
    _previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
    _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    _previewLayer.frame = self.previewView.bounds;
    [self.previewView.layer addSublayer:self.previewLayer];
}

- (void)startRunning {
//    [self.session startRunning];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self.session startRunning];
        });
}

- (void)stopRunning {
    [self.session stopRunning];
}

- (void)toggleCamera {
    AVCaptureDevicePosition position = self.videoInput.device.position;
    AVCaptureDevice *newVideoDevice = nil;
    if (position == AVCaptureDevicePositionBack) {
        newVideoDevice = [self videoDeviceWithPosition:AVCaptureDevicePositionFront];
    } else {
        newVideoDevice = [self videoDeviceWithPosition:AVCaptureDevicePositionBack];
    }
    NSError *error;
    AVCaptureDeviceInput *newVideoInput = [AVCaptureDeviceInput deviceInputWithDevice:newVideoDevice error:&error];
    if (error) {
        // 错误处理
        return;
    }
    [self.session beginConfiguration];
    [self.session removeInput:self.videoInput];
    if ([self.session canAddInput:newVideoInput]) {
        [self.session addInput:newVideoInput];
        self.videoInput = newVideoInput;
    } else {
        [self.session addInput:self.videoInput];
    }
    [self.session commitConfiguration];
}

- (AVCaptureVideoPreviewLayer *)getPreviewLayer {
    return self.previewLayer;
}

- (AVCaptureDevice *)videoDeviceWithPosition:(AVCaptureDevicePosition)position {
    AVCaptureDeviceDiscoverySession *discoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
    NSArray *devices = discoverySession.devices;
    for (AVCaptureDevice *device in devices) {
        if (device.position == position) {
            return device;
        }
    }
    return nil;
}

- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    // 处理视频帧数据
}
@end

使用:

    CameraSessionManager *manager = [[CameraSessionManager alloc] initWithPreviewView:self.view];
    [self.view.layer addSublayer:[manager getPreviewLayer]];
    self.manager = manager;
    [manager startRunning];

相关文章

  • 视频录制——概述

    分三块:图像录制、音频录制、混合封装 图像录制 为了有实时美颜效果,需要先把摄像头输出的数据转换成OpenGL可编...

  • 4.获取数据并赋值

    url封装 网络请求封装 首页获取数据并展示

  • iOS 保存摄像头H264视频流

    我们下面完成获取摄像头数据,并保存为h264格式的文件。 1、初始化获取摄像头数据相关代码 然后我们实行代理方法 ...

  • 关于ios视频录制切换前后摄像头后方向错误解决办法

    最近发现项目里,切换前后摄像头几次之后,会出现录制的视频方向上下颠倒,可是明明已经在切换摄像头后,给videoco...

  • 微信H5调用原生摄像头录像

    使用H5调用原生 getUserMedia方法获取摄像头权限进行录制视频,并且获取录制后的视频文件向后端进行存储,...

  • 2018-03-06

    从摄像头获取的视频数据,经过编码后(当然,也可以不编码,如果你觉得也很ok的话),可以视频录制,同时如果需要,当然...

  • 安卓音视频开发-USB外接MIC录制音频

    项目中需要使用外接摄像头录制音频和视频,需要切换到OTG模式,测试是发现视频是可以录制的,使用的是开源库andro...

  • Android开发(18) 摄像和播放

    需求 使用android手机的摄像头进行拍照。 录制过程: 结束拍摄: 我自己的封装类: 播放: 结束播放时: 参...

  • 【JavaScript实现Tab切换】

    使用类名实现最简单Tab切换 完成函数封装版Tab切换 this的下标获取实现Tab切换 自定义属性版Tab切换 ...

  • OpenCV Python 录制视频

    学到实用OpenCV调用笔记本电脑的摄像头,并录制视频保存到本地硬盘的时候,出现了一点故障,那就是获取到的文件总是...

网友评论

      本文标题:iOS-摄像头切换,并获取录制数据(封装)

      本文链接:https://www.haomeiwen.com/subject/jajxddtx.html