Github项目地址,欢迎star~!
为了方便没有准备好梯子的同学,我把项目在CSDN上打包下载,不过更新会慢一些
视频颠倒的问题
其实,不要更新mSTMatrix,将他设为单位阵,一般就会显示正常的视频。。
在使用mSTMatrix的情况下,解决方法就是修改顶点数组或者修改纹理数组,我们采用修改顶点数组的方案:
private final float[] vertexData = {
1f,-1f,0f,
-1f,-1f,0f,
1f,1f,0f,
-1f,1f,0f
};
屏幕尺寸自适应
如何才能让显示出来的宽高比符合视频的宽高比呢? 答案依然是正交投影!
但是有一些不同,因为我们现在有两个尺寸,一个是屏幕的宽高,一个是视频的宽高,在之前显示图片的时候,我们直接采用了把图片去掉一部分,以适应”绘制一个正方形区域”的要求,那有没有更好的解决方案呢?
分析一下吧,其实无非就两种情况:
- 屏幕宽高比小于视频宽高比,如图:
- 屏幕宽高比大于视频宽高比,如图:
其中,蓝色的是我们的视频区域,蓝色坐标轴是OpenGL屏幕坐标轴,黄色的是纹理坐标轴,注意,我将所有的规范坐标都放到了视频的四个角落,这是因为我们要保证视频完全显示,不变形并且最大化的显示,而我们的纹理坐标和顶点坐标就是像这四个顶点描述的这样子。
这两种情况,只要搞定一种,另外一种也就很容易推导出来了。
获取视频尺寸
获取视频的尺寸可以设置一个监听器:
mediaPlayer.setOnVideoSizeChangedListener(this);
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.d(TAG, "onVideoSizeChanged: "+width+" "+height);
updateProjection(width,height);
}
之前提过,屏幕尺寸是在onSurfaceCreated获取的。
有了这两个尺寸,我们就可以更新Projection矩阵了,代码可能有些难以理解,对于videoRatio>screenRatio,其实就是我们是将videoHeight/videoWidth
当做一个单位来处理(因为之前的坐标映射),然后我们用screenHeight/screenWidth
再去除这个单位,来获得屏幕Y轴方向应该有的范围
private void updateProjection(int videoWidth, int videoHeight){
float screenRatio=(float)screenWidth/screenHeight;
float videoRatio=(float)videoWidth/videoHeight;
if (videoRatio>screenRatio){
Matrix.orthoM(projectionMatrix,0,-1f,1f,-videoRatio/screenRatio,videoRatio/screenRatio,-1f,1f);
}else Matrix.orthoM(projectionMatrix,0,-screenRatio/videoRatio,screenRatio/videoRatio,-1f,1f,-1f,1f);
}
屏幕比例16:10,第一个视频比例4:3,第二个视频比例2:1
MediaPlayer和GLSurfaceView生命周期控制
首先,主活动的生命周期中和GLSurfaceView主要有两个,和MediaPlayer相关的有三个,我们会在后面做播放控制的时候再详细说明。
@Override
protected void onDestroy() {
super.onDestroy();
glRenderer.getMediaPlayer().release();
}
@Override
protected void onPause() {
super.onPause();
glSurfaceView.onPause();
glRenderer.getMediaPlayer().pause();
}
@Override
protected void onResume() {
super.onResume();
glSurfaceView.onResume();
}
顺便贴一下所有的代码
GLRenderer.java
package com.martin.ads.panoramaopengltutorial;
import android.content.Context;