openGL ES 在android中将mp4视频格式转换为RGB图像的代码解析
时间: 2024-02-27 16:52:56 浏览: 215
OpenGL ES Android
首先,将 mp4 视频文件加载进来,可以使用 Android 系统提供的 MediaPlayer 类来实现。
```java
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(videoFilePath);
mediaPlayer.prepare();
mediaPlayer.start();
```
然后,创建一个 SurfaceView 用于显示视频画面,同时获取该 SurfaceView 的 SurfaceHolder 对象,以及该 SurfaceView 的宽高信息。
```java
SurfaceView surfaceView = new SurfaceView(context);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
mediaPlayer.setDisplay(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// 获取 SurfaceView 的宽高信息
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
```
接下来,创建一个 OpenGL ES 的上下文环境,并初始化纹理、着色器等信息。
```java
EGLContext eglContext = EGL14.eglGetCurrentContext();
EGLDisplay eglDisplay = EGL14.eglGetCurrentDisplay();
EGLSurface eglSurface = EGL14.eglGetCurrentSurface(EGL14.EGL_DRAW);
int[] attribList = {
EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
EGL14.EGL_SURFACE_TYPE, EGL14.EGL_PBUFFER_BIT,
EGL14.EGL_RED_SIZE, 8,
EGL14.EGL_GREEN_SIZE, 8,
EGL14.EGL_BLUE_SIZE, 8,
EGL14.EGL_ALPHA_SIZE, 8,
EGL14.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1];
int[] numConfigs = new int[1];
EGL14.eglChooseConfig(eglDisplay, attribList, 0, configs, 0, configs.length, numConfigs, 0);
int[] attribList2 = {
EGL14.EGL_WIDTH, surfaceWidth,
EGL14.EGL_HEIGHT, surfaceHeight,
EGL14.EGL_NONE
};
EGLSurface eglSurface2 = EGL14.eglCreatePbufferSurface(eglDisplay, configs[0], attribList2, 0);
EGL14.eglMakeCurrent(eglDisplay, eglSurface2, eglSurface2, eglContext);
int[] textureIds = new int[1];
GLES20.glGenTextures(1, textureIds, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
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);
```
接着,通过 MediaPlayer 的 onFrameAvailableListener 回调函数获取视频的每一帧数据,并将其转换为 RGB 图像。
```java
mediaPlayer.setSurface(surfaceHolder.getSurface());
mediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
// 更新视频宽高信息
}
});
mediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
@Override
public void onSeekComplete(MediaPlayer mp) {
// 重新开始播放视频
mediaPlayer.start();
}
});
final float[] textureTransformMatrix = new float[16];
SurfaceTexture surfaceTexture = new SurfaceTexture(textureIds[0]);
surfaceTexture.setDefaultBufferSize(videoWidth, videoHeight);
surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
surfaceTexture.getTransformMatrix(textureTransformMatrix);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[0]);
surfaceTexture.updateTexImage();
ByteBuffer pixelBuffer = ByteBuffer.allocateDirect(videoWidth * videoHeight * 4);
pixelBuffer.order(ByteOrder.LITTLE_ENDIAN);
GLES20.glReadPixels(0, 0, videoWidth, videoHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixelBuffer);
pixelBuffer.rewind();
byte[] pixelArray = new byte[videoWidth * videoHeight * 3];
int index = 0;
while (pixelBuffer.hasRemaining()) {
pixelArray[index++] = pixelBuffer.get();
pixelArray[index++] = pixelBuffer.get();
pixelArray[index++] = pixelBuffer.get();
pixelBuffer.get();
}
// 处理 RGB 图像数据
}
});
```
最后,需要在程序退出时释放资源。
```java
surfaceTexture.release();
EGL14.eglMakeCurrent(eglDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
EGL14.eglDestroySurface(eglDisplay, eglSurface2);
EGL14.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
GLES20.glDeleteTextures(1, textureIds, 0);
mediaPlayer.stop();
mediaPlayer.release();
```
阅读全文