美文网首页《音视频进阶指南》读书笔记
OpenGL视频画面的居中预览预览

OpenGL视频画面的居中预览预览

作者: 天天_盖世英雄 | 来源:发表于2019-07-20 00:12 被阅读0次

    采集到的纹理画面如果跟预览的SurfaceView宽高不相同,如果不采取措施,把纹理直接绘制到Surface上,就会导致画面被压缩。

    有两种方法解决这个问题,下面是第一种方法:

        float textureAspectRatio = (float)texHeight / (float)texWidth;
        float viewAspectRatio = (float)screenHeight / (float)screenWidth;
        float xOffset = 0.0f;
        float yOffset = 0.0f;
        if(textureAspectRatio > viewAspectRatio){
            //Update Y Offset
            int expectedHeight = (int)((float)texHeight*screenWidth/(float)texWidth+0.5f);
            yOffset = (float)(expectedHeight-screenHeight)/(2*expectedHeight);
        } else if(textureAspectRatio < viewAspectRatio){
            //Update X Offset
            int expectedWidth = (int)((float)(texHeight * screenWidth) / (float)screenHeight + 0.5);
            xOffset = (float)(texWidth - expectedWidth)/(2*texWidth);
        }
    
        GLfloat texCoords[] = { xOffset, 1.0f - yOffset, 1.0f - xOffset, 1.0f - yOffset, xOffset, yOffset,
                1.0f - xOffset, yOffset };
        glVertexAttribPointer(mGLTextureCoords, 2, GL_FLOAT, 0, 0, texCoords);
    

    思路就是把纹理拉伸到跟屏幕等宽或者等高,然后将多余的部分进行裁剪。

    第二种方法:

        float texWH = (float)width / (float)height;
        float screenWH = (float)outputWidth / (float)outputHeight;
        bool cut = fabs(texWH - screenWH) <= (9.0f / 16.0f) - (9.0f / 20.0f);
        if (cut) {
            if(texWH < screenWH){
                x_scale = 1.0f;
                y_scale = screenWH / texWH;
            }else if(texWH > screenWH){
                x_scale = texWH / screenWH;
                y_scale = 1.0f;
            }else{
                x_scale = 1.0f;
                y_scale = 1.0f;
            }
        } else {
            if(texWH > screenWH){
                x_scale = 1.0f;
                y_scale = screenWH / texWH;
            }else if(texWH < screenWH){
                x_scale = texWH / screenWH;
                y_scale = 1.0f;
            }else{
                x_scale = 1.0f;
                y_scale = 1.0f;
            }
        }
    

    下面是vertexShader部分

    static const char * vs = STR(
            attribute vec2 position;
            attribute vec2 texcoord;
            uniform float x_scale;
            uniform float y_scale;
            varying vec2 tx;
            void main(){
                tx = vec2(texcoord.x, texcoord.y);
                vec2 xy = vec2(position.x * x_scale, position.y * y_scale);
                gl_Position = vec4(xy, 0, 1.0);
            }
    );
    

    下面是fragmentShader部分

    static const char * fs = STR(
            precision mediump float;
            varying vec2 tx;
            uniform sampler2D tex;
            void main(void){
                gl_FragColor = texture2D(tex, tx);
            }
    );
    

    fragmentShader的渲染范围是0到1,如果我们将图片拉伸到小于0或者大于1,则不会显示。利用gl的这个特性,将纹理进行裁剪。

    相关文章

      网友评论

        本文标题:OpenGL视频画面的居中预览预览

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