这是MediaExtractor -> MediaCodec (Decoder) -> MediaCodec (Encoder)
工作流程的一部分。更具体地说,将来自解码器输出缓冲器的纹理的部分渲染到编码器的输入缓冲器中。为此,我在解码器的输出表面设置了以下onDrawFrame()
函数:
public void drawFrame(SurfaceTexture st) {
checkGlError("onDrawFrame start");
st.getTransformMatrix(mPrelimSTMatrix);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
drawToFBO();
}
private void drawToFBO() {
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
int mainTextureLoc = GLES20.glGetUniformLocation(prelimShaderProgram, "u_Texture");
checkGlError("glGetMainTextureUniform");
GLES20.glUseProgram(prelimShaderProgram);
checkGlError("glUseProgram");
GLES20.glUniform1i(mainTextureLoc, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
checkGlError("glBindTexture");
onPrelimPreDrawFrame(); //Basically binding the extraneous textures the filter requires
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(maPrelimPositionHandle, 3, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maPosition");
GLES20.glEnableVertexAttribArray(maPrelimPositionHandle);
checkGlError("glEnableVertexAttribArray maPositionHandle");
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glVertexAttribPointer(maPrelimTextureHandle, 3, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maTextureHandle");
GLES20.glEnableVertexAttribArray(maPrelimTextureHandle);
checkGlError("glEnableVertexAttribArray maTextureHandle");
Matrix.setIdentityM(mPrelimMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muPrelimMVPMatrixHandle, 1, false, mPrelimMVPMatrix, 0);
checkGlError("glmuMVPMatrixHandleSetting");
GLES20.glUniformMatrix4fv(muPrelimSTMatrixHandle, 1, false, mPrelimSTMatrix, 0);
checkGlError("glmuSTMatrixHandleSetting");
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
checkGlError("glDrawArrays");
}
private void createPrelimShader() {
FRAGMENT_SHADER = VideoUtils.getPrelimFragmentShader(context, prelimFilterCode);
prelimShaderProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
if (prelimShaderProgram == 0) {
return;
}
maPrelimPositionHandle = GLES20.glGetAttribLocation(prelimShaderProgram, "aPosition");
checkGlError("glGetAttribLocation aPosition");
if (maPrelimPositionHandle == -1) {
throw new RuntimeException("Could not get attrib location for aPosition");
}
maPrelimTextureHandle = GLES20.glGetAttribLocation(prelimShaderProgram, "aTexCoordinate");
checkGlError("glGetAttribLocation aTexCoordinate");
if (maPrelimTextureHandle == -1) {
throw new RuntimeException("Could not get attrib location for aTexCoordinate");
}
muPrelimMVPMatrixHandle = GLES20.glGetUniformLocation(prelimShaderProgram, "uMVPMatrix");
checkGlError("glGetUniformLocation uMVPMatrix");
if (muPrelimMVPMatrixHandle == -1) {
throw new RuntimeException("Could not get attrib location for uMVPMatrix");
}
muPrelimSTMatrixHandle = GLES20.glGetUniformLocation(prelimShaderProgram, "uSTMatrix");
checkGlError("glGetUniformLocation uSTMatrix");
if (muPrelimSTMatrixHandle == -1) {
throw new RuntimeException("Could not get attrib location for uSTMatrix");
}
filterInputTextureUniform2 = GLES20.glGetUniformLocation(prelimShaderProgram, "inputImageTexture2");
filterInputTextureUniform3 = GLES20.glGetUniformLocation(prelimShaderProgram, "inputImageTexture3");
filterInputTextureUniform4 = GLES20.glGetUniformLocation(prelimShaderProgram, "inputImageTexture4");
filterInputTextureUniform5 = GLES20.glGetUniformLocation(prelimShaderProgram, "inputImageTexture5");
filterInputTextureUniform6 = GLES20.glGetUniformLocation(prelimShaderProgram, "inputImageTexture6");
preloadFilterAssets(VideoUtils.getFilterAssets(prelimFilterCode));
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
checkGlError("glGenFramebuffers");
mTextureID = textures[0];
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
}
顶点着色器如下所示:
uniform mat4 uMVPMatrix;
uniform mat4 uSTMatrix;
attribute vec4 aPosition;
attribute vec4 aTexCoordinate;
varying vec2 v_TexCoordinate;
void main() {
gl_Position = uMVPMatrix * aPosition;
v_TexCoordinate = (uSTMatrix * aTexCoordinate).xy;
}
片段着色器看起来像这样,带有一个额外的输入纹理:
#extension GL_OES_EGL_image_external : require
precision lowp float;
varying highp vec2 v_TexCoordinate;
uniform samplerExternalOES u_Texture;
uniform sampler2D inputImageTexture2;
uniform float uParamValue1;
void main()
{
vec3 texel = texture2D(u_Texture, v_TexCoordinate).rgb;
vec3 procTexel = vec3(dot(vec3(0.3, 0.6, 0.1), texel));
procTexel = vec3(texture2D(inputImageTexture2, vec2(procTexel.r, .16666)).r);
texel += (procTexel - texel) * uParamValue1;
gl_FragColor = vec4(texel, 1.0);
}
checkGlError()
次调用都没有返回任何异常,但视频呈现就像纹理没有通过createPrelimShader()
函数中创建的OpenGL程序一样。它未被过滤。
根据过去的经验,这可能是由流程中缺少的东西引起的。是吗?