web-dev-qa-db-fra.com

BufferQueue a été abandonnée: lors de la lecture de vidéos avec TextureView

Chaque fois que je suspends mon activité (en fait Fragment) pour aller à une autre application, à mon retour avec onResume, j'essaie de reprendre la lecture de la vidéo mais la lecture ne se lit pas: je reçois un écran vide. Après enquête, je vois ce qui suit dans le 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

Voici le code que j'ai appelé à l'intérieur sur CV

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

FYI: J'ai essayé d'appliquer cette réponse à mon cas, mais je ne peux pas: Que puis-je faire lorsque la BufferQueue a été abandonnée?

UPDATE

J'ai eu du mal à y aller seul, mais je suis toujours en train de chuter. Donc, je poste le code entier pour l'aide

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

    
    }
8
learner

J'ai eu le même problème lors de la commutation entre les activités et j'avais également MediaPlayer (1971): Erreur (100,0). Résolu en ajoutant ces lignes dans onSurfaceTextureDestroyed

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

Il semble qu'il y ait un bogue dans votre code: dans SurfaceTextureDestroyed (), vous n'avez pas réinitialisé surface ni mediaPlayer. Lors de la reprise, ni mediaPlayer ni la surface ne sont nuls, c’est pourquoi, dans resumeVideoUponReturningFromAnotherActivity (), définissez la surface et le début de la lecture, mais cette surface est déjà invalide en raison de la présence de SurfaceTextureDestroyed. C'est pourquoi vous obtenez une erreur.

Pour résoudre ce problème, vous devez réinitialiser la surface dans callback SurfaceTextureDestroyed. Lorsque vous reprenez, reconstruisez la surface dans le rappel SurfaceTextureAvailable, configurez-le sur mediaPlayer et appelez start à jouer. Les codes vont comme ceci:

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

Et vous n'avez pas du tout besoin de réinitialiser le lecteur multimédia. Si vous réinitialisez l'appareil, vous devez le ré-instancier et le remettre en mémoire tampon, ce qui provoque un délai, ce qui nuit à l'expérience de l'utilisateur car aucun délai de pause/reprise n'est plus souhaité.

0
alexhilton

Je trouve que setSurface(null) est utile.

Si vous utilisez un TextureView pour afficher quelque chose, lorsque TextureView.SurfaceTextureListener callback onSurfaceTextureDestroyed est appelé, vous devez cesser d'utiliser SurfaceTexture/new Surface(SurfaceTexture) lié par camera2, MediaCodec ou MediaPlayer.

Comme ça

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