Android GlSurfaceView渲染YUV图形

OpenGL ES 2.0 的代码,用来显示YUV格式的视频数据。这个示例将包括初始化OpenGL环境、加载Shader程序、绘制纹理等步骤


import android.content.Context;
import android.opengl.GLES20;import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;public class YUVShaderProgram {private int program;private int avPosition_yuv;private int afPosition_yuv;private final FloatBuffer vertexBuffer;private final FloatBuffer textureBuffer;private  int yTextureLocation;private  int uTextureLocation;private  int vTextureLocation;private static final String VERTEX_SHADER ="attribute vec4 av_Position;\n" +"attribute vec2 af_Position;\n" +"varying vec2 v_texCord;\n" +"void main() {\n" +"gl_Position = av_Position;\n" +"v_texCord = af_Position;\n" +"}\n";private static final String FRAGMENT_SHADER ="precision mediump float;\n" +"uniform sampler2D sampler_y;\n" +"uniform sampler2D sampler_u;\n" +"uniform sampler2D sampler_v;\n" +"varying vec2 v_texCord;\n" +"void main() {\n" +"vec4 c = vec4((texture2D(sampler_y, v_texCord).r - 16./255.) * 1.164);\n" +"vec4 U = vec4(texture2D(sampler_u, v_texCord).r - 128./255.);\n" +"vec4 V = vec4(texture2D(sampler_v, v_texCord).r - 128./255.);\n" +"c += V * vec4(1.596, -0.813, 0, 0);\n" +"c += U * vec4(0, -0.392, 2.017, 0);\n" +"c.a = 1.0;\n" +"gl_FragColor = c;\n" +"}\n";public YUVShaderProgram(Context context) {//顶点坐标float[] vertexData = {-1f, -1f,1f, -1f,-1f, 1f,1f, 1f};vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexData);vertexBuffer.position(0);//纹理坐标float[] textureData = {0f, 1f,1f, 1f,0f, 0f,1f, 0f};textureBuffer = ByteBuffer.allocateDirect(textureData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(textureData);textureBuffer.position(0);program = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);}public void useProgram() {GLES20.glUseProgram(program);}public void enableVertex(){GLES20.glEnableVertexAttribArray(avPosition_yuv);//使顶点属性数组有效GLES20.glVertexAttribPointer(avPosition_yuv, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer);//为顶点属性赋值GLES20.glEnableVertexAttribArray(afPosition_yuv);GLES20.glVertexAttribPointer(afPosition_yuv, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);}public void loadLocation(){avPosition_yuv = GLES20.glGetAttribLocation(program, "av_Position");afPosition_yuv = GLES20.glGetAttribLocation(program, "af_Position");}public void setUniforms() {yTextureLocation = GLES20.glGetUniformLocation(program, "sampler_y");uTextureLocation = GLES20.glGetUniformLocation(program, "sampler_u");vTextureLocation = GLES20.glGetUniformLocation(program, "sampler_v");}public void glUniform1i(){GLES20.glUniform1i(yTextureLocation, 0);GLES20.glUniform1i(uTextureLocation, 1);GLES20.glUniform1i(vTextureLocation, 2);}private int loadShader(int type, String shaderCode) {int shader = GLES20.glCreateShader(type);GLES20.glShaderSource(shader, shaderCode);GLES20.glCompileShader(shader);return shader;}private int createProgram(String vertexShaderCode, String fragmentShaderCode) {int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);int program = GLES20.glCreateProgram();GLES20.glAttachShader(program, vertexShader);GLES20.glAttachShader(program, fragmentShader);GLES20.glLinkProgram(program);return program;}
}```java
class EffectRender(var mContext:Context,var glView:GLSurfaceView,var mWidth:Int,var mHeight:Int):GLSurfaceView.Renderer,SurfaceTexture.OnFrameAvailableListener {private val TAG = "EffectRender"private val textures = IntArray(3) // 纹理句柄private val COORDS_PER_VERTEX = 2private val TEXTURE_COORDS_PER_VERTEX = 2private var positionHandle = 0private var textureCoordHandle = 0private var cameraData:ByteArray?=nullprivate var mDrawTextureBuffer: FloatBuffer? = nullprivate var mDrawGlCubeBuffer: FloatBuffer? = nullprivate var yData:ByteArray?=nullprivate var uData:ByteArray?=nullprivate var vData:ByteArray?=nullvar ySurfaceTexture: SurfaceTexture?=nullvar uSurfaceTexture: SurfaceTexture?=nullvar vSurfaceTexture: SurfaceTexture?=nullprivate val mvpMatrix = FloatArray(16)private var shaderProgram: YUVShaderProgram? = null//顶点坐标数据,表示预览图像的位置和大小。private var avPosition_yuv: Int = 0private val afPosition_yuv = 0private var mRenderInput: NveRenderInput?=nulloverride fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);shaderProgram = YUVShaderProgram(mContext)shaderProgram?.useProgram()shaderProgram?.loadLocation()shaderProgram?.setUniforms()// 创建三个纹理GLES20.glGenTextures(3, textures, 0)ySurfaceTexture = SurfaceTexture(textures[0])uSurfaceTexture = SurfaceTexture(textures[1])vSurfaceTexture = SurfaceTexture(textures[2])// 设置纹理参数for (i in 0..2) {GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[i])//设置环绕和过滤方式GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);}}override fun onSurfaceChanged(p0: GL10?, p1: Int, p2: Int) {Log.i(TAG,"onSurfaceChanged = $p1 $p2")GLES20.glViewport(0, 0, p1, p2);}override fun onDrawFrame(p0: GL10?) {effectData()GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);shaderProgram?.useProgram()shaderProgram?.enableVertex()yData?.let {GLES20.glActiveTexture(GLES20.GL_TEXTURE0);GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, mWidth, mHeight, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, ByteBuffer.wrap(it));}uData?.let {GLES20.glActiveTexture(GLES20.GL_TEXTURE1);GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[1]);GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, mWidth/2, mHeight/2, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, ByteBuffer.wrap(it))}vData?.let {GLES20.glActiveTexture(GLES20.GL_TEXTURE2);GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[2]);GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, mWidth/2, mHeight/2, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, ByteBuffer.wrap(it));}shaderProgram?.glUniform1i()GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);}private fun effectData(){cameraData?.let {val yPlaneSize: Int = mWidth * mHeightval uvPlaneSize: Int = yPlaneSize/4yData = ByteArray(yPlaneSize)System.arraycopy(it, 0, yData, 0, yPlaneSize)uData = ByteArray(uvPlaneSize)System.arraycopy(it, yPlaneSize, uData, 0, uvPlaneSize)vData = ByteArray(uvPlaneSize)System.arraycopy(it, yPlaneSize+uvPlaneSize, vData, 0, uvPlaneSize)}}fun refreshView(data:ByteArray){cameraData = dataglView.requestRender()}override fun onFrameAvailable(p0: SurfaceTexture?) {}
}

使用示例:

<android.opengl.GLSurfaceViewandroid:id="@+id/glsurface_view"android:layout_width="match_parent"android:layout_height="match_parent" />binding.glsurfaceView.setEGLContextClientVersion(2)
render = EffectRender(this,binding.glsurfaceView,1920,1080)
binding.glsurfaceView.setRenderer(render)
binding.glsurfaceView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
//开启摄像头获取数据送入渲染
cameraHelper = CameraHelper()
cameraHelper?.init(this,"0",1920,1080, object : CameraHelper.CallBack {override fun onCameraPreviewCallBack(data: ByteArray?) {data?.let { render?.refreshView(data) }}})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/48990.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu22.04安装与卸载nginx

换源 如果是国内的就不用换 中科大的源&#xff0c;由于我这里是Ubuntu&#xff0c;所以我就直接选Ubuntu22.04就行 点击下载&#xff0c;或者你直接复制这个sources.list的内容到linux中的/etc/apt/sources.list也可以&#xff0c;把原来的sources.list备份一下&#xff0c;…

nfs和samba

​webserver 服务器&#xff1a;作用是发布nginx的web项目 1、安装nginx&#xff08;只下载不安装&#xff09; [rootweb_server ~]# yum -y install --downloadonly --downloaddir./soft/ nginx 2、配置一个本地的nginx仓库 [rootweb_server ~]# yum -y install createrepo …

『 Linux 』信号概念与信号的产生

文章目录 信号概念前台进程与后台进程信号的本质硬件理解信号的产生 信号概念 "信号"一词指用来传达信息或只是的各种形式的提示或标志; 在生活中常见的信号例如红绿灯,交通标志,短信通知等 在操作系统中,"信号"是一种用于异步通知进程发生特定事件的机制;…

数据库-练习

题目要求&#xff1a;按照要求建立数据库与表&#xff0c;并完成相应的查询操作 解题步骤如下代码所示&#xff1a; //建立相关的数据库mydb8_worker mysql> show databases; -------------------- | Database | -------------------- | information_schema | | …

C++:智能指针 [auto_ptr]

文章目录 0x1 基本使用0x11 初步使用0x12 get()函数【获取指针指向的内存地址】0x13 release()函数 【仅仅是释放所有权&#xff0c;但是并没有清空内存】0x14 reset()函数 【旧值析构,重新设置指针】 0x2 迷惑点0x21 迷惑点1 &#xff08;拷贝赋值&#xff09;0x22 迷惑点2 &a…

NMEA 2000航空插头插座选择

一、概述 NMEA 2000航空插头插座是船舶电子设备中不可或缺的部分&#xff0c;它们负责在船舶的各种电子系统间传输数据和电源信号。选择合适的NMEA 2000航空插头插座对于确保船舶电子系统的稳定性和可靠性至关重要。本文将详细探讨如何选择合适的NMEA 2000航空插头插座&#xf…

NodeJS系列面试题

大家好&#xff0c;我是有用就扩散&#xff0c;有用就点赞。 有没有写过Koa中间件&#xff0c;说一下中间件原理&#xff0c;介绍下自己写过的中间件 koa本来就是一个轻量级框架&#xff0c;本身支持的功能并不多&#xff0c;功能都是通过中间件来实现不同的需求。开发者可以通…

Harmony学习(二)------ArkUI

ArkUI(方舟开发框架)是一套构建鸿蒙应用界面的框架&#xff0c;构建页面的最小单位就是组件&#xff0c;布局思路&#xff1a;先排版&#xff0c;再放内容&#xff0c;再美化。 官网图标库&#xff1a;HarmonyOS 主题图标库 | icon素材免费下载 | 华为开发者联盟 组件分类&am…

解决方案架构师系列 - AWS - Pinpoint

AWS Pinpoint介绍 Amazon Pinpoint 为营销人员和开发人员提供了一款可自定义的工具&#xff0c;助力他们大规模地开展跨渠道、行业和活动的客户通信。 Amazon Pinpoint是一个全面的客户参与平台&#xff0c;‌旨在帮助营销人员和开发人员大规模地开展跨渠道、‌行业和活动的客…

vivado INTERNAL_VREF

内部 具有差分输入缓冲器的单端I/O标准需要输入参考 电压&#xff08;VREF&#xff09;。当I/O组中需要VREF时&#xff0c;您可以使用专用VREF 引脚作为外部VREF电源&#xff0c;或使用INTERNAL_VREF内部生成的VREF 属性&#xff0c;或者对于UltraScale设备上的HP I/O组&#x…

【Golang 面试基础题】每日 5 题(一)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

如何定位及优化SQL语句的性能

定位及优化SQL语句的性能是一个复杂但至关重要的过程&#xff0c;它涉及到对数据库操作、索引使用、查询计划以及系统资源的深入理解。以下是一些步骤和技巧&#xff0c;可以帮助你定位并优化SQL语句的性能&#xff1a; 1. 使用EXPLAIN分析查询计划 执行EXPLAIN命令&#xff…

例行性工作crontab练习题

练习 请在5分钟后关闭系统中所有属于tab用户的进程&#xff0c;并用日志记录任务执行时间 基础知识&#xff1a; [rootlocalhost ~]# echo "date %F %R pkill tab finished" 2024-07-17 15:57 pkill tab finished ​ logger 123 将123写到/var/log/messages #法一&a…

Intellij IDEA 的Plugins加载不出来的解决方法

一、点开插件---右上角设置---HTTP代理设置 二、勾选自动检测代理设置 输入url&#xff1a; https://plugins.jetbrains.com/ 配置完成后&#xff0c;点击确定。 然后点击检查连接&#xff0c;再一次输入那个URL&#xff0c;一般来说可以连接成功了 然后 重启IDEA以刷新缓…

Android init常用调试工具

Android开机优化系列文档-CSDN博客 Android 14 开机时间优化措施汇总-CSDN博客Android 14 开机时间优化措施-CSDN博客根据systrace报告优化系统时需要关注的指标和优化策略-CSDN博客Android系统上常见的性能优化工具-CSDN博客Android上如何使用perfetto分析systrace-CSDN博客A…

UE TSharedPtr

文章目录 概述TSharedPtrTSharedPtr包含2部分 构造&#xff0c;析构&#xff0c;拷贝构造&#xff0c;移动构造构造拷贝构造移动构造 小结 概述 之前写过一篇c的智能指针的&#xff0c;这篇写下ue的。本质上来说是差不多的&#xff0c;可以简单看看。 TSharedPtr 如下图&…

基于SpringBoot+Vue的篮球竞赛预约平台(带1w+文档)

基于SpringBootVue的篮球竞赛预约平台(带1w文档) 基于SpringBootVue的篮球竞赛预约平台(带1w文档) 本系统提供给管理员对首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;项目分类管理&#xff0c;竞赛项目管理&#xff0c;赛事预约管理&#xff0c;系统管理等诸多功…

2-40 基于Matlab编写的3维FDTD(时域有限差分算法)计算了球的RCS经典散射问题

基于Matlab编写的3维FDTD(时域有限差分算法)计算了球的RCS经典散射问题&#xff0c;采用PEC作边界&#xff0c;高斯波束激励。程序已调通&#xff0c;可直接运行。 2-40 3维FDTD 时域有限差分算法 - 小红书 (xiaohongshu.com)

Meta Quest3 激活更新不动的问题

1. Meta Quest3激活过程中遇到更新不动的情况&#xff0c;如下图所示&#xff1a; 2. 关机 3. 开机检查连接的wifi&#xff0c;是否存在受限的情况&#xff0c;如果存在受限情况&#xff0c;则说明当前的mofa只支持TCP&#xff0c;需要设置支持UDP模式。 具体操作是设置魔法…

细节决定成败:电商详情页全攻略

电子商务产品细节页面作为电子商务信息的主要承载页面&#xff0c;也是电子商务业务转型的主要战场。因此&#xff0c;商业详细页面的设计和规划是电子商务产品设计的核心&#xff0c;承担着转化率&#xff0c;甚至是产品设计的KPI。 电子商务作为传统商品交易在互联网领域的表…