2015-10-22 1 views
8

Ogni volta che sospendo la mia attività (in realtà Frammento) per passare a un'altra app, al ritorno con onResume cerco di riprendere la riproduzione del video ma non viene riprodotto: ottengo uno spazio vuoto schermo. Dopo alcune indagini, vedo quanto segue nella LogcatBufferQueue è stato abbandonato: durante la riproduzione di video con TextureView

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 

Ecco il codice che io chiamo dentro il curriculum

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

FYI: Ho cercato di applicare questa risposta al mio caso, ma non posso 't: What can I do when the BufferQueue has been abandoned?

UPDATE

ho faticato a fare da soli, ma io sono ancora in crash. Così mi metto l'intero codice di aiuto

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

 
 } 
+0

Se la superficie del display sta andando via quando si passa attività allora avrete bisogno di chiamare SetDisplay()/setSurface() con la nuova superficie. – fadden

+0

Non riesco a capirlo. Ho messo 'mediaPlayer.setSurface (surface);' proprio prima della porzione seek non funzionava ancora. Inoltre ho provato qualche altra roba. – learner

+0

Hai passato un nuovo Surface dal nuovo TextureView? – fadden

risposta

8

Ho avuto lo stesso problema quando passa tra le attività e ha avuto anche MediaPlayer (1971): Errore (100,0). Risolto con l'aggiunta di queste righe all'interno onSurfaceTextureDestroyed

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

Grazie amico, questo l'ha risolto per me – josemigallas

0

Sembra che ci sia un bug nel codice: in SurfaceTextureDestroyed() non è stato reimpostato superficie o MediaPlayer. Quando riprendi, né mediaPlayer né superficie sono nulli, quindi in resumeVideoUponReturningFromAnotherActivity() imposta la superficie e l'inizio della chiamata, ma la superficie diventa già non valida a causa di SurfaceTextureDestroyed precedente. Ecco perché ottieni un errore.

Per risolvere il problema, è necessario ripristinare la superficie in richiamata SurfaceTextureDestroyed. Quando riprendi, ricostruisci la superficie in callback SurfaceTextureDisponibile, impostala su mediaPlayer e chiama start to play. I codici sono:

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

E non è necessario ripristinare il lettore multimediale. Se si ripristina, è necessario riattivarlo e reimpostare il buffer, il che causa un ritardo, questo danneggia l'esperienza dell'utente perché nessuna pausa/ripresa ritardata è più desiderata.

0

Trovo che lo setSurface(null) sia utile.

Se si utilizza un TextureView per visualizzare qualcosa, quando TextureView.SurfaceTextureListener callback onSurfaceTextureDestroyed è stato chiamato, è necessario interrompere l'uso SurfaceTexture/new Surface(SurfaceTexture) binded da camera2, MediaCodec o MediaPlayer.

Ti piace questa

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