public void seekTo(long usec) {
        if(mCurrentState.ordinal() < State.PREPARED.ordinal() && mCurrentState.ordinal() >= State.RELEASING.ordinal()) {
            mCurrentState = State.ERROR;
            throw new IllegalStateException();
        }

        /* 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. */

        Log.d(TAG, "seekTo " + usec + " with video sample offset " + mVideoMinPTS);

        if (mOnSeekListener != null) {
            mOnSeekListener.onSeek(MediaPlayer.this);
        }

        mSeeking = true;
        // The passed in target time is always aligned to a zero start time, while the actual video
        // can have an offset and must not necessarily start at zero. The offset can e.g. come from
        // the CTTS box SampleOffset field, and is only reported on Android 5+. In Android 4, the
        // offset is handled by the framework, not reported, and videos always start at zero.
        // By adding the offset to the seek target time, we always seek to a zero-reference time in
        // the stream.
        mSeekTargetTime = mVideoMinPTS + usec;
        mPlaybackThread.seekTo(mSeekTargetTime);
    }
@see android.media.MediaPlayer#setSurface(android.view.Surface)
MediaPlayer/src/main/java/net/protyposis/android/mediaplayer/MediaPlayer.java