package lilin.com.view;
|
|
import android.content.Context;
|
import android.graphics.SurfaceTexture;
|
import android.opengl.GLES11Ext;
|
import android.opengl.GLES20;
|
import android.opengl.GLSurfaceView;
|
import android.util.Log;
|
import android.view.Surface;
|
|
|
import java.nio.ByteBuffer;
|
import java.nio.ByteOrder;
|
import java.nio.FloatBuffer;
|
|
import javax.microedition.khronos.egl.EGLConfig;
|
import javax.microedition.khronos.opengles.GL10;
|
|
import lilin.com.R;
|
|
public class FFWlRender implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
|
|
public static final int RENDER_YUV = 1;
|
public static final int RENDER_MEDIACODEC = 2;
|
//渲染方式
|
private int renderType = RENDER_YUV;
|
|
private Context context;
|
//默认视频是横向的
|
private final float[] vertexData0 ={
|
-1f, -1f,
|
1f, -1f, -1f, 1f,
|
1f, 1f,
|
|
|
};
|
private final float[] vertexData1 ={
|
-0.5f, -1f,
|
0.5f, -1f,
|
-0.5f, 1f,
|
0.5f, 1f
|
};
|
|
private final float[] textureData ={
|
0f,1f,
|
1f, 1f,
|
0f, 0f,
|
1f, 0f
|
};
|
//yuv
|
private FloatBuffer vertexBuffer=null;
|
private FloatBuffer textureBuffer;
|
private int program_yuv;
|
private int avPosition_yuv;
|
private int afPosition_yuv;
|
|
private int sampler_y;
|
private int sampler_u;
|
private int sampler_v;
|
private int[] textureId_yuv;
|
|
private int width_yuv;
|
private int height_yuv;
|
private ByteBuffer y;
|
private ByteBuffer u;
|
private ByteBuffer v;
|
|
//mediacodec
|
private int program_mediacodec;
|
private int avPosition_mediacodec;
|
private int afPosition_mediacodec;
|
private int samplerOES_mediacodec;
|
private int textureId_mediacodec;
|
private SurfaceTexture surfaceTexture;
|
private Surface surface;
|
|
|
|
public FFWlRender(Context context)
|
{
|
this.context = context;
|
|
textureBuffer = ByteBuffer.allocateDirect(textureData.length * 4)
|
.order(ByteOrder.nativeOrder())
|
.asFloatBuffer()
|
.put(textureData);
|
textureBuffer.position(0);
|
}
|
|
|
@Override
|
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
initRenderYUV();
|
initRenderMediacodec();
|
}
|
|
@Override
|
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
GLES20.glViewport(0, 0, width, height);
|
|
}
|
|
@Override
|
public void onDrawFrame(GL10 gl) {
|
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
|
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
if(renderType == RENDER_YUV)
|
{
|
renderYUV();
|
}
|
else if(renderType == RENDER_MEDIACODEC)
|
{
|
renderMediacodec();
|
}
|
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
}
|
|
@Override
|
public void onFrameAvailable(SurfaceTexture surfaceTexture) {//刷新调用
|
if(onRenderListener != null)
|
{
|
onRenderListener.onRender();
|
}
|
}
|
|
private void initRenderYUV()
|
{
|
String vertexSource = FFWlShaderUtil.readRawTxt(context, R.raw.vertex_shader);
|
String fragmentSource = FFWlShaderUtil.readRawTxt(context, R.raw.fragment_yuv);
|
program_yuv = FFWlShaderUtil.createProgram(vertexSource, fragmentSource);
|
|
avPosition_yuv = GLES20.glGetAttribLocation(program_yuv, "av_Position");
|
afPosition_yuv = GLES20.glGetAttribLocation(program_yuv, "af_Position");
|
|
sampler_y = GLES20.glGetUniformLocation(program_yuv, "sampler_y");
|
sampler_u = GLES20.glGetUniformLocation(program_yuv, "sampler_u");
|
sampler_v = GLES20.glGetUniformLocation(program_yuv, "sampler_v");
|
|
textureId_yuv = new int[3];
|
GLES20.glGenTextures(3, textureId_yuv, 0);
|
|
for(int i = 0; i < 3; i++)
|
{
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[i]);
|
|
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);
|
}
|
}
|
|
public void setYUVRenderData(int width, int height, byte[] y, byte[] u, byte[] v)
|
{
|
this.width_yuv = width;
|
this.height_yuv = height;
|
this.y = ByteBuffer.wrap(y);
|
this.u = ByteBuffer.wrap(u);
|
this.v = ByteBuffer.wrap(v);
|
}
|
|
private void renderYUV()
|
{
|
if(width_yuv > 0 && height_yuv > 0 && y != null && u != null && v != null)
|
{
|
|
GLES20.glUseProgram(program_yuv);
|
|
GLES20.glEnableVertexAttribArray(avPosition_yuv);
|
GLES20.glVertexAttribPointer(avPosition_yuv, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);
|
|
GLES20.glEnableVertexAttribArray(afPosition_yuv);
|
GLES20.glVertexAttribPointer(afPosition_yuv, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
|
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[0]);
|
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, width_yuv, height_yuv, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, y);
|
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[1]);
|
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, width_yuv / 2, height_yuv / 2, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, u);
|
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[2]);
|
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, width_yuv / 2, height_yuv / 2, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, v);
|
|
GLES20.glUniform1i(sampler_y, 0);
|
GLES20.glUniform1i(sampler_u, 1);
|
GLES20.glUniform1i(sampler_v, 2);
|
|
y.clear();
|
u.clear();
|
v.clear();
|
y = null;
|
u = null;
|
v = null;
|
}
|
}
|
|
|
private OnSurfaceCreateListener onSurfaceCreateListener;
|
private OnRenderListener onRenderListener;
|
|
public void setRenderType(int renderType ) {
|
this.renderType = renderType;
|
}
|
|
public void setVideoType(int videoType){
|
Log.e("xxxxxx","来了");
|
if(videoType==0){
|
vertexBuffer = ByteBuffer.allocateDirect(vertexData0.length * 4)
|
.order(ByteOrder.nativeOrder())
|
.asFloatBuffer()
|
.put(vertexData0);
|
vertexBuffer.position(0);
|
}else{
|
vertexBuffer = ByteBuffer.allocateDirect(vertexData1.length * 4)
|
.order(ByteOrder.nativeOrder())
|
.asFloatBuffer()
|
.put(vertexData1);
|
vertexBuffer.position(0);
|
}
|
}
|
|
public void setOnSurfaceCreateListener(OnSurfaceCreateListener onSurfaceCreateListener) {
|
this.onSurfaceCreateListener = onSurfaceCreateListener;
|
}
|
|
public void setOnRenderListener(OnRenderListener onRenderListener) {
|
this.onRenderListener = onRenderListener;
|
}
|
|
|
private void initRenderMediacodec()
|
{
|
String vertexSource = FFWlShaderUtil.readRawTxt(context, R.raw.vertex_shader);
|
String fragmentSource = FFWlShaderUtil.readRawTxt(context, R.raw.fragment_mediacodec);
|
program_mediacodec = FFWlShaderUtil.createProgram(vertexSource, fragmentSource);
|
|
avPosition_mediacodec = GLES20.glGetAttribLocation(program_mediacodec, "av_Position");
|
afPosition_mediacodec = GLES20.glGetAttribLocation(program_mediacodec, "af_Position");
|
samplerOES_mediacodec = GLES20.glGetUniformLocation(program_mediacodec, "sTexture");
|
|
int[] textureids = new int[1];
|
GLES20.glGenTextures(1, textureids, 0);
|
textureId_mediacodec = textureids[0];
|
|
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
|
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
|
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
|
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
|
|
surfaceTexture = new SurfaceTexture(textureId_mediacodec);
|
surface = new Surface(surfaceTexture);
|
surfaceTexture.setOnFrameAvailableListener(this);
|
|
if(onSurfaceCreateListener != null)
|
{
|
onSurfaceCreateListener.onSurfaceCreate(surface);
|
}
|
}
|
|
private void renderMediacodec()
|
{
|
surfaceTexture.updateTexImage();
|
GLES20.glUseProgram(program_mediacodec);
|
|
GLES20.glEnableVertexAttribArray(avPosition_mediacodec);
|
GLES20.glVertexAttribPointer(avPosition_mediacodec, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);
|
|
GLES20.glEnableVertexAttribArray(afPosition_mediacodec);
|
GLES20.glVertexAttribPointer(afPosition_mediacodec, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
|
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId_mediacodec);
|
GLES20.glUniform1i(samplerOES_mediacodec, 0);
|
}
|
|
|
|
public interface OnSurfaceCreateListener
|
{
|
void onSurfaceCreate(Surface surface);
|
}
|
public interface OnRenderListener{
|
void onRender();
|
}
|
|
}
|