渲染方式surfaceview和Tex
大家好!今天让创意岭的小编来大家介绍下关于渲染方式surfaceview和Tex的问题,以下是小编对此问题的归纳整理,让我们一起来看看吧。
创意岭作为行业内优秀的企业,服务客户遍布全球各地,相关业务请拨打电话:175-8598-2043,或添加微信:1454722008
本文目录:
一、SurfaceView的简单使用
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
protected Button mBufferBtn;
protected Button mVideoBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_main);
initView();
}
@Override
public void onClick(View view) {
Intent intent = new Intent();
if (view.getId() == R.id.button) {
intent.setClass(this, BufferActivity.class);
} else if (view.getId() == R.id.button) {
intent.setClass(this, VideoActivity.class);
}
startActivity(intent);
}
private void initView() {
mBufferBtn = (Button) findViewById(R.id.button2);
mBufferBtn.setOnClickListener(MainActivity.this);
mVideoBtn = (Button) findViewById(R.id.button2);
mVideoBtn.setOnClickListener(MainActivity.this);
}
}
public class BufferActivity extends AppCompatActivity implements SurfaceHolder.Callback {
protected SurfaceView mSurfaceView;
private SurfaceHolder mHolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_buffer);
initView();
initSurfaceHolder();
}
// 初始化Surface的管理者
private void initSurfaceHolder() {
mHolder = mSurfaceView.getHolder();
// 添加管理生命周期的接口回调
mHolder.addCallback(this);
}
private void initView() {
mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);
}
// 缓冲区创建
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d("1507", "surfaceCreated");
new DrawThread().start();
}
// 缓冲区内容改变(子线程渲染UI的过程)
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d("1507", "surfaceChanged");
}
// 缓冲区销毁
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d("1507", "surfaceDestroyed");
}
// 绘制UI的子线程
private class DrawThread extends Thread {
@Override
public void run() {
super.run();
// 创建画笔
Paint paint = new Paint();
paint.setColor(Color.GREEN);// 画笔颜色
paint.setStrokeWidth(10);// 画笔粗细。注意:Java中设置的尺寸单位都是px
paint.setStyle(Paint.Style.FILL_AND_STROKE);// 设置实心
paint.setAntiAlias(true);// 设置是否抗锯齿
// 获取SurfaceView的盖度
int height = mSurfaceView.getHeight();
Canvas canvas = null;
for (int i = 0; i < height; i+= 5) {
// 获取Surface中的画布
canvas = mHolder.lockCanvas();// 锁定画布
// 使用画笔在画布上绘制指定形状
canvas.drawCircle(100, i + 50, 50, paint);// 圆心x坐标,圆心y坐标,半径,画笔
// 缓冲区的画布绘制完毕,需要解锁并提交给窗口展示
mHolder.unlockCanvasAndPost(canvas);
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
}
}
}
public class VideoActivity extends AppCompatActivity implements View.OnClickListener {
protected MyVideoSurfaceView mSurfaceView;
protected Button mPlayBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_video);
initView();
}
// 运行、可见
@Override
protected void onStart() {
super.onStart();
}
// 可交互
@Override
protected void onResume() {
super.onResume();
}
private void play() {
String videoPath = Environment.getExternalStorageDirectory().getPath() +
"/VID_20171117_144736.3gp";// 外部存储根路径
mSurfaceView.playVideo(videoPath);
}
private void initView() {
mSurfaceView = (MyVideoSurfaceView) findViewById(R.id.surface_view);
mPlayBtn = (Button) findViewById(R.id.play_btn);
mPlayBtn.setOnClickListener(VideoActivity.this);
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.play_btn) {
play();
}
}
}
public class MyVideoSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private MediaPlayer mMediaPlayer;
public MyVideoSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// 获取Surface换朝哪个区的持有者
mHolder = getHolder();
mHolder.addCallback(this);
}
// 设置播放源
public void playVideo(String path) {
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
}
try {
// 设置播放源
mMediaPlayer.setDataSource(path);
// 设置多媒体的显示部分:使用SurfaceHolder渲染画面
mMediaPlayer.setDisplay(mHolder);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}
二、什么是surfaceview?和surface有区别吗
SurfaceView是视图(View)的继承类,这个视图里内嵌了一个专门用于绘制的Surface。你可以控制这个Surface的格式和尺寸。Surfaceview控制这个Surface的绘制位置。
surface是纵深排序(Z-ordered)的,这表明它总在自己所在窗口的后面。surfaceview提供了一个可见区域,只有在这个可见区域内 的surface部分内容才可见,可见区域外的部分不可见。surface的排版显示受到视图层级关系的影响,它的兄弟视图结点会在顶端显示。这意味者 surface的内容会被它的兄弟视图遮挡,这一特性可以用来放置遮盖物(overlays)(例如,文本和按钮等控件)。注意,如果surface上面 有透明控件,那么它的每次变化都会引起框架重新计算它和顶层控件的透明效果,这会影响性能。
你可以通过SurfaceHolder接口访问这个surface,getHolder()方法可以得到这个接口。
三、Android使用surfaceView原生绘制
[TOC]
Activity的View hierachy的树形结构,最顶层的DecorView,也就是根结点视图,在SurfaceFlinger中有对应的Layer。
对于具有SurfaceView的窗口来说,每一个SurfaceView在SurfaceFlinger服务中还对应有一个独立的Layer,用来单独描述它的绘图表面,以区别于它的宿主窗口的绘图表面。
在WMS和SurfaceFlinger中,它与宿主窗口是分离的。这样的好处是对这个Surface的渲染可以放到单独线程去做。这对于一些游戏、视频等性能相关的应用非常有益,因为它不会影响主线程对事件的响应。但它也有缺点,因为这个Surface不在View hierachy中,它的显示也不受View的属性控制,所以不能进行平移,缩放等变换,一些View中的特性也无法使用。
优点:
可以在一个独立的线程中进行绘制,不会影响主线程。
使用双缓冲机制,播放视频时画面更流畅。
缺点:
Surface不在View hierachy中,显示也不受View的属性控制,所以不能进行平移,缩放等变换。
在4.0(API level 14)中引入。和SurfaceView不同,不会在WMS中单独创建窗口,而是作为View hierachy中的一个普通View,因此可以和其它普通View一样进行移动,旋转,缩放,动画等变化。TextureView必须在硬件加速的窗口中。
优点:
支持移动、旋转、缩放等动画,支持截图
缺点:
必须在硬件加速的窗口中使用,占用内存比SurfaceView高(因为开启了硬件加速),可能有1〜3帧延迟。
如果说Surface是画布(画框), SurfaceTexture则是一幅画。可以使用 new Surface(SurfaceTexture) 创建一个Surface。SurfaceTexture并不直接显示图像,而是转为一个外部纹理(图像),用于图像的二次处理。
视频码率就是数据传输时单位时间传送的数据位数,一般我们用的单位是kbps即千位每秒。通俗一点的理解就是取样率,单位时间内取样率越大,精度就越高,处理出来的文件就越接近原始文件。码率和质量成正比,但是文件体积也和码率成正比,即 码率越高越清晰,视频文件越大 。码率率超过一定数值,对图像的质量没有多大影响,因为 原始图像只有那么清晰,再高码率也不会变的比原图更清晰 。
每秒的帧数表示图形处理器处理场时每秒钟能够更新的次数,一般使用fps(Frames per Second)表示。因此帧率越高,画面越流畅。比如Android理论上是16ms一张图像,即60fps。
ANativeWindow代表的是本地窗口,可以看成NDK提供Native版本的Surface。通过 ANativeWindow_fromSurface 获得ANativeWindow指针, ANativeWindow_release 进行释放。类似Java,可以对它进行lock、unlockAndPost以及通过 ANativeWindow_Buffer 进行图像数据的修改。
在NDK中使用ANativeWindow编译时需要链接NDK中的 libandroid.so 库
四、什么是surfaceview?和surface有区别吗
Canvas是Java层构建的数据结构,是给View用的画布。ViewGroup会把自己的Canvas拆分给子View。View会在onDraw方法里将图形数据绘制在它获得的Canvas上。
而Surface是Native层构建的数据结构,是给SurfaceFlinger用的画布。它是直接被用来绘制到屏幕上的数据结构。
开发者一般所用的View都是在Canvas进行绘制,然后最顶层的View(通常是DecorView)的Canvas的数据信息会转换到一个Surface上。SurfaceFlinger会将各个应用窗口的Surface进行合成,然后绘制到屏幕上(实际上是一个Buffer,但一般开发者不用考虑这些,所以省略一些概念)。
那为什么会有一个SurfaceView呢?
这是因为View的测量(Measure),布局(Layout)以及绘制(Draw)的计算量比较大。计算完以后再从Canvas转换成Surface中数据,然后再绘制屏幕,这个流程比较耗时。对于常规的UI绘制不会有什么问题,但是像Camera的预览以及视频的播放这样的应用场景来说就不可接受了。
SurfaceView就是为了解决这个问题。SurfaceView内容不再是绘制在Canvas上,而是直接绘制在其持有的一个Surface上。由于省去了很多步骤,其绘制性能大大提高。而SurfaceView本身只是用来控制这个Surface的大小和位置而已。
以上就是关于渲染方式surfaceview和Tex相关问题的回答。希望能帮到你,如有更多相关问题,您也可以联系我们的客服进行咨询,客服也会为您讲解更多精彩的知识和内容。
推荐阅读: