public void stop() {
   if (mPlaybackThread != null) {
     mPlaybackThread.interrupt();
     mPlaybackThread = null;
   }
   stayAwake(false);
 }
  public void seekTo(long usec) {
    /* A seek needs to be performed in the decoding thread to execute commands in the correct
     * order. Otherwise it can happen that, after a seek in the media decoder, seeking procedure
     * starts, then a frame is decoded, and then the codec is flushed; the PTS of the decoded frame
     * then interferes the seeking procedure, the seek stops prematurely and a wrong waiting time
     * gets calculated. */

    // inform the decoder thread of an upcoming seek
    mSeekPrepare = true;
    mSeekTargetTime = Math.max(mVideoMinPTS, usec);

    // if the decoder is paused, wake it up for the seek
    if (mPlaybackThread.isPaused()) {
      mPlaybackThread.play();
      mPlaybackThread.pause();
    }
  }
  public void setDataSource(MediaSource source) throws IOException {
    mVideoExtractor = source.getVideoExtractor();
    mAudioExtractor = source.getAudioExtractor();

    mVideoTrackIndex = -1;
    mAudioTrackIndex = -1;

    for (int i = 0; i < mVideoExtractor.getTrackCount(); ++i) {
      MediaFormat format = mVideoExtractor.getTrackFormat(i);
      Log.d(TAG, format.toString());
      String mime = format.getString(MediaFormat.KEY_MIME);
      if (mVideoTrackIndex < 0 && mime.startsWith("video/")) {
        mVideoExtractor.selectTrack(i);
        mVideoTrackIndex = i;
        mVideoFormat = format;
        mVideoMinPTS = mVideoExtractor.getSampleTime();
      } else if (mAudioExtractor == null && mAudioTrackIndex < 0 && mime.startsWith("audio/")) {
        mVideoExtractor.selectTrack(i);
        mAudioTrackIndex = i;
        mAudioFormat = format;
        mAudioMinPTS = mVideoExtractor.getSampleTime();
      }
    }

    if (mAudioExtractor != null) {
      for (int i = 0; i < mAudioExtractor.getTrackCount(); ++i) {
        MediaFormat format = mAudioExtractor.getTrackFormat(i);
        Log.d(TAG, format.toString());
        String mime = format.getString(MediaFormat.KEY_MIME);
        if (mAudioTrackIndex < 0 && mime.startsWith("audio/")) {
          mAudioExtractor.selectTrack(i);
          mAudioTrackIndex = i;
          mAudioFormat = format;
          mAudioMinPTS = mAudioExtractor.getSampleTime();
        }
      }
    }

    if (mVideoFormat == null) {
      throw new IOException("no video track found");
    } else {
      if (mAudioFormat == null) {
        Log.i(TAG, "no audio track found");
      }
      if (mPlaybackThread == null) {
        if (mSurface == null) {
          Log.i(TAG, "no video output surface specified");
        }

        mPlaybackThread = new PlaybackThread();
        mPlaybackThread.start();
      }
    }
  }
 public boolean isPlaying() {
   return mPlaybackThread != null && !mPlaybackThread.isPaused();
 }
 public void pause() {
   mPlaybackThread.pause();
   stayAwake(false);
 }
 public void start() {
   mPlaybackThread.play();
   stayAwake(true);
 }