博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TextureView+SurfaceTexture+OpenGL ES来播放视频(一)
阅读量:6493 次
发布时间:2019-06-24

本文共 4685 字,大约阅读时间需要 15 分钟。

引自:http://www.ithao123.cn/content-8733143.html

 

最近发现视频直播类应用层出不穷,比如233手游直播,蓝鲸直播,微录客等等什么的,连android界大神老罗也在开发手游录制类的应用,这里面的技术含量也是挺高的,需要了解android 系统的UI渲染机制以及很多系统底层的知识,而我最近也在想好好研究研究android 的UI渲染机制并以此作为深入了解android的入口

 

好了,在讲代码实现之前,我先讲讲TextureView, SurfaceTexture,OpenGL ES都是些什么鬼东西,我又是怎么使用这几个东西来显示一个视频的。

TextureView 顾名思义也就是一个继承了View的一个View控件而已,官网的解释是这样的: 

A TextureView can be used to display a content stream. Such a content stream can for instance be a video or an OpenGL scene. The content stream can come from the application’s process as well as a remote process. 
它能够去显示一个内容流,比如视频流,OpenGL渲染的场景。这些流可以是本地程序进程也可以是远程进程流,有点绕,我的理解就是,比如既可以是本地视频流,也可以是网络视频流。 
注意的是: TextureView 采用的是硬件加速器去渲染,就类似视频的硬解码跟软解码,一个靠的是GPU解码,一个靠CPU解码。 
那么如何去使用这个TextureView呢? 
OK,现在SurfaceTexture就要上场了,从这两个类的命名我们就知道TextureView重点是View,而SurfaceTexture 重点是Texture它的官网解释: 
Captures frames from an image stream as an OpenGL ES texture.The image stream may come from either camera preview or video decode. 
也就是说它能捕获一个图像流的一帧来作为OpenGL 的texture也就是纹理。这个图片流主要是来自相机的预览或视频的解码。(我想这个特性是不应该可以用来做很多事了)。 
到这儿,texture也有了,那么OpenGL也就可以出来干活了,它能够绑定texture并将其在TextureView上一帧一帧的给绘制出来,就形成了我们所看到视频图像了(具体关于SurfaceTexture、TextureView大家可以参考这里) 
说了这么,是该来点代码来瞧瞧了,好的代码就跟读文学小说一样,那样的优美,并不是说我写的代码很优美啦,这只是追求。。。

代码

先从MainActicity主类开始:

public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener,        MediaPlayer.OnPreparedListener{    /**本地视频的路径*/    public String videoPath = Environment.getExternalStorageDirectory().getPath()+"/aoa.mkv";    private TextureView textureView;    private MediaPlayer mediaPlayer;    /**    * 视频绘制前的配置就发生在这个对象所在类中.    * 真正的绘制工作则在它的子类中VideoTextureSurfaceRenderer    */    private TextureSurfaceRenderer videoRenderer;    private int surfaceWidth;    private int surfaceHeight;    private Surface surface;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        textureView = (TextureView) findViewById(R.id.id_textureview);        //注册一个SurfaceTexture,用于监听SurfaceTexure        textureView.setSurfaceTextureListener(this);    }    /**    * 播放视频的入口,当SurfaceTexure可得到时被调用    */    private void playVideo() {        if (mediaPlayer == null) {            videoRenderer = new VideoTextureSurfaceRenderer(this, textureView.getSurfaceTexture(), surfaceWidth, surfaceHeight);            surface = new Surface(videoRenderer.getSurfaceTexture());            initMediaPlayer();        }    }    private void initMediaPlayer() {        this.mediaPlayer = new MediaPlayer();        try {            mediaPlayer.setDataSource(videoPath);            mediaPlayer.setSurface(surface);            mediaPlayer.prepareAsync();            mediaPlayer.setOnPreparedListener(this);            mediaPlayer.setLooping(true);        } catch (IllegalArgumentException e1) {            // TODO Auto-generated catch block            e1.printStackTrace();        } catch (SecurityException e1) {            // TODO Auto-generated catch block            e1.printStackTrace();        } catch (IllegalStateException e1) {            // TODO Auto-generated catch block            e1.printStackTrace();        } catch (IOException e1) {            // TODO Auto-generated catch block            e1.printStackTrace();        }    }    @Override    public void onPrepared(MediaPlayer mp) {        try {            if (mp != null) {                mp.start(); //视频开始播放了            }        } catch (IllegalStateException e) {            e.printStackTrace();        }    }    @Override    protected void onResume() {        super.onResume();        if (textureView.isAvailable()) {            playVideo();        }    }    @Override    protected void onPause() {        super.onPause();        if (videoRenderer != null) {            videoRenderer.onPause();        }        if (mediaPlayer != null) {            mediaPlayer.release();            mediaPlayer =null;        }    }    @Override    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {        surfaceWidth = width;        surfaceHeight = height;        playVideo();    }    @Override    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {    }    @Override    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {        return false;    }    @Override    public void onSurfaceTextureUpdated(SurfaceTexture surface) {    }}

这就是程序的入口类,关于Mediaplayer是怎么播放时视频源的,我就在此就不说了,这里面其实还有很多东西的,大家可以自行的查查。有一点我需要说说就是,一般MediaPlayer.setSurface(param)里面的参数param都是SurfaceView.SurfaceHolder,而我这儿直接用的是Surface (关于Surface可以参考这里),我这个视频播放与其它的视频播放的区别就在此。这篇先暂时写在这儿啦,后续核心的绘制工作,就后面有空就再写了。上面写的如果有什么问题希望大家能多多指点,感激不尽!

转载地址:http://ilkyo.baihongyu.com/

你可能感兴趣的文章
我的友情链接
查看>>
lnmp
查看>>
我的友情链接
查看>>
老程序员激情澎湃1000KM,祖国大地风光无限美好
查看>>
bash基础特性及基础命令
查看>>
黑马程序员之<hashset,treeset>
查看>>
网络连接相关类
查看>>
不上进的自己
查看>>
bash中花括号展开示例
查看>>
我的友情链接
查看>>
我们应具有的为人处事态度
查看>>
安卓机器人中的即时通讯
查看>>
机器学习-GBDT算法总结与源码分析
查看>>
后台开发应该读的书
查看>>
单点登录sso原理
查看>>
给一个不多于5位的整数,判断位数并逆序输出
查看>>
Linux命令行 (一)
查看>>
Java提取字符串中的手机号
查看>>
Linux基础命令---间歇执行程序watch
查看>>
cisco路由器常用命令
查看>>