com.ll.myapplication.vitamio.widget.VideoView.java Source code

Java tutorial

Introduction

Here is the source code for com.ll.myapplication.vitamio.widget.VideoView.java

Source

  /*
   * Copyright (C) 2006 The Android Open Source Project
   * Copyright (C) 2013 YIXIA.COM
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */

  package com.ll.myapplication.vitamio.widget;

  import android.app.Activity;
  import android.app.AlertDialog;
  import android.content.Context;
  import android.content.DialogInterface;
  import android.content.Intent;
  import android.graphics.ImageFormat;
  import android.graphics.PixelFormat;
  import android.media.AudioManager;
  import android.net.Uri;
  import android.os.Build;
  import android.support.v4.graphics.BitmapCompat;
  import android.util.AttributeSet;
  import android.util.Pair;
  import android.util.SparseArray;
  import android.view.KeyEvent;
  import android.view.MotionEvent;
  import android.view.SurfaceHolder;
  import android.view.SurfaceView;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.ViewGroup.LayoutParams;

  import com.ll.myapplication.vitamio.MediaFormat;
  import com.ll.myapplication.vitamio.MediaPlayer;
  import com.ll.myapplication.vitamio.utils.Log;
  import com.ll.myapplication.vitamio.utils.ScreenResolution;

  import java.io.IOException;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;

  /**
   * Displays a video file. The VideoView class can load images from various
   * sources (such as resources or content providers), takes care of computing its
   * measurement from the video so that it can be used in any layout manager, and
   * provides various display options such as scaling and tinting.
   * <p/>
   * VideoView also provide many wrapper methods for
   * {@link com.ll.myapplication.vitamio.MediaPlayer}, such as {@link #getVideoWidth()},
   * {@link #setTimedTextShown(boolean)}
   */
  public class VideoView extends SurfaceView implements MediaController.MediaPlayerControl {
      public static final int VIDEO_LAYOUT_ORIGIN = 0;
      public static final int VIDEO_LAYOUT_SCALE = 1;
      public static final int VIDEO_LAYOUT_STRETCH = 2;
      public static final int VIDEO_LAYOUT_ZOOM = 3;
      public static final int VIDEO_LAYOUT_FIT_PARENT = 4;
      private static final int STATE_ERROR = -1;
      private static final int STATE_IDLE = 0;
      private static final int STATE_PREPARING = 1;
      private static final int STATE_PREPARED = 2;
      private static final int STATE_PLAYING = 3;
      private static final int STATE_PAUSED = 4;
      private static final int STATE_PLAYBACK_COMPLETED = 5;
      private static final int STATE_SUSPEND = 6;
      private static final int STATE_RESUME = 7;
      private static final int STATE_SUSPEND_UNSUPPORTED = 8;
      MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
          public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
              Log.d("onVideoSizeChanged: (%dx%d)", width, height);
              mVideoWidth = mp.getVideoWidth();
              mVideoHeight = mp.getVideoHeight();
              mVideoAspectRatio = mp.getVideoAspectRatio();
              if (mVideoWidth != 0 && mVideoHeight != 0)
                  setVideoLayout(mVideoLayout, mAspectRatio);
          }
      };
      MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
          public void onPrepared(MediaPlayer mp) {
              Log.d("onPrepared");
              mCurrentState = STATE_PREPARED;
              // mTargetState = STATE_PLAYING;

              // Get the capabilities of the player for this stream
              //TODO mCanPause

              if (mOnPreparedListener != null)
                  mOnPreparedListener.onPrepared(mMediaPlayer);
              if (mMediaController != null)
                  mMediaController.setEnabled(true);
              mVideoWidth = mp.getVideoWidth();
              mVideoHeight = mp.getVideoHeight();
              mVideoAspectRatio = mp.getVideoAspectRatio();

              long seekToPosition = mSeekWhenPrepared;
              if (seekToPosition != 0)
                  seekTo(seekToPosition);

              if (mVideoWidth != 0 && mVideoHeight != 0) {
                  setVideoLayout(mVideoLayout, mAspectRatio);
                  if (mSurfaceWidth == mVideoWidth && mSurfaceHeight == mVideoHeight) {
                      if (mTargetState == STATE_PLAYING) {
                          start();
                          if (mMediaController != null)
                              mMediaController.show();
                      } else if (!isPlaying() && (seekToPosition != 0 || getCurrentPosition() > 0)) {
                          if (mMediaController != null)
                              mMediaController.show(0);
                      }
                  }
              } else if (mTargetState == STATE_PLAYING) {
                  start();
              }
          }
      };
      SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() {
          public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
              mSurfaceWidth = w;
              mSurfaceHeight = h;
              boolean isValidState = (mTargetState == STATE_PLAYING);
              boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h);
              if (mMediaPlayer != null && isValidState && hasValidSize) {
                  if (mSeekWhenPrepared != 0)
                      seekTo(mSeekWhenPrepared);
                  start();
                  if (mMediaController != null) {
                      if (mMediaController.isShowing())
                          mMediaController.hide();
                      mMediaController.show();
                  }
              }
          }

          public void surfaceCreated(SurfaceHolder holder) {
              mSurfaceHolder = holder;
              if (mMediaPlayer != null && mCurrentState == STATE_SUSPEND && mTargetState == STATE_RESUME) {
                  mMediaPlayer.setDisplay(mSurfaceHolder);
                  resume();
              } else {
                  openVideo();
              }
          }

          public void surfaceDestroyed(SurfaceHolder holder) {
              mSurfaceHolder = null;
              if (mMediaController != null)
                  mMediaController.hide();
              release(true);
          }
      };
      private Uri mUri;
      private long mDuration;
      private int mCurrentState = STATE_IDLE;
      private int mTargetState = STATE_IDLE;
      private float mAspectRatio = 0;
      private int mVideoLayout = VIDEO_LAYOUT_SCALE;
      private SurfaceHolder mSurfaceHolder = null;
      private MediaPlayer mMediaPlayer = null;
      private int mVideoWidth;
      private int mVideoHeight;
      private float mVideoAspectRatio;
      private int mVideoChroma = MediaPlayer.VIDEOCHROMA_RGBA;
      private boolean mHardwareDecoder = false;
      private int mSurfaceWidth;
      private int mSurfaceHeight;
      private MediaController mMediaController;
      private View mMediaBufferingIndicator;
      private MediaPlayer.OnCompletionListener mOnCompletionListener;
      private MediaPlayer.OnPreparedListener mOnPreparedListener;
      private MediaPlayer.OnErrorListener mOnErrorListener;
      private MediaPlayer.OnSeekCompleteListener mOnSeekCompleteListener;
      private MediaPlayer.OnTimedTextListener mOnTimedTextListener;
      private MediaPlayer.OnInfoListener mOnInfoListener;
      private MediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener;
      private int mCurrentBufferPercentage;
      private long mSeekWhenPrepared; // recording the seek position while preparing
      private Context mContext;
      private Map<String, String> mHeaders;
      private int mBufSize;
      private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
          public void onCompletion(MediaPlayer mp) {
              Log.d("onCompletion");
              mCurrentState = STATE_PLAYBACK_COMPLETED;
              mTargetState = STATE_PLAYBACK_COMPLETED;
              if (mMediaController != null)
                  mMediaController.hide();
              if (mOnCompletionListener != null)
                  mOnCompletionListener.onCompletion(mMediaPlayer);
          }
      };
      private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() {
          public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
              Log.d("Error: %d, %d", framework_err, impl_err);
              mCurrentState = STATE_ERROR;
              mTargetState = STATE_ERROR;
              if (mMediaController != null)
                  mMediaController.hide();

              if (mOnErrorListener != null) {
                  if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err))
                      return true;
              }

              if (getWindowToken() != null) {
                  int message = framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK
                          ? getResources().getIdentifier("VideoView_error_text_invalid_progressive_playback",
                                  "string", mContext.getPackageName())
                          : getResources().getIdentifier("VideoView_error_text_unknown", "string",
                                  mContext.getPackageName());

                  new AlertDialog.Builder(mContext)
                          .setTitle(getResources().getIdentifier("VideoView_error_title", "string",
                                  mContext.getPackageName()))
                          .setMessage(message)
                          .setPositiveButton(getResources().getIdentifier("VideoView_error_button", "string",
                                  mContext.getPackageName()), new DialogInterface.OnClickListener() {
                                      public void onClick(DialogInterface dialog, int whichButton) {
                                          if (mOnCompletionListener != null)
                                              mOnCompletionListener.onCompletion(mMediaPlayer);
                                      }
                                  })
                          .setCancelable(false).show();
              }
              return true;
          }
      };
      private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
          public void onBufferingUpdate(MediaPlayer mp, int percent) {
              mCurrentBufferPercentage = percent;
              if (mOnBufferingUpdateListener != null)
                  mOnBufferingUpdateListener.onBufferingUpdate(mp, percent);
          }
      };
      private MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() {
          @Override
          public boolean onInfo(MediaPlayer mp, int what, int extra) {
              Log.d("onInfo: (%d, %d)", what, extra);

              if (MediaPlayer.MEDIA_INFO_UNKNOW_TYPE == what) {
                  Log.e(" VITAMIO--TYPE_CHECK  stype  not include  onInfo mediaplayer unknow type ");
              }

              if (MediaPlayer.MEDIA_INFO_FILE_OPEN_OK == what) {
                  long buffersize = mMediaPlayer.audioTrackInit();
                  mMediaPlayer.audioInitedOk(buffersize);
              }

              Log.d("onInfo: (%d, %d)", what, extra);

              if (mOnInfoListener != null) {
                  mOnInfoListener.onInfo(mp, what, extra);
              } else if (mMediaPlayer != null) {
                  if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
                      mMediaPlayer.pause();
                      if (mMediaBufferingIndicator != null)
                          mMediaBufferingIndicator.setVisibility(View.VISIBLE);
                  } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
                      mMediaPlayer.start();
                      if (mMediaBufferingIndicator != null)
                          mMediaBufferingIndicator.setVisibility(View.GONE);
                  }
              }
              return true;
          }
      };
      private MediaPlayer.OnSeekCompleteListener mSeekCompleteListener = new MediaPlayer.OnSeekCompleteListener() {
          @Override
          public void onSeekComplete(MediaPlayer mp) {
              Log.d("onSeekComplete");
              if (mOnSeekCompleteListener != null)
                  mOnSeekCompleteListener.onSeekComplete(mp);
          }
      };
      private MediaPlayer.OnTimedTextListener mTimedTextListener = new MediaPlayer.OnTimedTextListener() {
          @Override
          public void onTimedTextUpdate(byte[] pixels, int width, int height) {
              Log.i("onSubtitleUpdate: bitmap subtitle, %dx%d", width, height);
              if (mOnTimedTextListener != null)
                  mOnTimedTextListener.onTimedTextUpdate(pixels, width, height);
          }

          @Override
          public void onTimedText(String text) {
              Log.i("onSubtitleUpdate: %s", text);
              if (mOnTimedTextListener != null)
                  mOnTimedTextListener.onTimedText(text);
          }
      };

      public VideoView(Context context) {
          super(context);
          initVideoView(context);
      }

      public VideoView(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
          initVideoView(context);
      }

      public VideoView(Context context, AttributeSet attrs, int defStyle) {
          super(context, attrs, defStyle);
          initVideoView(context);
      }

      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
          int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
          setMeasuredDimension(width, height);
      }

      /**
       * Set the display options
       *
       * @param layout      <ul>
       *                    <li>{@link #VIDEO_LAYOUT_ORIGIN}
       *                    <li>{@link #VIDEO_LAYOUT_SCALE}
       *                    <li>{@link #VIDEO_LAYOUT_STRETCH}
       *                    <li>{@link #VIDEO_LAYOUT_FIT_PARENT}
       *                    <li>{@link #VIDEO_LAYOUT_ZOOM}
       *                    </ul>
       * @param aspectRatio video aspect ratio, will audo detect if 0.
       */
      public void setVideoLayout(int layout, float aspectRatio) {
          LayoutParams lp = getLayoutParams();
          Pair<Integer, Integer> res = ScreenResolution.getResolution(mContext);
          int windowWidth = res.first.intValue(), windowHeight = res.second.intValue();
          float windowRatio = windowWidth / (float) windowHeight;
          float videoRatio = aspectRatio <= 0.01f ? mVideoAspectRatio : aspectRatio;
          mSurfaceHeight = mVideoHeight;
          mSurfaceWidth = mVideoWidth;
          if (VIDEO_LAYOUT_ORIGIN == layout && mSurfaceWidth < windowWidth && mSurfaceHeight < windowHeight) {
              lp.width = (int) (mSurfaceHeight * videoRatio);
              lp.height = mSurfaceHeight;
          } else if (layout == VIDEO_LAYOUT_ZOOM) {
              lp.width = windowRatio > videoRatio ? windowWidth : (int) (videoRatio * windowHeight);
              lp.height = windowRatio < videoRatio ? windowHeight : (int) (windowWidth / videoRatio);
          } else if (layout == VIDEO_LAYOUT_FIT_PARENT) {
              ViewGroup parent = (ViewGroup) getParent();
              float parentRatio = ((float) parent.getWidth()) / ((float) parent.getHeight());
              lp.width = (parentRatio < videoRatio) ? parent.getWidth()
                      : Math.round(((float) parent.getHeight()) * videoRatio);
              lp.height = (parentRatio > videoRatio) ? parent.getHeight()
                      : Math.round(((float) parent.getWidth()) / videoRatio);
          } else {
              boolean full = layout == VIDEO_LAYOUT_STRETCH;
              lp.width = (full || windowRatio < videoRatio) ? windowWidth : (int) (videoRatio * windowHeight);
              lp.height = (full || windowRatio > videoRatio) ? windowHeight : (int) (windowWidth / videoRatio);
          }
          setLayoutParams(lp);
          getHolder().setFixedSize(mSurfaceWidth, mSurfaceHeight);
          Log.d("VIDEO: %dx%dx%f, Surface: %dx%d, LP: %dx%d, Window: %dx%dx%f", mVideoWidth, mVideoHeight,
                  mVideoAspectRatio, mSurfaceWidth, mSurfaceHeight, lp.width, lp.height, windowWidth, windowHeight,
                  windowRatio);
          mVideoLayout = layout;
          mAspectRatio = aspectRatio;
      }

@SuppressWarnings("deprecation")
private void initVideoView(Context ctx) {
  mContext = ctx;
  mVideoWidth = 0;
  mVideoHeight = 0;
    ImageFormat
  getHolder().setFormat(PixelFormat.RGBA_8888); // PixelFormat.RGB_565
  getHolder().addCallback(mSHCallback);
  // this value only use Hardware decoder before Android 2.3
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB && mHardwareDecoder) {
    getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  }
  setFocusable(true);
  setFocusableInTouchMode(true);
  requestFocus();
  mCurrentState = STATE_IDLE;
  mTargetState = STATE_IDLE;
  if (ctx instanceof Activity)
    ((Activity) ctx).setVolumeControlStream(AudioManager.STREAM_MUSIC);
}

      public boolean isValid() {
          return (mSurfaceHolder != null && mSurfaceHolder.getSurface().isValid());
      }

      public void setVideoPath(String path) {
          setVideoURI(Uri.parse(path));
      }

      public void setVideoURI(Uri uri) {
          setVideoURI(uri, null);
      }

      public void setVideoURI(Uri uri, Map<String, String> headers) {
          mUri = uri;
          mHeaders = headers;
          mSeekWhenPrepared = 0;
          openVideo();
          requestLayout();
          invalidate();
      }

      public void stopPlayback() {
          if (mMediaPlayer != null) {
              mMediaPlayer.stop();
              mMediaPlayer.release();
              mMediaPlayer = null;
              mCurrentState = STATE_IDLE;
              mTargetState = STATE_IDLE;
          }
      }

      private void openVideo() {
          //    if (mUri == null || mSurfaceHolder == null || !Vitamio.isInitialized(mContext))
          //      return;
          if (mUri == null || mSurfaceHolder == null)
              return;
          Intent i = new Intent("com.android.music.musicservicecommand");
          i.putExtra("command", "pause");
          mContext.sendBroadcast(i);

          release(false);
          try {
              mDuration = -1;
              mCurrentBufferPercentage = 0;
              mMediaPlayer = new MediaPlayer(mContext, mHardwareDecoder);
              mMediaPlayer.setOnPreparedListener(mPreparedListener);
              mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
              mMediaPlayer.setOnCompletionListener(mCompletionListener);
              mMediaPlayer.setOnErrorListener(mErrorListener);
              mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
              mMediaPlayer.setOnInfoListener(mInfoListener);
              mMediaPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
              mMediaPlayer.setOnTimedTextListener(mTimedTextListener);
              mMediaPlayer.setDataSource(mContext, mUri, mHeaders);

              mMediaPlayer.setDisplay(mSurfaceHolder);
              mMediaPlayer.setBufferSize(mBufSize);
              mMediaPlayer
                      .setVideoChroma(mVideoChroma == MediaPlayer.VIDEOCHROMA_RGB565 ? MediaPlayer.VIDEOCHROMA_RGB565
                              : MediaPlayer.VIDEOCHROMA_RGBA);
              mMediaPlayer.setScreenOnWhilePlaying(true);
              mMediaPlayer.prepareAsync();
              mCurrentState = STATE_PREPARING;
              attachMediaController();
          } catch (IOException ex) {
              Log.e("Unable to open content: " + mUri, ex);
              mCurrentState = STATE_ERROR;
              mTargetState = STATE_ERROR;
              mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
              return;
          } catch (IllegalArgumentException ex) {
              Log.e("Unable to open content: " + mUri, ex);
              mCurrentState = STATE_ERROR;
              mTargetState = STATE_ERROR;
              mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
              return;
          }
      }

      public void setMediaController(MediaController controller) {
          if (mMediaController != null)
              mMediaController.hide();
          mMediaController = controller;
          attachMediaController();
      }

      public void setMediaBufferingIndicator(View mediaBufferingIndicator) {
          if (mMediaBufferingIndicator != null)
              mMediaBufferingIndicator.setVisibility(View.GONE);
          mMediaBufferingIndicator = mediaBufferingIndicator;
      }

      private void attachMediaController() {
          if (mMediaPlayer != null && mMediaController != null) {
              mMediaController.setMediaPlayer(this);
              View anchorView = this.getParent() instanceof View ? (View) this.getParent() : this;
              mMediaController.setAnchorView(anchorView);
              mMediaController.setEnabled(isInPlaybackState());

              if (mUri != null) {
                  List<String> paths = mUri.getPathSegments();
                  String name = paths == null || paths.isEmpty() ? "null" : paths.get(paths.size() - 1);
                  mMediaController.setFileName(name);
              }
          }
      }

      public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) {
          mOnPreparedListener = l;
      }

      public void setOnCompletionListener(MediaPlayer.OnCompletionListener l) {
          mOnCompletionListener = l;
      }

      public void setOnErrorListener(MediaPlayer.OnErrorListener l) {
          mOnErrorListener = l;
      }

      public void setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener l) {
          mOnBufferingUpdateListener = l;
      }

      public void setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener l) {
          mOnSeekCompleteListener = l;
      }

      public void setOnTimedTextListener(MediaPlayer.OnTimedTextListener l) {
          mOnTimedTextListener = l;
      }

      public void setOnInfoListener(MediaPlayer.OnInfoListener l) {
          mOnInfoListener = l;
      }

      private void release(boolean cleartargetstate) {
          if (mMediaPlayer != null) {
              mMediaPlayer.reset();
              mMediaPlayer.release();
              mMediaPlayer = null;
              mCurrentState = STATE_IDLE;
              if (cleartargetstate)
                  mTargetState = STATE_IDLE;
          }
      }

      @Override
      public boolean onTouchEvent(MotionEvent ev) {
          if (isInPlaybackState() && mMediaController != null)
              toggleMediaControlsVisiblity();
          return false;
      }

      @Override
      public boolean onTrackballEvent(MotionEvent ev) {
          if (isInPlaybackState() && mMediaController != null)
              toggleMediaControlsVisiblity();
          return false;
      }

      @Override
      public boolean onKeyDown(int keyCode, KeyEvent event) {
          boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_VOLUME_UP
                  && keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_MENU
                  && keyCode != KeyEvent.KEYCODE_CALL && keyCode != KeyEvent.KEYCODE_ENDCALL;
          if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) {
              if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
                      || keyCode == KeyEvent.KEYCODE_SPACE) {
                  if (mMediaPlayer.isPlaying()) {
                      pause();
                      mMediaController.show();
                  } else {
                      start();
                      mMediaController.hide();
                  }
                  return true;
              } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
                  if (!mMediaPlayer.isPlaying()) {
                      start();
                      mMediaController.hide();
                  }
                  return true;
              } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
                  if (mMediaPlayer.isPlaying()) {
                      pause();
                      mMediaController.show();
                  }
                  return true;
              } else {
                  toggleMediaControlsVisiblity();
              }
          }

          return super.onKeyDown(keyCode, event);
      }

      private void toggleMediaControlsVisiblity() {
          if (mMediaController.isShowing()) {
              mMediaController.hide();
          } else {
              mMediaController.show();
          }
      }

      public void start() {
          if (isInPlaybackState()) {
              mMediaPlayer.start();
              mCurrentState = STATE_PLAYING;
          }
          mTargetState = STATE_PLAYING;
      }

      public void pause() {
          if (isInPlaybackState()) {
              if (mMediaPlayer.isPlaying()) {
                  mMediaPlayer.pause();
                  mCurrentState = STATE_PAUSED;
              }
          }
          mTargetState = STATE_PAUSED;
      }

      public void suspend() {
          if (isInPlaybackState()) {
              release(false);
              mCurrentState = STATE_SUSPEND_UNSUPPORTED;
              Log.d("Unable to suspend video. Release MediaPlayer.");
          }
      }

      public void resume() {
          if (mSurfaceHolder == null && mCurrentState == STATE_SUSPEND) {
              mTargetState = STATE_RESUME;
          } else if (mCurrentState == STATE_SUSPEND_UNSUPPORTED) {
              openVideo();
          }
      }

      public long getDuration() {
          if (isInPlaybackState()) {
              if (mDuration > 0)
                  return mDuration;
              mDuration = mMediaPlayer.getDuration();
              return mDuration;
          }
          mDuration = -1;
          return mDuration;
      }

      public long getCurrentPosition() {
          if (isInPlaybackState())
              return mMediaPlayer.getCurrentPosition();
          return 0;
      }

      public void seekTo(long msec) {
          if (isInPlaybackState()) {
              mMediaPlayer.seekTo(msec);
              mSeekWhenPrepared = 0;
          } else {
              mSeekWhenPrepared = msec;
          }
      }

      public boolean isPlaying() {
          return isInPlaybackState() && mMediaPlayer.isPlaying();
      }

      public int getBufferPercentage() {
          if (mMediaPlayer != null)
              return mCurrentBufferPercentage;
          return 0;
      }

      public void setVolume(float leftVolume, float rightVolume) {
          if (mMediaPlayer != null)
              mMediaPlayer.setVolume(leftVolume, rightVolume);
      }

      public int getVideoWidth() {
          return mVideoWidth;
      }

      public int getVideoHeight() {
          return mVideoHeight;
      }

      public float getVideoAspectRatio() {
          return mVideoAspectRatio;
      }

      /**
       * Must set before {@link #setVideoURI}
       * @param chroma
       */
      public void setVideoChroma(int chroma) {
          getHolder()
                  .setFormat(chroma == MediaPlayer.VIDEOCHROMA_RGB565 ? PixelFormat.RGB_565 : PixelFormat.RGBA_8888); // PixelFormat.RGB_565
          mVideoChroma = chroma;
      }

      public void setHardwareDecoder(boolean hardware) {
          mHardwareDecoder = hardware;
      }

      public void setVideoQuality(int quality) {
          if (mMediaPlayer != null)
              mMediaPlayer.setVideoQuality(quality);
      }

      public void setBufferSize(int bufSize) {
          mBufSize = bufSize;
      }

      public boolean isBuffering() {
          if (mMediaPlayer != null)
              return mMediaPlayer.isBuffering();
          return false;
      }

      public String getMetaEncoding() {
          if (mMediaPlayer != null)
              return mMediaPlayer.getMetaEncoding();
          return null;
      }

      public void setMetaEncoding(String encoding) {
          if (mMediaPlayer != null)
              mMediaPlayer.setMetaEncoding(encoding);
      }

      public SparseArray<MediaFormat> getAudioTrackMap(String encoding) {
          if (mMediaPlayer != null)
              return mMediaPlayer.findTrackFromTrackInfo(MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO,
                      mMediaPlayer.getTrackInfo(encoding));
          return null;
      }

      public int getAudioTrack() {
          if (mMediaPlayer != null)
              return mMediaPlayer.getAudioTrack();
          return -1;
      }

      public void setAudioTrack(int audioIndex) {
          if (mMediaPlayer != null)
              mMediaPlayer.selectTrack(audioIndex);
      }

      public void setTimedTextShown(boolean shown) {
          if (mMediaPlayer != null)
              mMediaPlayer.setTimedTextShown(shown);
      }

      public void setTimedTextEncoding(String encoding) {
          if (mMediaPlayer != null)
              mMediaPlayer.setTimedTextEncoding(encoding);
      }

      public int getTimedTextLocation() {
          if (mMediaPlayer != null)
              return mMediaPlayer.getTimedTextLocation();
          return -1;
      }

      public void addTimedTextSource(String subPath) {
          if (mMediaPlayer != null)
              mMediaPlayer.addTimedTextSource(subPath);
      }

      public String getTimedTextPath() {
          if (mMediaPlayer != null)
              return mMediaPlayer.getTimedTextPath();
          return null;
      }

      public void setSubTrack(int trackId) {
          if (mMediaPlayer != null)
              mMediaPlayer.selectTrack(trackId);
      }

      public int getTimedTextTrack() {
          if (mMediaPlayer != null)
              return mMediaPlayer.getTimedTextTrack();
          return -1;
      }

      public SparseArray<MediaFormat> getSubTrackMap(String encoding) {
          if (mMediaPlayer != null)
              return mMediaPlayer.findTrackFromTrackInfo(MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT,
                      mMediaPlayer.getTrackInfo(encoding));
          return null;
      }

      protected boolean isInPlaybackState() {
          return (mMediaPlayer != null && mCurrentState != STATE_ERROR && mCurrentState != STATE_IDLE
                  && mCurrentState != STATE_PREPARING);
      }
  }