MediaPlayer: 在不同控件之间实现视频的无缝切换的方法

最近使用MediaPlayer + TextureView 实现了一个视频播放器,并且实现了它的横竖屏切换的效果,唯一美中不足的是在横竖屏切换的时候画面会卡顿一下,虽然也不影响播放,但是怕测试会报Bug,到时候还得自己解决,所以就先把这个问题处理下,并记录之:

TextureView的监听方法有以下四个:

复制代码
  @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {

    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

    }
复制代码

我们一般是在 onSurfaceTextureAvailable() 方法里面取得 SurfaceTexture 并包装成一个 Surface 再调用MediaPlayer的 setSurface 方法完成播放器的显示工作,然而在横竖屏切换的时候,由于当前TextureView所在的ViewGroup会把该TextureView remove掉,这里便触发了TextureView的 onSurfaceTextureDestroyed 方法,然后在横屏窗口中,由于需要重新添加TextureView以便于显示,所以这里又调用了 onSurfaceTextureAvailable 方法,我最开始的做法是这样的:

mSurface = new Surface(surfaceTexture);

然后传递给MediaPlayer, 由于在横竖屏切换时给MediaPlayer传递了两个不同的Surface,因此导致了这个问题,那么解决问题的方法也很简单,只要保存SurfaceTexture, 保证横竖屏切换时使用同一个Surface即可:

复制代码
@Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
        if (mSurfaceTexture == null) {
            mSurfaceTexture = surfaceTexture;
            openMediaPlayer();
        } else {
            mTextureView.setSurfaceTexture(mSurfaceTexture);
        }
    }
复制代码

这里将SurfaceTexture保存为一个成员变量,在使用前对其进行判断,保证使用的是同一个SurfaceTexture,也可以在

@Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
      Log.d(TAG, "onSurfaceTextureDestroyed: ");
      mSurfaceTexture = surface;
      return false;
    }

也可以在 onSurfaceTextureDestroyed 方法中保存,不过不管在哪个方法中保存这个SurfaceTexture, 都需要注意 onSurfaceTextureDestroyed 方法的返回值必须为false, 官方API的解释说明如下:

Invoked when the specified SurfaceTexture is about to be destroyed. If returns true, no rendering should happen inside the surface texture after this method is invoked. If returns false, the client needs to call release(). Most applications should return true.

大致的意思是如果返回ture,SurfaceTexture会自动销毁,如果返回false,SurfaceTexture不会销毁,需要用户手动调用release()进行销毁。
所以我们在销毁的时候返回false,并保存SurfaceTexture对象,然后在切换成全屏的时候在onSurfaceTextureAvailable()方法中,调用setSurfaceTexture(mSurfaceTexture)方法,这样就恢复之前的画面了。
另外,TextureView的生命周期为:
  • 切换至后台的时候会调用onSurfaceTextureDestroyed,从后台切换回来会调用onSurfaceTextureAvailable。
  • TextureView的ViewGroup remove TextureView的时候会调用onSurfaceTextureDestroyed方法。相同,TextureView的ViewGroup add TextureView的时候会调用onSurfaceTextureAvailable。这些都是建立在视图可见的基础上,如果视图不可见,add也不会调用onSurfaceTextureAvailable方法,remove也不会调用onSurfaceTextureDestroyed方法。
  • 当TextureView设置为Gone的时候,并不会调用onSurfaceTextureDestroyed方法法。
参考链接:
 
 


如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   夜行过客  阅读(3592)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示