博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[FFmpeg + OpenGL + OpenSL ES]OpenGL ES 渲染获取到的yuv数据 - 7
阅读量:272 次
发布时间:2019-03-01

本文共 7729 字,大约阅读时间需要 25 分钟。

OpenGL中是不能直接渲染YUV数据的,可以用3个纹理来分别获取Y、U和V的值,然后根据公式:

r = y + 1.403 * v;

g = y - 0.344 * u - 0.714 * v;
b = y + 1.770 * u;

转为rgb颜色格式显示出来。这个转换过程是在GPU中完成的,计算效率比在CPU中计算高很多倍


在工程目录res目录下新建    raw文件夹    新建    顶点着色器/片元着色器

vertex_shader.glsl

aattribute vec4 av_Position;attribute vec2 af_Position;varying vec2 v_texPosition;void main() { v_texPosition = af_Position; gl_Position = av_Position;}

fragment_shader.glsl

precision mediump float;varying vec2 v_texPosition;uniform sampler2D sampler_y;uniform sampler2D sampler_u;uniform sampler2D sampler_v;void main() {    float y,u,v;    y = texture2D(sampler_y,v_texPosition).r;    u = texture2D(sampler_u,v_texPosition).r- 0.5;    v = texture2D(sampler_v,v_texPosition).r- 0.5;    vec3 rgb;    rgb.r = y + 1.403 * v;    rgb.g = y - 0.344 * u - 0.714 * v;    rgb.b = y + 1.770 * u;    gl_FragColor = vec4(rgb,1);}

在java工程目录下新建opengl包

将    WlGLSurfaceView    WlRender    WlShaderUtil    粘贴过来

修改   WlRender   

package com.ywl5320.myplayer.opengl;import android.content.Context;import android.opengl.GLES20;import android.opengl.GLSurfaceView;import com.ywl5320.myplayer.R;import com.ywl5320.myplayer.log.MyLog;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import static android.opengl.GLES30.GL_RGB32F;import static android.opengl.GLES30.GL_RGBA32F;public class WlRender implements GLSurfaceView.Renderer {    private Context mContext;    private int program_yuv;    private int avPosition_yuv;    private int afPosition_yuv;    private int textureid;    private int sampler_y;    private int sampler_u;    private int sampler_v;    private int[] textureId_yuv;    private int width_yuv;    private int height_yuv;    private ByteBuffer y;    private ByteBuffer u;    private ByteBuffer v;    //声明顶点坐标数组 绘制坐标范围    private final float[] vertexData = {            -1f, -1f,            1f, -1f,            -1f, 1f,            1f, 1f    };    //纹理坐标    private final float[] textureData = {            0f, 1f,            1f, 1f,            0f, 0f,            1f, 0f    };    private FloatBuffer vertexBuffer;    private FloatBuffer textureBuffer;    public WlRender(Context context) {        MyLog.d("WlRender");        this.mContext = context;        //为坐标分配本地内存地址        //.order排序        //.asFloatBuffer()类型        //.put(vertexData);放置        vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)                .order(ByteOrder.nativeOrder())                .asFloatBuffer()                .put(vertexData);        //移动指针到0        vertexBuffer.position(0);        //纹理坐标        textureBuffer = ByteBuffer.allocateDirect(textureData.length * 4)                .order(ByteOrder.nativeOrder())                .asFloatBuffer()                .put(textureData);        textureBuffer.position(0);    }    //加载    @Override    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {        MyLog.d("onSurfaceCreated");        initRanderYUV();    }    @Override    public void onSurfaceChanged(GL10 gl10, int i, int i1) {        MyLog.d("onSurfaceChanged");        //设置长宽高        GLES20.glViewport(0, 0, i, i1);    }    @Override    public void onDrawFrame(GL10 gl10) {        MyLog.d("onDrawFrame");        //清屏        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);        //使用颜色清屏        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);        renderYUV();        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);    }    private void initRanderYUV() {        //获取着色器语言    program        String vertexSource = WlShaderUtil.readRawTxt(mContext, R.raw.vertex_shader);        String fragmentSource = WlShaderUtil.readRawTxt(mContext, R.raw.fragment_shader);        program_yuv = WlShaderUtil.createProgram(vertexSource, fragmentSource);        //顶点坐标        avPosition_yuv = GLES20.glGetAttribLocation(program_yuv, "av_Position");        //纹理坐标        afPosition_yuv = GLES20.glGetAttribLocation(program_yuv, "af_Position");        sampler_y = GLES20.glGetUniformLocation(program_yuv, "sampler_y");        sampler_u = GLES20.glGetUniformLocation(program_yuv, "sampler_u");        sampler_v = GLES20.glGetUniformLocation(program_yuv, "sampler_v");        //创建纹理        textureId_yuv = new int[3];        //创建和绑定纹理        GLES20.glGenTextures(3, textureId_yuv, 0);        for (int i = 0; i < 3; i++) {            //绑定纹理            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[i]);            //设置环绕过滤方法            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);        }    }    public void setYUVRenderData(int width, int height, byte[] y, byte[] u, byte[] v) {        MyLog.d("setYUVRenderData");        this.width_yuv = width;        this.height_yuv = height;        this.y = ByteBuffer.wrap(y);        this.u = ByteBuffer.wrap(u);        this.v = ByteBuffer.wrap(v);    }    private void renderYUV() {        MyLog.d("width_yuv " + width_yuv +                "height_yuv " + height_yuv +                "y " + y +                "u " + u +                "v " + v);        if (width_yuv > 0 && height_yuv > 0 && y != null && u != null && v != null) {            MyLog.d("renderYUV");            //使用program            GLES20.glUseProgram(program_yuv);            MyLog.d("glUseProgram");            //使用顶点坐标            GLES20.glEnableVertexAttribArray(avPosition_yuv);            GLES20.glVertexAttribPointer(avPosition_yuv, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);            MyLog.d("glVertexAttribPointer");            //绘制            //参数2从哪个顶点绘制            //参数3 绘制顶点个数            GLES20.glEnableVertexAttribArray(afPosition_yuv);            GLES20.glVertexAttribPointer(afPosition_yuv, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);            //纹理赋值            //激活纹理            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);            //绑定            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[0]);            GLES20.glTexImage2D(                    GLES20.GL_TEXTURE_2D,                    0,                    GL_RGBA32F,                    width_yuv, height_yuv,                    0,                    GL_RGBA32F,                    GLES20.GL_UNSIGNED_BYTE,                    y);            GLES20.glActiveTexture(GLES20.GL_TEXTURE1);            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[1]);            GLES20.glTexImage2D(                    GLES20.GL_TEXTURE_2D,                    0,                    GL_RGBA32F,                    width_yuv / 2, height_yuv / 2,                    0,                    GL_RGBA32F,                    GLES20.GL_UNSIGNED_BYTE,                    u);            GLES20.glActiveTexture(GLES20.GL_TEXTURE2);            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[2]);            GLES20.glTexImage2D(                    GLES20.GL_TEXTURE_2D,                    0,                    GLES20.GL_LUMINANCE,                    width_yuv / 2, height_yuv / 2,                    0,                    GLES20.GL_LUMINANCE,                    GLES20.GL_UNSIGNED_BYTE,                    v);            GLES20.glUniform1i(sampler_y, 0);            GLES20.glUniform1i(sampler_u, 1);            GLES20.glUniform1i(sampler_v, 2);            y.clear();            u.clear();            v.clear();            y = null;            u = null;            v = null;            MyLog.d("END");        }    }}

* 注意这个类目前绘制有问题但是能保证程序运行   后面明白了怎么做就改掉

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载地址:http://udzo.baihongyu.com/

你可能感兴趣的文章