BufferQueue has been abandoned: When playing video with TextureView

浪子不回头ぞ 提交于 2019-11-29 04:02:02

问题


Every time I pause my activity (actually Fragment) to go to another app, upon returning with onResume I try to resume the video playing but it does not play: I get a blank screen. Upon investigation, I see the following in the Logcat

E/BufferQueueProducer: [unnamed-23827-0] queueBuffer: BufferQueue has been abandoned
E/MediaPlayer: error (1, -38)
E/MediaPlayer: error (1, -38)
E/MediaPlayer: error (1, -38)
E/MediaPlayer: error (1, -38)
E/BufferQueueProducer: [unnamed-23827-0] connect(P): BufferQueue has been abandoned

Here is the code I call inside on resume

player.seekTo(mVideoSeekPosition);
player.start();

FYI: I have been trying to apply this answer to my case, but I can't: What can I do when the BufferQueue has been abandoned?

UPDATE

I struggled to go it alone, but I am still crashing. So I am posting the whole code for help

private void setupVideoPlayingSystem(View root) {
  textureView = (TextureView) root.findViewById(R.id.textureView);
    
  textureView.setSurfaceTextureListener(this);
}
    
    
    

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
  Log.d(TAG, "onSurfaceTextureAvailable");
  if (null == surface) {
    Log.d(TAG, "new surface");
    surface = new Surface(surfaceTexture);
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setSurface(surface);
    mediaPlayer.setLooping(false);
  }
    
  /*
    
  outstandingVideoRequest is IOU for orentation change (verifed: onResume before onSurfaceTextureAvailable)
  but for cold startup, must check mVideoUrl
  */
    
  if (outstandingVideoRequest && null != mVideoUrl) {
    
    outstandingVideoRequest = false;

        playNewVideo(mVideoUrl);
  }
    
}
    
    

@Override
    
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
    
  Log.d(TAG, "onSurfaceTextureSizeChanged");

    }
    
    

@Override

    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
    
  Log.d(TAG, "onSurfaceTextureDestroyed");
  return false;//leave destruction for onDestroy
    
}

@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        }
    

    private void playNewVideo(String url) {
        
      if (null == mediaPlayer || null == surface) {
        
        Log.d(TAG, "playNewVideo not ready");
    
            synchronized (outstandingVideoRequest) {
    
              Log.d(TAG, "playNewVideo outstandingVideoRequest");
    
               outstandingVideoRequest = true;
        }
         
      } else {
        
        try {
        
          mediaPlayer.reset();
        
          mediaPlayer.setDataSource(getContext(), Uri.parse(url));
        
          mediaPlayer.setLooping(false);
        
          mediaPlayer.prepareAsync();
         
          mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

            @Override
        
            public void onPrepared(MediaPlayer player) {
        
              Log.d(TAG, "onPrepared changeMediaPlayerDatasource");
        
              onReadyToPlay(player);
            }
        
          });
        
       } catch (Exception e) {//IOException && IllegalStateException
        
         Log.d(TAG, "textureview playNewVideo ERORR");
        
         e.printStackTrace();
        
       }
        
        
     }
        
    }

  private void resumeVideoUponReturningFromAnotherActivity() {

            if (null == mediaPlayer || null == surface) {

                Log.d(TAG, "resumeVideoUponReturningFromAnotherActivity outstandingVideoRequest");

                outstandingVideoRequest = true;
    
        } else {
    
//            playNewVideo(mVideoUrl);

                Log.d(TAG, "resumeVideoUponReturningFromAnotherActivity go NOW");

                mediaPlayer.setSurface(surface);
    
            onReadyToPlay(mediaPlayer);

            }
    
    
    }
    
    

    private void onReadyToPlay(MediaPlayer player) {
    
        //play video
    
        mProgressCircle.setVisibility(View.GONE);

            showVideoOverlayChildren();
    
        if (0 == mVideoSeekPosition) {
    
            Log.d(TAG, "onReadyToPlay start");

                player.start();

            } else {
    
            Log.d(TAG, "onReadyToPlay seek");

                player.seekTo(mVideoSeekPosition);
     
           player.start();

            }
    
        mHandler.postDelayed(new Runnable() {

                @Override

                public void run() {

                    Log.d(TAG, "postDelayed resumeVideo");
    
                hideVideoOverlayChildren();

                }
    
        }, Constant.BEFORE_VIDEO_OVERLAY_DISAPPEAR);

        }


    
        private void destroyMediaPlayer() {

            if (null != mediaPlayer) {//move to video todo
    
            mediaPlayer.stop();

                mediaPlayer.release();
    
            mediaPlayer = null;

            }
    
        if (null != surface) {

                surface.release();

                surface = null;
    
        }
    
    }
    
    

    private void pauseVideo() {

            if (null != mediaPlayer) {

                Log.d(TAG, "pause");
    
            mediaPlayer.pause();

                mVideoSeekPosition = mediaPlayer.getCurrentPosition();

            }
    
    }


    
        private void stopVideo(){
    
        if (null != mediaPlayer) {

                Log.d(TAG, "stop video");

                mediaPlayer.pause();

                mVideoSeekPosition = mediaPlayer.getCurrentPosition();

                mediaPlayer.stop();

            }
    
    }

@Override
    public void onResume() {

        super.onResume();

        Log.d(TAG, "onResume");
    
    mLocalBroadcastManager.registerReceiver(mVideoSelectionReceiver, mVideoSelectedIntentFilter);
    
    resumeVideoUponReturningFromAnotherActivity();

    
    }

回答1:


I had the same problem when switched between activities and also had MediaPlayer(1971): Error (100,0). Solved it by adding these lines inside onSurfaceTextureDestroyed

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        if (mediaPlayer != null) {
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
        }
        return true;
    }



回答2:


It seems there is a bug in your code: in SurfaceTextureDestroyed() you did not reset surface or mediaPlayer. When resume, neither mediaPlayer nor surface is null, so in resumeVideoUponReturningFromAnotherActivity() set the surface and call start to play, but surface already become invalid because of previous SurfaceTextureDestroyed. That's why you get error.

To fix it, you should reset surface in callback SurfaceTextureDestroyed. When resume, rebuild surface in callback SurfaceTextureAvailable, set it to mediaPlayer and call start to play. The codes go like this:

public void onResume() {
   if (mSurface == null) {
      mResumeRequested = true;
      return;
   }
   mMediaPlayer.start();
}

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
   mSurface = new Surface(surface);
   if (mMediaPlayer != null) {
      mMediaPlayer.setSurface(mSurface);
      if (mResumeRequested) {
         mMediaPlayer.start();
         mResumeRequested = false;
      }
   }
}

@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
   mSurface = null;
   return false;
}

And you do not have to reset media player at all. If you reset, you have to re-instantiate it and re-buffering, which causes delay, this harms user experience because no delaying pause/resume is more desired.




回答3:


I find setSurface(null) is useful.

If you use a TextureView to display something, when TextureView.SurfaceTextureListener callback onSurfaceTextureDestroyed was called, you must stop use SurfaceTexture/new Surface(SurfaceTexture) binded by camera2, MediaCodec or MediaPlayer.

Like this

@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
   mediaPlayer.setDisplayer(null);
   return false;//do not return true if you reuse it.
}


来源:https://stackoverflow.com/questions/33288303/bufferqueue-has-been-abandoned-when-playing-video-with-textureview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!