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();
      }
    }
  }
 // Dequeue and return an output buffer index, -1 if no output
 // buffer available or -2 if error happened.
 private DecoderOutputBufferInfo dequeueOutputBuffer(int dequeueTimeoutUs) {
   checkOnMediaCodecThread();
   try {
     MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
     int result = mediaCodec.dequeueOutputBuffer(info, dequeueTimeoutUs);
     while (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED
         || result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
       if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
         outputBuffers = mediaCodec.getOutputBuffers();
         Logging.d(TAG, "Decoder output buffers changed: " + outputBuffers.length);
       } else if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
         MediaFormat format = mediaCodec.getOutputFormat();
         Logging.d(TAG, "Decoder format changed: " + format.toString());
         width = format.getInteger(MediaFormat.KEY_WIDTH);
         height = format.getInteger(MediaFormat.KEY_HEIGHT);
         if (!useSurface && format.containsKey(MediaFormat.KEY_COLOR_FORMAT)) {
           colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
           Logging.d(TAG, "Color: 0x" + Integer.toHexString(colorFormat));
           // Check if new color space is supported.
           boolean validColorFormat = false;
           for (int supportedColorFormat : supportedColorList) {
             if (colorFormat == supportedColorFormat) {
               validColorFormat = true;
               break;
             }
           }
           if (!validColorFormat) {
             Logging.e(TAG, "Non supported color format");
             return new DecoderOutputBufferInfo(-1, 0, 0, -1);
           }
         }
         if (format.containsKey("stride")) {
           stride = format.getInteger("stride");
         }
         if (format.containsKey("slice-height")) {
           sliceHeight = format.getInteger("slice-height");
         }
         Logging.d(TAG, "Frame stride and slice height: " + stride + " x " + sliceHeight);
         stride = Math.max(width, stride);
         sliceHeight = Math.max(height, sliceHeight);
       }
       result = mediaCodec.dequeueOutputBuffer(info, dequeueTimeoutUs);
     }
     if (result >= 0) {
       return new DecoderOutputBufferInfo(result, info.offset, info.size, info.presentationTimeUs);
     }
     return null;
   } catch (IllegalStateException e) {
     Logging.e(TAG, "dequeueOutputBuffer failed", e);
     return new DecoderOutputBufferInfo(-1, 0, 0, -1);
   }
 }