[置顶] 基于iOS的网络音视频实时传输系统(二)- 捕获音视频数据
2017-09-25 20:41
661 查看
下载
GitHub:client 端:https://github.com/AmoAmoAmo/Smart_Device_Client
server端:https://github.com/AmoAmoAmo/Smart_Device_Server
另还写了一份macOS版的server,但是目前还有一些问题,有兴趣的去看看吧:https://github.com/AmoAmoAmo/Server_Mac
获取音视频数据,这里使用的是AVCaptureSession,可以方便地自定义相机界面,看起来大概是这样的:
关于AVCaptureSession的使用步骤这里不赘述,网上一搜一大把,无非就是设置输入输出对象,设置代理、预览层之类。
这里直接上代码了,具体注释都有哦。
过程
初始化session
self.avSession = [[AVCaptureSession alloc] init]; self.avSession.sessionPreset = AVCaptureSessionPreset640x480; // 设备对象 (audio) AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; // 输入流 AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil]; // 输出流 AVCaptureAudioDataOutput *audioOutput = [[AVCaptureAudioDataOutput alloc] init]; [audioOutput setSampleBufferDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; // 添加输入输出流 if ([_avSession canAddInput:audioInput]) { [_avSession addInput:audioInput]; } if ([_avSession canAddOutput:audioOutput]) { [_avSession addOutput:audioOutput]; } // 设备对象 (video) AVCaptureDevice *inputCamera = nil; NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; for (AVCaptureDevice *device in devices) { if ([device position] == AVCaptureDevicePositionBack) { inputCamera = device; } } AVCaptureDeviceInput *videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:inputCamera error:nil]; if ([self.avSession canAddInput:videoInput]) { [self.avSession addInput:videoInput]; } self.videoOutput = [[AVCaptureVideoDataOutput alloc] init]; [self.videoOutput setAlwaysDiscardsLateVideoFrames:NO]; // 是否抛弃延迟的帧:NO [self.videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; [self.videoOutput setSampleBufferDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; if ([self.avSession canAddOutput:self.videoOutput]) { [self.avSession addOutput:self.videoOutput]; } AVCaptureConnection *connection = [self.videoOutput connectionWithMediaType:AVMediaTypeVideo]; [connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight]; // 因为要横屏,所以让输出视频图像旋转90° self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.avSession]; [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; [[self.previewLayer connection] setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];// 预览层也让它右转90° [self.previewLayer setFrame:self.captureView.bounds]; [self.captureView.layer insertSublayer:self.previewLayer above:0];
AVCapture输出流代理
设备捕获到的音视频数据都在这里取得,然后进行编码等操作。// 默认情况下,为30 fps,意味着该函数每秒调用30次 - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { // 获取输入设备数据,有可能是音频有可能是视频 if (captureOutput == self.videoOutput) { // 收到数据,开始编码 [self.videoEncoder startH264EncodeWithSampleBuffer:sampleBuffer andReturnData:^(NSData *data) { // 当TCP需要开始传输数据时,开始传编码后的数据 if (self.isReadyToEncode) { // 返回一个编码后的数据 data,传给TCP 开始发送给client [self.tcpServer sendVideoDataToClientWithData:data]; } }]; } else { // 音频 dispatch_sync(mEncodeQueue, ^{ // block回调 返回编码后的音频数据 // printf("----- audio -------\n"); [self.audioEncoder encodeSampleBuffer:sampleBuffer completionBlock:^(NSData *encodedData, NSError *error) { printf("----- Audio encodedData length = %d ----- \n", (int)[encodedData length]); // 写入socket if (self.isReadyToEncode) { [self.tcpServer sendAudioDataToClientWithData:encodedData]; } }]; }); } }
问题记录
server端使用VideoToolbox进行视频编码时,发现在client端解析出来的视频画面方向发生了旋转,client端如下所示:首先排除了client端接收数据或硬解码的过程中的问题,因为把server端编码后的数据使用NSFileHandle写入文件,用VLC播放的情况与上图所示一致。
首先,判断源及目标图像是否翻转:
BOOL isFlipped = CVImageBufferIsFlipped(pixelBuffer); NSLog(@"pixelBuffer is %s", isFlipped ? "flipped" : "not flipped");打印结果如下:
pixelBuffer is flipped发现在原始数据中,图像都是翻转的
找了好久,最后发现在server端设置捕获视频的output的地方把它旋转(左右横屏):
AVCaptureConnection *connection = [self.videoOutput connectionWithMediaType:AVMediaTypeVideo]; [connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight]; // 因为要横屏,所以让输出视频图像旋转90°
运行一下:
问题就这么解决啦
相关文章
基于iOS的网络音视频实时传输系统(一)- 前言基于iOS的网络音视频实时传输系统(二)- 捕获音视频数据
基于iOS的网络音视频实时传输系统(三)- VideoToolbox编码音视频数据为H264、AAC
基于iOS的网络音视频实时传输系统(四)- 自定义socket协议(TCP、UDP)
基于iOS的网络音视频实时传输系统(五)- 使用VideoToolbox硬解码H264
基于iOS的网络音视频实时传输系统(六)- AudioQueue播放音频,OpenGL渲染显示图像
相关文章推荐
- [置顶] 基于iOS的网络音视频实时传输系统(三)- VideoToolbox编码音视频数据为H264、AAC
- [置顶] 基于iOS的网络音视频实时传输系统(五)- 使用VideoToolbox硬解码H264
- [置顶] 基于iOS的网络音视频实时传输系统(四)- 自定义socket协议(TCP、UDP)
- [置顶] 基于iOS的网络音视频实时传输系统(六)- AudioQueue播放音频,OpenGL渲染显示图像
- 1小时学会:最简单的iOS直播推流(三)使用系统接口捕获音视频数据
- 关于网络发送的数据缓冲例子(读数据和发送采用双线程)主要用于视频的实时传输
- 阶段4-独挡一面\项目-基于视频压缩的实时监控系统\Sprint3-采集端传输子系统设计
- 基于嵌入式Linux的视频采集系统8----基于RTP协议的实时传输模块
- 基于LVDS技术的远端数据传输系统实现
- 基于DirectShow的MPEG-4视频传输系统的研究与实现
- 基于嵌入式TCP/IP的实时数据传输
- 基于ARM9的视频采集传输系统
- 基于NS-2的网络视频传输仿真平台的建立
- 基于Linux的视频传输系统
- (转)利用VC++实现局域网实时视频传输(网络视频)
- 基于蓝牙的数据传输系统的设计
- 基于Linux的视频传输系统
- 基于Linux的视频传输系统(上大学时参加的一个大赛的论文)
- 基于HFC系统的高效数据传输协议
- 基于ARM高精度数据采集及网络传输方案