HOME 首頁
SERVICE 服務(wù)產(chǎn)品
XINMEITI 新媒體代運(yùn)營
CASE 服務(wù)案例
NEWS 熱點(diǎn)資訊
ABOUT 關(guān)于我們
CONTACT 聯(lián)系我們
創(chuàng)意嶺
讓品牌有溫度、有情感
專注品牌策劃15年

    渲染方式surfaceview和Tex

    發(fā)布時(shí)間:2023-03-12 08:39:14     稿源: 創(chuàng)意嶺    閱讀: 1021        問大家

    大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關(guān)于渲染方式surfaceview和Tex的問題,以下是小編對此問題的歸納整理,讓我們一起來看看吧。

    創(chuàng)意嶺作為行業(yè)內(nèi)優(yōu)秀的企業(yè),服務(wù)客戶遍布全球各地,相關(guān)業(yè)務(wù)請撥打電話:175-8598-2043,或添加微信:1454722008

    本文目錄:

    渲染方式surfaceview和Tex

    一、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ì)師招聘)

    學(xué)渲染的前景

    微信朋友圈投票怎么弄

    唯品奧萊和唯品自營的區(qū)別(唯品奧萊和唯品自營的區(qū)別在哪里)