Skip to content

Commit 429d21f

Browse files
committed
update opengl notes
1 parent 7ddae18 commit 429d21f

8 files changed

+56
-38
lines changed

VideoDevelopment/OpenGL/1.OpenGL简介.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ OpenGL(Open Graphics Library开放图形库)是用于渲染2D、3D矢量图形
66

77
OpenGL的前身是硅谷图形功能(SGI)公司为其图形工作站开发的IRIS GL,后来因为IRIS GL的移植性不好,所以在其基础上,开发出了OpenGl。OpenGl一般用于在图形工作站,PC端使用,由于性能各方面原因,在移动端使用OpenGl基本带不动。为此,Khronos公司就为OpenGl提供了一个子集,OpenGl ES(OpenGl for Embedded System)。
88

9-
网上已经有很多文章,这里为什么还要写?主要是因为最近在学的时候发现那些文章看完后还是雨里雾里的不明白。我想写一个简单的,能从入门开始一步步学习的,能简单的学会,文章里面有一些是从下面写的参考链接中拷贝过来的,也有一些是自己从书上看的。
9+
网上已经有很多文章,这里为什么还要写?主要是因为最近在学的时候发现那些文章看完后还是雨里雾里的不明白。方法不明白,不知道为什么要那样用,而且版本不同,最开始看的3.0版本,后面我就都用3.0的来写,结果网上的例子都是2.0的,GLSL的语法不一样,搞的死活出不来效果,耽误时间,所以干脆我系统学一遍,顺便记录下来,写一个简单的,能从入门开始一步步学习的,文章里面有一些是从下面写的参考链接中拷贝过来的,也有一些是自己从书上看的。本书所有的例子都是用OpenGL ES3.0版本、GLSL ES 300版本来写
1010

1111

1212
### OpenGL ES
@@ -21,9 +21,7 @@ OpenGL ES是免费的跨平台的功能完善的2D/3D图形库接口的API,是Op
2121

2222
### OpenGL的作用
2323

24-
25-
26-
手机上做图像处理用很多方法,但是目前为止最高效的方法就是有效的使用图形处理单元(GPU),图像的处理和渲染就是在将要渲染到窗口上的像素上做很多的浮点匀速,而GPU可以并行的做浮点运算,所以用GPU来分担CPU的部分,可以提高效率。
24+
在手机上有两大元件,一个是CPU一个是GPU。显示图形界面也有两种方式,一个是使用CPU渲染,一个是使用GPU渲染,但是目前为止最高效的方法就是有效的使用图形处理单元(GPU),图像的处理和渲染就是在将要渲染到窗口上的像素上做很多的浮点匀速,而GPU可以并行的做浮点运算,所以用GPU来分担CPU的部分,可以提高效率,可以说GPU渲染其实是一种硬件加速。
2725

2826
- 图片处理:比如图片色调转换、美颜等。
2927
- 摄像头预览效果处理。比如美颜相机、恶搞相机等。
@@ -229,7 +227,7 @@ Android 框架中有如下两个基本类,用于通过 OpenGL ES API 来创建
229227

230228

231229

232-
230+
233231
[下一篇: 2.GLSurfaceView简介](https://github.com/CharonChui/AndroidNote/blob/master/VideoDevelopment/OpenGL/2.GLSurfaceView%E7%AE%80%E4%BB%8B.md)
234232

235233
---

VideoDevelopment/OpenGL/10.GLSurfaceView+MediaPlayer播放视频.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
## 10.GLSurfaceView+MediaPlayer播放视频
22

3+
平时的视频播放都是使用mediaplayer+textureview或者mediaplayer+surfaceview,但是如果我们要对视频进行一些OpenGL的操作,打个比方说我要在视频播放的时候添加一个滤镜,这个时候就需要用都SurfaceTexture了。
34

5+
大体步骤如下:
46

5-
平时的视频播放都是使用mediaplayer+textureview或者mediaplayer+surfaceview,但是如果我们要对视频进行一些OpenGL的操作,打个比方说我要在视频播放的时候添加一个滤镜,这个时候就需要用都SurfaceTexture了
7+
GLSurfaceView -> setRender -> onSurfaceCreated回调方法中构造一个SurfaceTexture对象,然后设置到Camera预览或者MediaPlayer中 -> SurfaceTexture中的回调方法onFrameAvailable来得知一帧的数据真好完成 -> requestRender通知Render来绘制数据 -> 在Render的回调方法onDrawFrame中调用SurfaceTexture的updateTexImage方法来获取一帧数据,然后开始使用GL进行绘制预览
68

79

810

VideoDevelopment/OpenGL/5.OpenGL ES绘制三角形.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ OpenGL ES的绘制需要有以下步骤:
88

99
- 顶点着色器
1010

11+
着色器都是使用GLSL语言来写的而GLSL版本之间有差异。
12+
1113
```glsl
12-
#version 330 core
14+
#version 300 es
1315
layout (location = 0) in vec3 position;
1416
1517
void main()
@@ -18,7 +20,7 @@ OpenGL ES的绘制需要有以下步骤:
1820
}
1921
```
2022

21-
每个着色器都起始于一个版本声明。OpenGL 3.3以及和更高版本中,GLSL版本号和OpenGL的版本是匹配的(比如说GLSL 420版本对应于OpenGL 4.2)。我们同样明确表示我们会使用核心模式
23+
每个着色器都起始于一个版本声明,这里声明的是GLSL ES 300版本,在Android中它对应的OpenGL ES版本为3.0,而GLSL ES 100版本则对应的是OpenGL ES 2.0版本。如果不写版本默认的就是100
2224

2325
下一步,使用in关键字,在顶点着色器中声明所有的输入顶点属性(Input Vertex Attribute)。现在我们只关心位置(Position)数据,所以我们只需要一个顶点属性。GLSL有一个向量数据类型,它包含1到4个float分量,包含的数量可以从它的后缀数字看出来。由于每个顶点都有一个3D坐标,我们就创建一个vec3输入变量position。我们同样也通过layout (location = 0)设定了输入变量的位置值(Location)你后面会看到为什么我们会需要这个位置值。
2426

@@ -33,7 +35,7 @@ OpenGL ES的绘制需要有以下步骤:
3335
片断着色器全是关于计算你的像素最后的颜色输出。颜色使用RGBA。
3436

3537
```glsl
36-
#version 330 core
38+
#version 300 es
3739
out vec4 color;
3840
void main() {
3941
color = vec4(1.0f, 0.5f, 0.2f, 1.0f);

VideoDevelopment/OpenGL/6.OpenGL ES绘制矩形及圆形.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,8 @@
307307
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
308308

309309
//将变换矩阵传入顶点渲染器
310-
GLES20.glUniformMatrix4fv(uMatrixLocation,1,false,mMVPMatrix,0);
310+
GLES
311+
0.glUniformMatrix4fv(uMatrixLocation,1,false,mMVPMatrix,0);
311312
//准备坐标数据
312313
GLES30.glVertexAttribPointer(aPositionLocation, 3, GLES30.GL_FLOAT, false, 0, vertexBuffer);
313314
//启用顶点位置句柄
@@ -423,7 +424,7 @@ public class CircularRender implements GLSurfaceView.Renderer {
423424
@Override
424425
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
425426
//将背景设置为白色
426-
GLES20.glClearColor(1.0f,1.0f,1.0f,1.0f);
427+
GLES30.glClearColor(1.0f,1.0f,1.0f,1.0f);
427428

428429
//编译顶点着色程序
429430
String vertexShaderStr = ResReadUtils.readResource(R.raw.vertex_simple_shade);
@@ -478,7 +479,7 @@ public class CircularRender implements GLSurfaceView.Renderer {
478479
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
479480

480481
//将变换矩阵传入顶点渲染器
481-
GLES20.glUniformMatrix4fv(uMatrixLocation,1,false,mMVPMatrix,0);
482+
GLES30.glUniformMatrix4fv(uMatrixLocation,1,false,mMVPMatrix,0);
482483
//准备坐标数据
483484
GLES30.glVertexAttribPointer(aPositionLocation, 3, GLES30.GL_FLOAT, false, 0, vertexBuffer);
484485
//启用顶点位置句柄
@@ -500,7 +501,7 @@ public class CircularRender implements GLSurfaceView.Renderer {
500501
```
501502

502503

503-
[上一篇: 5.OpenGL ES绘制三角形](https://github.com/CharonChui/AndroidNote/blob/master/VideoDevelopment/OpenGL/5.OpenGL%20ES%E7%BB%98%E5%88%B6%E4%B8%89%E8%A7%92%E5%BD%A2.md
504+
[上一篇: 5.OpenGL ES绘制三角形](https://github.com/CharonChui/AndroidNote/blob/master/VideoDevelopment/OpenGL/5.OpenGL%20ES%E7%BB%98%E5%88%B6%E4%B8%89%E8%A7%92%E5%BD%A2.md)
504505
[下一篇: 7.OpenGL ES着色器语言GLSL](https://github.com/CharonChui/AndroidNote/blob/master/VideoDevelopment/OpenGL/7.OpenGL%20ES%E7%9D%80%E8%89%B2%E5%99%A8%E8%AF%AD%E8%A8%80GLSL.md)
505506

506507
---

VideoDevelopment/OpenGL/7.OpenGL ES着色器语言GLSL.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
顶点着色器:
44

55
```
6-
#version 330 core
6+
#version 300 es
77
layout (location = 0) in vec3 position; // position变量的属性位置值为0
88
99
out vec4 vertexColor; // 为片段着色器指定一个颜色输出
@@ -18,7 +18,7 @@ void main()
1818
片段着色器:
1919

2020
```
21-
#version 330 core
21+
#version 300 es
2222
in vec4 vertexColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)
2323
2424
out vec4 color; // 片段着色器输出的变量名可以任意命名,类型必须是vec4
@@ -31,6 +31,20 @@ void main()
3131

3232

3333

34+
这里需要重点讲一下上面的版本: OpenGL ES版本有自己的着色器语言,其中OpenGL ES的版本与GLSL的版本有对应的关联关心:
35+
36+
- OpenGL ES 2.0版本对应GLSL ES 100版本
37+
- OpenGL ES 3.0版本对应GLSL ES 300版本
38+
39+
我们这里使用的都是GLSL ES 300版本。但是GLSL ES 100 和 300版本中间有一些差异,这就是为什么我们有时候网上的一些代码编译时却报错的原因:
40+
41+
- GLSL ES 300版本中in和out代替了之前的属性和变化(attribute和varying)
42+
- texture()方法代替了之前的texture2D()方法
43+
- 300版本中布局限定符可以声明顶点着色器输入和片段着色器输出的问题,例如layout(location = 2) in vec3 values[4];
44+
- 舍弃了gl_FragColor的内置属性,变成我们需要自己使用out关键字定义的属性,这就是为什么你从网还是哪个找到的代码换成GLSL ES 300版本后报错的原因。
45+
46+
47+
3448
### GLSL的特点
3549

3650
OpenGLES的着色器语言GLSL是一种高级的图形化编程语言,其源自应用广泛的C语言。与传统的C语言不同的是,它提供了更加丰富的针对于图像处理的原生类型,诸如向量、矩阵之类。GLSL主要包含以下特性:
@@ -102,9 +116,9 @@ GLSL的类型转换与C不同。在GLSL中类型不可以自动提升,比如fl
102116

103117
与Java中的限定符类似,放在变量类型前面,并且只能用于全局变量。
104118

105-
- attritude:一般用于各个顶点各不相同的量。如顶点颜色、坐标等。
119+
- attritude:一般用于各个顶点各不相同的量。如顶点颜色、坐标等。(GLSL 200 es版本的使用方法,在GLSL 300 es中已经被in替代)
106120
- uniform:一般用于对于3D物体中所有顶点都相同的量。比如光源位置,统一变换矩阵等。
107-
- varying:表示易变量,一般用于顶点着色器传递到片元着色器的量。
121+
- varying:表示易变量,一般用于顶点着色器传递到片元着色器的量。(GLSL 200 es版本的使用方法,在GLSL 300 es中已经被out替代)
108122
- const:常量。
109123

110124
- 流程控制
@@ -148,8 +162,8 @@ GLSL的类型转换与C不同。在GLSL中类型不可以自动提升,比如fl
148162
- gl_FragFacing:bool型,表示是否为属于光栅化生成此片元的对应图元的正面。
149163
- gl_PointCoord:经过插值计算后的纹理坐标,点的范围是0.0到1.0
150164
- 输出变量
151-
- gl_FragColor:当前片元颜色
152-
- gl_FragData:vec4类型的数据。设置当前片元的颜色,供渲染管线的后继过程使用。
165+
- gl_FragColor:当前片元颜色(GLSL 200 es版本的内置属性,在GLSL 300 es中已经没有了,需要自己用out关键字定义)
166+
- gl_FragData:vec4类型的数据。设置当前片元的颜色,供渲染管线的后继过程使用。(GLSL 200 es版本的内置属性,在GLSL 300 es中已经没有了,需要自己用out关键字定义)
153167

154168
### 内置函数
155169

VideoDevelopment/OpenGL/8.GLES类及Matrix类.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33

44

5-
GLES30作为我们与着色器连接的工具类提供了丰富的api
5+
GLES作为我们与着色器连接的工具类提供了丰富的api
66

77
上一篇文章说到GLSL中的变量修饰符有以下部分:
88

99
- none:(默认的可省略)本地变量,可读可写,函数的输入参数既是这种类型
1010
- const:声明变量或函数的参数为只读类型
11-
- attribute:用于保存顶点或法线数据,它可以在数据缓冲区中读取数据,仅能用于顶点着色器
11+
- attribute:用于保存顶点或法线数据,它可以在数据缓冲区中读取数据,仅能用于顶点着色器(GLSL 200 es版本,在GLSL 300 es中已经被in替代)
1212
- uniform:在运行时 shader 无法改变 uniform 变量,一般用来放置程序传递给 shader 的变换矩阵,材质,光照参数等等,可用于顶点着色器和片元着色器
13-
- varying:用于修饰从顶点着色器向片元着色器传递的变量
13+
- varying:用于修饰从顶点着色器向片元着色器传递的变量(仅能用GLSL 200 es版本,在GLSL 300 es中已经被out替代)
1414

1515

1616

@@ -52,7 +52,7 @@ GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 20, mRe
5252

5353
### 启用或禁用顶点属性数组
5454

55-
调用GLES20.glEnableVertexAttribArray和GLES20.glDisableVertexAttribArray传入参数index。如果启用,那么当GLES20.glDrawArrays或者GLES20.glDrawElements被调用时,顶点属性数组会被使用。
55+
调用GLES30.glEnableVertexAttribArray和GLES30.glDisableVertexAttribArray传入参数index。如果启用,那么当GLES30.glDrawArrays或者GLES30.glDrawElements被调用时,顶点属性数组会被使用。
5656

5757
### 选择活动纹理单元
5858

VideoDevelopment/OpenGL/9.OpenGL ES纹理.md

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
### 纹理
66

7-
在OpenGL中简单理解就是一张图片
7+
在OpenGL中简单理解就是一张图片,在学习之前需要明白这几个概念,不然很容易迷糊,不知道为什么要这样去调用api,到底是什么意思.
88

9-
- 纹理Id:纹理的直接饮用
9+
- 纹理Id:句柄,纹理的直接引用
1010

11-
- 纹理单元:纹理的操作容器,有GL_TEXTURE0、GL_TEXTURE1、GL_TEXTURE2等,纹理单元的数量是有限的,最多16个。所以在最多只能同时操作16个纹理。在切换使用纹理单元的时候,使用glActiveTexture方法。
11+
- 纹理单元:纹理的操作容器,有GL_TEXTURE0、GL_TEXTURE1、GL_TEXTURE2等,纹理单元的数量是有限的,最多16个。所以在最多只能同时操作16个纹理。在切换使用纹理单元的时候,使用glActiveTexture方法。也就是说OpenGL ES中内置了很多个纹理单元,并且是连续的,我们在使用的时候要选择其中一个,一般默认选择第一个(GLES_TEXTURE0),并且如果不选的话OpenGL默认激活的也就是第一个纹理单元。激活纹理单元后需要把它和纹理Id绑定,然后再通过GLES30.glUniform1i()方法传递给着色器中。
1212

1313
- 纹理目标:一个纹理单元中包含了多个类型的纹理目标,有GL_TEXTURE_1D、GL_TEXTURE_2D、CUBE_MAP等。本章中,将纹理ID绑定到纹理单元0的GL_TEXTURE_2D纹理目标上,之后对纹理目标的操作都是对纹理Id对应的数据进行操作。
1414

@@ -83,15 +83,15 @@ public class TextureHelper {
8383
Log.w(TAG, "Resource ID " + resourceId + " could not be decoded.");
8484
}
8585
// 加载Bitmap资源失败,删除纹理Id
86-
GLES20.glDeleteTextures(1, textureObjectIds, 0);
86+
GLES30.glDeleteTextures(1, textureObjectIds, 0);
8787
return bean;
8888
}
8989
// 2. 将纹理绑定到OpenGL对象上
90-
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureObjectIds[0]);
90+
GLES30.glBindTexture(GLES20.GL_TEXTURE_2D, textureObjectIds[0]);
9191

9292
// 3. 设置纹理过滤参数:解决纹理缩放过程中的锯齿问题。若不设置,则会导致纹理为黑色
93-
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);
94-
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
93+
GLES30.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);
94+
GLES30.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
9595
// 4. 通过OpenGL对象读取Bitmap数据,并且绑定到纹理对象上,之后就可以回收Bitmap对象
9696
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
9797

@@ -191,6 +191,7 @@ public class TextureHelper {
191191
in vec2 vTexCoord;
192192
out vec4 vFragColor;
193193
void main() {
194+
// 100 es版本中是texture2D
194195
vFragColor = texture(uTextureUnit,vTexCoord);
195196
}
196197
```
@@ -278,7 +279,7 @@ public class TextureHelper {
278279
@Override
279280
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
280281
//将背景设置为白色
281-
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
282+
GLES30.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
282283

283284
//编译顶点着色程序
284285
String vertexShaderStr = ResReadUtils.readResource(R.raw.texture_vertex_simple_shade);
@@ -321,7 +322,7 @@ public class TextureHelper {
321322
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
322323

323324
//将变换矩阵传入顶点渲染器
324-
GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, mProjectionMatrix, 0);
325+
GLES30.glUniformMatrix4fv(uMatrixLocation, 1, false, mProjectionMatrix, 0);
325326
//准备坐标数据
326327
GLES30.glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GLES30.GL_FLOAT, false, 0, vertexBuffer);
327328
//启用顶点位置句柄
@@ -341,7 +342,7 @@ public class TextureHelper {
341342

342343

343344
// 开始绘制
344-
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, POINT_DATA.length / POSITION_COMPONENT_COUNT);
345+
GLES30.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, POINT_DATA.length / POSITION_COMPONENT_COUNT);
345346
//禁止顶点数组的句柄
346347
GLES30.glDisableVertexAttribArray(aPositionLocation);
347348
GLES30.glDisableVertexAttribArray(aTextureLocation);
@@ -437,7 +438,7 @@ public class TextureHelper {
437438
@Override
438439
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
439440
//将背景设置为白色
440-
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
441+
GLES30.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
441442
442443
//编译顶点着色程序
443444
String vertexShaderStr = ResReadUtils.readResource(R.raw.texture_vertex_simple_shade);
@@ -480,7 +481,7 @@ public class TextureHelper {
480481
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
481482
482483
//将变换矩阵传入顶点渲染器
483-
GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, mProjectionMatrix, 0);
484+
GLES30.glUniformMatrix4fv(uMatrixLocation, 1, false, mProjectionMatrix, 0);
484485
//准备坐标数据
485486
GLES30.glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GLES30.GL_FLOAT,
486487
false, 0, vertexBuffer);
@@ -498,9 +499,9 @@ public class TextureHelper {
498499
//绑定纹理
499500
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);
500501
// 将纹理单元传递片段着色器的u_TextureUnit
501-
GLES20.glUniform1i(aTextureLocation, 0);
502+
GLES30.glUniform1i(aTextureLocation, 0);
502503
// 开始绘制
503-
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, POINT_DATA.length / POSITION_COMPONENT_COUNT);
504+
GLES30.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, POINT_DATA.length / POSITION_COMPONENT_COUNT);
504505
505506
506507
//准备第二个纹理的坐标数据

VideoDevelopment/音视频基础知识.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@
168168
YUV
169169
---
170170

171-
YUV(也成YCbCr)是电视系统所采用的一种颜色编码方法。其中Y表示明亮度也就是灰阶值,它是基础信号。U和V表示的则是色度,UV的作用是描述影像色彩及饱和度,它们用于指定像素的颜色。U和V不是基础信号,他俩都是被正交调制的。
171+
YUV(也成YCbCr)是电视系统所采用的一种颜色编码方法,他是一种亮度与色度分离的色彩格式。其中Y表示明亮度也就是灰阶值,它是基础信号。U和V表示的则是色度,UV的作用是描述影像色彩及饱和度,它们用于指定像素的颜色。U和V不是基础信号,他俩都是被正交调制的。早期的电视都是黑白的,即只有亮度值(Y),有了彩色电视之后,加入了UV两种色度,形成现在的YUV,也叫YCbCr。人眼对亮度敏感,对色度不敏感,因此减少部分UV的数据量,人眼也无法感知出来,这样就可以通过压缩UV的分辨率,在不影响观感的前提下,减少视频的体积
172172

173173
YUV和RGB视频信号相比,最大的优点在于只需要占用极少的带宽,YUV只需要占用RGB一般的带宽。
174174

0 commit comments

Comments
 (0)