美文网首页
第三十一节 录制视频时添加水印

第三十一节 录制视频时添加水印

作者: 最美下雨天 | 来源:发表于2018-12-06 14:47 被阅读1次
    image.png
    image.png
    image.png
    image.png

    由于我们使用了FBO,绘制水印的工作就放在了FBO中
    主要逻辑代码:
    WlCameraFboRender.java

    package com.ywl5320.wllivepusher.camera;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.opengl.GLES20;
    
    import com.ywl5320.wllivepusher.R;
    import com.ywl5320.wllivepusher.egl.WlShaderUtil;
    
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.nio.FloatBuffer;
    
    public class WlCameraFboRender {
    
        private Context context;
    
        private float[] vertexData = {
                -1f, -1f,
                1f, -1f,
                -1f, 1f,
                1f, 1f,
    
                0f, 0f,
                0f, 0f,
                0f, 0f,
                0f, 0f
        };
        private FloatBuffer vertexBuffer;
    
        private float[] fragmentData = {
                0f, 1f,
                1f, 1f,
                0f, 0f,
                1f, 0f
        };
        private FloatBuffer fragmentBuffer;
    
        private int program;
        private int vPosition;
        private int fPosition;
        private int textureid;
        private int sampler;
    
        private int vboId;
    
        private Bitmap bitmap;
    
        private int bitmapTextureid;
    
        public WlCameraFboRender(Context context) {
            this.context = context;
    
            bitmap = WlShaderUtil.createTextImage("视频直播和推流:ywl5320", 50, "#ff0000", "#00000000", 0);
    
    
            float r = 1.0f * bitmap.getWidth() / bitmap.getHeight();
            float w = r * 0.1f;
    
            vertexData[8] = 0.8f - w;
            vertexData[9] = -0.8f;
    
            vertexData[10] = 0.8f;
            vertexData[11] = -0.8f;
    
            vertexData[12] = 0.8f - w;
            vertexData[13] = -0.7f;
    
            vertexData[14] = 0.8f;
            vertexData[15] = -0.7f;
    
            vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
                    .order(ByteOrder.nativeOrder())
                    .asFloatBuffer()
                    .put(vertexData);
            vertexBuffer.position(0);
    
            fragmentBuffer = ByteBuffer.allocateDirect(fragmentData.length * 4)
                    .order(ByteOrder.nativeOrder())
                    .asFloatBuffer()
                    .put(fragmentData);
            fragmentBuffer.position(0);
    
        }
    
        public void onCreate()
        {
    
            GLES20.glEnable (GLES20.GL_BLEND);
            GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
    
            String vertexSource = WlShaderUtil.getRawResource(context, R.raw.vertex_shader_screen);
            String fragmentSource = WlShaderUtil.getRawResource(context, R.raw.fragment_shader_screen);
    
            program = WlShaderUtil.createProgram(vertexSource, fragmentSource);
    
            vPosition = GLES20.glGetAttribLocation(program, "v_Position");
            fPosition = GLES20.glGetAttribLocation(program, "f_Position");
            sampler = GLES20.glGetUniformLocation(program, "sTexture");
    
            int [] vbos = new int[1];
            GLES20.glGenBuffers(1, vbos, 0);
            vboId = vbos[0];
    
            GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
            GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4 + fragmentData.length * 4, null, GLES20. GL_STATIC_DRAW);
            GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, vertexData.length * 4, vertexBuffer);
            GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4, fragmentData.length * 4, fragmentBuffer);
            GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    
            bitmapTextureid = WlShaderUtil.loadBitmapTexture(bitmap);
        }
    
        public void onChange(int width, int height)
        {
            GLES20.glViewport(0, 0, width, height);
        }
    
        public void onDraw(int textureId)
        {
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
            GLES20.glClearColor(1f,0f, 0f, 1f);
    
            GLES20.glUseProgram(program);
            GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
    
            //fbo
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
    
            GLES20.glEnableVertexAttribArray(vPosition);
            GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8,
                    0);
    
            GLES20.glEnableVertexAttribArray(fPosition);
            GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8,
                    vertexData.length * 4);
    
            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    
            //bitmap
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, bitmapTextureid);
    
            GLES20.glEnableVertexAttribArray(vPosition);
            GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8,
                    32);
    
            GLES20.glEnableVertexAttribArray(fPosition);
            GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8,
                    vertexData.length * 4);
    
            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    
    
    
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
            GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
        }
    }
    
    

    需要注意的地方:
    1、在顶点数组中定义好水印的位置

    private float[] vertexData = {
                -1f, -1f,
                1f, -1f,
                -1f, 1f,
                1f, 1f,
    
                0f, 0f,
                0f, 0f,
                0f, 0f,
                0f, 0f
        };
    

    2、初始化水印bitmap,如果是文字也要转化为bitmap

    public static Bitmap createTextImage(String text, int textSize, String textColor, String bgColor, int padding) {
    
            Paint paint = new Paint();
            paint.setColor(Color.parseColor(textColor));
            paint.setTextSize(textSize);
            paint.setStyle(Paint.Style.FILL);
            paint.setAntiAlias(true);
    
            float width = paint.measureText(text, 0, text.length());
    
            float top = paint.getFontMetrics().top;
            float bottom = paint.getFontMetrics().bottom;
    
            Bitmap bm = Bitmap.createBitmap((int) (width + padding * 2), (int) ((bottom - top) + padding * 2), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bm);
    
            canvas.drawColor(Color.parseColor(bgColor));
            canvas.drawText(text, padding, - top + padding, paint);
            return bm;
        }
    

    3、得到水印的纹理id

    public static int loadBitmapTexture(Bitmap bitmap)
        {
            int[] textureIds = new int[1];
            GLES20.glGenTextures(1, textureIds, 0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[0]);
            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);
    
            ByteBuffer bitmapBuffer = ByteBuffer.allocate(bitmap.getHeight() * bitmap.getWidth() * 4);
            bitmap.copyPixelsToBuffer(bitmapBuffer);
            bitmapBuffer.flip();
    
            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap.getWidth(),
                bitmap.getHeight(), 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, bitmapBuffer);
            return textureIds[0];
        }
    

    4、在绘制玩视频画面后绘制水印纹理

     //bitmap
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, bitmapTextureid);
    
            GLES20.glEnableVertexAttribArray(vPosition);
            GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8,
                    32);
    
            GLES20.glEnableVertexAttribArray(fPosition);
            GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8,
                    vertexData.length * 4);
    
            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    

    5、注意水印坐标的归一化

    //因为顶点坐标范围都是在-1到1之间的,我们规定水印的高度是0.1   那么水印的宽度怎么算呢?
            float r = 1.0f * bitmap.getWidth() / bitmap.getHeight();  //   15/5=3
            float w = r * 0.1f;   //  3*0.1=0.3   这就是水印高度为0.1的时候,水印的宽度大小
    
            vertexData[8] = 0.8f - w;
            vertexData[9] = -0.8f;
    
            vertexData[10] = 0.8f;
            vertexData[11] = -0.8f;
    
            vertexData[12] = 0.8f - w;
            vertexData[13] = -0.7f;
    
            vertexData[14] = 0.8f;
            vertexData[15] = -0.7f;
    

    相关文章

      网友评论

          本文标题:第三十一节 录制视频时添加水印

          本文链接:https://www.haomeiwen.com/subject/smwjqqtx.html