简单地解释一下安卓的SurfaceView和TextureView:
- SurfaceView是一个可以在子线程中更新UI的View,它有自己的Surface,也就是一块绘图缓冲区,可以直接显示在屏幕上,不受视图层级的影响。SurfaceView适合用于高帧率的场景,如游戏或摄像头预览,但是它不支持动画或变形效果,也不能进行截图。
- TextureView是一个可以像普通View一样进行平移、缩放、旋转等操作的View,它也有自己的SurfaceTexture,也就是一块可以转换为OpenGL ES外部纹理的图像流缓冲区。TextureView可以用于对图像流进行二次处理,如添加滤镜等,也可以进行截图,但是它需要开启硬件加速,而且相比SurfaceView有更高的内存和耗电消耗。
- SurfaceView和TextureView都可以用于播放视频或渲染动画,具体选择哪个要根据需求和性能考虑。一般来说,如果需要高性能和低延迟,可以选择SurfaceView;如果需要更多的视图特性和图像处理能力,可以选择TextureView。
SurfaceView或TextureView渲染视频的基本流程
SurfaceView或TextureView播放视频和渲染动画的流程大致如下:
- 首先,需要创建一个SurfaceView或TextureView的实例,并添加到布局中,设置好宽高和位置等属性。
- 然后,需要获取SurfaceView或TextureView的SurfaceHolder或SurfaceTexture,这是一个用于管理绘图缓冲区的对象,可以通过getHolder()或getSurfaceTexture()方法获取。
- 接着,需要创建一个MediaPlayer的实例,并设置好数据源,如视频文件的路径或网络地址。MediaPlayer是一个用于控制音视频播放的对象,可以通过setDataSource()方法设置数据源。
- 接下来,需要将MediaPlayer和SurfaceHolder或SurfaceTexture关联起来,这样MediaPlayer就可以将视频帧绘制到SurfaceView或TextureView上。可以通过setDisplay()或setSurface()方法实现关联。
- 最后,需要调用MediaPlayer的prepare()或prepareAsync()方法准备播放,并在准备完成后调用start()方法开始播放。可以通过setOnPreparedListener()方法设置一个监听器,在准备完成时回调。
渲染动画的流程和播放视频类似,只是不需要使用MediaPlayer,而是使用自己的绘制逻辑,在子线程中不断地更新SurfaceView或TextureView的内容。具体的绘制逻辑可以根据需求自定义,例如使用Canvas或OpenGL ES等。
自定义绘制逻辑
如果你想自定义绘制逻辑,可以使用OpenGL ES或者Canvas等技术来对视频帧进行处理,例如添加滤镜、水印、动画等效果。可以在SurfaceView或TextureView的绘制线程中实现你的绘制逻辑,或者使用自定义的渲染器类来封装绘制逻辑。
使用TextureView渲染视频并将视频从中间分开,左右两部分叠加在一起绘制的示例代码:
//创建一个TextureView
TextureView textureView = new TextureView(this);
//设置SurfaceTextureListener
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
//创建一个MediaPlayer
MediaPlayer mediaPlayer = new MediaPlayer();
//设置数据源为视频文件的路径或网络地址
mediaPlayer.setDataSource(videoPath);
//设置SurfaceTexture
mediaPlayer.setSurface(new Surface(surface));
//准备播放
mediaPlayer.prepareAsync();
//设置OnPreparedListener
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
//开始播放
mp.start();
}
});
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
//获取当前帧的Bitmap
Bitmap bitmap = textureView.getBitmap();
//将Bitmap从中间分开,左右两部分叠加在一起绘制
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.drawBitmap(bitmap, -bitmap.getWidth() / 2, 0, paint);
//将处理后的Bitmap显示在TextureView上
textureView.draw(canvas);
}
});
最后一次更新于April 3rd, 2024