8.1 KiB
iOS音视频开发-采集、编码、滤镜
1.OpenGL(绘制点 线 三角形)
OpenGL 是⼀种图形编程接口(Application Programming Interface, API).简单理解就是开发的图形库,可以进行一些视频,图形,图⽚的渲染(顶点着色 光栅化(连线 完成定点之间的像素点) 片元着色)处理、2D/3D 游戏引擎开发等。
1.1 管线(渲染流程)
管线分为2个部分,上半部分是客户端(C/C++,以及OpenGL API), 下半部分为服务器端(接受Attributies属性、Uniforms、TextureData纹理数据,传递到顶点着色器(处理坐标),顶点着色器的输出最终会传递到片元着色器(注意片元着色器不接受Attributies,但可以接受Uniforms和TextureData)).
- **固定管线:**提供一个渲染流程的管线;
- 可编程管线(GLSL(着色语言): 专⻔为图形开发设计的编程语⾔):只有定点着色器(旋转平移缩放投影)和片元着色器部分来进行编程;
其中:
- **Attributies:**就是对⼀个顶点都要作出改变的数据元素.实际上,顶点位置本身就是⼀个属性。
- **Uniform:**通过设置Uniform 变量就紧接着发送⼀个图元批次处理命令. Uniform 变量实际上可以⽆限次的使⽤. 设置⼀个应⽤于整个表⾯的单个颜⾊值,还可也是⼀个时间值.
- Texture Data: 一般在片元着色器中处理,给图形填充/添加一些颜色/质感;
1.2 iOS实现OpenGL ES(Embedded Systems)的两种方式
- GLSL
- GLKit
2. GLSL语法
2.1 基本数据类型
- 整型(有符号/无符号) uint a= 32u;
- 浮点数(单精度) float fValue = 3.1f;
- 布尔值 bool isDisplay= false;
- 向量、分量类型/矩阵类型
v1 = vec4(10,10,10,10);
//឴ 通过x y z w来获取向量中的元素
v1.x = 3.0f;
v1.y = 4.0f;
v1.z = 5.0f;
v1.w = 1.0f;
v1.xyz = vec3(1,2,3);
//឴ 也可通过r g b a来获取向量中的元素
v1.r = 1.0f;
//឴ 也可通过s t p q来获取向量中的元素
v1.st = vec2(1.0,2.0);
m1 = mat4(
1.0,1.0,1.0,1.0,
1.0,1.0,1.0,1.0,
1.0,1.0,1.0,1.0,
1.0,1.0,1.0,1.0,
)
m1 = mat4(1.0f);
2.2 存储限定符(着色器变量(输入输出变量)声明过程中的修饰符)
- 输入变量: 从外部(客户端/上一个阶段着色器传递的属性/Uniform等).
- 输出变量: 从任何着色器阶段进行写入的变量。
常用const varying attribute uniform
- Const:⽤来修饰任何基本数据类型,不能⽤来修饰包含数组的数组、结构体;声明的变量在其所属的着⾊器器中均是只读的。
- 其中varying: 传递变量的作用,表示从顶点着色器传递到片元着色器.一般会传递顶点坐标/顶点颜色/纹理值(在.vsh中定义varying修饰的变量,在.fsh中定义varying修饰的同名变量,实现将一个变量从定点着色器传递到片元着色器)。
- 被uniform(glUniform**())修饰的变量,只能被shader使用,不能被修改;可理解问vertext和fragment的全局变量。比如变换矩阵/材质/光照/颜色。
- 被attribute修饰的变量只能永在vertex shader中。使用场景:顶点坐标/法线/纹理坐标/顶点颜色。
GLSL渲染思路:
- -> 创建图层(CAEAGLayer 针对OpenGL ES的渲染的图层)
- -> 创建图形上下文(EAGLContext)
- -> 清空缓冲区
- -> 设置RenderBuffer (glGenRenderbuffers)
- -> 设置FrameBuffer (glGenFrameBuffers)
- -> 开始绘制 loadShaders
3. GLKit(无法处理3个以上的光源 和2个以上的纹理)
- -> 新建上下文 并配置GLKView
self.context = [[EAFGContext all] init... APIOpenGLES2];
GLKView *view = self.view;
view.context = self,context;
然后配置颜色深度...
// 设置上下文
[EAGLContext setCurrentContext: self。context];
// 开启深度测试
glEnable(GL_DEPTH_TEST)
- -> 实现glkView:drawInRect代理方法
//在这个代理方法中准备绘制
[baseEffect prepareToDraw..];
//索引绘图
glDrawElements(...)
- -> 渲染图形
//确定顶点数据GLFloat 绘制索引GLuint 索引数组个数 sizeOf(indices)/sizeOf(GLunit)
//绑定缓冲区:将顶点数组数据载入数组缓冲区 将索引数据存储到索引数组缓冲区
//给着色器中传入顶点数据 颜色数据 纹理数据(用GLKBaseEffect(着色器对象)加载纹理数据)
- -> 实现update代理方法
4. 滤镜(GPUImage(底层是OpenGL ES、AV Foundation采集)、CoreImage)
4.1 用OpenGL ES的片元着色器来实现滤镜
原理:利用片元着色器读取每一个像素,对其灰度进行处理(饱和度、曝光),计算出一个新的颜色。
4.2 GPUImage实现滤镜(100多种滤镜,也可以自定义滤镜)
原理:把图片或者视频的每一帧图片进行图形变化(饱和度/色温)处理之后,再显示到屏幕上。本质就是像素点颜色的变化。
流程:数据源Source -> 滤镜Filter -> Final
Source(数据源环节):
- GPUImageVideoCamera :摄像头(用于拍摄视频);
- GPUImageStillCamera:摄像头(用于拍摄照片);
- GPUImagePicture : 用于处理拍摄完成的图片;
- GPUImageMovie : 用于处理已拍摄好的视频;
Filter(滤镜环节):
GPUImageFilter:用来接受图形源,通过(自定义)顶点/片源着色器来渲染新的图像。
Final(输出Outputs):
- GPUImageView
- GPUImageMovieWrite
5. Matal
MTKView:在MetalKit中提供了一个视图类MTKView
,类似于GLKit中GLKView
,用于处理metal绘制并显示到屏幕过程中的细节。即首先需要先创建MTKView
对象。
MTLDevice:由于metal是操作GPU的,所以Metal中提供了MTLDevice
协议表示GPU接口,通过式MTLCreateSystemDefaultDevice()
获取GPU。
MTLCommandQueue:在获取了GPU后,创建渲染队列,队列中存储的是将要渲染的命令。MTLCommandBuffer
。
渲染流程:
- 先用MTLCommandBuffer创建渲染缓存区。
- 其次通过MTLRenderPassDescriptor创建渲染描述符。
- 然后再通过渲染缓存区和渲染描述符创建命令编辑器MTLRenderCommandEncoder进行编码。
- 最后是结束编码 -> 提交渲染命令 -> 在完成渲染后,将命令缓存区提交至GPU。
6. 音视频开发
音视频采集 -> 视频滤镜(GPUImage) -> 音视频编码 -> 推流 -> 流媒体服务器处理 -> 拉流 -> 音视频解码 -> 音视频播放
6.1 AVFoundation(主要是音视频的采集)
- 捕捉会话: AVCaptureSession.
- 捕捉设备: AVCaptureDevice(获取摄像头设备,以及调节摄像头一些属性 聚焦、曝光、闪光灯).
- 捕捉设备输入: AVCaptureDeviceInput (音频输入、视频输入)
- 捕捉设备输出: AVCaptureOutput抽象类.
- ->AVCaptureStillImageOutput
- ->AVCaputureMovieFileOutput
- ->AVCaputureAudioDataOutput
- ->AVCaputureVideoDataOutput
- 捕捉链接 : AVCaptureConnection
- 捕捉预览: AVCaptureVideoPreviewLayer (显示摄像头实时捕捉的内容)
6.2 音视频编码
硬编码(GPU编码):VideoToolBox和AudioToolBox
软编码(CPU编码):
- 视频:用FFmpeg,x264算法把视频原数据YUV/RGB编码成H264编码格式,码率比较低,压缩比高
- 音频:使用fdk_aac 将音频数据PCM转成AAC
6.3 推流(将音视频数据通过流媒体协议发送到流媒体服务器)
流媒体协议:RTMP\RTSP\HLS\FLV
- 视频流式封装格式:TS\FLV
- 音频封装格式:Mp3\AAC
6.3 流媒体服务器
- 数据分发
- 实时转码
- 内容检测
6.4 播放
ijkplayer 播放框架