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方法法。
參考鏈接:
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM