BufferQueue已被放弃:当使用TextureView播放video时

每当我暂停我的活动(实际上是Fragment)去另一个应用程序,一旦返回onResume我尝试恢复video播放,但它不播放:我得到一个空白的屏幕。 经过调查,我在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 

这里是我在简历中调用的代码

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

仅供参考:我一直在尝试将这个答案应用于我的案例,但是我不能: 当BufferQueue被放弃时我该怎么办?

UPDATE

我努力独自一人,但我仍然崩溃。 所以我张贴整个代码的帮助

 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();  } 

Solutions Collecting From Web of "BufferQueue已被放弃:当使用TextureView播放video时"

当在活动之间切换时,我也遇到了同样的问题,并且MediaPlayer(1971):Error(100,0)。 通过在onSurfaceTextureDestroyed中添加这些行来解决这个问题

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

看起来你的代码中有一个bug:在SurfaceTextureDestroyed()你没有重置表面或mediaPlayer。 当resume时,mediaPlayer和surface都不为null,所以在resumeVideoUponReturningFromAnotherActivity()设置表面并调用开始播放,但由于之前的SurfaceTextureDestroyed表面已经变为无效。 这就是为什么你会得到错误。

要修复它,你应该在callbackSurfaceTextureDestroyed中重置曲面。 当恢复时,在callbackSurfaceTextureAvailable中重build曲面,将其设置为mediaPlayer并调用开始播放。 代码是这样的:

 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; } 

而且你根本不需要重置媒体播放器。 如果重置,则必须重新实例化并重新缓冲,这会导致延迟,这会损害用户体验,因为不需要延迟暂停/恢复。

我发现setSurface(null)是有用的。

如果使用TextureView显示某些内容,则在TextureView.SurfaceTextureListenercallbackonSurfaceTextureDestroyed时,必须停止使用由camera2MediaCodecMediaPlayer绑定的camera2 SurfaceTexture/new Surface(SurfaceTexture)

喜欢这个

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