-
當(dāng)前位置:首頁 > 創(chuàng)意學(xué)院 > 營銷推廣 > 專題列表 > 正文
渲染方式surfaceview和Tex
大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關(guān)于渲染方式surfaceview和Tex的問題,以下是小編對此問題的歸納整理,讓我們一起來看看吧。
創(chuàng)意嶺作為行業(yè)內(nèi)優(yōu)秀的企業(yè),服務(wù)客戶遍布全球各地,相關(guān)業(yè)務(wù)請撥打電話: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();
// 添加管理生命周期的接口回調(diào)
mHolder.addCallback(this);
}
private void initView() {
mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);
}
// 緩沖區(qū)創(chuàng)建
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d("1507", "surfaceCreated");
new DrawThread().start();
}
// 緩沖區(qū)內(nèi)容改變(子線程渲染UI的過程)
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d("1507", "surfaceChanged");
}
// 緩沖區(qū)銷毀
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d("1507", "surfaceDestroyed");
}
// 繪制UI的子線程
private class DrawThread extends Thread {
@Override
public void run() {
super.run();
// 創(chuàng)建畫筆
Paint paint = new Paint();
paint.setColor(Color.GREEN);// 畫筆顏色
paint.setStrokeWidth(10);// 畫筆粗細(xì)。注意:Java中設(shè)置的尺寸單位都是px
paint.setStyle(Paint.Style.FILL_AND_STROKE);// 設(shè)置實(shí)心
paint.setAntiAlias(true);// 設(shè)置是否抗鋸齒
// 獲取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坐標(biāo),圓心y坐標(biāo),半徑,畫筆
// 緩沖區(qū)的畫布繪制完畢,需要解鎖并提交給窗口展示
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();
}
// 運(yùn)行、可見
@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換朝哪個(gè)區(qū)的持有者
mHolder = getHolder();
mHolder.addCallback(this);
}
// 設(shè)置播放源
public void playVideo(String path) {
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
}
try {
// 設(shè)置播放源
mMediaPlayer.setDataSource(path);
// 設(shè)置多媒體的顯示部分:使用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有區(qū)別嗎
SurfaceView是視圖(View)的繼承類,這個(gè)視圖里內(nèi)嵌了一個(gè)專門用于繪制的Surface。你可以控制這個(gè)Surface的格式和尺寸。Surfaceview控制這個(gè)Surface的繪制位置。
surface是縱深排序(Z-ordered)的,這表明它總在自己所在窗口的后面。surfaceview提供了一個(gè)可見區(qū)域,只有在這個(gè)可見區(qū)域內(nèi) 的surface部分內(nèi)容才可見,可見區(qū)域外的部分不可見。surface的排版顯示受到視圖層級關(guān)系的影響,它的兄弟視圖結(jié)點(diǎn)會在頂端顯示。這意味者 surface的內(nèi)容會被它的兄弟視圖遮擋,這一特性可以用來放置遮蓋物(overlays)(例如,文本和按鈕等控件)。注意,如果surface上面 有透明控件,那么它的每次變化都會引起框架重新計(jì)算它和頂層控件的透明效果,這會影響性能。
你可以通過SurfaceHolder接口訪問這個(gè)surface,getHolder()方法可以得到這個(gè)接口。
三、Android使用surfaceView原生繪制
[TOC]
Activity的View hierachy的樹形結(jié)構(gòu),最頂層的DecorView,也就是根結(jié)點(diǎn)視圖,在SurfaceFlinger中有對應(yīng)的Layer。
對于具有SurfaceView的窗口來說,每一個(gè)SurfaceView在SurfaceFlinger服務(wù)中還對應(yīng)有一個(gè)獨(dú)立的Layer,用來單獨(dú)描述它的繪圖表面,以區(qū)別于它的宿主窗口的繪圖表面。
在WMS和SurfaceFlinger中,它與宿主窗口是分離的。這樣的好處是對這個(gè)Surface的渲染可以放到單獨(dú)線程去做。這對于一些游戲、視頻等性能相關(guān)的應(yīng)用非常有益,因?yàn)樗粫绊懼骶€程對事件的響應(yīng)。但它也有缺點(diǎn),因?yàn)檫@個(gè)Surface不在View hierachy中,它的顯示也不受View的屬性控制,所以不能進(jìn)行平移,縮放等變換,一些View中的特性也無法使用。
優(yōu)點(diǎn):
可以在一個(gè)獨(dú)立的線程中進(jìn)行繪制,不會影響主線程。
使用雙緩沖機(jī)制,播放視頻時(shí)畫面更流暢。
缺點(diǎn):
Surface不在View hierachy中,顯示也不受View的屬性控制,所以不能進(jìn)行平移,縮放等變換。
在4.0(API level 14)中引入。和SurfaceView不同,不會在WMS中單獨(dú)創(chuàng)建窗口,而是作為View hierachy中的一個(gè)普通View,因此可以和其它普通View一樣進(jìn)行移動,旋轉(zhuǎn),縮放,動畫等變化。TextureView必須在硬件加速的窗口中。
優(yōu)點(diǎn):
支持移動、旋轉(zhuǎn)、縮放等動畫,支持截圖
缺點(diǎn):
必須在硬件加速的窗口中使用,占用內(nèi)存比SurfaceView高(因?yàn)殚_啟了硬件加速),可能有1〜3幀延遲。
如果說Surface是畫布(畫框), SurfaceTexture則是一幅畫??梢允褂?new Surface(SurfaceTexture) 創(chuàng)建一個(gè)Surface。SurfaceTexture并不直接顯示圖像,而是轉(zhuǎn)為一個(gè)外部紋理(圖像),用于圖像的二次處理。
視頻碼率就是數(shù)據(jù)傳輸時(shí)單位時(shí)間傳送的數(shù)據(jù)位數(shù),一般我們用的單位是kbps即千位每秒。通俗一點(diǎn)的理解就是取樣率,單位時(shí)間內(nèi)取樣率越大,精度就越高,處理出來的文件就越接近原始文件。碼率和質(zhì)量成正比,但是文件體積也和碼率成正比,即 碼率越高越清晰,視頻文件越大 。碼率率超過一定數(shù)值,對圖像的質(zhì)量沒有多大影響,因?yàn)?原始圖像只有那么清晰,再高碼率也不會變的比原圖更清晰 。
每秒的幀數(shù)表示圖形處理器處理場時(shí)每秒鐘能夠更新的次數(shù),一般使用fps(Frames per Second)表示。因此幀率越高,畫面越流暢。比如Android理論上是16ms一張圖像,即60fps。
ANativeWindow代表的是本地窗口,可以看成NDK提供Native版本的Surface。通過 ANativeWindow_fromSurface 獲得ANativeWindow指針, ANativeWindow_release 進(jìn)行釋放。類似Java,可以對它進(jìn)行l(wèi)ock、unlockAndPost以及通過 ANativeWindow_Buffer 進(jìn)行圖像數(shù)據(jù)的修改。
在NDK中使用ANativeWindow編譯時(shí)需要鏈接NDK中的 libandroid.so 庫
四、什么是surfaceview?和surface有區(qū)別嗎
Canvas是Java層構(gòu)建的數(shù)據(jù)結(jié)構(gòu),是給View用的畫布。ViewGroup會把自己的Canvas拆分給子View。View會在onDraw方法里將圖形數(shù)據(jù)繪制在它獲得的Canvas上。
而Surface是Native層構(gòu)建的數(shù)據(jù)結(jié)構(gòu),是給SurfaceFlinger用的畫布。它是直接被用來繪制到屏幕上的數(shù)據(jù)結(jié)構(gòu)。
開發(fā)者一般所用的View都是在Canvas進(jìn)行繪制,然后最頂層的View(通常是DecorView)的Canvas的數(shù)據(jù)信息會轉(zhuǎn)換到一個(gè)Surface上。SurfaceFlinger會將各個(gè)應(yīng)用窗口的Surface進(jìn)行合成,然后繪制到屏幕上(實(shí)際上是一個(gè)Buffer,但一般開發(fā)者不用考慮這些,所以省略一些概念)。
那為什么會有一個(gè)SurfaceView呢?
這是因?yàn)閂iew的測量(Measure),布局(Layout)以及繪制(Draw)的計(jì)算量比較大。計(jì)算完以后再從Canvas轉(zhuǎn)換成Surface中數(shù)據(jù),然后再繪制屏幕,這個(gè)流程比較耗時(shí)。對于常規(guī)的UI繪制不會有什么問題,但是像Camera的預(yù)覽以及視頻的播放這樣的應(yīng)用場景來說就不可接受了。
SurfaceView就是為了解決這個(gè)問題。SurfaceView內(nèi)容不再是繪制在Canvas上,而是直接繪制在其持有的一個(gè)Surface上。由于省去了很多步驟,其繪制性能大大提高。而SurfaceView本身只是用來控制這個(gè)Surface的大小和位置而已。
以上就是關(guān)于渲染方式surfaceview和Tex相關(guān)問題的回答。希望能幫到你,如有更多相關(guān)問題,您也可以聯(lián)系我們的客服進(jìn)行咨詢,客服也會為您講解更多精彩的知識和內(nèi)容。
推薦閱讀:
渲染和不渲染的區(qū)別圖片對比(3d建模師一個(gè)月的真實(shí)收入)
渲染設(shè)計(jì)師(渲染設(shè)計(jì)師招聘)
唯品奧萊和唯品自營的區(qū)別(唯品奧萊和唯品自營的區(qū)別在哪里)