opengles+videoPlay

ManActivity.java:

public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener, MediaPlayer.OnPreparedListener {

//    public String videoPath = "/sdcard/DCIM/Camera/VID_20160718_153206.mp4";//Environment.getExternalStorageDirectory().getPath();

    public String videoPath = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/VID_20160718_153206.mp4";
    private TextureView textureView;
    private MediaPlayer mediaPlayer;

    private TextureSurfaceRenderer videoRenderer;
    private int surfaceWidth;
    private int surfaceHeight;
    private Surface surface;


    public native int getValue();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textureView = (TextureView) findViewById(R.id.id_textureview);
        textureView.setSurfaceTextureListener(this);
    }


    private boolean bReadSDCard() {
        boolean state = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
        return state;
    }

    private void playVideo(SurfaceTexture surfaceTexture) {
        if (mediaPlayer == null) {
            videoRenderer = new VideoTextureSurfaceRenderer(this, surfaceTexture, surfaceWidth, surfaceHeight);
//            surface = new Surface(videoRenderer.getSurfaceTexture());
            initMediaPlayer();
        }
    }

    private boolean bFileExist() {
        return true;
    }

    private void initMediaPlayer() {

        bReadSDCard();
        this.mediaPlayer = new MediaPlayer();
        try {

            while (videoRenderer.getSurfaceTexture() == null) {
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            Surface surface = new Surface(videoRenderer.getSurfaceTexture());
            mediaPlayer.setDataSource(videoPath);
            mediaPlayer.setSurface(surface);
            surface.release();

            mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(this);
            mediaPlayer.setLooping(true);


        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        try {
            if (mp != null) {
                mp.start();
            }
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (textureView.isAvailable()) {
//            playVideo();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();// ATTENTION: This was auto-generated to implement the App Indexing API.

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (videoRenderer != null) {
            videoRenderer.onPause();
            videoRenderer = null;
        }

        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }

    }


    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        surfaceWidth = width;
        surfaceHeight = height;
        playVideo(surface);
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }


    @Override
    public void onStop() {
        super.onStop();// ATTENTION: This was auto-generated to implement the App Indexing API.

    }
}


TextureSurfaceRenderer.java:
public abstract class TextureSurfaceRenderer implements Runnable {
    public static String LOG_TAG = TextureSurfaceRenderer.class.getSimpleName();

    protected final SurfaceTexture surfaceTexture;
    protected  int width;
    protected  int height;

    private EGL10 egl;
    private EGLContext eglContext;
    private EGLDisplay eglDisplay;
    private EGLSurface eglSurface;

    private boolean running = false;

    public TextureSurfaceRenderer(SurfaceTexture surfaceTexture,int width,int height){
        this.surfaceTexture = surfaceTexture;
        this.width = width;
        this.height = height;
        this.running = true;

        Thread thread = new Thread(this);
        thread.start();
    }


    private void initEGL(){
        egl = (EGL10)EGLContext.getEGL();
        eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
        int version[] = new int[2];
        egl.eglInitialize(eglDisplay,version);

        EGLConfig eglConfig = chooseEglConfig();
        eglSurface = egl.eglCreateWindowSurface(eglDisplay,eglConfig,surfaceTexture,null);
        eglContext = createContext(egl,eglDisplay,eglConfig);

        try{
            if(eglSurface == null || eglSurface == EGL10.EGL_NO_SURFACE){
                throw  new RuntimeException("GL error");
            }

            if(!egl.eglMakeCurrent(eglDisplay,eglSurface,eglSurface,eglContext)){
                throw  new RuntimeException("MAKE CURRENT ERROR");
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void run(){
        initEGL();
        initGLComponents();

        while (running){
            if(draw()){
                egl.eglSwapBuffers(eglDisplay,eglSurface);
            }
        }

        deinitGLComponents();
        deinitEGL();
    }

    private void deinitEGL(){
        egl.eglMakeCurrent(eglDisplay,EGL10.EGL_NO_SURFACE,EGL10.EGL_NO_SURFACE,EGL10.EGL_NO_CONTEXT);
        egl.eglDestroySurface(eglDisplay,eglSurface);
        egl.eglDestroyContext(eglDisplay,eglContext);
        egl.eglTerminate(eglDisplay);
    }

    protected  abstract boolean draw();

    protected  abstract void initGLComponents();

    protected  abstract void deinitGLComponents();

    public abstract SurfaceTexture getSurfaceTexture();

    private EGLContext createContext(EGL10 egl,EGLDisplay eglDisplay,EGLConfig eglconfig){
        int[] attrs = {
                EGL14.EGL_CONTEXT_CLIENT_VERSION,2,
                EGL10.EGL_NONE
        };
        return egl.eglCreateContext(eglDisplay,eglconfig,EGL10.EGL_NO_CONTEXT,attrs);
    }

    private EGLConfig chooseEglConfig(){
        int[] configsCount = new int[1];
        EGLConfig[] configs = new EGLConfig[1];
        int[] attributes = getAttributes();
        int confSize = 1;

        if(!egl.eglChooseConfig(eglDisplay,attributes,configs,confSize,configsCount)){
            throw new IllegalArgumentException("failed to choose config");
        }else if(configsCount[0]>0){
            return configs[0];
        }

        return null;
    }

    private int[] getAttributes(){
        return new int[]{
                EGL10.EGL_RENDERABLE_TYPE,EGL14.EGL_OPENGL_ES2_BIT,
                EGL10.EGL_RED_SIZE,8,
                EGL10.EGL_GREEN_SIZE, 8,
                EGL10.EGL_BLUE_SIZE, 8,
                EGL10.EGL_ALPHA_SIZE, 8,
                EGL10.EGL_DEPTH_SIZE, 0,
                EGL10.EGL_STENCIL_SIZE, 0,
                EGL10.EGL_NONE      //总是以EGL10.EGL_NONE结尾
        };
    }

    public void onPause()
    {
        running = false;
    }

    @Override
    protected void finalize() throws Throwable{
        super.finalize();
        running = false;
    }

}


VideoTextureSurfaceRenderer.java:
public class VideoTextureSurfaceRenderer extends TextureSurfaceRenderer implements SurfaceTexture.OnFrameAvailableListener
{
    public static final String TAG = VideoTextureSurfaceRenderer.class.getSimpleName();

    private static float squareSize = 1.0f;
    private static float squareCoords[] = {
            -squareSize,squareSize,0.0f,
            -squareSize,-squareSize,0.0f,
            squareSize,-squareSize,0.0f,
            squareSize,squareSize,0.0f
    };

    private static short drawOrder[] = {
      0,1,2,
      0,2,3
    };

    private FloatBuffer textureBuffer;

    private float textureCoords[] = {
            0.0f,1.0f,0.0f,1.0f,
            0.0f,0.0f,0.0f,1.0f,
            1.0f,0.0f,0.0f,1.0f,
            1.0f,1.0f,0.0f,1.0f,
    };

    private int[] textures = new int[1];

    private int shaderProgram;

    private FloatBuffer vertexBuffer;

    private ShortBuffer drawOrderBuffer;

    private float[] videoTextureTransform;

    private boolean frameAvailable = false;

    private Context context;

    private SurfaceTexture videoTexture;

    public VideoTextureSurfaceRenderer(Context context,SurfaceTexture texture,int width,int height){
        super(texture,width,height);
        this.context = context;
        videoTextureTransform = new float[16];
    }

    @Override
    protected void initGLComponents(){
        setupVertexBuffer();
        setupTexture();
        loadShaders();
    }


    @Override
    protected void deinitGLComponents()
    {
        GLES20.glDeleteTextures(1, textures, 0);
        GLES20.glDeleteProgram(shaderProgram);
        videoTexture.release();
        videoTexture.setOnFrameAvailableListener(null);
    }


    @Override
    public SurfaceTexture getSurfaceTexture(){

        return videoTexture;
    }
    @Override
    public void onFrameAvailable(SurfaceTexture surfaceTexture)
    {
        synchronized (this)
        {
            frameAvailable = true;
        }
    }


    private void setupVertexBuffer(){
        ByteBuffer orderByteBuffer = ByteBuffer.allocateDirect(drawOrder.length*2);
        orderByteBuffer.order(ByteOrder.nativeOrder());
        drawOrderBuffer = orderByteBuffer.asShortBuffer();
        drawOrderBuffer.put(drawOrder);
        drawOrderBuffer.position(0);

        ByteBuffer bf = ByteBuffer.allocateDirect(squareCoords.length*4);
        bf.order(ByteOrder.nativeOrder());
        vertexBuffer = bf.asFloatBuffer();
        vertexBuffer.put(squareCoords);
        vertexBuffer.position(0);
    }

    private void setupTexture(){
        ByteBuffer texture = ByteBuffer.allocateDirect(textureCoords.length*4);
        texture.order(ByteOrder.nativeOrder());

        textureBuffer = texture.asFloatBuffer();
        textureBuffer.put(textureCoords);
        textureBuffer.position(0);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glGenTextures(1,textures,0);
        GLES20.glBindTexture(GLES11Ext.GL_BLEND_EQUATION_RGB_OES,textures[0]);

        videoTexture = new SurfaceTexture(textures[0]);
        videoTexture.setOnFrameAvailableListener(this);
    }

    private void loadShaders()
    {
        final String vertexShader =   RawResourceReader.readTextFileFromRawResource(context, R.raw.vertext_sharder);
        final String fragmentShader = RawResourceReader.readTextFileFromRawResource(context, R.raw.fragment_sharder);

        final int vertexShaderHandle = ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
        final int fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
        shaderProgram = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle,
                new String[]{"texture","vPosition","vTexCoordinate","textureTransform"});
    }

    @Override
    protected  boolean draw()
    {
        synchronized (this)
        {
            if (frameAvailable)
            {
                videoTexture.updateTexImage();
                videoTexture.getTransformMatrix(videoTextureTransform);
                frameAvailable = false;
            }
            else
            {
                return false;
            }
        }

        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glViewport(0, 0, width, height);
        this.drawTexture();

        return true;
    }

    private void drawTexture(){
        // Draw texture
        GLES20.glUseProgram(shaderProgram); //绘制时使用着色程序
        int textureParamHandle = GLES20.glGetUniformLocation(shaderProgram, "texture"); //返回一个于着色器程序中变量名为"texture"相关联的索引
        int textureCoordinateHandle = GLES20.glGetAttribLocation(shaderProgram, "vTexCoordinate");
        int positionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
        int textureTransformHandle = GLES20.glGetUniformLocation(shaderProgram, "textureTransform");
        //在用VertexAttribArray前必须先激活它
        GLES20.glEnableVertexAttribArray(positionHandle);
        //指定positionHandle的数据值可以在什么地方访问。 vertexBuffer在内部(NDK)是个指针,指向数组的第一组值的内存
        GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
        GLES20.glBindTexture(GLES20.GL_TEXTURE0, textures[0]);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        //指定一个当前的textureParamHandle对象为一个全局的uniform 变量
        GLES20.glUniform1i(textureParamHandle, 0);

        GLES20.glEnableVertexAttribArray(textureCoordinateHandle);
        GLES20.glVertexAttribPointer(textureCoordinateHandle, 4, GLES20.GL_FLOAT, false, 0, textureBuffer);

        GLES20.glUniformMatrix4fv(textureTransformHandle, 1, false, videoTextureTransform, 0);
        //GLES20.GL_TRIANGLES(以无数小三角行的模式)去绘制出这个纹理图像
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawOrderBuffer);
        GLES20.glDisableVertexAttribArray(positionHandle);
        GLES20.glDisableVertexAttribArray(textureCoordinateHandle);
    }

}

RawResourceReader.java:
public class RawResourceReader
{
   public static String readTextFileFromRawResource(final Context context,
         final int resourceId)
   {
      final InputStream inputStream = context.getResources().openRawResource(
            resourceId);
      final InputStreamReader inputStreamReader = new InputStreamReader(
            inputStream);
      final BufferedReader bufferedReader = new BufferedReader(
            inputStreamReader);

      String nextLine;
      final StringBuilder body = new StringBuilder();

      try
      {
         while ((nextLine = bufferedReader.readLine()) != null)
         {
            body.append(nextLine);
            body.append('\n');
         }
      }
      catch (IOException e)
      {
         return null;
      }

      return body.toString();
   }
}

ShaderHelper.java:

public class ShaderHelper
{
   private static final String TAG = "ShaderHelper";
   
   /** 
    * Helper function to compile a shader.
    * 
    * @param shaderType The shader type.
    * @param shaderSource The shader source code.
    * @return An OpenGL handle to the shader.
    */
   public static int compileShader(final int shaderType, final String shaderSource) 
   {
      int shaderHandle = GLES20.glCreateShader(shaderType);

      if (shaderHandle != 0) 
      {
         // Pass in the shader source.
         GLES20.glShaderSource(shaderHandle, shaderSource);

         // Compile the shader.
         GLES20.glCompileShader(shaderHandle);

         // Get the compilation status.
         final int[] compileStatus = new int[1];
         GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);

         // If the compilation failed, delete the shader.
         if (compileStatus[0] == 0) 
         {
            Log.e(TAG, "Error compiling shader: " + GLES20.glGetShaderInfoLog(shaderHandle));
            GLES20.glDeleteShader(shaderHandle);
            shaderHandle = 0;
         }
      }

      if (shaderHandle == 0)
      {        
         throw new RuntimeException("Error creating shader.");
      }
      
      return shaderHandle;
   }
   
   /**
    * Helper function to compile and link a program.
    * 
    * @param vertexShaderHandle An OpenGL handle to an already-compiled vertex shader.
    * @param fragmentShaderHandle An OpenGL handle to an already-compiled fragment shader.
    * @param attributes Attributes that need to be bound to the program.
    * @return An OpenGL handle to the program.
    */
   public static int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes) 
   {
      int programHandle = GLES20.glCreateProgram();
      
      if (programHandle != 0) 
      {
         // Bind the vertex shader to the program.
         GLES20.glAttachShader(programHandle, vertexShaderHandle);        

         // Bind the fragment shader to the program.
         GLES20.glAttachShader(programHandle, fragmentShaderHandle);
         
         // Bind attributes
         if (attributes != null)
         {
            final int size = attributes.length;
            for (int i = 0; i < size; i++)
            {
               GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
            }                 
         }
         
         // Link the two shaders together into a program.
         GLES20.glLinkProgram(programHandle);

         // Get the link status.
         final int[] linkStatus = new int[1];
         GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);

         // If the link failed, delete the program.
         if (linkStatus[0] == 0) 
         {           
            Log.e(TAG, "Error compiling program: " + GLES20.glGetProgramInfoLog(programHandle));
            GLES20.glDeleteProgram(programHandle);
            programHandle = 0;
         }
      }
      
      if (programHandle == 0)
      {
         throw new RuntimeException("Error creating program.");
      }
      
      return programHandle;
   }
}


TextureHelper.java:

public class TextureHelper {
   public static int loadTexture(final Context context, final int resourceId) {
      final int[] textureHandle = new int[1];

      GLES20.glGenTextures(1, textureHandle, 0);

      if (textureHandle[0] != 0) {
         final BitmapFactory.Options options = new BitmapFactory.Options();
         options.inScaled = false; // No pre-scaling

         // Read in the resource
         final Bitmap bitmap = BitmapFactory.decodeResource(
               context.getResources(), resourceId, options);

         // Bind to the texture in OpenGL
         GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);

         // Set filtering
         GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
               GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
         GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
               GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);

         // Load the bitmap into the bound texture.
         GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

         // Recycle the bitmap, since its data has been loaded into OpenGL.
         bitmap.recycle();
      }

      if (textureHandle[0] == 0) {
         throw new RuntimeException("Error loading texture.");
      }

      return textureHandle[0];
   }
}


/res/raw/fragment_sharder.glsl:

#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform samplerExternalOES texture;
varying vec2 v_TexCoordinate;

void main () {
    vec4 color = texture2D(texture, v_TexCoordinate);
    gl_FragColor = color;
}


/res/raw/vertext_sharder.glsl:
attribute vec4 vPosition;
attribute vec4 vTexCoordinate;
uniform mat4 textureTransform;
varying vec2 v_TexCoordinate;

void main(){
    v_TexCoordinate = (textureTransform * vTexCoordinate).xy;
    gl_Position = vPosition;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值