private void createCodecFromGL(){
mRtmpView = (RTMPDisplayView2)findViewById(R.id.view_preview);
mRtmpView.init();
new Thread(){
@Override
public void run() {
super.run();
synchronized (mRtmpView.sSync){
try {
mRtmpView.sSync.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Surface mSurface = mRtmpView.getSurface();
mRtmpView.mSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() { //TODO move to decode chread.
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
Log.i(TAG, "onFrameAvailable");
mRtmpView.requestRender();
}
});
mVideoDecoder.init(mSurface);
mVideoDecoder.start();
}
}.start();
}
编码器初始化:
mDecoder = MediaCodec.createDecoderByType(VIDEO_TYPE);
MediaFormat format = MediaFormat.createVideoFormat(VIDEO_TYPE, 1540, 1280);
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1540 * 1280);
format.setInteger("durationUs", 63446722);
mDecoder.start();
解码线程不贴了。GLSurfaceView的初始化,注意设置为dirty模式:
setEGLContextClientVersion(2);
setPreserveEGLContextOnPause(true);
render = new ViewRenderer();
setRenderer(render);
setRenderMode(RENDERMODE_WHEN_DIRTY);
在GLThread初始化中创建SurfaceTexture和Surface:
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
Log.i(TAG,"onSurfaceCreated");
mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
if (mProgram == 0) {
throw new RuntimeException("failed creating program");
}
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix");
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
mTextureID = textures[0];
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
checkGlError("glBindTexture mTextureID");
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
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);
checkGlError("glTexParameter");
mSurfaceTexture = new SurfaceTexture(mTextureID);//注意这里
mSurface = new Surface(mSurfaceTexture);
synchronized (sSync){
sSync.notifyAll();
}
}
@Override
public void onDrawFrame(GL10 gl10) {
mSurfaceTexture.getTransformMatrix(mSTMatrix);
mSurfaceTexture.updateTexImage();
//draw more...
}
那个线程锁是因为GL线程要等Activity OnResume生命周期走完才会创建。而SurfaceTexture的监听又需要独立于GL线程。所以开头创建一个线程。
最后贴一下示例Shader:
private static final String VERTEX_SHADER =
"uniform mat4 uMVPMatrix;\n" +
"uniform mat4 uSTMatrix;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec4 aTextureCoord;\n" +
"varying vec2 vTextureCoord;\n" +
"void main() {\n" +
" gl_Position = uMVPMatrix * aPosition;\n" +
" vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
"}\n";
private static final String FRAGMENT_SHADER =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;\n" + // highp here doesn't seem to matter
"varying vec2 vTextureCoord;\n" +
"uniform samplerExternalOES sTexture;\n" +
"void main() {\n" +
" gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
"}\n";