《音视频进阶指南》读书笔记

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

2019-07-20  本文已影响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的这个特性,将纹理进行裁剪。

上一篇 下一篇

猜你喜欢

热点阅读