音视频之opengl绘制三角形

音视频之opengl渲染图片

音视频之渲染yuv图片

前一篇我们讨论了如何渲染一个普通图片(rgb)
现在我们来讨论如何渲染一个yuv图片。

什么是yuv我们这里有一个说的不错的文章

yuv解释链接

我们摄像头采集到的,最后我们用来显示的都是yuv数据。所以我们必须的理解yuv格式,yuv有很多种格式,什么yuv420p,yuv422等。需要学习的就在上面的连接进行学习。

我们先看看下面效果图:

我们直接来看看对应的着色器代码:

顶点着色器

attribute  vec4 aPosition;
attribute  vec2 aTexCoord;
varying vec2 vTexCoord;
void main() {//这个1.0 - aTexCoord.y 是让yuv图像倒一个方向。vTexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);       gl_Position = aPosition;
}

aPosition:让顶点坐标传递进来的变量
aTexCoord:让纹理坐标传递进来的变量
vTexCoord:将纹理坐标从顶点着色器中传递到片段着色器中,当然我们看到他使用了1.0 - aTexCoord.y ,是为了将图片倒一个方向

片段着色器

precision  mediump float;
varying  vec2 vTexCoord;
uniform sampler2D yTexture;
uniform sampler2D uTexture;
uniform sampler2D vTexture;
void main() {vec3 yuv;vec3 rgb;yuv.r = texture2D(yTexture, vTexCoord).r;yuv.g = texture2D(uTexture, vTexCoord).r - 0.5;yuv.b = texture2D(vTexture, vTexCoord).r - 0.5;rgb = mat3(1.0, 1.0, 1.0,0.0, -0.39465, 2.03211,1.13983, -0.58060, 0.0) * yuv;gl_FragColor = vec4(rgb, 1.0);
}

传入三个纹理,分别对应y,u,v然后yuv需要转换成rgb,yuv转rgb就是以上的方式。
对应的公式是:
R = Y + 1.13983V
G = Y - 0.394
U - 0.58060V
B = Y + 2.03211
U
但是在opengl使用的是线性代数的方式来处理。

好了我们直接看代码部分:
这次我们把顶点坐标和纹理坐标分开声明的

float vertexVertices[] = {
//顶点坐标1.0f, 1.0f,-1.0f, 1.0f,1.0f,  -1.0f,-1.0f,  -1.0f,
};float textureVertices[] = {//纹理坐标0.0f,  1.0f,1.0f,  1.0f,0.0f,  0.0f,1.0f,  0.0f,
};

注意:我把文件读取路径写的是sdcard/FFmpeg,以后我的很多操作都是写入的这个地方。

try {byte[] buffer = new byte[yuvSize];fis = new FileInputStream("sdcard/FFmpeg/oneframe.yuv");fis.read(buffer);byteY = new byte[yLen];byteU = new byte[yLen / 4];byteV = new byte[yLen / 4];System.arraycopy(buffer, 0, byteY, 0, yLen);System.arraycopy(buffer, yLen, byteU, 0, yLen / 4);System.arraycopy(buffer, yLen * 5 / 4, byteV, 0, yLen / 4);bufferY = ByteBuffer.wrap(byteY);bufferU = ByteBuffer.wrap(byteU);bufferV = ByteBuffer.wrap(byteV);
} catch (Exception e) {Log.e("xhc", " message " + e.getMessage());e.printStackTrace();
}

声明了三个本地缓存

private ByteBuffer bufferY;
private ByteBuffer bufferU;
private ByteBuffer bufferV;

分别保存的是y,u,v对应的数据

编译,连接,使能的代码部分就不一一拿出来说了,和之前的渲染三角形等一样,直接贴出:

@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {glClearColor(0.0f, 0.0f, 0.0f, 0.0f);String vertexShaderSource = TextResourceReader.readTextFileFromResource(context, R.raw.yuv_vertex_shader);String frgShaderSource = TextResourceReader.readTextFileFromResource(context, R.raw.yuv_frg_shader);int vertextShader = ShaderHelper.compileVertextShader(vertexShaderSource);int fragmentShader = ShaderHelper.compileFragmentShader(frgShaderSource);program = ShaderHelper.linkProgram(vertextShader, fragmentShader);ShaderHelper.validatePrograme(program);glUseProgram(program);textureYL = glGetUniformLocation(program, "yTexture");textureUL = glGetUniformLocation(program, "uTexture");textureVL = glGetUniformLocation(program, "vTexture");aPositionL = glGetAttribLocation(program, "aPosition");aTextureCoordinatesL = glGetAttribLocation(program, "aTexCoord");vertexData.position(0);int[] textures = TextureHelper.initYuvTexture();if (textures == null) {return;}textureYid = textures[0];textureUid = textures[1];textureVid = textures[2];glVertexAttribPointer(aPositionL, 2, GL_FLOAT,false , 0, vertexData);glEnableVertexAttribArray(aPositionL);glVertexAttribPointer(aTextureCoordinatesL, 2, GL_FLOAT, false, 0, texData);glEnableVertexAttribArray(aTextureCoordinatesL);
}

我们在这里拿到y,u,v纹理数据,顶点,和纹理坐标的location。稍后再绘制的时候会使用。

我们这里直接绘制纹理:

@Override
public void onDrawFrame(GL10 gl10) {glClear(GL_COLOR_BUFFER_BIT);glUseProgram(program);//激活纹理单元GL_TEXTURE0glActiveTexture(GL_TEXTURE0);//绑定对应的纹理对象textureYid glBindTexture(GL_TEXTURE_2D, textureYid);//详细看后面glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bufferY);//调用glUniformli(textureYL,0)把被选定的纹理单元传递给片段着色器中。glUniform1i(textureYL, 0);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, textureUid);glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,width/2, height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bufferU);glUniform1i(textureUL, 1);glActiveTexture(GL_TEXTURE2);glBindTexture(GL_TEXTURE_2D, textureVid);glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,width/2, height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bufferV);glUniform1i(textureVL, 2);glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

glTexImage2D中对应的参数:

target
指定活动纹理单元的目标纹理。必须是GL_TEXTURE_2D,GL_TEXTURE_CUBE_MAP_POSITIVE_X,GL_TEXTURE_CUBE_MAP_NEGATIVE_X,GL_TEXTURE_CUBE_MAP_POSITIVE_Y,GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,GL_TEXTURE_CUBE_MAP_POSITIVE_Z,或GL_TEXTURE_CUBE_MAP_NEGATIVE_Z。

level
指定详细程度编号。级别0是基本图像级别。级别n是第n个缩略图缩小图像。

internalformat
指定纹理的内部格式。必须是下列符号常量之一:GL_ALPHA(按照alpha值存储纹理单元),GL_LUMINANCE(按照亮度值存储纹理单元),GL_LUMINANCE_ALPHA(按照亮度值和alpha值存储纹理单元),GL_RGB(按照r,g,b成分存储纹理单元),GL_RGBA(按照r,g,b,alpha方式存储纹理单元)。

Width:尽量使用2的整数次方,不然会有可能有性能损耗,注意:y纹理的宽度,就是图片的宽度,但是u,v的宽度却除了2,那是因为yuv420p格式的数据是4个y共用一个uv,所以宽高都需要除2

Height:同上

border
指定边框的宽度。必须为0。

format
指定纹理数据的格式。必须匹配internalformat。下面的符号值被接受:GL_ALPHA,GL_RGB,GL_RGBA,GL_LUMINANCE,和GL_LUMINANCE_ALPHA。

type
指定纹理数据的数据类型。下面的符号值被接受:GL_UNSIGNED_BYTE,GL_UNSIGNED_SHORT_5_6_5,GL_UNSIGNED_SHORT_4_4_4_4,和GL_UNSIGNED_SHORT_5_5_5_1。

data
指定一个指向内存中图像数据的指针。

github地址

音视频之渲染yuv图片相关推荐

  1. 使用Matlab将抖音视频转换成gif图片

    文章目录 1. 原由 2. 方法 3. 演示 3.1 将视频完整转换为gif图片 3.2 将指定时间的视频片段转换为gif图片 3.3 改变gif图片的播放速度 4. 联系作者 1. 原由 昨天的博文 ...

  2. 音视频学习之-YUV裸数据

    音视频技术分层结构(雷神的图) 1 什么是yuv? YUV中,Y表示明亮度,也就是灰度值:而U,V则表示色度,用于描述影像色彩及饱和度,用于指定像素的颜色. YUV将亮度信息Y与色彩信息UV分离,没有 ...

  3. RTCPeerConnection基本概念 -- 以及创建和绑定音视频以及渲染远端视频时候的作用

    RTCPeerConnection 是WebRTC的核心的 是其暴露个用户的统一接口 其由多个模块组成 · 网络处理模块 · 服务质量模块 · 音视频引擎模块 等等 最最厉害的就是根据网络情况动态调整 ...

  4. 音视频编解码: YUV采样格式中的YUV444,YUV422,YUV420理解

    YUV各种采样格式的说明 通常我们用RGB表示一种彩色.计算机系统里的LCD显示的数据就是RGB来表示每个像素的颜色. 而在我们生活里,有黑白电视机与彩色电视机两种,拍摄节目源时不可以用两种不同的摄像 ...

  5. Qt音视频开发31-Onvif抓拍图片

    一.前言 抓拍是个很重要的功能,比如在报警视频联动中需要一张实时的图片,很多SDK不提供抓拍功能,而通过预览抓图,得到的图片已不具有实时性,那如何得到实时的图片呢?现在的IPC基本上都支持ONVIF协 ...

  6. 音视频之opengl渲染图片

    音视频之opengl绘制三角形 音视频之opengl渲染图片 音视频之渲染yuv图片 首先来看看渲染效果 我们先来看看关于纹理的坐标: 他是如下图: 顶点着色器代码:texture_vertext_s ...

  7. 音视频之opengl绘制三角形

    音视频之opengl绘制三角形 音视频之opengl渲染图片 音视频之渲染yuv图片 2018年用了一年业余时间学习了音视频,直播,解码,编码,倍速,跳转,滤镜,倒放等.,慢慢把这部分内容写到博客上, ...

  8. Android音视频学习系列(七) — 从0~1开发一款Android端播放器(支持多协议网络拉流本地文件)

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  9. Android音视频开发---0基础入门准备篇

    文章目录 0,题记 1,学习路线 2,学习目标 任务列表 基础知识 FFmpeg 3,开始音视频开发必备的技能 1,C语言. 2,Linux. 3,基本的Linux编译执行命令,以及vim操作. 4, ...

最新文章

  1. 使用 PEAR的Text_CAPTCHA保护Web表单[翻译]
  2. python_bomb----函数高级特性(生成器)
  3. Testin云测试:QQ(4.2.0)安卓版客户端可用性优秀
  4. 认识httphandler
  5. pycharm新建文件夹时新建python package和新建directory有什么区别?
  6. java对redis的基本操作
  7. 错误记录(八)could not initialize proxy - no Session
  8. OSI参考模型(2)
  9. caffe 绘制accuracy和loss曲线
  10. echarts:迁徙图
  11. 机器学习入门好文章--超级推荐
  12. 基于java+jsp房屋租赁管理系统
  13. 介绍几种wifi电源管理模式
  14. 新西兰皇后镇-我眼中的西施
  15. matlab中如何调用子函数
  16. cmd模式下用cd命令进入其他盘或者文件夹
  17. 芭比波朗品牌的男性市场
  18. 常见阈值分割代码(Otsu、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法)
  19. 【优化求解】粒子群优化和重力搜索算法求解MLP问题matlab代码
  20. VCS+Verdi ubuntu18.04安装教程

热门文章

  1. H.265视频流媒体EasyPlayer播放器无法禁用自动播放的问题修复
  2. 不用的MacBook这样处理比较好
  3. java项目中获取真实ip地址
  4. JVM 栈分配与TLAB
  5. 怎么搜索到最新最全的热点新闻资讯呢?有这四个工具就够了
  6. 移动通信各制式、调制的速率及频谱利用率(2G-4G)
  7. Mysql索引的本质深入浅出(一)
  8. [杂谈] 14. Catalan卡特兰数
  9. Android Status Bar
  10. Android基础控件—SearchView