iOS 音视频采集 AVCaptureSession

  • 多媒体开发技术概要

在之前的文章中,对多媒体音视频开发的经典流程做过一个简单的介绍。在这篇文章中,将首先就音视频从采集部分做一个实例的讲解。首先以iOS平台为例。

AVFoundation

Apple 官方给我们提供了一个很大的一个集合框架 AVFoundation。Apple的官方介绍原文如下

AVFoundation is one of several frameworks that you can use to play and create time-based audiovisual media. It provides an Objective-C interface you use to work on a detailed level with time-based audiovisual data. For example, you can use it to examine, create, edit, or reencode media files. You can also get input streams from devices and manipulate video during realtime capture and playback. 

AVFoundation是你可以用来播放和创建基于时间的多媒体视听体验的框架之一,它提供了Objective-C的接口来让我们操作这些基于时间的视听多媒体数据。比如,你可以用它来检测,创建,编辑或者重新编码媒体文件。你也可以从设备中获取流,并且在媒体流的实时采集和播放的过程中对它进行操作。

iOS 音视频采集 AVCaptureSession_第1张图片

AVCaptureSession

我们在音视频的采集技术选择上我们可以首先考虑AVFoundation 提供的AVCaptureSeesion 及其涉及的一系列输入输出对象。

AVCaptureSession是iOS提供的一个管理和协调输入设备到输出设备之间数据流的对象。

iOS 音视频采集 AVCaptureSession_第2张图片

在这个期间我们除了会涉及到AVCaptureSession之外,我们还会涉及到例如AVCaptureDevice, AVCaptureInput, AVCaptureOutput,AVCaptureVideoPreviewLayer等一系列的类。
其中AVCpatureDevice抽象了具体的设备,比如麦克风,摄像头
AVCaptureInput 是一个抽象类,用于给Capture session中提供输入数据的作用。它的子类AVCaptureDeviceInput就是 输入数据是从AVCaptureDevice中获得。
AVCaptureOutput 也是一个抽象类,用于从Capture session中获取输出数据。它的子类包括,AVCaptureAudioDataOutput 音频数据输出,AVCaptureVideoDataOutput 视频数据输出,AVCaptureMovieFileOutput 文件输出,AVCaptureStillImageOutput 图像照片输出等等。
AVCaptureVideoPreviewLayer 是CALayer的子类,用于显示采集到的视频图像数据的。起预览作用。

首先我们需要创建一个AVCaptureSession 的实例对象。

_captureSession = [[AVCaptureSession alloc]init];

然后我么就可以开始创建输入输出设备了并将他们添加到之前创建好的AVCaptureSession 中。

        //get an AVCaptureDevice instance , here we want camera
        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
        for(AVCaptureDevice *device in devices){
            if(device.position == AVCaptureDevicePositionBack){
                _inputCamera = device;
            }
        }

        NSError *error = nil;
        //initialize an AVCaptureDeviceInput with camera (AVCaptureDevice)
        _videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:_inputCamera error:&error];
        if(error){
            NSLog(@"Camera error");
            return nil;
        }

        //add video input to AVCaptureSession
        if([self.captureSession canAddInput:_videoInput]){
            [self.captureSession addInput:_videoInput];
        }

        //initialize an AVCaptureVideoDataOuput instance
        _videoDataOutput = [[AVCaptureVideoDataOutput alloc]init];
        [self.videoDataOutput setAlwaysDiscardsLateVideoFrames:NO];
        [self.videoDataOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];
        [self.videoDataOutput setSampleBufferDelegate:self queue:videoCaptureQueue];

        //add video data output to capture session
        if([self.captureSession canAddOutput:self.videoDataOutput]){
            [self.captureSession addOutput:self.videoDataOutput];
        }

        //setting orientaion
        AVCaptureConnection *connection = [self.videoDataOutput connectionWithMediaType:AVMediaTypeVideo];
        connection.videoOrientation = AVCaptureVideoOrientationPortrait;
        if ([connection isVideoStabilizationSupported]) {
            connection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
        }
        connection.videoScaleAndCropFactor = connection.videoMaxScaleAndCropFactor;


        error = nil;
        //get an AVCaptureDevice for audio, here we want micphone
        _inputMicphone = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];

        //intialize the AVCaputreDeviceInput instance with micphone device
        _audioInput =[[AVCaptureDeviceInput alloc]initWithDevice:_inputMicphone error:&error];
        if(error){
            NSLog(@"micphone error");
        }

        //add audio device input to capture session
        if([self.captureSession canAddInput:_audioInput]){
            [self.captureSession addInput:_audioInput];
        }

        //initliaze an AVCaptureAudioDataOutput instance and set to capture session
        self.audioDataOutput = [[AVCaptureAudioDataOutput alloc] init];
        if([self.captureSession canAddOutput:self.audioDataOutput]){
            [self.captureSession addOutput:self.audioDataOutput];
        }

        [self.audioDataOutput setSampleBufferDelegate:self queue:audioCaptureQueue];

我们还需要告诉AVCaptureSession,我们希望采集什么样的质量等级的音视频数据。在这里我们不用一个个参数去设置。iOS给我们提供了很多可用的preset(预制值)。我们只需选择符合我们要求的preset就可以了。

        if([_captureSession canSetSessionPreset:AVCaptureSessionPreset640x480]){
            [_captureSession setSessionPreset:AVCaptureSessionPreset640x480];
            _capturePresent = AVCaptureSessionPreset640x480;
        }

最后如果我们想开始音视频采集的话,就直接给AVCaptureSession发 startRunning 消息

-(void)start{
    [self.captureSession startRunning];
}

具体代码在Github: MultiMedia 的AVCaptureSessionTry

你可能感兴趣的:(多媒体,媒体播放器,多媒体技术)