当前位置: 首页 > 编程日记 > 正文

1小时学会:最简单的iOS直播推流(五)yuv、pcm数据的介绍和获取

最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!!

源代码:https://github.com/hardman/AWLive

前面介绍了如何通过相机实时获取音视频数据。

我们接下来就需要了解获取到的数据到底是什么样的。

使用系统提供的接口获取到的音视频数据都保存在CMSampleBufferRef中。

使用GPUImamge获取到的音频数据为CMSampleBufferRef,获取到的视频格式为BGRA格式的二进制数据。

CMSampleBufferRef介绍

这个结构在iOS中表示一帧音频/视频数据。

它里面包含了这一帧数据的内容和格式。

我们可以把它的内容取出来,提取出/转换成 我们想要的数据。

代表视频的CMSampleBufferRef中保存的数据是yuv420格式的视频帧(因为我们在视频输出设置中将输出格式设为:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)。

代表音频的CMSampleBufferRef中保存的数据是PCM格式的音频帧。

yuv是什么?NV12又是什么?

视频是由一帧一帧的数据连接而成,而一帧视频数据其实就是一张图片。

yuv是一种图片储存格式,跟RGB格式类似。

RGB格式的图片很好理解,计算机中的大多数图片,都是以RGB格式存储的。

yuv中,y表示亮度,单独只有y数据就可以形成一张图片,只不过这张图片是灰色的。u和v表示色差(u和v也被称为:Cb-蓝色差,Cr-红色差),

为什么要yuv?

有一定历史原因,最早的电视信号,为了兼容黑白电视,采用的就是yuv格式。

一张yuv的图像,去掉uv,只保留y,这张图片就是黑白的。

而且yuv可以通过抛弃色差来进行带宽优化。

比如yuv420格式图像相比RGB来说,要节省一半的字节大小,抛弃相邻的色差对于人眼来说,差别不大。

一张yuv格式的图像,占用字节数为 (width * height + (width * height) / 4 + (width * height) / 4) = (width * height) * 3 / 2
一张RGB格式的图像,占用字节数为(width * height) * 3

在传输上,yuv格式的视频也更灵活(yuv3种数据可分别传输)。

很多视频编码器最初是不支持rgb格式的。但是所有的视频编码器都支持yuv格式。

综合来讲,我们选择使用yuv格式,所以我们编码之前,首先将视频数据转成yuv格式。

我们这里使用的就是yuv420格式的视频。

yuv420也包含不同的数据排列格式:I420,NV12,NV21.

其格式分别如下,
I420格式:y,u,v 3个部分分别存储:Y0,Y1…Yn,U0,U1…Un/2,V0,V1…Vn/2
NV12格式:y和uv 2个部分分别存储:Y0,Y1…Yn,U0,V0,U1,V1…Un/2,Vn/2
NV21格式:同NV12,只是U和V的顺序相反。

综合来说,除了存储顺序不同之外,上述格式对于显示来说没有任何区别。

使用哪种视频的格式,取决于初始化相机时设置的视频输出格式。
设置为kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange时,表示输出的视频格式为NV12;
设置为kCVPixelFormatType_420YpCbCr8Planar时,表示使用I420。

GPUImage设置相机输出数据时,使用的就是NV12.

为了一致,我们这里也选择NV12格式输出视频。

PCM是什么?

脉冲编码调制,其实是将不规则的模拟信号转换成数字信号,这样就可以通过物理介质存储起来。

而声音也是一种特定频率(20-20000HZ)的模拟信号,也可以通过这种技术转换成数字信号,从而保存下来。

PCM格式,就是录制声音时,保存的最原始的声音数据格式。

相信你应该听说过wav格式的音频,它其实就是给PCM数据流加上一段header数据,就成为了wav格式。

而wav格式有时候之所以被称为无损格式,就是因为他保存的是原始pcm数据(也跟采样率和比特率有关)。

像我们耳熟能详的那些音频格式,mp3,aac等等,都是有损压缩,为了节约占用空间,在很少损失音效的基础上,进行最大程度的压缩。

所有的音频编码器,都支持pcm编码,而且录制的声音,默认也是PCM格式,所以我们下一步就是要获取录制的PCM数据。

从CMSampleBufferRef中提取yuv数据

在前面的文章(使用系统接口捕获视频)中,初始化输出设备时,我们将输出的数据设置为kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange。
因此在CMSampleBufferRef中保存的是yuv420(NV12)格式数据。
通过下面的方法将CMSampleBufferRef转为yuv420(NV12)。

// AWVideoEncoder.m文件
-(NSData *) convertVideoSmapleBufferToYuvData:(CMSampleBufferRef) videoSample{// 获取yuv数据// 通过CMSampleBufferGetImageBuffer方法,获得CVImageBufferRef。// 这里面就包含了yuv420(NV12)数据的指针CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(videoSample);//表示开始操作数据CVPixelBufferLockBaseAddress(pixelBuffer, 0);//图像宽度(像素)size_t pixelWidth = CVPixelBufferGetWidth(pixelBuffer);//图像高度(像素)size_t pixelHeight = CVPixelBufferGetHeight(pixelBuffer);//yuv中的y所占字节数size_t y_size = pixelWidth * pixelHeight;//yuv中的uv所占的字节数size_t uv_size = y_size / 2;uint8_t *yuv_frame = aw_alloc(uv_size + y_size);//获取CVImageBufferRef中的y数据uint8_t *y_frame = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);memcpy(yuv_frame, y_frame, y_size);//获取CMVImageBufferRef中的uv数据uint8_t *uv_frame = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);memcpy(yuv_frame + y_size, uv_frame, uv_size);CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);//返回数据return [NSData dataWithBytesNoCopy:yuv_frame length:y_size + uv_size];
}

将GPUImage获取到的BGRA格式的图片转成yuv(NV12)格式

//AWGPUImageAVCapture.m文件
-(void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex{[super newFrameReadyAtTime:frameTime atIndex:textureIndex];if(!self.capture || !self.capture.isCapturing){return;}//将bgra转为yuv//图像宽度int width = imageSize.width;//图像高度int height = imageSize.height;//宽*高int w_x_h = width * height;//yuv数据长度 = (宽 * 高) * 3 / 2int yuv_len = w_x_h * 3 / 2;//yuv数据uint8_t *yuv_bytes = malloc(yuv_len);//ARGBToNV12这个函数是libyuv这个第三方库提供的一个将bgra图片转为yuv420格式的一个函数。//libyuv是google提供的高性能的图片转码操作。支持大量关于图片的各种高效操作,是视频推流不可缺少的重要组件,你值得拥有。[self lockFramebufferForReading];ARGBToNV12(self.rawBytesForImage, width * 4, yuv_bytes, width, yuv_bytes + w_x_h, width, width, height);[self unlockFramebufferAfterReading];NSData *yuvData = [NSData dataWithBytesNoCopy:yuv_bytes length:yuv_len];[self.capture sendVideoYuvData:yuvData];
}

从CMSampleBufferRef中提取PCM数据

// AWAudioEncoder.m 文件
-(NSData *) convertAudioSmapleBufferToPcmData:(CMSampleBufferRef) audioSample{//获取pcm数据大小NSInteger audioDataSize = CMSampleBufferGetTotalSampleSize(audioSample);//分配空间int8_t *audio_data = aw_alloc((int32_t)audioDataSize);//获取CMBlockBufferRef//这个结构里面就保存了 PCM数据CMBlockBufferRef dataBuffer = CMSampleBufferGetDataBuffer(audioSample);//直接将数据copy至我们自己分配的内存中CMBlockBufferCopyDataBytes(dataBuffer, 0, audioDataSize, audio_data);//返回数据return [NSData dataWithBytesNoCopy:audio_data length:audioDataSize];
}

至此我们已经将捕获的视频数据转为了yuv420格式,将音频数据转为了pcm格式。

接下来就可以对这些数据进行各种编码了。编码完成后,就可以将数据发送给服务器了。

文章列表

  1. 1小时学会:最简单的iOS直播推流(一)项目介绍
  2. 1小时学会:最简单的iOS直播推流(二)代码架构概述
  3. 1小时学会:最简单的iOS直播推流(三)使用系统接口捕获音视频
  4. 1小时学会:最简单的iOS直播推流(四)如何使用GPUImage,如何美颜
  5. 1小时学会:最简单的iOS直播推流(五)yuv、pcm数据的介绍和获取
  6. 1小时学会:最简单的iOS直播推流(六)h264、aac、flv介绍
  7. 1小时学会:最简单的iOS直播推流(七)h264/aac 硬编码
  8. 1小时学会:最简单的iOS直播推流(八)h264/aac 软编码
  9. 1小时学会:最简单的iOS直播推流(九)flv 编码与音视频时间戳同步
  10. 1小时学会:最简单的iOS直播推流(十)librtmp使用介绍
  11. 1小时学会:最简单的iOS直播推流(十一)sps&pps和AudioSpecificConfig介绍(完结)

相关文章:

beta冲刺第一天

1、今天解决的进度 成员进度陈家权回复界面设计,由于成员变动加上和其他成员距离较远,服务器404赖晓连改进Alpha版本页面没能及时更新的问题雷晶获取提问问题时间更新到数据库林巧娜今天的任务是夜间模式功能块,没有完成,查找了很…

angular绑定数据_Angular中的数据绑定说明

angular绑定数据数据绑定 (Data Binding) 动机 (Motivation) Data often defines the look of an application. Interpreting that data into the user interface involves class logic (.component.html) and a template view (.component.ts) . Angular connects them throug…

WPF判断两个时间大小避免误差

进行查询操作的时候,经常用到判断开始时间和结束时间大小的条件,由于从控件上获取的时间除了年月日时分秒,还包括毫秒、微秒等,导致直接判断时间大小的时候会产生一些误差,如下: 结果分析:年月日…

1小时学会:最简单的iOS直播推流(六)h264、aac、flv介绍

最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有…

分享一款Markdown的css样式

使用 本样式在这个样式的基础上做了一些修改, 主要是对于表格和代码块以及一些细节的修改。 主要目的是用在chrome的扩展 Markdown Preview Plus中, 替换其内置的样式。 由于 Markdown Preview Plus对css文件大大小有要求(小于8K)…

远程桌面怎么持续连接_如何拥有成功且可持续的远程产品管理职业

远程桌面怎么持续连接Remote work is rapidly growing in all industries. Some professionals might try to push away this new way of working, seeing it as simply a current necessity. They might not think its fit for a product manager who’s constantly managing …

1小时学会:最简单的iOS直播推流(七)h264/aac 硬编码

最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有…

Linux日常命令记录

1、查找进程 ps -ef | grep javajps 2、杀死进程 kill -9 1827 3、进入tomcat中的日志文件夹 cd logs 4、查看日志 tail -f catalina.outtail -n 10000 catalina.out 5、查看tomcat的连接数 ss -nat|grep -i "8081"|wc -lnetstat -nat | grep -i "8081" | …

【特效】移入显示移出隐藏

移入显示移出隐藏的效果也是很常见的,例如: 如果页面有有多处地方有此效果,那么也可以合并到一块,只写一段js代码,只要注意控制样式和class名字和用于js获取元素的class名字分开设置就可以了。代码很简单,用…

web前端开发最佳实践_学习前端Web开发的最佳方法

web前端开发最佳实践为什么要进行网站开发? (Why web development?) Web development is a field that is not going anywhere anytime soon. The web is moving quickly, and there are regular improvements to the devices many people use daily. Web开发是一个…

使用C#的HttpWebRequest模拟登陆网站

很久没有写新的东西了,今天在工作中遇到的一个问题,感觉很有用,有种想记下来的冲动。 这篇文章是有关模拟登录网站方面的。 实现步骤; 启用一个web会话发送模拟数据请求(POST或者GET)获取会话的CooKie 并根…

1小时学会:最简单的iOS直播推流(番外)运行不起AWLive的demo的同学请看这里

最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有…

学习css布局

非常经典 http://zh.learnlayout.com/ float和position:absolute都是inline-block,破坏性的。absolute根据父元素定位(static父元素除外)。div也将不再是一行的块了。 position:relative自身定位。top,left是根据自己原本位置&…

csv文件示例_如何在R中使用数据框和CSV文件-带有示例的详细介绍

csv文件示例Welcome! If you want to start diving into data science and statistics, then data frames, CSV files, and R will be essential tools for you. Lets see how you can use their amazing capabilities.欢迎! 如果您想开始研究数据科学和统计学&…

1小时学会:最简单的iOS直播推流(八)h264/aac 软编码

最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有…

003小插曲之变量和字符串

变量:赋值(名字值);变量名:字母分大小写/数字/下划线,不能以数字开头;拼接;原始字符串r; 专业优秀的名称:teacher/num/name/test/temp >>> teacher小…

mysql插入大量数据

创建实验表: CREATE TABLE a ( id int(11) NOT NULL AUTO_INCREMENT, name char(50) NOT NULL, type char(20) NOT NULL, PRIMARY KEY (id)) ENGINEInnoDB; 创建存储语句: delimiter // create procedure insertdata() begin declare i int …

十六进制190的2进制数_十六进制数系统解释

十六进制190的2进制数Hexadecimal numbers, often shortened to “hex numbers” or “hex”, are numbers represented in base 16 as opposed to base 10 that we use for everyday arithmetic and counting.十六进制数字(通常缩写为“十六进制数字”或“十六进制”)是以16为…

初学ssm框架的信息

ssm框架,就是Spring ,SpringMVC ,mybstis 的简称,我们是从mybstis 开始学起的,mybatis的作用作为一个连接数据库的框架,可以很好配置连接好数据库, 有mybatis,我们对数据库增删改查的操作更为简便了。SSM框架&#xff…

转:YUV RGB 常见视频格式解析

转: http://www.cnblogs.com/qinjunni/archive/2012/02/23/2364446.html YUV RGB 常见视频格式解析 I420是YUV格式的一种,而YUV有packed format和planar format两种,而I420属于planar format的一种。  同时I420表示了YUV的采样比例4:2:0。4…

1小时学会:最简单的iOS直播推流(十)librtmp使用介绍

最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有…

导入语句 python_Python导入语句说明

导入语句 pythonWhile learning programming and reading some resources you’d have come across this word ‘abstraction’ which simply means to reduce and reuse the code as much as possible.在学习编程和阅读一些资源时,您会遇到“抽象”一词&#xff0c…

网页性能测试---webpagetest

http://www.webpagetest.org/转载于:https://www.cnblogs.com/cai-yu-candice/p/8194866.html

1小时学会:最简单的iOS直播推流(十一)spspps和AudioSpecificConfig介绍(完结)

最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有…

ES5 数组方法forEach

ES6已经到了非学不可的地步了&#xff0c;对于ES5都不太熟的我决定是时候学习ES5了。 1. js 数组循环遍历。 数组循环变量&#xff0c;最先想到的就是 for(var i0;i<count;i)这样的方式了。 除此之外&#xff0c;也可以使用较简便的forEach 方式 2. forEach 函数。 使用如…

pytorch深度学习_了解如何使用PyTorch进行深度学习

pytorch深度学习PyTorch is an open source machine learning library for Python that facilitates building deep learning projects. Weve published a 10-hour course that will take you from being complete beginner in PyTorch to using it to code your own GANs (gen…

LwIP Application Developers Manual12---Configuring lwIP

1.前言 2.LwIP makefiles With minimal featuresC_SOURCES \ src/api/err.c \ src/core/init.c \ src/core/mem.c \ src/core/memp.c \ src/core/netif.c \ src/core/pbuf.c \ src/core/stats.c \ src/core/udp.c \ src/core/ipv4/icmp.c \ src/core/ipv4/inet.c \ src/core/i…

仿斗鱼聊天:基于CoreText的面向对象图文排版工具AWRichText

AWRichText 基于CoreText&#xff0c;面向对象&#xff0c;极简&#xff0c;易用&#xff0c;高效&#xff0c;支持精确点击&#xff0c;UIView混排&#xff0c;GIF动图&#xff0c;并不仅仅局限于图文混排的富文本排版神器。 代码地址&#xff1a;https://github.com/hardman/…

搭建nexus后,进入首页的时候出现warning: Could not connect to Nexus.错误

nexus出现这种问题&#xff0c;一般是版本太旧&#xff0c;换一个高版本的nexus就能解决了。 转载于:https://www.cnblogs.com/tietazhan/p/5459393.html

微软hackathon_武汉Hackathon的黑客之路–开发人员如何抗击COVID-19

微软hackathonThe Chinese New Year in 2020 was one of the saddest Chinese New Years in recent memory. After the sudden outbreak of the COVID-19 virus, the city pressed pause on all celebrations.2020年的农历新年是最近记忆中最可悲的农历新年之一。 在COVID-19病…