From af0fba87e43a4a3fbcd7fefc6614c222fdec5e7a Mon Sep 17 00:00:00 2001
From: xiaowusky <chenyangyang3858@dingtalk.com>
Date: Mon, 5 Jun 2023 11:07:03 +0800
Subject: [PATCH] =?UTF-8?q?desc:=E5=8D=87=E7=BA=A7=E6=9C=80=E6=96=B0ijk?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/build.gradle                              |    4 +-
 .../player/ProVideoActivity.java              |    8 +-
 .../safetywatcher/player/ProVideoView.java    |   43 +-
 library-ijkplayer/build.gradle                |    4 +
 .../ijk/media/player/AbstractMediaPlayer.java |  126 --
 .../ijk/media/player/AndroidMediaPlayer.java  |  436 ------
 .../ijk/media/player/IMediaPlayer.java        |  208 ---
 .../media/player/ISurfaceTextureHolder.java   |   27 -
 .../ijk/media/player/ISurfaceTextureHost.java |   23 -
 .../ijk/media/player/IjkLibLoader.java        |   22 -
 .../ijk/media/player/IjkMediaCodecInfo.java   |  293 ----
 .../ijk/media/player/IjkMediaMeta.java        |  401 -----
 .../ijk/media/player/IjkMediaPlayer.java      | 1365 -----------------
 .../ijk/media/player/IjkTimedText.java        |   39 -
 .../danmaku/ijk/media/player/MediaInfo.java   |   29 -
 .../ijk/media/player/MediaPlayerProxy.java    |  343 -----
 .../ijk/media/player/TextureMediaPlayer.java  |   99 --
 .../ijk/media/player/TxtOverlayAdd.java       |   14 -
 .../player/annotations/AccessedByNative.java  |   31 -
 .../player/annotations/CalledByNative.java    |   35 -
 .../player/exceptions/IjkMediaException.java  |   21 -
 .../ijk/media/player/ffmpeg/FFmpegApi.java    |    5 -
 .../media/player/misc/AndroidMediaFormat.java |   62 -
 .../media/player/misc/AndroidTrackInfo.java   |  108 --
 .../ijk/media/player/misc/IIjkIOHttp.java     |   27 -
 .../media/player/misc/IMediaDataSource.java   |   28 -
 .../ijk/media/player/misc/IMediaFormat.java   |   30 -
 .../ijk/media/player/misc/ITrackInfo.java     |   34 -
 .../ijk/media/player/misc/IjkMediaFormat.java |  258 ----
 .../ijk/media/player/misc/IjkTrackInfo.java   |   98 --
 .../ijk/media/player/pragma/DebugLog.java     |  142 --
 .../ijk/media/player/pragma/Pragma.java       |   23 -
 .../widget/media/FileMediaDataSource.java     |    3 +
 .../media/widget/media/IMediaController.java  |    1 +
 .../ijk/media/widget/media/IRenderView.java   |    1 +
 .../ijk/media/widget/media/IjkVideoView.java  | 1018 ++++++------
 .../ijk/media/widget/media/MeasureHelper.java |   57 +-
 .../media/widget/media/MediaPlayerCompat.java |    1 +
 .../media/widget/media/SurfaceRenderView.java |    8 +-
 .../media/widget/media/TextureRenderView.java |    8 +-
 40 files changed, 511 insertions(+), 4972 deletions(-)
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/AndroidMediaPlayer.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHolder.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHost.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkLibLoader.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaMeta.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkTimedText.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/MediaInfo.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/TextureMediaPlayer.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/TxtOverlayAdd.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/annotations/AccessedByNative.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/annotations/CalledByNative.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/exceptions/IjkMediaException.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ffmpeg/FFmpegApi.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidMediaFormat.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidTrackInfo.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IIjkIOHttp.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaDataSource.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaFormat.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/ITrackInfo.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IjkMediaFormat.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IjkTrackInfo.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/pragma/DebugLog.java
 delete mode 100644 library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/pragma/Pragma.java

diff --git a/app/build.gradle b/app/build.gradle
index 00d91ae..0fe9d28 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -36,7 +36,6 @@ dependencies {
     implementation fileTree(include: ['*.jar'], dir: 'libs')
     implementation 'androidx.appcompat:appcompat:1.4.1'
     implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
-    implementation project(':library-push')
     implementation(name: 'libuvccamera-release', ext: 'aar') {
         exclude module: 'support-v4'
         exclude module: 'appcompat-v7'
@@ -47,6 +46,7 @@ dependencies {
     implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
     implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.4.1'
     //libs
+    implementation project(':library-push')
     implementation project(path: ':library-ijkplayer')
     implementation project(path: ':library-serialPort')
     implementation project(path: ':library-common')
@@ -54,6 +54,8 @@ dependencies {
     implementation rootProject.ext.dependencies.jxl
     // 时间日期选择控件
     implementation 'com.github.loper7:DateTimePicker:0.6.3'
+    //ijk
+    implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
 
     implementation 'com.google.android.material:material:1.5.0'
     annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.0.0'
diff --git a/app/src/main/java/com/yinuo/safetywatcher/player/ProVideoActivity.java b/app/src/main/java/com/yinuo/safetywatcher/player/ProVideoActivity.java
index a0285e1..3e65da3 100644
--- a/app/src/main/java/com/yinuo/safetywatcher/player/ProVideoActivity.java
+++ b/app/src/main/java/com/yinuo/safetywatcher/player/ProVideoActivity.java
@@ -41,12 +41,10 @@ import androidx.core.view.ViewCompat;
 import androidx.core.view.ViewConfigurationCompat;
 
 import com.bumptech.glide.Glide;
-import com.yinuo.safetywatcher.BuildConfig;
 import com.yinuo.safetywatcher.databinding.ActivityMainProBinding;
 import com.yinuo.safetywatcher.player.utils.SPUtil;
 
 import tv.danmaku.ijk.media.player.IMediaPlayer;
-import tv.danmaku.ijk.media.player.IjkMediaPlayer;
 
 public class ProVideoActivity extends AppCompatActivity {
     private static final String TAG = "ProVideoActivity";
@@ -120,10 +118,6 @@ public class ProVideoActivity extends AppCompatActivity {
 
         SPUtil.setDefaultParams(this);
 
-        if (BuildConfig.DEBUG) {
-            IjkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG);// init player
-        }
-
         mediaController = new VideoControllerView(this);
         mediaController.setMediaPlayer(mBinding.videoView);
         mVideoView = mBinding.videoView;
@@ -205,7 +199,7 @@ public class ProVideoActivity extends AppCompatActivity {
             @Override
             public boolean onSingleTapConfirmed(MotionEvent e) {
                 if (mVideoView.isInPlaybackState()) {
-                    mVideoView.toggleMediaControlsVisibility();
+                    mVideoView.toggleMediaControlsVisiblity();
                     return true;
                 }
 
diff --git a/app/src/main/java/com/yinuo/safetywatcher/player/ProVideoView.java b/app/src/main/java/com/yinuo/safetywatcher/player/ProVideoView.java
index 6e02d3d..4e01984 100644
--- a/app/src/main/java/com/yinuo/safetywatcher/player/ProVideoView.java
+++ b/app/src/main/java/com/yinuo/safetywatcher/player/ProVideoView.java
@@ -1,7 +1,5 @@
 package com.yinuo.safetywatcher.player;
 
-import static tv.danmaku.ijk.media.player.IjkMediaPlayer.native_active_days;
-
 import android.Manifest;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -45,34 +43,14 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
         super(context, attrs, defStyleAttr, defStyleRes);
     }
 
-    public static void setKey(String key) {
-        Player_KEY = key;
-    }
-
-    public static long getActiveDays(Context context, String key) {
-        return native_active_days(context, key);
-    }
-
     /**
      * ================ super override ================
      */
 
     public void startRecord(String path, int seconds) {
-        if (mMediaPlayer == null) {
-            return;
-        }
-
-        super.startRecord(path, seconds);
-        mRecordPath = path;
     }
 
     public void stopRecord() {
-        if (mMediaPlayer == null) {
-            return;
-        }
-
-        super.stopRecord();
-        mRecordPath = null;
     }
 
     /**
@@ -99,7 +77,7 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
 
     @Override
     public boolean recordEnable() {
-        Uri uri = mUri;
+        Uri uri = null;
 
         if (uri == null)
             return false;
@@ -112,7 +90,7 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
 
     @Override
     public boolean speedCtrlEnable() {
-        Uri uri = mUri;
+        Uri uri = null;
 
         if (uri == null)
             return false;
@@ -132,11 +110,6 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
         return !TextUtils.isEmpty(mRecordPath);
     }
 
-    @Override
-    public void reStart() {
-        super.reStart();
-    }
-
     @Override
     public void toggleRecord() {
         if (getContext() instanceof ProVideoActivity) {
@@ -149,7 +122,7 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
         }
 
         if (!isRecording()) {
-            Uri uri = mUri;
+            Uri uri = null;
             if (uri == null)
                 return;
 
@@ -176,7 +149,7 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
 
         if (mMediaPlayer instanceof IjkMediaPlayer) {
             IjkMediaPlayer player = (IjkMediaPlayer) mMediaPlayer;
-            return player.getSpeed();
+            return player.getSpeed(0f);
         }
 
         return 1.0f;
@@ -207,10 +180,10 @@ public class ProVideoView extends IjkVideoView implements VideoControllerView.Fu
 
     @Override
     public boolean isCompleted() {
-        if (mMediaPlayer instanceof IjkMediaPlayer) {
-            IjkMediaPlayer player = (IjkMediaPlayer) mMediaPlayer;
-            return player.isCompleted();
-        }
+//        if (mMediaPlayer instanceof IjkMediaPlayer) {
+//            IjkMediaPlayer player = (IjkMediaPlayer) mMediaPlayer;
+//            return player.isCompleted();
+//        }
 
         return false;
     }
diff --git a/library-ijkplayer/build.gradle b/library-ijkplayer/build.gradle
index 2a2a344..0ad593d 100644
--- a/library-ijkplayer/build.gradle
+++ b/library-ijkplayer/build.gradle
@@ -9,5 +9,9 @@ android {
 
 dependencies {
     implementation fileTree(include: ['*.jar'], dir: 'libs')
+
+    //ijk
+    implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
+    implementation 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.8'
 }
 
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java
deleted file mode 100644
index 742602a..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player;
-
-import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
-
-@SuppressWarnings("WeakerAccess")
-public abstract class AbstractMediaPlayer implements IMediaPlayer {
-    private OnPreparedListener mOnPreparedListener;
-    private OnCompletionListener mOnCompletionListener;
-    private OnBufferingUpdateListener mOnBufferingUpdateListener;
-    private OnSeekCompleteListener mOnSeekCompleteListener;
-    private OnVideoSizeChangedListener mOnVideoSizeChangedListener;
-    private OnErrorListener mOnErrorListener;
-    private OnInfoListener mOnInfoListener;
-    private OnTimedTextListener mOnTimedTextListener;
-    protected boolean mCompleted;
-
-    public final void setOnPreparedListener(OnPreparedListener listener) {
-        mOnPreparedListener = listener;
-    }
-
-    public final void setOnCompletionListener(OnCompletionListener listener) {
-        mOnCompletionListener = listener;
-    }
-
-    public final void setOnBufferingUpdateListener(
-            OnBufferingUpdateListener listener) {
-        mOnBufferingUpdateListener = listener;
-    }
-
-    public final void setOnSeekCompleteListener(OnSeekCompleteListener listener) {
-        mOnSeekCompleteListener = listener;
-    }
-
-    public final void setOnVideoSizeChangedListener(
-            OnVideoSizeChangedListener listener) {
-        mOnVideoSizeChangedListener = listener;
-    }
-
-    public final void setOnErrorListener(OnErrorListener listener) {
-        mOnErrorListener = listener;
-    }
-
-    public final void setOnInfoListener(OnInfoListener listener) {
-        mOnInfoListener = listener;
-    }
-
-    public final void setOnTimedTextListener(OnTimedTextListener listener) {
-        mOnTimedTextListener = listener;
-    }
-
-    public void resetListeners() {
-        mOnPreparedListener = null;
-        mOnBufferingUpdateListener = null;
-        mOnCompletionListener = null;
-        mOnSeekCompleteListener = null;
-        mOnVideoSizeChangedListener = null;
-        mOnErrorListener = null;
-        mOnInfoListener = null;
-        mOnTimedTextListener = null;
-    }
-
-    protected final void notifyOnPrepared() {
-        if (mOnPreparedListener != null)
-            mOnPreparedListener.onPrepared(this);
-    }
-
-    protected final void notifyOnCompletion() {
-        mCompleted = true;
-        if (mOnCompletionListener != null)
-            mOnCompletionListener.onCompletion(this);
-    }
-
-    protected final void notifyOnBufferingUpdate(int percent) {
-        if (mOnBufferingUpdateListener != null)
-            mOnBufferingUpdateListener.onBufferingUpdate(this, percent);
-    }
-
-    protected final void notifyOnSeekComplete() {
-        if (mOnSeekCompleteListener != null)
-            mOnSeekCompleteListener.onSeekComplete(this);
-    }
-
-    protected final void notifyOnVideoSizeChanged(int width, int height,
-                                                  int sarNum, int sarDen) {
-        if (mOnVideoSizeChangedListener != null)
-            mOnVideoSizeChangedListener.onVideoSizeChanged(this, width, height,
-                    sarNum, sarDen);
-    }
-
-    protected final boolean notifyOnError(int what, int extra) {
-        return mOnErrorListener != null && mOnErrorListener.onError(this, what, extra);
-    }
-
-    protected final boolean notifyOnInfo(int what, int extra) {
-        return mOnInfoListener != null && mOnInfoListener.onInfo(this, what, extra);
-    }
-
-    protected final void notifyOnTimedText(IjkTimedText text) {
-        if (mOnTimedTextListener != null)
-            mOnTimedTextListener.onTimedText(this, text);
-    }
-
-    public void setDataSource(IMediaDataSource mediaDataSource) {
-        throw new UnsupportedOperationException();
-    }
-
-    public boolean isCompleted(){
-        return mCompleted;
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/AndroidMediaPlayer.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/AndroidMediaPlayer.java
deleted file mode 100644
index 8689851..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/AndroidMediaPlayer.java
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- * Copyright (C) 2013 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.media.AudioManager;
-import android.media.MediaDataSource;
-import android.media.MediaPlayer;
-import android.media.TimedText;
-import android.net.Uri;
-import android.os.Build;
-import android.text.TextUtils;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.util.Map;
-
-import tv.danmaku.ijk.media.player.misc.AndroidTrackInfo;
-import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
-import tv.danmaku.ijk.media.player.misc.ITrackInfo;
-import tv.danmaku.ijk.media.player.pragma.DebugLog;
-
-public class AndroidMediaPlayer extends AbstractMediaPlayer {
-    private final MediaPlayer mInternalMediaPlayer;
-    private final AndroidMediaPlayerListenerHolder mInternalListenerAdapter;
-    private String mDataSource;
-    private MediaDataSource mMediaDataSource;
-
-    private final Object mInitLock = new Object();
-    private boolean mIsReleased;
-
-    private static MediaInfo sMediaInfo;
-
-    public AndroidMediaPlayer() {
-        synchronized (mInitLock) {
-            mInternalMediaPlayer = new MediaPlayer();
-        }
-        mInternalMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
-        mInternalListenerAdapter = new AndroidMediaPlayerListenerHolder(this);
-        attachInternalListeners();
-    }
-
-    public MediaPlayer getInternalMediaPlayer() {
-        return mInternalMediaPlayer;
-    }
-
-    @Override
-    public void setDisplay(SurfaceHolder sh) {
-        synchronized (mInitLock) {
-            if (!mIsReleased) {
-                mInternalMediaPlayer.setDisplay(sh);
-            }
-        }
-    }
-
-    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
-    @Override
-    public void setSurface(Surface surface) {
-        mInternalMediaPlayer.setSurface(surface);
-    }
-
-    @Override
-    public void setDataSource(Context context, Uri uri)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
-        mInternalMediaPlayer.setDataSource(context, uri);
-    }
-
-    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
-    @Override
-    public void setDataSource(Context context, Uri uri, Map<String, String> headers)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
-        mInternalMediaPlayer.setDataSource(context, uri, headers);
-    }
-
-    @Override
-    public void setDataSource(FileDescriptor fd)
-            throws IOException, IllegalArgumentException, IllegalStateException {
-        mInternalMediaPlayer.setDataSource(fd);
-    }
-
-    @Override
-    public void setDataSource(String path) throws IOException,
-            IllegalArgumentException, SecurityException, IllegalStateException {
-        mDataSource = path;
-
-        Uri uri = Uri.parse(path);
-        String scheme = uri.getScheme();
-        if (!TextUtils.isEmpty(scheme) && scheme.equalsIgnoreCase("file")) {
-            mInternalMediaPlayer.setDataSource(uri.getPath());
-        } else {
-            mInternalMediaPlayer.setDataSource(path);
-        }
-    }
-
-    @TargetApi(Build.VERSION_CODES.M)
-    @Override
-    public void setDataSource(IMediaDataSource mediaDataSource) {
-        releaseMediaDataSource();
-
-        mMediaDataSource = new MediaDataSourceProxy(mediaDataSource);
-        mInternalMediaPlayer.setDataSource(mMediaDataSource);
-    }
-
-    @TargetApi(Build.VERSION_CODES.M)
-    private static class MediaDataSourceProxy extends MediaDataSource {
-        private final IMediaDataSource mMediaDataSource;
-
-        public MediaDataSourceProxy(IMediaDataSource mediaDataSource) {
-            mMediaDataSource = mediaDataSource;
-        }
-
-        @Override
-        public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
-            return mMediaDataSource.readAt(position, buffer, offset, size);
-        }
-
-        @Override
-        public long getSize() throws IOException {
-            return mMediaDataSource.getSize();
-        }
-
-        @Override
-        public void close() throws IOException {
-            mMediaDataSource.close();
-        }
-    }
-
-    @Override
-    public String getDataSource() {
-        return mDataSource;
-    }
-
-    private void releaseMediaDataSource() {
-        if (mMediaDataSource != null) {
-            try {
-                mMediaDataSource.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-            mMediaDataSource = null;
-        }
-    }
-
-    @Override
-    public void prepareAsync() throws IllegalStateException {
-        mInternalMediaPlayer.prepareAsync();
-    }
-
-    @Override
-    public void start() throws IllegalStateException {
-        mInternalMediaPlayer.start();
-    }
-
-    @Override
-    public void stop() throws IllegalStateException {
-        mInternalMediaPlayer.stop();
-    }
-
-    @Override
-    public void pause() throws IllegalStateException {
-        mInternalMediaPlayer.pause();
-    }
-
-    @Override
-    public void setScreenOnWhilePlaying(boolean screenOn) {
-        mInternalMediaPlayer.setScreenOnWhilePlaying(screenOn);
-    }
-
-    @Override
-    public ITrackInfo[] getTrackInfo() {
-        return AndroidTrackInfo.fromMediaPlayer(mInternalMediaPlayer);
-    }
-
-    @Override
-    public int getVideoWidth() {
-        return mInternalMediaPlayer.getVideoWidth();
-    }
-
-    @Override
-    public int getVideoHeight() {
-        return mInternalMediaPlayer.getVideoHeight();
-    }
-
-    @Override
-    public int getVideoSarNum() {
-        return 1;
-    }
-
-    @Override
-    public int getVideoSarDen() {
-        return 1;
-    }
-
-    @Override
-    public boolean isPlaying() {
-        try {
-            return mInternalMediaPlayer.isPlaying();
-        } catch (IllegalStateException e) {
-            DebugLog.printStackTrace(e);
-            return false;
-        }
-    }
-
-    @Override
-    public void seekTo(long msec) throws IllegalStateException {
-        mInternalMediaPlayer.seekTo((int) msec);
-    }
-
-    @Override
-    public long getCurrentPosition() {
-        try {
-            return mInternalMediaPlayer.getCurrentPosition();
-        } catch (IllegalStateException e) {
-            DebugLog.printStackTrace(e);
-            return 0;
-        }
-    }
-
-    @Override
-    public long getDuration() {
-        try {
-            return mInternalMediaPlayer.getDuration();
-        } catch (IllegalStateException e) {
-            DebugLog.printStackTrace(e);
-            return 0;
-        }
-    }
-
-    @Override
-    public void release() {
-        mIsReleased = true;
-        mInternalMediaPlayer.release();
-        releaseMediaDataSource();
-        resetListeners();
-        attachInternalListeners();
-    }
-
-    @Override
-    public void reset() {
-        try {
-            mInternalMediaPlayer.reset();
-        } catch (IllegalStateException e) {
-            DebugLog.printStackTrace(e);
-        }
-        releaseMediaDataSource();
-        resetListeners();
-        attachInternalListeners();
-    }
-
-    @Override
-    public void record(String path, int seconds) {
-
-    }
-
-    @Override
-    public void setLooping(boolean looping) {
-        mInternalMediaPlayer.setLooping(looping);
-    }
-
-    @Override
-    public boolean isLooping() {
-        return mInternalMediaPlayer.isLooping();
-    }
-
-    @Override
-    public void setVolume(float leftVolume, float rightVolume) {
-        mInternalMediaPlayer.setVolume(leftVolume, rightVolume);
-    }
-
-    @Override
-    public int getAudioSessionId() {
-        return mInternalMediaPlayer.getAudioSessionId();
-    }
-
-    @Override
-    public MediaInfo getMediaInfo() {
-        if (sMediaInfo == null) {
-            MediaInfo module = new MediaInfo();
-
-            module.mVideoDecoder = "android";
-            module.mVideoDecoderImpl = "HW";
-
-            module.mAudioDecoder = "android";
-            module.mAudioDecoderImpl = "HW";
-
-            sMediaInfo = module;
-        }
-
-        return sMediaInfo;
-    }
-
-    @Override
-    public void setLogEnabled(boolean enable) {
-    }
-
-    @Override
-    public boolean isPlayable() {
-        return true;
-    }
-
-    /*--------------------
-     * misc
-     */
-    @Override
-    public void setWakeMode(Context context, int mode) {
-        mInternalMediaPlayer.setWakeMode(context, mode);
-    }
-
-    @Override
-    public void setAudioStreamType(int streamtype) {
-        mInternalMediaPlayer.setAudioStreamType(streamtype);
-    }
-
-    @Override
-    public void setKeepInBackground(boolean keepInBackground) {
-    }
-
-    /*--------------------
-     * Listeners adapter
-     */
-    private void attachInternalListeners() {
-        mInternalMediaPlayer.setOnPreparedListener(mInternalListenerAdapter);
-        mInternalMediaPlayer
-                .setOnBufferingUpdateListener(mInternalListenerAdapter);
-        mInternalMediaPlayer.setOnCompletionListener(mInternalListenerAdapter);
-        mInternalMediaPlayer
-                .setOnSeekCompleteListener(mInternalListenerAdapter);
-        mInternalMediaPlayer
-                .setOnVideoSizeChangedListener(mInternalListenerAdapter);
-        mInternalMediaPlayer.setOnErrorListener(mInternalListenerAdapter);
-        mInternalMediaPlayer.setOnInfoListener(mInternalListenerAdapter);
-        mInternalMediaPlayer.setOnTimedTextListener(mInternalListenerAdapter);
-    }
-
-    private class AndroidMediaPlayerListenerHolder implements
-            MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener,
-            MediaPlayer.OnBufferingUpdateListener,
-            MediaPlayer.OnSeekCompleteListener,
-            MediaPlayer.OnVideoSizeChangedListener,
-            MediaPlayer.OnErrorListener, MediaPlayer.OnInfoListener,
-            MediaPlayer.OnTimedTextListener {
-        public final WeakReference<AndroidMediaPlayer> mWeakMediaPlayer;
-
-        public AndroidMediaPlayerListenerHolder(AndroidMediaPlayer mp) {
-            mWeakMediaPlayer = new WeakReference<AndroidMediaPlayer>(mp);
-        }
-
-        @Override
-        public boolean onInfo(MediaPlayer mp, int what, int extra) {
-            AndroidMediaPlayer self = mWeakMediaPlayer.get();
-            return self != null && notifyOnInfo(what, extra);
-
-        }
-
-        @Override
-        public boolean onError(MediaPlayer mp, int what, int extra) {
-            AndroidMediaPlayer self = mWeakMediaPlayer.get();
-            return self != null && notifyOnError(what, extra);
-
-        }
-
-        @Override
-        public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
-            AndroidMediaPlayer self = mWeakMediaPlayer.get();
-            if (self == null)
-                return;
-
-            notifyOnVideoSizeChanged(width, height, 1, 1);
-        }
-
-        @Override
-        public void onSeekComplete(MediaPlayer mp) {
-            AndroidMediaPlayer self = mWeakMediaPlayer.get();
-            if (self == null)
-                return;
-
-            notifyOnSeekComplete();
-        }
-
-        @Override
-        public void onBufferingUpdate(MediaPlayer mp, int percent) {
-            AndroidMediaPlayer self = mWeakMediaPlayer.get();
-            if (self == null)
-                return;
-
-            notifyOnBufferingUpdate(percent);
-        }
-
-        @Override
-        public void onCompletion(MediaPlayer mp) {
-            AndroidMediaPlayer self = mWeakMediaPlayer.get();
-            if (self == null)
-                return;
-
-            notifyOnCompletion();
-        }
-
-        @Override
-        public void onPrepared(MediaPlayer mp) {
-            AndroidMediaPlayer self = mWeakMediaPlayer.get();
-            if (self == null)
-                return;
-
-            notifyOnPrepared();
-        }
-
-        @Override
-        public void onTimedText(MediaPlayer mp, TimedText text) {
-            AndroidMediaPlayer self = mWeakMediaPlayer.get();
-            if (self == null)
-                return;
-
-            IjkTimedText ijkText = new IjkTimedText(text.getBounds(), text.getText());
-            notifyOnTimedText(ijkText);
-        }
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java
deleted file mode 100644
index cd0e096..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Build;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.util.Map;
-
-import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
-import tv.danmaku.ijk.media.player.misc.ITrackInfo;
-
-public interface IMediaPlayer {
-    /*
-     * Do not change these values without updating their counterparts in native
-     */
-    int MEDIA_INFO_UNKNOWN = 1;
-    int MEDIA_INFO_STARTED_AS_NEXT = 2;
-    int MEDIA_INFO_VIDEO_RENDERING_START = 3;
-    int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700;
-    int MEDIA_INFO_BUFFERING_START = 701;
-    int MEDIA_INFO_BUFFERING_END = 702;
-    int MEDIA_INFO_NETWORK_BANDWIDTH = 703;
-    int MEDIA_INFO_BAD_INTERLEAVING = 800;
-    int MEDIA_INFO_NOT_SEEKABLE = 801;
-    int MEDIA_INFO_METADATA_UPDATE = 802;
-    int MEDIA_INFO_TIMED_TEXT_ERROR = 900;
-    int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901;
-    int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;
-
-    int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;
-    int MEDIA_INFO_AUDIO_RENDERING_START = 10002;
-
-    int MEDIA_ERROR_UNKNOWN = 1;
-    int MEDIA_ERROR_SERVER_DIED = 100;
-    int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;
-    int MEDIA_ERROR_IO = -1004;
-    int MEDIA_ERROR_MALFORMED = -1007;
-    int MEDIA_ERROR_UNSUPPORTED = -1010;
-    int MEDIA_ERROR_TIMED_OUT = -110;
-
-    void setDisplay(SurfaceHolder sh);
-
-    void setDataSource(Context context, Uri uri)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
-
-    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
-    void setDataSource(Context context, Uri uri, Map<String, String> headers)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
-
-    void setDataSource(FileDescriptor fd)
-            throws IOException, IllegalArgumentException, IllegalStateException;
-
-    void setDataSource(String path)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
-
-    String getDataSource();
-
-    void prepareAsync() throws IllegalStateException;
-
-    void start() throws IllegalStateException;
-
-    void stop() throws IllegalStateException;
-
-    void pause() throws IllegalStateException;
-
-    void setScreenOnWhilePlaying(boolean screenOn);
-
-    int getVideoWidth();
-
-    int getVideoHeight();
-
-    boolean isPlaying();
-
-    void seekTo(long msec) throws IllegalStateException;
-
-    long getCurrentPosition();
-
-    long getDuration();
-
-    void release();
-
-    void reset();
-
-    void record(String path, int seconds);
-
-    void setVolume(float leftVolume, float rightVolume);
-
-    int getAudioSessionId();
-
-    MediaInfo getMediaInfo();
-
-    @SuppressWarnings("EmptyMethod")
-    @Deprecated
-    void setLogEnabled(boolean enable);
-
-    @Deprecated
-    boolean isPlayable();
-
-    void setOnPreparedListener(OnPreparedListener listener);
-
-    void setOnCompletionListener(OnCompletionListener listener);
-
-    void setOnBufferingUpdateListener(
-            OnBufferingUpdateListener listener);
-
-    void setOnSeekCompleteListener(
-            OnSeekCompleteListener listener);
-
-    void setOnVideoSizeChangedListener(
-            OnVideoSizeChangedListener listener);
-
-    void setOnErrorListener(OnErrorListener listener);
-
-    void setOnInfoListener(OnInfoListener listener);
-
-    void setOnTimedTextListener(OnTimedTextListener listener);
-
-    /*--------------------
-     * Listeners
-     */
-    interface OnPreparedListener {
-        void onPrepared(IMediaPlayer mp);
-    }
-
-    interface OnCompletionListener {
-        void onCompletion(IMediaPlayer mp);
-    }
-
-    interface OnBufferingUpdateListener {
-        void onBufferingUpdate(IMediaPlayer mp, int percent);
-    }
-
-    interface OnSeekCompleteListener {
-        void onSeekComplete(IMediaPlayer mp);
-    }
-
-    interface OnVideoSizeChangedListener {
-        void onVideoSizeChanged(IMediaPlayer mp, int width, int height,
-                                int sar_num, int sar_den);
-    }
-
-    interface OnErrorListener {
-        boolean onError(IMediaPlayer mp, int what, int extra);
-    }
-
-    interface OnInfoListener {
-        boolean onInfo(IMediaPlayer mp, int what, int extra);
-    }
-
-    interface OnTimedTextListener {
-        void onTimedText(IMediaPlayer mp, IjkTimedText text);
-    }
-
-    /*--------------------
-     * Optional
-     */
-    void setAudioStreamType(int streamtype);
-
-    @Deprecated
-    void setKeepInBackground(boolean keepInBackground);
-
-    int getVideoSarNum();
-
-    int getVideoSarDen();
-
-    @Deprecated
-    void setWakeMode(Context context, int mode);
-
-    void setLooping(boolean looping);
-
-    boolean isLooping();
-
-    /*--------------------
-     * AndroidMediaPlayer: JELLY_BEAN
-     */
-    ITrackInfo[] getTrackInfo();
-
-    /*--------------------
-     * AndroidMediaPlayer: ICE_CREAM_SANDWICH:
-     */
-    void setSurface(Surface surface);
-
-    /*--------------------
-     * AndroidMediaPlayer: M:
-     */
-    void setDataSource(IMediaDataSource mediaDataSource);
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHolder.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHolder.java
deleted file mode 100644
index d62e9cb..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHolder.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player;
-
-import android.graphics.SurfaceTexture;
-
-public interface ISurfaceTextureHolder {
-    void setSurfaceTexture(SurfaceTexture surfaceTexture);
-
-    SurfaceTexture getSurfaceTexture();
-
-    void setSurfaceTextureHost(ISurfaceTextureHost surfaceTextureHost);
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHost.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHost.java
deleted file mode 100644
index ff10c56..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHost.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player;
-
-import android.graphics.SurfaceTexture;
-
-public interface ISurfaceTextureHost {
-    void releaseSurfaceTexture(SurfaceTexture surfaceTexture);
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkLibLoader.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkLibLoader.java
deleted file mode 100644
index f846fc6..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkLibLoader.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player;
-
-public interface IjkLibLoader {
-    void loadLibrary(String libName) throws UnsatisfiedLinkError,
-            SecurityException;
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java
deleted file mode 100644
index 4428c40..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java
+++ /dev/null
@@ -1,293 +0,0 @@
-package tv.danmaku.ijk.media.player;
-
-import android.annotation.TargetApi;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaCodecInfo.CodecProfileLevel;
-import android.os.Build;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.Locale;
-import java.util.Map;
-import java.util.TreeMap;
-
-public class IjkMediaCodecInfo {
-    private final static String TAG = "IjkMediaCodecInfo";
-
-    public static final int RANK_MAX = 1000;
-    public static final int RANK_TESTED = 800;
-    public static final int RANK_ACCEPTABLE = 700;
-    public static final int RANK_LAST_CHANCE = 600;
-    public static final int RANK_SECURE = 300;
-    public static final int RANK_SOFTWARE = 200;
-    public static final int RANK_NON_STANDARD = 100;
-    public static final int RANK_NO_SENSE = 0;
-
-    public MediaCodecInfo mCodecInfo;
-    public int mRank = 0;
-    public String mMimeType;
-
-    private static Map<String, Integer> sKnownCodecList;
-
-    private static synchronized Map<String, Integer> getKnownCodecList() {
-        if (sKnownCodecList != null)
-            return sKnownCodecList;
-
-        sKnownCodecList = new TreeMap<String, Integer>(
-                String.CASE_INSENSITIVE_ORDER);
-
-        // ----- Nvidia -----
-        // Tegra3
-        // Nexus 7 (2012)
-        // Tegra K1
-        // Nexus 9
-        sKnownCodecList.put("OMX.Nvidia.h264.decode", RANK_TESTED);
-        sKnownCodecList.put("OMX.Nvidia.h264.decode.secure", RANK_SECURE);
-
-        // ----- Intel -----
-        // Atom Z3735
-        // Teclast X98 Air
-        sKnownCodecList.put("OMX.Intel.hw_vd.h264", RANK_TESTED + 1);
-        // Atom Z2560
-        // Dell Venue 7 3730
-        sKnownCodecList.put("OMX.Intel.VideoDecoder.AVC", RANK_TESTED);
-
-        // ----- Qualcomm -----
-        // MSM8260
-        // Xiaomi MI 1S
-        sKnownCodecList.put("OMX.qcom.video.decoder.avc", RANK_TESTED);
-        sKnownCodecList.put("OMX.ittiam.video.decoder.avc", RANK_NO_SENSE);
-
-        // ----- Samsung -----
-        // Exynos 3110
-        // Nexus S
-        sKnownCodecList.put("OMX.SEC.avc.dec", RANK_TESTED);
-        sKnownCodecList.put("OMX.SEC.AVC.Decoder", RANK_TESTED - 1);
-        // OMX.SEC.avcdec doesn't reorder output pictures on GT-9100
-        sKnownCodecList.put("OMX.SEC.avcdec", RANK_TESTED - 2);
-        sKnownCodecList.put("OMX.SEC.avc.sw.dec", RANK_SOFTWARE);
-        // Exynos 5 ?
-        sKnownCodecList.put("OMX.Exynos.avc.dec", RANK_TESTED);
-        sKnownCodecList.put("OMX.Exynos.AVC.Decoder", RANK_TESTED - 1);
-
-        // ------ Huawei hisilicon ------
-        // Kirin 910, Mali 450 MP
-        // Huawei HONOR 3C (H30-L01)
-        sKnownCodecList.put("OMX.k3.video.decoder.avc", RANK_TESTED);
-        // Kirin 920, Mali T624
-        // Huawei HONOR 6
-        sKnownCodecList.put("OMX.IMG.MSVDX.Decoder.AVC", RANK_TESTED);
-
-        // ----- TI -----
-        // TI OMAP4460
-        // Galaxy Nexus
-        sKnownCodecList.put("OMX.TI.DUCATI1.VIDEO.DECODER", RANK_TESTED);
-
-        // ------ RockChip ------
-        // Youku TVBox
-        sKnownCodecList.put("OMX.rk.video_decoder.avc", RANK_TESTED);
-
-        // ------ AMLogic -----
-        // MiBox1, 1s, 2
-        sKnownCodecList.put("OMX.amlogic.avc.decoder.awesome", RANK_TESTED);
-
-        // ------ Marvell ------
-        // Lenovo A788t
-        sKnownCodecList.put("OMX.MARVELL.VIDEO.HW.CODA7542DECODER", RANK_TESTED);
-        sKnownCodecList.put("OMX.MARVELL.VIDEO.H264DECODER", RANK_SOFTWARE);
-
-        // ----- TODO: need test -----
-        sKnownCodecList.remove("OMX.Action.Video.Decoder");
-        sKnownCodecList.remove("OMX.allwinner.video.decoder.avc");
-        sKnownCodecList.remove("OMX.BRCM.vc4.decoder.avc");
-        sKnownCodecList.remove("OMX.brcm.video.h264.hw.decoder");
-        sKnownCodecList.remove("OMX.brcm.video.h264.decoder");
-        sKnownCodecList.remove("OMX.cosmo.video.decoder.avc");
-        sKnownCodecList.remove("OMX.duos.h264.decoder");
-        sKnownCodecList.remove("OMX.hantro.81x0.video.decoder");
-        sKnownCodecList.remove("OMX.hantro.G1.video.decoder");
-        sKnownCodecList.remove("OMX.hisi.video.decoder");
-        sKnownCodecList.remove("OMX.LG.decoder.video.avc");
-        sKnownCodecList.remove("OMX.MS.AVC.Decoder");
-        sKnownCodecList.remove("OMX.RENESAS.VIDEO.DECODER.H264");
-        sKnownCodecList.remove("OMX.RTK.video.decoder");
-        sKnownCodecList.remove("OMX.sprd.h264.decoder");
-        sKnownCodecList.remove("OMX.ST.VFM.H264Dec");
-        sKnownCodecList.remove("OMX.vpu.video_decoder.avc");
-        sKnownCodecList.remove("OMX.WMT.decoder.avc");
-
-        // Really ?
-        sKnownCodecList.remove("OMX.bluestacks.hw.decoder");
-
-        // ---------------
-        // Useless codec
-        // ----- google -----
-        sKnownCodecList.put("OMX.google.h264.decoder", RANK_TESTED);
-        sKnownCodecList.put("OMX.google.h264.lc.decoder", RANK_SOFTWARE);
-        // ----- huawei k920 -----
-        sKnownCodecList.put("OMX.k3.ffmpeg.decoder", RANK_SOFTWARE);
-        sKnownCodecList.put("OMX.ffmpeg.video.decoder", RANK_SOFTWARE);
-        // ----- unknown -----
-        sKnownCodecList.put("OMX.sprd.soft.h264.decoder", RANK_SOFTWARE);
-
-        return sKnownCodecList;
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    public static IjkMediaCodecInfo setupCandidate(MediaCodecInfo codecInfo,
-            String mimeType) {
-        if (codecInfo == null
-                || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
-            return null;
-
-        String name = codecInfo.getName();
-        if (TextUtils.isEmpty(name))
-            return null;
-
-        name = name.toLowerCase(Locale.US);
-        int rank = RANK_NO_SENSE;
-        if (!name.startsWith("omx.")) {
-            rank = RANK_NON_STANDARD;
-        } else if (name.startsWith("omx.pv")) {
-            rank = RANK_SOFTWARE;
-        } else if (false && name.startsWith("omx.google.")) {
-            rank = RANK_SOFTWARE;
-        } else if (name.startsWith("omx.ffmpeg.")) {
-            rank = RANK_SOFTWARE;
-        } else if (name.startsWith("omx.k3.ffmpeg.")) {
-            rank = RANK_SOFTWARE;
-        } else if (name.startsWith("omx.avcodec.")) {
-            rank = RANK_SOFTWARE;
-        } else if (name.startsWith("omx.ittiam.")) {
-            // unknown codec in qualcomm SoC
-            rank = RANK_NO_SENSE;
-        } else if (name.startsWith("omx.mtk.")) {
-            // 1. MTK only works on 4.3 and above
-            // 2. MTK works on MIUI 6 (4.2.1)
-            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2)
-                rank = RANK_NO_SENSE;
-            else
-                rank = RANK_TESTED;
-        } else {
-            Integer knownRank = getKnownCodecList().get(name);
-            if (knownRank != null) {
-                rank = knownRank;
-            } else {
-                try {
-                    CodecCapabilities cap = codecInfo
-                            .getCapabilitiesForType(mimeType);
-                    if (cap != null)
-                        rank = RANK_ACCEPTABLE;
-                    else
-                        rank = RANK_LAST_CHANCE;
-                } catch (Throwable e) {
-                    rank = RANK_LAST_CHANCE;
-                }
-            }
-        }
-
-        IjkMediaCodecInfo candidate = new IjkMediaCodecInfo();
-        candidate.mCodecInfo = codecInfo;
-        candidate.mRank = rank;
-        candidate.mMimeType = mimeType;
-        return candidate;
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    public void dumpProfileLevels(String mimeType) {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
-            return;
-
-        try {
-            CodecCapabilities caps = mCodecInfo
-                    .getCapabilitiesForType(mimeType);
-            int maxProfile = 0;
-            int maxLevel = 0;
-            if (caps != null) {
-                if (caps.profileLevels != null) {
-                    for (CodecProfileLevel profileLevel : caps.profileLevels) {
-                        if (profileLevel == null)
-                            continue;
-
-                        maxProfile = Math.max(maxProfile, profileLevel.profile);
-                        maxLevel = Math.max(maxLevel, profileLevel.level);
-                    }
-                }
-            }
-
-            Log.i(TAG,
-                    String.format(Locale.US, "%s",
-                            getProfileLevelName(maxProfile, maxLevel)));
-        } catch (Throwable e) {
-            Log.i(TAG, "profile-level: exception");
-        }
-    }
-
-    public static String getProfileLevelName(int profile, int level) {
-        return String.format(Locale.US, " %s Profile Level %s (%d,%d)",
-                getProfileName(profile), getLevelName(level), profile, level);
-    }
-
-    public static String getProfileName(int profile) {
-        switch (profile) {
-        case CodecProfileLevel.AVCProfileBaseline:
-            return "Baseline";
-        case CodecProfileLevel.AVCProfileMain:
-            return "Main";
-        case CodecProfileLevel.AVCProfileExtended:
-            return "Extends";
-        case CodecProfileLevel.AVCProfileHigh:
-            return "High";
-        case CodecProfileLevel.AVCProfileHigh10:
-            return "High10";
-        case CodecProfileLevel.AVCProfileHigh422:
-            return "High422";
-        case CodecProfileLevel.AVCProfileHigh444:
-            return "High444";
-        default:
-            return "Unknown";
-        }
-    }
-
-    public static String getLevelName(int level) {
-        switch (level) {
-        case CodecProfileLevel.AVCLevel1:
-            return "1";
-        case CodecProfileLevel.AVCLevel1b:
-            return "1b";
-        case CodecProfileLevel.AVCLevel11:
-            return "11";
-        case CodecProfileLevel.AVCLevel12:
-            return "12";
-        case CodecProfileLevel.AVCLevel13:
-            return "13";
-        case CodecProfileLevel.AVCLevel2:
-            return "2";
-        case CodecProfileLevel.AVCLevel21:
-            return "21";
-        case CodecProfileLevel.AVCLevel22:
-            return "22";
-        case CodecProfileLevel.AVCLevel3:
-            return "3";
-        case CodecProfileLevel.AVCLevel31:
-            return "31";
-        case CodecProfileLevel.AVCLevel32:
-            return "32";
-        case CodecProfileLevel.AVCLevel4:
-            return "4";
-        case CodecProfileLevel.AVCLevel41:
-            return "41";
-        case CodecProfileLevel.AVCLevel42:
-            return "42";
-        case CodecProfileLevel.AVCLevel5:
-            return "5";
-        case CodecProfileLevel.AVCLevel51:
-            return "51";
-        case 65536: // CodecProfileLevel.AVCLevel52:
-            return "52";
-        default:
-            return "0";
-        }
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaMeta.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaMeta.java
deleted file mode 100644
index d2ba5f6..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaMeta.java
+++ /dev/null
@@ -1,401 +0,0 @@
-package tv.danmaku.ijk.media.player;
-
-import android.os.Bundle;
-import android.text.TextUtils;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-@SuppressWarnings("SameParameterValue")
-public class IjkMediaMeta {
-    // media meta
-    public static final String IJKM_KEY_FORMAT = "format";
-    public static final String IJKM_KEY_DURATION_US = "duration_us";
-    public static final String IJKM_KEY_START_US = "start_us";
-    public static final String IJKM_KEY_BITRATE = "bitrate";
-    public static final String IJKM_KEY_VIDEO_STREAM = "video";
-    public static final String IJKM_KEY_AUDIO_STREAM = "audio";
-    public static final String IJKM_KEY_TIMEDTEXT_STREAM = "timedtext";
-
-    // stream meta
-    public static final String IJKM_KEY_TYPE = "type";
-    public static final String IJKM_VAL_TYPE__VIDEO = "video";
-    public static final String IJKM_VAL_TYPE__AUDIO = "audio";
-    public static final String IJKM_VAL_TYPE__TIMEDTEXT = "timedtext";
-    public static final String IJKM_VAL_TYPE__UNKNOWN = "unknown";
-    public static final String IJKM_KEY_LANGUAGE = "language";
-
-    public static final String IJKM_KEY_CODEC_NAME = "codec_name";
-    public static final String IJKM_KEY_CODEC_PROFILE = "codec_profile";
-    public static final String IJKM_KEY_CODEC_LEVEL = "codec_level";
-    public static final String IJKM_KEY_CODEC_LONG_NAME = "codec_long_name";
-    public static final String IJKM_KEY_CODEC_PIXEL_FORMAT = "codec_pixel_format";
-    public static final String IJKM_KEY_CODEC_PROFILE_ID = "codec_profile_id";
-
-    // stream: video
-    public static final String IJKM_KEY_WIDTH = "width";
-    public static final String IJKM_KEY_HEIGHT = "height";
-    public static final String IJKM_KEY_FPS_NUM = "fps_num";
-    public static final String IJKM_KEY_FPS_DEN = "fps_den";
-    public static final String IJKM_KEY_TBR_NUM = "tbr_num";
-    public static final String IJKM_KEY_TBR_DEN = "tbr_den";
-    public static final String IJKM_KEY_SAR_NUM = "sar_num";
-    public static final String IJKM_KEY_SAR_DEN = "sar_den";
-    // stream: audio
-    public static final String IJKM_KEY_SAMPLE_RATE = "sample_rate";
-    public static final String IJKM_KEY_CHANNEL_LAYOUT = "channel_layout";
-
-    public static final String IJKM_KEY_STREAMS = "streams";
-
-    public static final long AV_CH_FRONT_LEFT = 0x00000001;
-    public static final long AV_CH_FRONT_RIGHT = 0x00000002;
-    public static final long AV_CH_FRONT_CENTER = 0x00000004;
-    public static final long AV_CH_LOW_FREQUENCY = 0x00000008;
-    public static final long AV_CH_BACK_LEFT = 0x00000010;
-    public static final long AV_CH_BACK_RIGHT = 0x00000020;
-    public static final long AV_CH_FRONT_LEFT_OF_CENTER = 0x00000040;
-    public static final long AV_CH_FRONT_RIGHT_OF_CENTER = 0x00000080;
-    public static final long AV_CH_BACK_CENTER = 0x00000100;
-    public static final long AV_CH_SIDE_LEFT = 0x00000200;
-    public static final long AV_CH_SIDE_RIGHT = 0x00000400;
-    public static final long AV_CH_TOP_CENTER = 0x00000800;
-    public static final long AV_CH_TOP_FRONT_LEFT = 0x00001000;
-    public static final long AV_CH_TOP_FRONT_CENTER = 0x00002000;
-    public static final long AV_CH_TOP_FRONT_RIGHT = 0x00004000;
-    public static final long AV_CH_TOP_BACK_LEFT = 0x00008000;
-    public static final long AV_CH_TOP_BACK_CENTER = 0x00010000;
-    public static final long AV_CH_TOP_BACK_RIGHT = 0x00020000;
-    public static final long AV_CH_STEREO_LEFT = 0x20000000;
-    public static final long AV_CH_STEREO_RIGHT = 0x40000000;
-    public static final long AV_CH_WIDE_LEFT = 0x0000000080000000L;
-    public static final long AV_CH_WIDE_RIGHT = 0x0000000100000000L;
-    public static final long AV_CH_SURROUND_DIRECT_LEFT = 0x0000000200000000L;
-    public static final long AV_CH_SURROUND_DIRECT_RIGHT = 0x0000000400000000L;
-    public static final long AV_CH_LOW_FREQUENCY_2 = 0x0000000800000000L;
-
-    public static final long AV_CH_LAYOUT_MONO = (AV_CH_FRONT_CENTER);
-    public static final long AV_CH_LAYOUT_STEREO = (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT);
-    public static final long AV_CH_LAYOUT_2POINT1 = (AV_CH_LAYOUT_STEREO | AV_CH_LOW_FREQUENCY);
-    public static final long AV_CH_LAYOUT_2_1 = (AV_CH_LAYOUT_STEREO | AV_CH_BACK_CENTER);
-    public static final long AV_CH_LAYOUT_SURROUND = (AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER);
-    public static final long AV_CH_LAYOUT_3POINT1 = (AV_CH_LAYOUT_SURROUND | AV_CH_LOW_FREQUENCY);
-    public static final long AV_CH_LAYOUT_4POINT0 = (AV_CH_LAYOUT_SURROUND | AV_CH_BACK_CENTER);
-    public static final long AV_CH_LAYOUT_4POINT1 = (AV_CH_LAYOUT_4POINT0 | AV_CH_LOW_FREQUENCY);
-    public static final long AV_CH_LAYOUT_2_2 = (AV_CH_LAYOUT_STEREO
-            | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT);
-    public static final long AV_CH_LAYOUT_QUAD = (AV_CH_LAYOUT_STEREO
-            | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT);
-    public static final long AV_CH_LAYOUT_5POINT0 = (AV_CH_LAYOUT_SURROUND
-            | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT);
-    public static final long AV_CH_LAYOUT_5POINT1 = (AV_CH_LAYOUT_5POINT0 | AV_CH_LOW_FREQUENCY);
-    public static final long AV_CH_LAYOUT_5POINT0_BACK = (AV_CH_LAYOUT_SURROUND
-            | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT);
-    public static final long AV_CH_LAYOUT_5POINT1_BACK = (AV_CH_LAYOUT_5POINT0_BACK | AV_CH_LOW_FREQUENCY);
-    public static final long AV_CH_LAYOUT_6POINT0 = (AV_CH_LAYOUT_5POINT0 | AV_CH_BACK_CENTER);
-    public static final long AV_CH_LAYOUT_6POINT0_FRONT = (AV_CH_LAYOUT_2_2
-            | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER);
-    public static final long AV_CH_LAYOUT_HEXAGONAL = (AV_CH_LAYOUT_5POINT0_BACK | AV_CH_BACK_CENTER);
-    public static final long AV_CH_LAYOUT_6POINT1 = (AV_CH_LAYOUT_5POINT1 | AV_CH_BACK_CENTER);
-    public static final long AV_CH_LAYOUT_6POINT1_BACK = (AV_CH_LAYOUT_5POINT1_BACK | AV_CH_BACK_CENTER);
-    public static final long AV_CH_LAYOUT_6POINT1_FRONT = (AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_LOW_FREQUENCY);
-    public static final long AV_CH_LAYOUT_7POINT0 = (AV_CH_LAYOUT_5POINT0
-            | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT);
-    public static final long AV_CH_LAYOUT_7POINT0_FRONT = (AV_CH_LAYOUT_5POINT0
-            | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER);
-    public static final long AV_CH_LAYOUT_7POINT1 = (AV_CH_LAYOUT_5POINT1
-            | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT);
-    public static final long AV_CH_LAYOUT_7POINT1_WIDE = (AV_CH_LAYOUT_5POINT1
-            | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER);
-    public static final long AV_CH_LAYOUT_7POINT1_WIDE_BACK = (AV_CH_LAYOUT_5POINT1_BACK
-            | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER);
-    public static final long AV_CH_LAYOUT_OCTAGONAL = (AV_CH_LAYOUT_5POINT0
-            | AV_CH_BACK_LEFT | AV_CH_BACK_CENTER | AV_CH_BACK_RIGHT);
-    public static final long AV_CH_LAYOUT_STEREO_DOWNMIX = (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT);
-
-    public static final int FF_PROFILE_H264_CONSTRAINED = (1<<9);  // 8+1; constraint_set1_flag
-    public static final int FF_PROFILE_H264_INTRA = (1<<11);       // 8+3; constraint_set3_flag
-
-    public static final int FF_PROFILE_H264_BASELINE = 66;
-    public static final int FF_PROFILE_H264_CONSTRAINED_BASELINE = (66|FF_PROFILE_H264_CONSTRAINED);
-    public static final int FF_PROFILE_H264_MAIN = 77;
-    public static final int FF_PROFILE_H264_EXTENDED = 88;
-    public static final int FF_PROFILE_H264_HIGH = 100;
-    public static final int FF_PROFILE_H264_HIGH_10 = 110;
-    public static final int FF_PROFILE_H264_HIGH_10_INTRA = (110|FF_PROFILE_H264_INTRA);
-    public static final int FF_PROFILE_H264_HIGH_422 = 122;
-    public static final int FF_PROFILE_H264_HIGH_422_INTRA = (122|FF_PROFILE_H264_INTRA);
-    public static final int FF_PROFILE_H264_HIGH_444 = 144;
-    public static final int FF_PROFILE_H264_HIGH_444_PREDICTIVE = 244;
-    public static final int FF_PROFILE_H264_HIGH_444_INTRA = (244|FF_PROFILE_H264_INTRA);
-    public static final int FF_PROFILE_H264_CAVLC_444 = 44;
-
-    public Bundle mMediaMeta;
-
-    public String mFormat;
-    public long mDurationUS;
-    public long mStartUS;
-    public long mBitrate;
-
-    public final ArrayList<IjkStreamMeta> mStreams = new ArrayList<IjkStreamMeta>();
-    public IjkStreamMeta mVideoStream;
-    public IjkStreamMeta mAudioStream;
-
-    public String getString(String key) {
-        return mMediaMeta.getString(key);
-    }
-
-    public int getInt(String key) {
-        return getInt(key, 0);
-    }
-
-    public int getInt(String key, int defaultValue) {
-        String value = getString(key);
-        if (TextUtils.isEmpty(value))
-            return defaultValue;
-
-        try {
-            return Integer.parseInt(value);
-        } catch (NumberFormatException e) {
-            return defaultValue;
-        }
-    }
-
-    public long getLong(String key) {
-        return getLong(key, 0);
-    }
-
-    public long getLong(String key, long defaultValue) {
-        String value = getString(key);
-        if (TextUtils.isEmpty(value))
-            return defaultValue;
-
-        try {
-            return Long.parseLong(value);
-        } catch (NumberFormatException e) {
-            return defaultValue;
-        }
-    }
-
-    public ArrayList<Bundle> getParcelableArrayList(String key) {
-        return mMediaMeta.getParcelableArrayList(key);
-    }
-
-    public String getDurationInline() {
-        long duration = mDurationUS + 5000;
-        long secs = duration / 1000000;
-        long mins = secs / 60;
-        secs %= 60;
-        long hours = mins / 60;
-        mins %= 60;
-        return String.format(Locale.US, "%02d:%02d:%02d", hours, mins, secs);
-    }
-
-    public static IjkMediaMeta parse(Bundle mediaMeta) {
-        if (mediaMeta == null)
-            return null;
-
-        IjkMediaMeta meta = new IjkMediaMeta();
-        meta.mMediaMeta = mediaMeta;
-
-        meta.mFormat = meta.getString(IJKM_KEY_FORMAT);
-        meta.mDurationUS = meta.getLong(IJKM_KEY_DURATION_US);
-        meta.mStartUS = meta.getLong(IJKM_KEY_START_US);
-        meta.mBitrate = meta.getLong(IJKM_KEY_BITRATE);
-
-        int videoStreamIndex = meta.getInt(IJKM_KEY_VIDEO_STREAM, -1);
-        int audioStreamIndex = meta.getInt(IJKM_KEY_AUDIO_STREAM, -1);
-        int subtitleStreamIndex = meta.getInt(IJKM_KEY_TIMEDTEXT_STREAM, -1);
-
-        ArrayList<Bundle> streams = meta
-                .getParcelableArrayList(IJKM_KEY_STREAMS);
-        if (streams == null)
-            return meta;
-
-        int index = -1;
-        for (Bundle streamBundle : streams) {
-            index++;
-
-            if (streamBundle == null) {
-                continue;
-            }
-
-            IjkStreamMeta streamMeta = new IjkStreamMeta(index);
-            streamMeta.mMeta = streamBundle;
-            streamMeta.mType = streamMeta.getString(IJKM_KEY_TYPE);
-            streamMeta.mLanguage = streamMeta.getString(IJKM_KEY_LANGUAGE);
-            if (TextUtils.isEmpty(streamMeta.mType))
-                continue;
-
-            streamMeta.mCodecName = streamMeta.getString(IJKM_KEY_CODEC_NAME);
-            streamMeta.mCodecProfile = streamMeta
-                    .getString(IJKM_KEY_CODEC_PROFILE);
-            streamMeta.mCodecLongName = streamMeta
-                    .getString(IJKM_KEY_CODEC_LONG_NAME);
-            streamMeta.mBitrate = streamMeta.getInt(IJKM_KEY_BITRATE);
-
-            if (streamMeta.mType.equalsIgnoreCase(IJKM_VAL_TYPE__VIDEO)) {
-                streamMeta.mWidth = streamMeta.getInt(IJKM_KEY_WIDTH);
-                streamMeta.mHeight = streamMeta.getInt(IJKM_KEY_HEIGHT);
-                streamMeta.mFpsNum = streamMeta.getInt(IJKM_KEY_FPS_NUM);
-                streamMeta.mFpsDen = streamMeta.getInt(IJKM_KEY_FPS_DEN);
-                streamMeta.mTbrNum = streamMeta.getInt(IJKM_KEY_TBR_NUM);
-                streamMeta.mTbrDen = streamMeta.getInt(IJKM_KEY_TBR_DEN);
-                streamMeta.mSarNum = streamMeta.getInt(IJKM_KEY_SAR_NUM);
-                streamMeta.mSarDen = streamMeta.getInt(IJKM_KEY_SAR_DEN);
-
-                if (videoStreamIndex == index) {
-                    meta.mVideoStream = streamMeta;
-                }
-            } else if (streamMeta.mType.equalsIgnoreCase(IJKM_VAL_TYPE__AUDIO)) {
-                streamMeta.mSampleRate = streamMeta
-                        .getInt(IJKM_KEY_SAMPLE_RATE);
-                streamMeta.mChannelLayout = streamMeta
-                        .getLong(IJKM_KEY_CHANNEL_LAYOUT);
-
-                if (audioStreamIndex == index) {
-                    meta.mAudioStream = streamMeta;
-                }
-            }
-            meta.mStreams.add(streamMeta);
-        }
-
-        return meta;
-    }
-
-    public static class IjkStreamMeta {
-        public Bundle mMeta;
-
-        public final int mIndex;
-        public String mType;
-        public String mLanguage;
-
-        // common
-        public String mCodecName;
-        public String mCodecProfile;
-        public String mCodecLongName;
-        public long mBitrate;
-
-        // video
-        public int mWidth;
-        public int mHeight;
-        public int mFpsNum;
-        public int mFpsDen;
-        public int mTbrNum;
-        public int mTbrDen;
-        public int mSarNum;
-        public int mSarDen;
-
-        // audio
-        public int mSampleRate;
-        public long mChannelLayout;
-
-        public IjkStreamMeta(int index) {
-            mIndex = index;
-        }
-
-        public String getString(String key) {
-            return mMeta.getString(key);
-        }
-
-        public int getInt(String key) {
-            return getInt(key, 0);
-        }
-
-        public int getInt(String key, int defaultValue) {
-            String value = getString(key);
-            if (TextUtils.isEmpty(value))
-                return defaultValue;
-
-            try {
-                return Integer.parseInt(value);
-            } catch (NumberFormatException e) {
-                return defaultValue;
-            }
-        }
-
-        public long getLong(String key) {
-            return getLong(key, 0);
-        }
-
-        public long getLong(String key, long defaultValue) {
-            String value = getString(key);
-            if (TextUtils.isEmpty(value))
-                return defaultValue;
-
-            try {
-                return Long.parseLong(value);
-            } catch (NumberFormatException e) {
-                return defaultValue;
-            }
-        }
-
-        public String getCodecLongNameInline() {
-            if (!TextUtils.isEmpty(mCodecLongName)) {
-                return mCodecLongName;
-            } else if (!TextUtils.isEmpty(mCodecName)) {
-                return mCodecName;
-            } else {
-                return "N/A";
-            }
-        }
-
-        public String getCodecShortNameInline() {
-            if (!TextUtils.isEmpty(mCodecName)) {
-                return mCodecName;
-            } else {
-                return "N/A";
-            }
-        }
-
-        public String getResolutionInline() {
-            if (mWidth <= 0 || mHeight <= 0) {
-                return "N/A";
-            } else if (mSarNum <= 0 || mSarDen <= 0) {
-                return String.format(Locale.US, "%d x %d", mWidth, mHeight);
-            } else {
-                return String.format(Locale.US, "%d x %d [SAR %d:%d]", mWidth,
-                        mHeight, mSarNum, mSarDen);
-            }
-        }
-
-        public String getFpsInline() {
-            if (mFpsNum <= 0 || mFpsDen <= 0) {
-                return "N/A";
-            } else {
-                return String.valueOf(((float) (mFpsNum)) / mFpsDen);
-            }
-        }
-
-        public String getBitrateInline() {
-            if (mBitrate <= 0) {
-                return "N/A";
-            } else if (mBitrate < 1000) {
-                return String.format(Locale.US, "%d bit/s", mBitrate);
-            } else {
-                return String.format(Locale.US, "%d kb/s", mBitrate / 1000);
-            }
-        }
-
-        public String getSampleRateInline() {
-            if (mSampleRate <= 0) {
-                return "N/A";
-            } else {
-                return String.format(Locale.US, "%d Hz", mSampleRate);
-            }
-        }
-
-        public String getChannelLayoutInline() {
-            if (mChannelLayout <= 0) {
-                return "N/A";
-            } else {
-                if (mChannelLayout == AV_CH_LAYOUT_MONO) {
-                    return "mono";
-                } else if (mChannelLayout == AV_CH_LAYOUT_STEREO) {
-                    return "stereo";
-                } else {
-                    return String.format(Locale.US, "%x", mChannelLayout);
-                }
-            }
-        }
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java
deleted file mode 100644
index f48de47..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java
+++ /dev/null
@@ -1,1365 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- * Copyright (C) 2013 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player;
-
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.graphics.SurfaceTexture;
-import android.graphics.Rect;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-
-import java.io.FileDescriptor;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
-import java.security.InvalidParameterException;
-import java.util.ArrayList;
-import java.util.Locale;
-import java.util.Map;
-
-import tv.danmaku.ijk.media.player.annotations.AccessedByNative;
-import tv.danmaku.ijk.media.player.annotations.CalledByNative;
-import tv.danmaku.ijk.media.player.misc.IIjkIOHttp;
-import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
-import tv.danmaku.ijk.media.player.misc.ITrackInfo;
-import tv.danmaku.ijk.media.player.misc.IjkTrackInfo;
-import tv.danmaku.ijk.media.player.pragma.DebugLog;
-
-/**
- * @author bbcallen
- *
- * Java wrapper of ffplay.
- */
-public final class IjkMediaPlayer extends AbstractMediaPlayer {
-
-    static {
-        sLocalLibLoader = new IjkLibLoader() {
-            @Override
-            public void loadLibrary(String libName) throws UnsatisfiedLinkError, SecurityException {
-                System.loadLibrary(libName);
-            }
-        };
-
-        IjkMediaPlayer.loadLibrariesOnce(null);
-    }
-
-    private final static String TAG = "PRO";
-
-    private static final int MEDIA_NOP = 0; // interface test message
-    private static final int MEDIA_PREPARED = 1;
-    private static final int MEDIA_PLAYBACK_COMPLETE = 2;
-    private static final int MEDIA_BUFFERING_UPDATE = 3;
-    private static final int MEDIA_SEEK_COMPLETE = 4;
-    private static final int MEDIA_SET_VIDEO_SIZE = 5;
-    private static final int MEDIA_TIMED_TEXT = 99;
-    private static final int MEDIA_ERROR = 100;
-    private static final int MEDIA_INFO = 200;
-
-    protected static final int MEDIA_SET_VIDEO_SAR = 10001;
-
-    //----------------------------------------
-    // options
-    public static final int IJK_LOG_UNKNOWN = 0;
-    public static final int IJK_LOG_DEFAULT = 1;
-
-    public static final int IJK_LOG_VERBOSE = 2;
-    public static final int IJK_LOG_DEBUG = 3;
-    public static final int IJK_LOG_INFO = 4;
-    public static final int IJK_LOG_WARN = 5;
-    public static final int IJK_LOG_ERROR = 6;
-    public static final int IJK_LOG_FATAL = 7;
-    public static final int IJK_LOG_SILENT = 8;
-
-    public static final int OPT_CATEGORY_FORMAT     = 1;
-    public static final int OPT_CATEGORY_CODEC      = 2;
-    public static final int OPT_CATEGORY_SWS        = 3;
-    public static final int OPT_CATEGORY_PLAYER     = 4;
-
-    public static final int SDL_FCC_YV12 = 0x32315659; // YV12
-    public static final int SDL_FCC_RV16 = 0x36315652; // RGB565
-    public static final int SDL_FCC_RV32 = 0x32335652; // RGBX8888
-    //----------------------------------------
-
-    //----------------------------------------
-    // properties
-    public static final int PROP_FLOAT_VIDEO_DECODE_FRAMES_PER_SECOND       = 10001;
-    public static final int PROP_FLOAT_VIDEO_OUTPUT_FRAMES_PER_SECOND       = 10002;
-    public static final int FFP_PROP_FLOAT_PLAYBACK_RATE                    = 10003;
-
-    public static final int FFP_PROP_INT64_SELECTED_VIDEO_STREAM            = 20001;
-    public static final int FFP_PROP_INT64_SELECTED_AUDIO_STREAM            = 20002;
-    public static final int FFP_PROP_INT64_SELECTED_TIMEDTEXT_STREAM        = 20011;
-
-    public static final int FFP_PROP_INT64_VIDEO_DECODER                    = 20003;
-    public static final int FFP_PROP_INT64_AUDIO_DECODER                    = 20004;
-    public static final int     FFP_PROPV_DECODER_UNKNOWN                   = 0;
-    public static final int     FFP_PROPV_DECODER_AVCODEC                   = 1;
-    public static final int     FFP_PROPV_DECODER_MEDIACODEC                = 2;
-    public static final int     FFP_PROPV_DECODER_VIDEOTOOLBOX              = 3;
-    public static final int FFP_PROP_INT64_VIDEO_CACHED_DURATION            = 20005;
-    public static final int FFP_PROP_INT64_AUDIO_CACHED_DURATION            = 20006;
-    public static final int FFP_PROP_INT64_VIDEO_CACHED_BYTES               = 20007;
-    public static final int FFP_PROP_INT64_AUDIO_CACHED_BYTES               = 20008;
-    public static final int FFP_PROP_INT64_VIDEO_CACHED_PACKETS             = 20009;
-    public static final int FFP_PROP_INT64_AUDIO_CACHED_PACKETS             = 20010;
-    public static final int FFP_PROP_INT64_ASYNC_STATISTIC_BUF_BACKWARDS    = 20201;
-    public static final int FFP_PROP_INT64_ASYNC_STATISTIC_BUF_FORWARDS     = 20202;
-    public static final int FFP_PROP_INT64_ASYNC_STATISTIC_BUF_CAPACITY     = 20203;
-    public static final int FFP_PROP_INT64_TRAFFIC_STATISTIC_BYTE_COUNT     = 20204;
-    public static final int FFP_PROP_INT64_CACHE_STATISTIC_PHYSICAL_POS     = 20205;
-    public static final int FFP_PROP_INT64_CACHE_STATISTIC_BUF_FORWARDS     = 20206;
-    public static final int FFP_PROP_INT64_CACHE_STATISTIC_FILE_POS         = 20207;
-    public static final int FFP_PROP_INT64_CACHE_STATISTIC_COUNT_BYTES      = 20208;
-    public static final int FFP_PROP_INT64_STATISTIC_COUNT_BYTES            = 20209;
-    public static final int FFP_PROP_INT64_STATISTIC_COUNT_FRAMES           = 20210;
-
-
-    public static final int FFP_PROP_INT64_BIT_RATE                         = 20100;
-    public static final int FFP_PROP_INT64_TCP_SPEED                        = 20200;
-    public static final int FFP_PROP_INT64_LATEST_SEEK_LOAD_DURATION        = 20300;
-    //----------------------------------------
-
-    @AccessedByNative
-    private long mNativeMediaPlayer;
-
-    @AccessedByNative
-    private long mNativeMediaDataSource;
-
-    @AccessedByNative
-    private long mNativeIjkIOHttp;
-
-    @AccessedByNative
-    private int mNativeSurfaceTexture;
-
-    @AccessedByNative
-    private int mListenerContext;
-
-    private SurfaceHolder mSurfaceHolder;
-    private EventHandler mEventHandler;
-    private PowerManager.WakeLock mWakeLock = null;
-    private boolean mScreenOnWhilePlaying;
-    private boolean mStayAwake;
-
-    private int mVideoWidth;
-    private int mVideoHeight;
-    private int mVideoSarNum;
-    private int mVideoSarDen;
-
-    private String mDataSource;
-    private final Context ctx;
-
-    /**
-     * Default library loader
-     * Load them by yourself, if your libraries are not installed at default place.
-     */
-    private static final IjkLibLoader sLocalLibLoader;
-
-    private static volatile boolean mIsLibLoaded = false;
-    private int mAudioStream;
-    private Surface mSurface;
-
-    public static void loadLibrariesOnce(IjkLibLoader libLoader) {
-        synchronized (IjkMediaPlayer.class) {
-            if (!mIsLibLoaded) {
-                if (libLoader == null)
-                    libLoader = sLocalLibLoader;
-
-                libLoader.loadLibrary("proffmpeg");
-                libLoader.loadLibrary("prosdl");
-                libLoader.loadLibrary("proplayer");
-                mIsLibLoaded = true;
-            }
-        }
-    }
-
-    private static volatile boolean mIsNativeInitialized = false;
-
-    private static void initNativeOnce() {
-        synchronized (IjkMediaPlayer.class) {
-            if (!mIsNativeInitialized) {
-                native_init();
-                mIsNativeInitialized = true;
-            }
-        }
-    }
-
-    /**
-     * Default constructor. Consider using one of the create() methods for
-     * synchronously instantiating a IjkMediaPlayer from a Uri or resource.
-     * <p>
-     * When done with the IjkMediaPlayer, you should call {@link #release()}, to
-     * free the resources. If not released, too many IjkMediaPlayer instances
-     * may result in an exception.
-     * </p>
-     */
-    public IjkMediaPlayer(Context context,String key) {
-        this(context, sLocalLibLoader, key);
-    }
-
-    /**
-     * do not loadLibaray
-     * @param libLoader
-     *              custom library loader, can be null.
-     */
-    public IjkMediaPlayer(Context context, IjkLibLoader libLoader, String key) {
-        ctx = context;
-        initPlayer(libLoader, key);
-    }
-
-    private void initPlayer(IjkLibLoader libLoader, String key) {
-        loadLibrariesOnce(libLoader);
-        initNativeOnce();
-
-        Looper looper;
-
-        if ((looper = Looper.myLooper()) != null) {
-            mEventHandler = new EventHandler(this, looper);
-        } else if ((looper = Looper.getMainLooper()) != null) {
-            mEventHandler = new EventHandler(this, looper);
-        } else {
-            mEventHandler = null;
-        }
-
-        /*
-         * Native setup requires a weak reference to our object. It's easier to
-         * create it here than in C++.
-         */
-        try {
-            native_setup(ctx, new WeakReference<IjkMediaPlayer>(this), key);
-        } catch (Throwable ex) {
-            throw new IllegalStateException("Key不合法或已过期");
-        }
-
-//        native_setup(new WeakReference<IjkMediaPlayer>(this));
-    }
-
-    /*
-     * Update the IjkMediaPlayer SurfaceTexture. Call after setting a new
-     * display surface.
-     */
-    private native void _setVideoSurface(Surface surface);
-
-    /**
-     * Sets the {@link SurfaceHolder} to use for displaying the video portion of
-     * the media.
-     *
-     * Either a surface holder or surface must be set if a display or video sink
-     * is needed. Not calling this method or {@link #setSurface(Surface)} when
-     * playing back a video will result in only the audio track being played. A
-     * null surface holder or surface will result in only the audio track being
-     * played.
-     *
-     * @param sh
-     *            the SurfaceHolder to use for video display
-     */
-    @Override
-    public void setDisplay(SurfaceHolder sh) {
-        mSurfaceHolder = sh;
-        Surface surface;
-
-        if (sh != null) {
-            surface = sh.getSurface();
-        } else {
-            surface = null;
-        }
-
-        _setVideoSurface(surface);
-        updateSurfaceScreenOn();
-    }
-
-    public boolean isSurfaceValid(){
-        return mSurface != null || mSurfaceHolder != null;
-    }
-
-    /**
-     * Sets the {@link Surface} to be used as the sink for the video portion of
-     * the media. This is similar to {@link #setDisplay(SurfaceHolder)}, but
-     * does not support {@link #setScreenOnWhilePlaying(boolean)}. Setting a
-     * Surface will un-set any Surface or SurfaceHolder that was previously set.
-     * A null surface will result in only the audio track being played.
-     *
-     * If the Surface sends frames to a {@link SurfaceTexture}, the timestamps
-     * returned from {@link SurfaceTexture#getTimestamp()} will have an
-     * unspecified zero point. These timestamps cannot be directly compared
-     * between different media sources, different instances of the same media
-     * source, or multiple runs of the same program. The timestamp is normally
-     * monotonically increasing and is unaffected by time-of-day adjustments,
-     * but it is reset when the position is set.
-     *
-     * @param surface
-     *            The {@link Surface} to be used for the video portion of the
-     *            media.
-     */
-    @Override
-    public void setSurface(Surface surface) {
-        if (mScreenOnWhilePlaying && surface != null) {
-            DebugLog.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface");
-        }
-
-        mSurfaceHolder = null;
-        _setVideoSurface(surface);
-        updateSurfaceScreenOn();
-        mSurface = surface;
-    }
-
-    /**
-     * Sets the data source as a content Uri.
-     *
-     * @param context the Context to use when resolving the Uri
-     * @param uri the Content URI of the data you want to play
-     * @throws IllegalStateException if it is called in an invalid state
-     */
-    @Override
-    public void setDataSource(Context context, Uri uri) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
-        setDataSource(context, uri, null);
-    }
-
-    /**
-     * Sets the data source as a content Uri.
-     *
-     * @param context the Context to use when resolving the Uri
-     * @param uri the Content URI of the data you want to play
-     * @param headers the headers to be sent together with the request for the data
-     *                Note that the cross domain redirection is allowed by default, but that can be
-     *                changed with key/value pairs through the headers parameter with
-     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
-     *                to disallow or allow cross domain redirection.
-     * @throws IllegalStateException if it is called in an invalid state
-     */
-    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
-    @Override
-    public void setDataSource(Context context, Uri uri, Map<String, String> headers)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
-        final String scheme = uri.getScheme();
-
-        if (ContentResolver.SCHEME_FILE.equals(scheme)) {
-            setDataSource(uri.getPath());
-            return;
-        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
-                && Settings.AUTHORITY.equals(uri.getAuthority())) {
-            // Redirect ringtones to go directly to underlying provider
-            uri = RingtoneManager.getActualDefaultRingtoneUri(context,
-                    RingtoneManager.getDefaultType(uri));
-            if (uri == null) {
-                throw new FileNotFoundException("Failed to resolve default ringtone");
-            }
-        }
-
-        AssetFileDescriptor fd = null;
-
-        try {
-            ContentResolver resolver = context.getContentResolver();
-            fd = resolver.openAssetFileDescriptor(uri, "r");
-
-            if (fd == null) {
-                return;
-            }
-
-            // Note: using getDeclaredLength so that our behavior is the same
-            // as previous versions when the content provider is returning
-            // a full file.
-            if (fd.getDeclaredLength() < 0) {
-                setDataSource(fd.getFileDescriptor());
-            } else {
-                setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength());
-            }
-
-            return;
-        } catch (SecurityException ignored) {
-
-        } catch (IOException ignored) {
-
-        } finally {
-            if (fd != null) {
-                fd.close();
-            }
-        }
-
-        Log.d(TAG, "Couldn't open file on client side, trying server side");
-
-        setDataSource(uri.toString(), headers);
-    }
-
-    /**
-     * Sets the data source (file-path or http/rtsp URL) to use.
-     *
-     * @param path
-     *            the path of the file, or the http/rtsp URL of the stream you
-     *            want to play
-     * @throws IllegalStateException
-     *             if it is called in an invalid state
-     *
-     *             <p>
-     *             When <code>path</code> refers to a local file, the file may
-     *             actually be opened by a process other than the calling
-     *             application. This implies that the pathname should be an
-     *             absolute path (as any other process runs with unspecified
-     *             current working directory), and that the pathname should
-     *             reference a world-readable file.
-     */
-    @Override
-    public void setDataSource(String path)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
-        mDataSource = path;
-        mCompleted = false;
-        _setDataSource(path, null, null);
-    }
-
-    /**
-     * Sets the data source (file-path or http/rtsp URL) to use.
-     *
-     * @param path the path of the file, or the http/rtsp URL of the stream you want to play
-     * @param headers the headers associated with the http request for the stream you want to play
-     * @throws IllegalStateException if it is called in an invalid state
-     */
-    public void setDataSource(String path, Map<String, String> headers)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
-        if (headers != null && !headers.isEmpty()) {
-            StringBuilder sb = new StringBuilder();
-
-            for(Map.Entry<String, String> entry: headers.entrySet()) {
-                sb.append(entry.getKey());
-                sb.append(":");
-                String value = entry.getValue();
-
-                if (!TextUtils.isEmpty(value))
-                    sb.append(entry.getValue());
-
-                sb.append("\r\n");
-                setOption(OPT_CATEGORY_FORMAT, "headers", sb.toString());
-                setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "protocol_whitelist", "async,cache,crypto,file,http,https,ijkhttphook,ijkinject,ijklivehook,ijklongurl,ijksegment,ijktcphook,pipe,rtp,tcp,tls,udp,ijkurlhook,data");
-            }
-        }
-
-        setDataSource(path);
-    }
-
-    /**
-     * Sets the data source (FileDescriptor) to use. It is the caller's responsibility
-     * to close the file descriptor. It is safe to do so as soon as this call returns.
-     *
-     * @param fd the FileDescriptor for the file you want to play
-     * @throws IllegalStateException if it is called in an invalid state
-     */
-    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
-    @Override
-    public void setDataSource(FileDescriptor fd)
-            throws IOException, IllegalArgumentException, IllegalStateException {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
-            int native_fd = -1;
-
-            try {
-                Field f = fd.getClass().getDeclaredField("descriptor"); //NoSuchFieldException
-                f.setAccessible(true);
-                native_fd = f.getInt(fd); //IllegalAccessException
-            } catch (NoSuchFieldException e) {
-                throw new RuntimeException(e);
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException(e);
-            }
-            _setDataSourceFd(native_fd);
-        } else {
-            ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fd);
-
-            try {
-                _setDataSourceFd(pfd.getFd());
-            } finally {
-                pfd.close();
-            }
-        }
-    }
-
-    /**
-     * Sets the data source (FileDescriptor) to use.  The FileDescriptor must be
-     * seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility
-     * to close the file descriptor. It is safe to do so as soon as this call returns.
-     *
-     * @param fd the FileDescriptor for the file you want to play
-     * @param offset the offset into the file where the data to be played starts, in bytes
-     * @param length the length in bytes of the data to be played
-     * @throws IllegalStateException if it is called in an invalid state
-     */
-    private void setDataSource(FileDescriptor fd, long offset, long length)
-            throws IOException, IllegalArgumentException, IllegalStateException {
-        // FIXME: handle offset, length
-        setDataSource(fd);
-    }
-
-    public void setDataSource(IMediaDataSource mediaDataSource)
-            throws IllegalArgumentException, SecurityException, IllegalStateException {
-        _setDataSource(mediaDataSource);
-    }
-
-    public void setDataSourceIjkIOHttp(IIjkIOHttp ijkIOHttp)
-            throws IllegalArgumentException, SecurityException, IllegalStateException {
-        _setDataSourceIjkIOHttp(ijkIOHttp);
-    }
-
-    private native void _setDataSource(String path, String[] keys, String[] values)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
-
-    private native void _setDataSourceFd(int fd)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
-
-    private native void _setDataSource(IMediaDataSource mediaDataSource)
-            throws IllegalArgumentException, SecurityException, IllegalStateException;
-
-    private native void _setDataSourceIjkIOHttp(IIjkIOHttp ijkIOHttp)
-            throws IllegalArgumentException, SecurityException, IllegalStateException;
-
-    @Override
-    public String getDataSource() {
-        return mDataSource;
-    }
-
-    @Override
-    public void prepareAsync() throws IllegalStateException {
-        _prepareAsync();
-    }
-
-    public native void _prepareAsync() throws IllegalStateException;
-
-    @Override
-    public void start() throws IllegalStateException {
-        mCompleted = false;
-        stayAwake(true);
-        _start();
-    }
-
-    private native void _start() throws IllegalStateException;
-
-    @Override
-    public void stop() throws IllegalStateException {
-        mCompleted = false;
-        stayAwake(false);
-        _stop();
-    }
-
-    private native void _stop() throws IllegalStateException;
-
-    @Override
-    public void pause() throws IllegalStateException {
-        stayAwake(false);
-        _pause();
-    }
-
-    private native void _pause() throws IllegalStateException;
-
-    @SuppressLint("Wakelock")
-    @Override
-    public void setWakeMode(Context context, int mode) {
-        boolean washeld = false;
-
-        if (mWakeLock != null) {
-            if (mWakeLock.isHeld()) {
-                washeld = true;
-                mWakeLock.release();
-            }
-
-            mWakeLock = null;
-        }
-
-        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(mode | PowerManager.ON_AFTER_RELEASE, IjkMediaPlayer.class.getName());
-        mWakeLock.setReferenceCounted(false);
-
-        if (washeld) {
-            mWakeLock.acquire();
-        }
-    }
-
-    @Override
-    public void setScreenOnWhilePlaying(boolean screenOn) {
-        if (mScreenOnWhilePlaying != screenOn) {
-            if (screenOn && mSurfaceHolder == null) {
-                DebugLog.w(TAG, "setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder");
-            }
-
-            mScreenOnWhilePlaying = screenOn;
-            updateSurfaceScreenOn();
-        }
-    }
-
-    @SuppressLint("Wakelock")
-    private void stayAwake(boolean awake) {
-        if (mWakeLock != null) {
-            if (awake && !mWakeLock.isHeld()) {
-                mWakeLock.acquire();
-            } else if (!awake && mWakeLock.isHeld()) {
-                mWakeLock.release();
-            }
-        }
-
-        mStayAwake = awake;
-        updateSurfaceScreenOn();
-    }
-
-    private void updateSurfaceScreenOn() {
-        if (mSurfaceHolder != null) {
-            mSurfaceHolder.setKeepScreenOn(mScreenOnWhilePlaying && mStayAwake);
-        }
-    }
-
-    @Override
-    public IjkTrackInfo[] getTrackInfo() {
-        Bundle bundle = getMediaMeta();
-        if (bundle == null)
-            return null;
-
-        IjkMediaMeta mediaMeta = IjkMediaMeta.parse(bundle);
-        if (mediaMeta == null || mediaMeta.mStreams == null)
-            return null;
-
-        ArrayList<IjkTrackInfo> trackInfos = new ArrayList<IjkTrackInfo>();
-        for (IjkMediaMeta.IjkStreamMeta streamMeta: mediaMeta.mStreams) {
-            IjkTrackInfo trackInfo = new IjkTrackInfo(streamMeta);
-
-            if (streamMeta.mType.equalsIgnoreCase(IjkMediaMeta.IJKM_VAL_TYPE__VIDEO)) {
-                trackInfo.setTrackType(ITrackInfo.MEDIA_TRACK_TYPE_VIDEO);
-            } else if (streamMeta.mType.equalsIgnoreCase(IjkMediaMeta.IJKM_VAL_TYPE__AUDIO)) {
-                trackInfo.setTrackType(ITrackInfo.MEDIA_TRACK_TYPE_AUDIO);
-            } else if (streamMeta.mType.equalsIgnoreCase(IjkMediaMeta.IJKM_VAL_TYPE__TIMEDTEXT)) {
-                trackInfo.setTrackType(ITrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT);
-            }
-
-            trackInfos.add(trackInfo);
-        }
-
-        return trackInfos.toArray(new IjkTrackInfo[trackInfos.size()]);
-    }
-
-    // TODO: @Override
-    public int getSelectedTrack(int trackType) {
-        switch (trackType) {
-            case ITrackInfo.MEDIA_TRACK_TYPE_VIDEO:
-                return (int)_getPropertyLong(FFP_PROP_INT64_SELECTED_VIDEO_STREAM, -1);
-            case ITrackInfo.MEDIA_TRACK_TYPE_AUDIO:
-                return (int)_getPropertyLong(FFP_PROP_INT64_SELECTED_AUDIO_STREAM, -1);
-            case ITrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT:
-                return (int)_getPropertyLong(FFP_PROP_INT64_SELECTED_TIMEDTEXT_STREAM, -1);
-            default:
-                return -1;
-        }
-    }
-
-    // experimental, should set DEFAULT_MIN_FRAMES and MAX_MIN_FRAMES to 25
-    // TODO: @Override
-    public void selectTrack(int track) {
-        _setStreamSelected(track, true);
-    }
-
-    // experimental, should set DEFAULT_MIN_FRAMES and MAX_MIN_FRAMES to 25
-    // TODO: @Override
-    public void deselectTrack(int track) {
-        _setStreamSelected(track, false);
-    }
-
-    private native void _setStreamSelected(int stream, boolean select);
-
-    @Override
-    public int getVideoWidth() {
-        return mVideoWidth;
-    }
-
-    @Override
-    public int getVideoHeight() {
-        return mVideoHeight;
-    }
-
-    @Override
-    public int getVideoSarNum() {
-        return mVideoSarNum;
-    }
-
-    @Override
-    public int getVideoSarDen() {
-        return mVideoSarDen;
-    }
-
-    @Override
-    public native boolean isPlaying();
-
-    @Override
-    public native void seekTo(long msec) throws IllegalStateException;
-
-    @Override
-    public native long getCurrentPosition();
-
-    @Override
-    public native long getDuration();
-
-    /**
-     * Releases resources associated with this IjkMediaPlayer object. It is
-     * considered good practice to call this method when you're done using the
-     * IjkMediaPlayer. In particular, whenever an Activity of an application is
-     * paused (its onPause() method is called), or stopped (its onStop() method
-     * is called), this method should be invoked to release the IjkMediaPlayer
-     * object, unless the application has a special need to keep the object
-     * around. In addition to unnecessary resources (such as memory and
-     * instances of codecs) being held, failure to call this method immediately
-     * if a IjkMediaPlayer object is no longer needed may also lead to
-     * continuous battery consumption for mobile devices, and playback failure
-     * for other applications if no multiple instances of the same codec are
-     * supported on a device. Even if multiple instances of the same codec are
-     * supported, some performance degradation may be expected when unnecessary
-     * multiple instances are used at the same time.
-     */
-    @Override
-    public void release() {
-        stayAwake(false);
-        updateSurfaceScreenOn();
-        resetListeners();
-        _release();
-    }
-
-    private native void _release();
-
-    @Override
-    public void reset() {
-        stayAwake(false);
-        _reset();
-        // make sure none of the listeners get called anymore
-        mEventHandler.removeCallbacksAndMessages(null);
-
-        mVideoWidth = 0;
-        mVideoHeight = 0;
-    }
-
-    private native void _reset();
-
-    /**
-     * Sets the player to be looping or non-looping.
-     *
-     * @param looping whether to loop or not
-     */
-    @Override
-    public void setLooping(boolean looping) {
-        int loopCount = looping ? 0 : 1;
-        setOption(OPT_CATEGORY_PLAYER, "loop", loopCount);
-        _setLoopCount(loopCount);
-    }
-
-    private native void _setLoopCount(int loopCount);
-
-    /**
-     * Checks whether the MediaPlayer is looping or non-looping.
-     *
-     * @return true if the MediaPlayer is currently looping, false otherwise
-     */
-    @Override
-    public boolean isLooping() {
-        int loopCount = _getLoopCount();
-        return loopCount != 1;
-    }
-
-    private native int _getLoopCount();
-
-    public void setSpeed(float speed) {
-        int selectedTrack = getSelectedTrack(ITrackInfo.MEDIA_TRACK_TYPE_AUDIO);
-
-        if (selectedTrack != -1) {
-            mAudioStream = selectedTrack;
-        }
-
-        if (speed != 1.0f) {
-            deselectTrack(mAudioStream);
-            _setPropertyFloat(FFP_PROP_FLOAT_PLAYBACK_RATE, speed);
-        } else {
-            _setPropertyFloat(FFP_PROP_FLOAT_PLAYBACK_RATE, speed);
-            selectTrack(mAudioStream);
-
-//            long pos = getCurrentPosition();
-//            stop();
-//            try {
-//                setDataSource(mDataSource);
-//                prepareAsync();
-//                start();
-//                seekTo(pos);
-//            } catch (IOException e) {
-//                e.printStackTrace();
-//            }
-        }
-    }
-
-    public float getSpeed() {
-        return _getPropertyFloat(FFP_PROP_FLOAT_PLAYBACK_RATE, .0f);
-    }
-
-    public int getVideoDecoder() {
-        return (int)_getPropertyLong(FFP_PROP_INT64_VIDEO_DECODER, FFP_PROPV_DECODER_UNKNOWN);
-    }
-
-    public float getVideoOutputFramesPerSecond() {
-        return _getPropertyFloat(PROP_FLOAT_VIDEO_OUTPUT_FRAMES_PER_SECOND, 0.0f);
-    }
-
-    public float getVideoDecodeFramesPerSecond() {
-        return _getPropertyFloat(PROP_FLOAT_VIDEO_DECODE_FRAMES_PER_SECOND, 0.0f);
-    }
-
-    public long getVideoCachedDuration() {
-        return _getPropertyLong(FFP_PROP_INT64_VIDEO_CACHED_DURATION, 0);
-    }
-
-    public long getAudioCachedDuration() {
-        return _getPropertyLong(FFP_PROP_INT64_AUDIO_CACHED_DURATION, 0);
-    }
-
-    public long getVideoCachedBytes() {
-        return _getPropertyLong(FFP_PROP_INT64_VIDEO_CACHED_BYTES, 0);
-    }
-
-    public long getAudioCachedBytes() {
-        return _getPropertyLong(FFP_PROP_INT64_AUDIO_CACHED_BYTES, 0);
-    }
-
-    public long getVideoCachedPackets() {
-        return _getPropertyLong(FFP_PROP_INT64_VIDEO_CACHED_PACKETS, 0);
-    }
-
-    public long getReceivedBytes() {
-        return _getPropertyLong(FFP_PROP_INT64_STATISTIC_COUNT_BYTES, 0);
-    }
-
-    public long getReceivedVideoFrames() {
-        return _getPropertyLong(FFP_PROP_INT64_STATISTIC_COUNT_FRAMES, 0);
-    }
-
-    public long getAudioCachedPackets() {
-        return _getPropertyLong(FFP_PROP_INT64_AUDIO_CACHED_PACKETS, 0);
-    }
-
-    public long getAsyncStatisticBufBackwards() {
-        return _getPropertyLong(FFP_PROP_INT64_ASYNC_STATISTIC_BUF_BACKWARDS, 0);
-    }
-
-    public long getAsyncStatisticBufForwards() {
-        return _getPropertyLong(FFP_PROP_INT64_ASYNC_STATISTIC_BUF_FORWARDS, 0);
-    }
-
-    public long getAsyncStatisticBufCapacity() {
-        return _getPropertyLong(FFP_PROP_INT64_ASYNC_STATISTIC_BUF_CAPACITY, 0);
-    }
-
-    public long getTrafficStatisticByteCount() {
-        return _getPropertyLong(FFP_PROP_INT64_TRAFFIC_STATISTIC_BYTE_COUNT, 0);
-    }
-
-    public long getCacheStatisticPhysicalPos() {
-        return _getPropertyLong(FFP_PROP_INT64_CACHE_STATISTIC_PHYSICAL_POS, 0);
-    }
-
-    public long getCacheStatisticBufForwards() {
-        return _getPropertyLong(FFP_PROP_INT64_CACHE_STATISTIC_BUF_FORWARDS, 0);
-    }
-
-    public long getCacheStatisticFilePos() {
-        return _getPropertyLong(FFP_PROP_INT64_CACHE_STATISTIC_FILE_POS, 0);
-    }
-
-    public long getCacheStatisticCountBytes() {
-        return _getPropertyLong(FFP_PROP_INT64_CACHE_STATISTIC_COUNT_BYTES, 0);
-    }
-
-    public long getBitRate() {
-        return _getPropertyLong(FFP_PROP_INT64_BIT_RATE, 0);
-    }
-
-    public long getTcpSpeed() {
-        return _getPropertyLong(FFP_PROP_INT64_TCP_SPEED, 0);
-    }
-
-    public long getSeekLoadDuration() {
-        return _getPropertyLong(FFP_PROP_INT64_LATEST_SEEK_LOAD_DURATION, 0);
-    }
-
-    private native float _getPropertyFloat(int property, float defaultValue);
-    private native void  _setPropertyFloat(int property, float value);
-    private native long  _getPropertyLong(int property, long defaultValue);
-    private native void  _setPropertyLong(int property, long value);
-
-    @Override
-    public native void setVolume(float leftVolume, float rightVolume);
-
-    @Override
-    public native int getAudioSessionId();
-
-    @Override
-    public MediaInfo getMediaInfo() {
-        MediaInfo mediaInfo = new MediaInfo();
-        mediaInfo.mMediaPlayerName = "ijkplayer";
-
-        String videoCodecInfo = _getVideoCodecInfo();
-
-        if (!TextUtils.isEmpty(videoCodecInfo)) {
-            String nodes[] = videoCodecInfo.split(",");
-
-            if (nodes.length >= 2) {
-                mediaInfo.mVideoDecoder = nodes[0];
-                mediaInfo.mVideoDecoderImpl = nodes[1];
-            } else if (nodes.length >= 1) {
-                mediaInfo.mVideoDecoder = nodes[0];
-                mediaInfo.mVideoDecoderImpl = "";
-            }
-        }
-
-        String audioCodecInfo = _getAudioCodecInfo();
-
-        if (!TextUtils.isEmpty(audioCodecInfo)) {
-            String nodes[] = audioCodecInfo.split(",");
-
-            if (nodes.length >= 2) {
-                mediaInfo.mAudioDecoder = nodes[0];
-                mediaInfo.mAudioDecoderImpl = nodes[1];
-            } else if (nodes.length >= 1) {
-                mediaInfo.mAudioDecoder = nodes[0];
-                mediaInfo.mAudioDecoderImpl = "";
-            }
-        }
-
-        try {
-            mediaInfo.mMeta = IjkMediaMeta.parse(_getMediaMeta());
-        } catch (Throwable e) {
-            e.printStackTrace();
-        }
-
-        return mediaInfo;
-    }
-
-    @Override
-    public void setLogEnabled(boolean enable) {
-        // do nothing
-    }
-
-    @Override
-    public boolean isPlayable() {
-        return true;
-    }
-
-    private native String _getVideoCodecInfo();
-    private native String _getAudioCodecInfo();
-
-    public native void record(String path, int seconds);
-
-    public void setOption(int category, String name, String value) {
-        _setOption(category, name, value);
-    }
-
-    public void setOption(int category, String name, long value) {
-        _setOption(category, name, value);
-    }
-
-    private native void _setOption(int category, String name, String value);
-    private native void _setOption(int category, String name, long value);
-
-    public Bundle getMediaMeta() {
-        return _getMediaMeta();
-    }
-
-    private native Bundle _getMediaMeta();
-
-    public static String getColorFormatName(int mediaCodecColorFormat) {
-        return _getColorFormatName(mediaCodecColorFormat);
-    }
-
-    private static native String _getColorFormatName(int mediaCodecColorFormat);
-
-    @Override
-    public void setAudioStreamType(int streamtype) {
-        // do nothing
-    }
-
-    @Override
-    public void setKeepInBackground(boolean keepInBackground) {
-        // do nothing
-    }
-
-    public static native long native_active_days(Object context, String key);
-
-    private static native void native_init();
-
-    private native void native_setup(Object ctx, Object IjkMediaPlayer_this, String key);
-//    private native void native_setup(Object IjkMediaPlayer_this);
-
-    private native void native_finalize();
-
-    private native void native_message_loop(Object IjkMediaPlayer_this);
-
-    protected void finalize() throws Throwable {
-        super.finalize();
-        native_finalize();
-    }
-
-    private static class EventHandler extends Handler {
-        private final WeakReference<IjkMediaPlayer> mWeakPlayer;
-
-        public EventHandler(IjkMediaPlayer mp, Looper looper) {
-            super(looper);
-            mWeakPlayer = new WeakReference<IjkMediaPlayer>(mp);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            IjkMediaPlayer player = mWeakPlayer.get();
-
-            if (player == null || player.mNativeMediaPlayer == 0) {
-                DebugLog.w(TAG, "IjkMediaPlayer went away with unhandled events");
-                return;
-            }
-
-            switch (msg.what) {
-            case MEDIA_PREPARED:
-                player.notifyOnPrepared();
-                return;
-
-            case MEDIA_PLAYBACK_COMPLETE:
-                player.stayAwake(false);
-                player.notifyOnCompletion();
-                return;
-
-            case MEDIA_BUFFERING_UPDATE:
-                long bufferPosition = msg.arg1;
-
-                if (bufferPosition < 0) {
-                    bufferPosition = 0;
-                }
-
-                long percent = 0;
-                long duration = player.getDuration();
-
-                if (duration > 0) {
-                    percent = bufferPosition * 100 / duration;
-                }
-
-                if (percent >= 100) {
-                    percent = 100;
-                }
-
-                // DebugLog.efmt(TAG, "Buffer (%d%%) %d/%d",  percent, bufferPosition, duration);
-                player.notifyOnBufferingUpdate((int)percent);
-                return;
-
-            case MEDIA_SEEK_COMPLETE:
-                player.notifyOnSeekComplete();
-                return;
-
-            case MEDIA_SET_VIDEO_SIZE:
-                player.mVideoWidth = msg.arg1;
-                player.mVideoHeight = msg.arg2;
-                player.notifyOnVideoSizeChanged(player.mVideoWidth,
-                        player.mVideoHeight,
-                        player.mVideoSarNum,
-                        player.mVideoSarDen);
-                return;
-
-            case MEDIA_ERROR:
-                DebugLog.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
-
-                if (!player.notifyOnError(msg.arg1, msg.arg2)) {
-                    player.notifyOnCompletion();
-                }
-
-                player.stayAwake(false);
-                return;
-
-            case MEDIA_INFO:
-                switch (msg.arg1) {
-                    case MEDIA_INFO_VIDEO_RENDERING_START:
-                        DebugLog.i(TAG, "Info: MEDIA_INFO_VIDEO_RENDERING_START\n");
-                        break;
-                }
-
-                player.notifyOnInfo(msg.arg1, msg.arg2);
-                // No real default action so far.
-                return;
-            case MEDIA_TIMED_TEXT:
-                if (msg.obj == null) {
-                    player.notifyOnTimedText(null);
-                } else {
-                    IjkTimedText text = new IjkTimedText(new Rect(0, 0, 1, 1), (String)msg.obj);
-                    player.notifyOnTimedText(text);
-                }
-
-                return;
-            case MEDIA_NOP: // interface test message - ignore
-                break;
-
-            case MEDIA_SET_VIDEO_SAR:
-                player.mVideoSarNum = msg.arg1;
-                player.mVideoSarDen = msg.arg2;
-                player.notifyOnVideoSizeChanged(player.mVideoWidth, player.mVideoHeight,
-                        player.mVideoSarNum, player.mVideoSarDen);
-                break;
-
-            default:
-                DebugLog.e(TAG, "Unknown message type " + msg.what);
-            }
-        }
-    }
-
-    /*
-     * Called from native code when an interesting event happens. This method
-     * just uses the EventHandler system to post the event back to the main app
-     * thread. We use a weak reference to the original IjkMediaPlayer object so
-     * that the native code is safe from the object disappearing from underneath
-     * it. (This is the cookie passed to native_setup().)
-     */
-    @CalledByNative
-    private static void postEventFromNative(Object weakThiz, int what, int arg1, int arg2, Object obj) {
-        if (weakThiz == null)
-            return;
-
-        @SuppressWarnings("rawtypes")
-        IjkMediaPlayer mp = (IjkMediaPlayer) ((WeakReference) weakThiz).get();
-        if (mp == null) {
-            return;
-        }
-
-        if (what == MEDIA_INFO && arg1 == MEDIA_INFO_STARTED_AS_NEXT) {
-            // this acquires the wakelock if needed, and sets the client side
-            // state
-            mp.start();
-        }
-
-        if (mp.mEventHandler != null) {
-            Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
-            mp.mEventHandler.sendMessage(m);
-        }
-    }
-
-    /*
-     * ControlMessage
-     */
-    private OnControlMessageListener mOnControlMessageListener;
-
-    public void setOnControlMessageListener(OnControlMessageListener listener) {
-        mOnControlMessageListener = listener;
-    }
-
-    public interface OnControlMessageListener {
-        String onControlResolveSegmentUrl(int segment);
-    }
-
-    /*
-     * NativeInvoke
-     */
-    private OnNativeInvokeListener mOnNativeInvokeListener;
-
-    public void setOnNativeInvokeListener(OnNativeInvokeListener listener) {
-        mOnNativeInvokeListener = listener;
-    }
-
-    public interface OnNativeInvokeListener {
-        int CTRL_WILL_TCP_OPEN = 0x20001;               // NO ARGS
-        int CTRL_DID_TCP_OPEN = 0x20002;                // ARG_ERROR, ARG_FAMILIY, ARG_IP, ARG_PORT, ARG_FD
-
-        int CTRL_WILL_HTTP_OPEN = 0x20003;              // ARG_URL, ARG_SEGMENT_INDEX, ARG_RETRY_COUNTER
-        int CTRL_WILL_LIVE_OPEN = 0x20005;              // ARG_URL, ARG_RETRY_COUNTER
-        int CTRL_WILL_CONCAT_RESOLVE_SEGMENT = 0x20007; // ARG_URL, ARG_SEGMENT_INDEX, ARG_RETRY_COUNTER
-
-        int EVENT_WILL_HTTP_OPEN = 0x1;                 // ARG_URL
-        int EVENT_DID_HTTP_OPEN = 0x2;                  // ARG_URL, ARG_ERROR, ARG_HTTP_CODE
-        int EVENT_WILL_HTTP_SEEK = 0x3;                 // ARG_URL, ARG_OFFSET
-        int EVENT_DID_HTTP_SEEK = 0x4;                  // ARG_URL, ARG_OFFSET, ARG_ERROR, ARG_HTTP_CODE
-
-        String ARG_URL = "url";
-        String ARG_SEGMENT_INDEX = "segment_index";
-        String ARG_RETRY_COUNTER = "retry_counter";
-
-        String ARG_ERROR = "error";
-        String ARG_FAMILIY = "family";
-        String ARG_IP = "ip";
-        String ARG_PORT = "port";
-        String ARG_FD = "fd";
-
-        String ARG_OFFSET = "offset";
-        String ARG_HTTP_CODE = "http_code";
-
-        /*
-         * @return true if invoke is handled
-         * @throws Exception on any error
-         */
-        boolean onNativeInvoke(int what, Bundle args);
-    }
-
-    @CalledByNative
-    private static boolean onNativeInvoke(Object weakThiz, int what, Bundle args) {
-        DebugLog.ifmt(TAG, "onNativeInvoke %d", what);
-        if (weakThiz == null || !(weakThiz instanceof WeakReference<?>))
-            throw new IllegalStateException("<null weakThiz>.onNativeInvoke()");
-
-        @SuppressWarnings("unchecked")
-        WeakReference<IjkMediaPlayer> weakPlayer = (WeakReference<IjkMediaPlayer>) weakThiz;
-        IjkMediaPlayer player = weakPlayer.get();
-
-        if (player == null)
-            throw new IllegalStateException("<null weakPlayer>.onNativeInvoke()");
-
-        OnNativeInvokeListener listener = player.mOnNativeInvokeListener;
-
-        if (listener != null && listener.onNativeInvoke(what, args))
-            return true;
-
-        switch (what) {
-            case OnNativeInvokeListener.CTRL_WILL_CONCAT_RESOLVE_SEGMENT: {
-                OnControlMessageListener onControlMessageListener = player.mOnControlMessageListener;
-                if (onControlMessageListener == null)
-                    return false;
-
-                int segmentIndex = args.getInt(OnNativeInvokeListener.ARG_SEGMENT_INDEX, -1);
-                if (segmentIndex < 0)
-                    throw new InvalidParameterException("onNativeInvoke(invalid segment index)");
-
-                String newUrl = onControlMessageListener.onControlResolveSegmentUrl(segmentIndex);
-                if (newUrl == null)
-                    throw new RuntimeException(new IOException("onNativeInvoke() = <NULL newUrl>"));
-
-                args.putString(OnNativeInvokeListener.ARG_URL, newUrl);
-                return true;
-            }
-            default:
-                return false;
-        }
-    }
-
-    /*
-     * MediaCodec select
-     */
-    public interface OnMediaCodecSelectListener {
-        String onMediaCodecSelect(IMediaPlayer mp, String mimeType, int profile, int level);
-    }
-
-    private OnMediaCodecSelectListener mOnMediaCodecSelectListener;
-
-    public void setOnMediaCodecSelectListener(OnMediaCodecSelectListener listener) {
-        mOnMediaCodecSelectListener = listener;
-    }
-
-    public void resetListeners() {
-        super.resetListeners();
-        mOnMediaCodecSelectListener = null;
-    }
-
-    @CalledByNative
-    private static String onSelectCodec(Object weakThiz, String mimeType, int profile, int level) {
-        if (weakThiz == null || !(weakThiz instanceof WeakReference<?>))
-            return null;
-
-        @SuppressWarnings("unchecked")
-        WeakReference<IjkMediaPlayer> weakPlayer = (WeakReference<IjkMediaPlayer>) weakThiz;
-        IjkMediaPlayer player = weakPlayer.get();
-        if (player == null)
-            return null;
-
-        OnMediaCodecSelectListener listener = player.mOnMediaCodecSelectListener;
-        if (listener == null)
-            listener = DefaultMediaCodecSelector.sInstance;
-
-        return listener.onMediaCodecSelect(player, mimeType, profile, level);
-    }
-
-    public static class DefaultMediaCodecSelector implements OnMediaCodecSelectListener {
-        public static final DefaultMediaCodecSelector sInstance = new DefaultMediaCodecSelector();
-
-        @SuppressWarnings("deprecation")
-        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-        public String onMediaCodecSelect(IMediaPlayer mp, String mimeType, int profile, int level) {
-            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
-                return null;
-
-            if (TextUtils.isEmpty(mimeType))
-                return null;
-
-            Log.i(TAG, String.format(Locale.US, "onSelectCodec: mime=%s, profile=%d, level=%d", mimeType, profile, level));
-            ArrayList<IjkMediaCodecInfo> candidateCodecList = new ArrayList<IjkMediaCodecInfo>();
-            int numCodecs = MediaCodecList.getCodecCount();
-
-            for (int i = 0; i < numCodecs; i++) {
-                MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-                Log.d(TAG, String.format(Locale.US, "  found codec: %s", codecInfo.getName()));
-
-                if (codecInfo.isEncoder())
-                    continue;
-
-                String[] types = codecInfo.getSupportedTypes();
-                if (types == null)
-                    continue;
-
-                for(String type: types) {
-                    if (TextUtils.isEmpty(type))
-                        continue;
-
-                    Log.d(TAG, String.format(Locale.US, "    mime: %s", type));
-                    if (!type.equalsIgnoreCase(mimeType))
-                        continue;
-
-                    IjkMediaCodecInfo candidate = IjkMediaCodecInfo.setupCandidate(codecInfo, mimeType);
-                    if (candidate == null)
-                        continue;
-
-                    candidateCodecList.add(candidate);
-                    Log.i(TAG, String.format(Locale.US, "candidate codec: %s rank=%d", codecInfo.getName(), candidate.mRank));
-                    candidate.dumpProfileLevels(mimeType);
-                }
-            }
-
-            if (candidateCodecList.isEmpty()) {
-                return null;
-            }
-
-            IjkMediaCodecInfo bestCodec = candidateCodecList.get(0);
-
-            for (IjkMediaCodecInfo codec : candidateCodecList) {
-                if (codec.mRank > bestCodec.mRank) {
-                    bestCodec = codec;
-                }
-            }
-
-            if (bestCodec.mRank < IjkMediaCodecInfo.RANK_LAST_CHANCE) {
-                Log.w(TAG, String.format(Locale.US, "unaccetable codec: %s", bestCodec.mCodecInfo.getName()));
-                return null;
-            }
-
-            Log.i(TAG, String.format(Locale.US, "selected codec: %s rank=%d", bestCodec.mCodecInfo.getName(), bestCodec.mRank));
-            return bestCodec.mCodecInfo.getName();
-        }
-    }
-
-    public static native void native_profileBegin(String libName);
-    public static native void native_profileEnd();
-    public static native void native_setLogLevel(int level);
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkTimedText.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkTimedText.java
deleted file mode 100644
index 0d11ae4..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/IjkTimedText.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 Zheng Yuan <zhengyuan10503@gmail.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 tv.danmaku.ijk.media.player;
-
-import android.graphics.Rect;
-import java.lang.String;
-
-public final class IjkTimedText {
-
-    private Rect mTextBounds = null;
-    private String mTextChars = null;
-
-    public IjkTimedText(Rect bounds, String text) {
-        mTextBounds = bounds;
-        mTextChars = text;
-    }
-
-    public Rect getBounds() {
-        return mTextBounds;
-    }
-
-    public String getText() {
-        return mTextChars;
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/MediaInfo.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/MediaInfo.java
deleted file mode 100644
index 6cd5004..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/MediaInfo.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player;
-
-public class MediaInfo {
-    public String mMediaPlayerName;
-
-    public String mVideoDecoder;
-    public String mVideoDecoderImpl;
-
-    public String mAudioDecoder;
-    public String mAudioDecoderImpl;
-
-    public IjkMediaMeta mMeta;
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java
deleted file mode 100644
index f33ce0b..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Build;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.util.Map;
-
-import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
-import tv.danmaku.ijk.media.player.misc.ITrackInfo;
-
-public class MediaPlayerProxy implements IMediaPlayer {
-    protected final IMediaPlayer mBackEndMediaPlayer;
-
-    public MediaPlayerProxy(IMediaPlayer backEndMediaPlayer) {
-        mBackEndMediaPlayer = backEndMediaPlayer;
-    }
-
-    public IMediaPlayer getInternalMediaPlayer() {
-        return mBackEndMediaPlayer;
-    }
-
-    @Override
-    public void setDisplay(SurfaceHolder sh) {
-        mBackEndMediaPlayer.setDisplay(sh);
-    }
-
-    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
-    @Override
-    public void setSurface(Surface surface) {
-        mBackEndMediaPlayer.setSurface(surface);
-    }
-
-    @Override
-    public void setDataSource(Context context, Uri uri)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
-        mBackEndMediaPlayer.setDataSource(context, uri);
-    }
-
-    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
-    @Override
-    public void setDataSource(Context context, Uri uri, Map<String, String> headers)
-            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
-        mBackEndMediaPlayer.setDataSource(context, uri, headers);
-    }
-
-    @Override
-    public void setDataSource(FileDescriptor fd)
-            throws IOException, IllegalArgumentException, IllegalStateException {
-        mBackEndMediaPlayer.setDataSource(fd);
-    }
-
-    @Override
-    public void setDataSource(String path) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
-        mBackEndMediaPlayer.setDataSource(path);
-    }
-
-    @Override
-    public void setDataSource(IMediaDataSource mediaDataSource)  {
-        mBackEndMediaPlayer.setDataSource(mediaDataSource);
-    }
-
-    @Override
-    public String getDataSource() {
-        return mBackEndMediaPlayer.getDataSource();
-    }
-
-    @Override
-    public void prepareAsync() throws IllegalStateException {
-        mBackEndMediaPlayer.prepareAsync();
-    }
-
-    @Override
-    public void start() throws IllegalStateException {
-        mBackEndMediaPlayer.start();
-    }
-
-    @Override
-    public void stop() throws IllegalStateException {
-        mBackEndMediaPlayer.stop();
-    }
-
-    @Override
-    public void pause() throws IllegalStateException {
-        mBackEndMediaPlayer.pause();
-    }
-
-    @Override
-    public void setScreenOnWhilePlaying(boolean screenOn) {
-        mBackEndMediaPlayer.setScreenOnWhilePlaying(screenOn);
-    }
-
-    @Override
-    public int getVideoWidth() {
-        return mBackEndMediaPlayer.getVideoWidth();
-    }
-
-    @Override
-    public int getVideoHeight() {
-        return mBackEndMediaPlayer.getVideoHeight();
-    }
-
-    @Override
-    public boolean isPlaying() {
-        return mBackEndMediaPlayer.isPlaying();
-    }
-
-    @Override
-    public void seekTo(long msec) throws IllegalStateException {
-        mBackEndMediaPlayer.seekTo(msec);
-    }
-
-    @Override
-    public long getCurrentPosition() {
-        return mBackEndMediaPlayer.getCurrentPosition();
-    }
-
-    @Override
-    public long getDuration() {
-        return mBackEndMediaPlayer.getDuration();
-    }
-
-    @Override
-    public void release() {
-        mBackEndMediaPlayer.release();
-    }
-
-    @Override
-    public void reset() {
-        mBackEndMediaPlayer.reset();
-    }
-
-    @Override
-    public void record(String path, int seconds) {
-
-    }
-
-    @Override
-    public void setVolume(float leftVolume, float rightVolume) {
-        mBackEndMediaPlayer.setVolume(leftVolume, rightVolume);
-    }
-
-    @Override
-    public int getAudioSessionId() {
-        return mBackEndMediaPlayer.getAudioSessionId();
-    }
-
-    @Override
-    public MediaInfo getMediaInfo() {
-        return mBackEndMediaPlayer.getMediaInfo();
-    }
-
-    @Override
-    public void setLogEnabled(boolean enable) {
-
-    }
-
-    @Override
-    public boolean isPlayable() {
-        return false;
-    }
-
-    @Override
-    public void setOnPreparedListener(OnPreparedListener listener) {
-        if (listener != null) {
-            final OnPreparedListener finalListener = listener;
-            mBackEndMediaPlayer.setOnPreparedListener(new OnPreparedListener() {
-                @Override
-                public void onPrepared(IMediaPlayer mp) {
-                    finalListener.onPrepared(MediaPlayerProxy.this);
-                }
-            });
-        } else {
-            mBackEndMediaPlayer.setOnPreparedListener(null);
-        }
-    }
-
-    @Override
-    public void setOnCompletionListener(OnCompletionListener listener) {
-        if (listener != null) {
-            final OnCompletionListener finalListener = listener;
-            mBackEndMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
-                @Override
-                public void onCompletion(IMediaPlayer mp) {
-                    finalListener.onCompletion(MediaPlayerProxy.this);
-                }
-            });
-        } else {
-            mBackEndMediaPlayer.setOnCompletionListener(null);
-        }
-    }
-
-    @Override
-    public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) {
-        if (listener != null) {
-            final OnBufferingUpdateListener finalListener = listener;
-            mBackEndMediaPlayer.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
-                @Override
-                public void onBufferingUpdate(IMediaPlayer mp, int percent) {
-                    finalListener.onBufferingUpdate(MediaPlayerProxy.this, percent);
-                }
-            });
-        } else {
-            mBackEndMediaPlayer.setOnBufferingUpdateListener(null);
-        }
-    }
-
-    @Override
-    public void setOnSeekCompleteListener(OnSeekCompleteListener listener) {
-        if (listener != null) {
-            final OnSeekCompleteListener finalListener = listener;
-            mBackEndMediaPlayer.setOnSeekCompleteListener(new OnSeekCompleteListener() {
-                @Override
-                public void onSeekComplete(IMediaPlayer mp) {
-                    finalListener.onSeekComplete(MediaPlayerProxy.this);
-                }
-            });
-        } else {
-            mBackEndMediaPlayer.setOnSeekCompleteListener(null);
-        }
-    }
-
-    @Override
-    public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener) {
-        if (listener != null) {
-            final OnVideoSizeChangedListener finalListener = listener;
-            mBackEndMediaPlayer.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {
-                @Override
-                public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sar_num, int sar_den) {
-                    finalListener.onVideoSizeChanged(MediaPlayerProxy.this, width, height, sar_num, sar_den);
-                }
-            });
-        } else {
-            mBackEndMediaPlayer.setOnVideoSizeChangedListener(null);
-        }
-    }
-
-    @Override
-    public void setOnErrorListener(OnErrorListener listener) {
-        if (listener != null) {
-            final OnErrorListener finalListener = listener;
-            mBackEndMediaPlayer.setOnErrorListener(new OnErrorListener() {
-                @Override
-                public boolean onError(IMediaPlayer mp, int what, int extra) {
-                    return finalListener.onError(MediaPlayerProxy.this, what, extra);
-                }
-            });
-        } else {
-            mBackEndMediaPlayer.setOnErrorListener(null);
-        }
-    }
-
-    @Override
-    public void setOnInfoListener(OnInfoListener listener) {
-        if (listener != null) {
-            final OnInfoListener finalListener = listener;
-            mBackEndMediaPlayer.setOnInfoListener(new OnInfoListener() {
-                @Override
-                public boolean onInfo(IMediaPlayer mp, int what, int extra) {
-                    return finalListener.onInfo(MediaPlayerProxy.this, what, extra);
-                }
-            });
-        } else {
-            mBackEndMediaPlayer.setOnInfoListener(null);
-        }
-    }
-
-    @Override
-    public void setOnTimedTextListener(OnTimedTextListener listener) {
-        if (listener != null) {
-            final OnTimedTextListener finalListener = listener;
-            mBackEndMediaPlayer.setOnTimedTextListener(new OnTimedTextListener() {
-                @Override
-                public void onTimedText(IMediaPlayer mp, IjkTimedText text) {
-                    finalListener.onTimedText(MediaPlayerProxy.this, text);
-                }
-            });
-        } else {
-            mBackEndMediaPlayer.setOnTimedTextListener(null);
-        }
-    }
-
-    @Override
-    public void setAudioStreamType(int streamtype) {
-        mBackEndMediaPlayer.setAudioStreamType(streamtype);
-    }
-
-    @Override
-    public void setKeepInBackground(boolean keepInBackground) {
-        mBackEndMediaPlayer.setKeepInBackground(keepInBackground);
-    }
-
-    @Override
-    public int getVideoSarNum() {
-        return mBackEndMediaPlayer.getVideoSarNum();
-    }
-
-    @Override
-    public int getVideoSarDen() {
-        return mBackEndMediaPlayer.getVideoSarDen();
-    }
-
-    @Override
-    public void setWakeMode(Context context, int mode) {
-        mBackEndMediaPlayer.setWakeMode(context, mode);
-    }
-
-    @Override
-    public ITrackInfo[] getTrackInfo() {
-        return mBackEndMediaPlayer.getTrackInfo();
-    }
-
-    @Override
-    public void setLooping(boolean looping) {
-        mBackEndMediaPlayer.setLooping(looping);
-    }
-
-    @Override
-    public boolean isLooping() {
-        return mBackEndMediaPlayer.isLooping();
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/TextureMediaPlayer.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/TextureMediaPlayer.java
deleted file mode 100644
index 22a269e..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/TextureMediaPlayer.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player;
-
-import android.annotation.TargetApi;
-import android.graphics.SurfaceTexture;
-import android.os.Build;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-
-@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
-public class TextureMediaPlayer extends MediaPlayerProxy implements IMediaPlayer, ISurfaceTextureHolder {
-    private SurfaceTexture mSurfaceTexture;
-    private ISurfaceTextureHost mSurfaceTextureHost;
-
-    public TextureMediaPlayer(IMediaPlayer backEndMediaPlayer) {
-        super(backEndMediaPlayer);
-    }
-
-    public void releaseSurfaceTexture() {
-        if (mSurfaceTexture != null) {
-            if (mSurfaceTextureHost != null) {
-                mSurfaceTextureHost.releaseSurfaceTexture(mSurfaceTexture);
-            } else {
-                mSurfaceTexture.release();
-            }
-            mSurfaceTexture = null;
-        }
-    }
-
-    //--------------------
-    // IMediaPlayer
-    //--------------------
-    @Override
-    public void reset() {
-        super.reset();
-        releaseSurfaceTexture();
-    }
-
-    @Override
-    public void release() {
-        super.release();
-        releaseSurfaceTexture();
-    }
-
-    @Override
-    public void setDisplay(SurfaceHolder sh) {
-        if (mSurfaceTexture == null)
-            super.setDisplay(sh);
-    }
-
-    @Override
-    public void setSurface(Surface surface) {
-        if (mSurfaceTexture == null)
-            super.setSurface(surface);
-    }
-
-    //--------------------
-    // ISurfaceTextureHolder
-    //--------------------
-
-    @Override
-    public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
-        if (mSurfaceTexture == surfaceTexture)
-            return;
-
-        releaseSurfaceTexture();
-        mSurfaceTexture = surfaceTexture;
-        if (surfaceTexture == null) {
-            super.setSurface(null);
-        } else {
-            super.setSurface(new Surface(surfaceTexture));
-        }
-    }
-
-    @Override
-    public SurfaceTexture getSurfaceTexture() {
-        return mSurfaceTexture;
-    }
-
-    @Override
-    public void setSurfaceTextureHost(ISurfaceTextureHost surfaceTextureHost) {
-        mSurfaceTextureHost = surfaceTextureHost;
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/TxtOverlayAdd.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/TxtOverlayAdd.java
deleted file mode 100644
index 158eb20..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/TxtOverlayAdd.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package tv.danmaku.ijk.media.player;
-
-import tv.danmaku.ijk.media.player.annotations.AccessedByNative;
-
-/**
- * Created by jiaozebo on 2017/2/23.
- */
-
-public class TxtOverlayAdd {
-
-    @AccessedByNative
-    private long mNativeMediaPlayer;
-
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/annotations/AccessedByNative.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/annotations/AccessedByNative.java
deleted file mode 100644
index c613660..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/annotations/AccessedByNative.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * is used by the JNI generator to create the necessary JNI
- * bindings and expose this method to native code.
- */
-@Target(ElementType.FIELD)
-@Retention(RetentionPolicy.CLASS)
-public @interface AccessedByNative {
-}
\ No newline at end of file
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/annotations/CalledByNative.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/annotations/CalledByNative.java
deleted file mode 100644
index 2a2caf3..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/annotations/CalledByNative.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * is used by the JNI generator to create the necessary JNI
- * bindings and expose this method to native code.
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.CLASS)
-public @interface CalledByNative {
-    /*
-     * If present, tells which inner class the method belongs to.
-     */
-    String value() default "";
-}
\ No newline at end of file
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/exceptions/IjkMediaException.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/exceptions/IjkMediaException.java
deleted file mode 100644
index dbd1add..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/exceptions/IjkMediaException.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.exceptions;
-
-public class IjkMediaException extends Exception {
-    private static final long serialVersionUID = 7234796519009099506L;
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ffmpeg/FFmpegApi.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ffmpeg/FFmpegApi.java
deleted file mode 100644
index e13ba1b..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ffmpeg/FFmpegApi.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package tv.danmaku.ijk.media.player.ffmpeg;
-
-public class FFmpegApi {
-    public static native String av_base64_encode(byte in[]);
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidMediaFormat.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidMediaFormat.java
deleted file mode 100644
index 9338a24..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidMediaFormat.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.misc;
-
-import android.annotation.TargetApi;
-import android.media.MediaFormat;
-import android.os.Build;
-
-public class AndroidMediaFormat implements IMediaFormat {
-    private final MediaFormat mMediaFormat;
-
-    public AndroidMediaFormat(MediaFormat mediaFormat) {
-        mMediaFormat = mediaFormat;
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    @Override
-    public int getInteger(String name) {
-        if (mMediaFormat == null)
-            return 0;
-
-        return mMediaFormat.getInteger(name);
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    @Override
-    public String getString(String name) {
-        if (mMediaFormat == null)
-            return null;
-
-        return mMediaFormat.getString(name);
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    @Override
-    public String toString() {
-        StringBuilder out = new StringBuilder(128);
-        out.append(getClass().getName());
-        out.append('{');
-        if (mMediaFormat != null) {
-            out.append(mMediaFormat.toString());
-        } else {
-            out.append("null");
-        }
-        out.append('}');
-        return out.toString();
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidTrackInfo.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidTrackInfo.java
deleted file mode 100644
index 33e7556..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidTrackInfo.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.misc;
-
-import android.annotation.TargetApi;
-import android.media.MediaFormat;
-import android.media.MediaPlayer;
-import android.os.Build;
-
-public class AndroidTrackInfo implements ITrackInfo {
-    private final MediaPlayer.TrackInfo mTrackInfo;
-
-    public static AndroidTrackInfo[] fromMediaPlayer(MediaPlayer mp) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
-            return fromTrackInfo(mp.getTrackInfo());
-
-        return null;
-    }
-
-    private static AndroidTrackInfo[] fromTrackInfo(MediaPlayer.TrackInfo[] trackInfos) {
-        if (trackInfos == null)
-            return null;
-
-        AndroidTrackInfo androidTrackInfo[] = new AndroidTrackInfo[trackInfos.length];
-        for (int i = 0; i < trackInfos.length; ++i) {
-            androidTrackInfo[i] = new AndroidTrackInfo(trackInfos[i]);
-        }
-
-        return androidTrackInfo;
-    }
-
-    private AndroidTrackInfo(MediaPlayer.TrackInfo trackInfo) {
-        mTrackInfo = trackInfo;
-    }
-
-    @TargetApi(Build.VERSION_CODES.KITKAT)
-    @Override
-    public IMediaFormat getFormat() {
-        if (mTrackInfo == null)
-            return null;
-
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
-            return null;
-
-        MediaFormat mediaFormat = mTrackInfo.getFormat();
-        if (mediaFormat == null)
-            return null;
-
-        return new AndroidMediaFormat(mediaFormat);
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    @Override
-    public String getLanguage() {
-        if (mTrackInfo == null)
-            return "und";
-
-        return mTrackInfo.getLanguage();
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    @Override
-    public int getTrackType() {
-        if (mTrackInfo == null)
-            return MEDIA_TRACK_TYPE_UNKNOWN;
-
-        return mTrackInfo.getTrackType();
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    @Override
-    public String toString() {
-        StringBuilder out = new StringBuilder(128);
-        out.append(getClass().getSimpleName());
-        out.append('{');
-        if (mTrackInfo != null) {
-            out.append(mTrackInfo.toString());
-        } else {
-            out.append("null");
-        }
-        out.append('}');
-        return out.toString();
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    @Override
-    public String getInfoInline() {
-        if (mTrackInfo != null) {
-            return mTrackInfo.toString();
-        } else {
-            return "null";
-        }
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IIjkIOHttp.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IIjkIOHttp.java
deleted file mode 100644
index 914fc35..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IIjkIOHttp.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2016 Raymond Zheng <raymondzheng1412@gmail.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 tv.danmaku.ijk.media.player.misc;
-
-import java.io.IOException;
-
-@SuppressWarnings("RedundantThrows")
-public interface IIjkIOHttp {
-    int  open() throws IOException;
-    int  read(byte[] buffer, int size) throws IOException;
-    long seek(long offset, int whence) throws IOException;
-    int  close() throws IOException;
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaDataSource.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaDataSource.java
deleted file mode 100644
index a298aa9..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaDataSource.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.misc;
-
-import java.io.IOException;
-
-@SuppressWarnings("RedundantThrows")
-public interface IMediaDataSource {
-    int	 readAt(long position, byte[] buffer, int offset, int size) throws IOException;
-
-    long getSize() throws IOException;
-
-    void close() throws IOException;
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaFormat.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaFormat.java
deleted file mode 100644
index b1cd4db..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaFormat.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.misc;
-
-public interface IMediaFormat {
-    // Common keys
-    String KEY_MIME = "mime";
-
-    // Video Keys
-    String KEY_WIDTH = "width";
-    String KEY_HEIGHT = "height";
-
-    String getString(String name);
-
-    int getInteger(String name);
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/ITrackInfo.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/ITrackInfo.java
deleted file mode 100644
index a9c5101..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/ITrackInfo.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.misc;
-
-public interface ITrackInfo {
-    int MEDIA_TRACK_TYPE_AUDIO = 2;
-    int MEDIA_TRACK_TYPE_METADATA = 5;
-    int MEDIA_TRACK_TYPE_SUBTITLE = 4;
-    int MEDIA_TRACK_TYPE_TIMEDTEXT = 3;
-    int MEDIA_TRACK_TYPE_UNKNOWN = 0;
-    int MEDIA_TRACK_TYPE_VIDEO = 1;
-
-    IMediaFormat getFormat();
-
-    String getLanguage();
-
-    int getTrackType();
-
-    String getInfoInline();
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IjkMediaFormat.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IjkMediaFormat.java
deleted file mode 100644
index e878c8f..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IjkMediaFormat.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.misc;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.text.TextUtils;
-
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import tv.danmaku.ijk.media.player.IjkMediaMeta;
-
-public class IjkMediaFormat implements IMediaFormat {
-    // Common
-    public static final String KEY_IJK_CODEC_LONG_NAME_UI = "ijk-codec-long-name-ui";
-    public static final String KEY_IJK_CODEC_NAME_UI = "ijk-codec-name-ui";
-    public static final String KEY_IJK_BIT_RATE_UI = "ijk-bit-rate-ui";
-
-    // Video
-    public static final String KEY_IJK_CODEC_PROFILE_LEVEL_UI = "ijk-profile-level-ui";
-    public static final String KEY_IJK_CODEC_PIXEL_FORMAT_UI = "ijk-pixel-format-ui";
-    public static final String KEY_IJK_RESOLUTION_UI = "ijk-resolution-ui";
-    public static final String KEY_IJK_FRAME_RATE_UI = "ijk-frame-rate-ui";
-
-    // Audio
-    public static final String KEY_IJK_SAMPLE_RATE_UI = "ijk-sample-rate-ui";
-    public static final String KEY_IJK_CHANNEL_UI = "ijk-channel-ui";
-
-    // Codec
-    public static final String CODEC_NAME_H264 = "h264";
-
-    public final IjkMediaMeta.IjkStreamMeta mMediaFormat;
-
-    public IjkMediaFormat(IjkMediaMeta.IjkStreamMeta streamMeta) {
-        mMediaFormat = streamMeta;
-    }
-
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-    @Override
-    public int getInteger(String name) {
-        if (mMediaFormat == null)
-            return 0;
-
-        return mMediaFormat.getInt(name);
-    }
-
-    @Override
-    public String getString(String name) {
-        if (mMediaFormat == null)
-            return null;
-
-        if (sFormatterMap.containsKey(name)) {
-            Formatter formatter = sFormatterMap.get(name);
-            return formatter.format(this);
-        }
-
-        return mMediaFormat.getString(name);
-    }
-
-    //-------------------------
-    // Formatter
-    //-------------------------
-
-    private static abstract class Formatter {
-        public String format(IjkMediaFormat mediaFormat) {
-            String value = doFormat(mediaFormat);
-            if (TextUtils.isEmpty(value))
-                return getDefaultString();
-            return value;
-        }
-
-        protected abstract String doFormat(IjkMediaFormat mediaFormat);
-
-        @SuppressWarnings("SameReturnValue")
-        protected String getDefaultString() {
-            return "N/A";
-        }
-    }
-
-    private static final Map<String, Formatter> sFormatterMap = new HashMap<String, Formatter>();
-
-    {
-        sFormatterMap.put(KEY_IJK_CODEC_LONG_NAME_UI, new Formatter() {
-            @Override
-            public String doFormat(IjkMediaFormat mediaFormat) {
-                return mMediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_LONG_NAME);
-            }
-        });
-        sFormatterMap.put(KEY_IJK_CODEC_NAME_UI, new Formatter() {
-            @Override
-            public String doFormat(IjkMediaFormat mediaFormat) {
-                return mMediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_NAME);
-            }
-        });
-        sFormatterMap.put(KEY_IJK_BIT_RATE_UI, new Formatter() {
-            @Override
-            protected String doFormat(IjkMediaFormat mediaFormat) {
-                int bitRate = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_BITRATE);
-                if (bitRate <= 0) {
-                    return null;
-                } else if (bitRate < 1000) {
-                    return String.format(Locale.US, "%d bit/s", bitRate);
-                } else {
-                    return String.format(Locale.US, "%d kb/s", bitRate / 1000);
-                }
-            }
-        });
-        sFormatterMap.put(KEY_IJK_CODEC_PROFILE_LEVEL_UI, new Formatter() {
-            @Override
-            protected String doFormat(IjkMediaFormat mediaFormat) {
-                int profileIndex = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_CODEC_PROFILE_ID);
-                String profile;
-                switch (profileIndex) {
-                    case IjkMediaMeta.FF_PROFILE_H264_BASELINE:
-                        profile = "Baseline";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_CONSTRAINED_BASELINE:
-                        profile = "Constrained Baseline";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_MAIN:
-                        profile = "Main";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_EXTENDED:
-                        profile = "Extended";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_HIGH:
-                        profile = "High";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_HIGH_10:
-                        profile = "High 10";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_HIGH_10_INTRA:
-                        profile = "High 10 Intra";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_HIGH_422:
-                        profile = "High 4:2:2";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_HIGH_422_INTRA:
-                        profile = "High 4:2:2 Intra";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_HIGH_444:
-                        profile = "High 4:4:4";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_HIGH_444_PREDICTIVE:
-                        profile = "High 4:4:4 Predictive";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_HIGH_444_INTRA:
-                        profile = "High 4:4:4 Intra";
-                        break;
-                    case IjkMediaMeta.FF_PROFILE_H264_CAVLC_444:
-                        profile = "CAVLC 4:4:4";
-                        break;
-                    default:
-                        return null;
-                }
-
-                StringBuilder sb = new StringBuilder();
-                sb.append(profile);
-
-                String codecName = mediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_NAME);
-                if (!TextUtils.isEmpty(codecName) && codecName.equalsIgnoreCase(CODEC_NAME_H264)) {
-                    int level = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_CODEC_LEVEL);
-                    if (level < 10)
-                        return sb.toString();
-
-                    sb.append(" Profile Level ");
-                    sb.append((level / 10) % 10);
-                    if ((level % 10) != 0) {
-                        sb.append(".");
-                        sb.append(level % 10);
-                    }
-                }
-
-                return sb.toString();
-            }
-        });
-        sFormatterMap.put(KEY_IJK_CODEC_PIXEL_FORMAT_UI, new Formatter() {
-            @Override
-            protected String doFormat(IjkMediaFormat mediaFormat) {
-                return mediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_PIXEL_FORMAT);
-            }
-        });
-        sFormatterMap.put(KEY_IJK_RESOLUTION_UI, new Formatter() {
-            @Override
-            protected String doFormat(IjkMediaFormat mediaFormat) {
-                int width = mediaFormat.getInteger(KEY_WIDTH);
-                int height = mediaFormat.getInteger(KEY_HEIGHT);
-                int sarNum = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAR_NUM);
-                int sarDen = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAR_DEN);
-
-                if (width <= 0 || height <= 0) {
-                    return null;
-                } else if (sarNum <= 0 || sarDen <= 0) {
-                    return String.format(Locale.US, "%d x %d", width, height);
-                } else {
-                    return String.format(Locale.US, "%d x %d [SAR %d:%d]", width,
-                            height, sarNum, sarDen);
-                }
-            }
-        });
-        sFormatterMap.put(KEY_IJK_FRAME_RATE_UI, new Formatter() {
-            @Override
-            protected String doFormat(IjkMediaFormat mediaFormat) {
-                int fpsNum = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_FPS_NUM);
-                int fpsDen = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_FPS_DEN);
-                if (fpsNum <= 0 || fpsDen <= 0) {
-                    return null;
-                } else {
-                    return String.valueOf(((float) (fpsNum)) / fpsDen);
-                }
-            }
-        });
-        sFormatterMap.put(KEY_IJK_SAMPLE_RATE_UI, new Formatter() {
-            @Override
-            protected String doFormat(IjkMediaFormat mediaFormat) {
-                int sampleRate = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAMPLE_RATE);
-                if (sampleRate <= 0) {
-                    return null;
-                } else {
-                    return String.format(Locale.US, "%d Hz", sampleRate);
-                }
-            }
-        });
-        sFormatterMap.put(KEY_IJK_CHANNEL_UI, new Formatter() {
-            @Override
-            protected String doFormat(IjkMediaFormat mediaFormat) {
-                int channelLayout = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_CHANNEL_LAYOUT);
-                if (channelLayout <= 0) {
-                    return null;
-                } else {
-                    if (channelLayout == IjkMediaMeta.AV_CH_LAYOUT_MONO) {
-                        return "mono";
-                    } else if (channelLayout == IjkMediaMeta.AV_CH_LAYOUT_STEREO) {
-                        return "stereo";
-                    } else {
-                        return String.format(Locale.US, "%x", channelLayout);
-                    }
-                }
-            }
-        });
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IjkTrackInfo.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IjkTrackInfo.java
deleted file mode 100644
index 52572c5..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IjkTrackInfo.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.misc;
-
-import android.text.TextUtils;
-
-import tv.danmaku.ijk.media.player.IjkMediaMeta;
-
-public class IjkTrackInfo implements ITrackInfo {
-    private int mTrackType = MEDIA_TRACK_TYPE_UNKNOWN;
-    private IjkMediaMeta.IjkStreamMeta mStreamMeta;
-
-    public IjkTrackInfo(IjkMediaMeta.IjkStreamMeta streamMeta) {
-        mStreamMeta = streamMeta;
-    }
-
-    public void setMediaMeta(IjkMediaMeta.IjkStreamMeta streamMeta) {
-        mStreamMeta = streamMeta;
-    }
-
-    @Override
-    public IMediaFormat getFormat() {
-        return new IjkMediaFormat(mStreamMeta);
-    }
-
-    @Override
-    public String getLanguage() {
-        if (mStreamMeta == null || TextUtils.isEmpty(mStreamMeta.mLanguage))
-            return "und";
-
-        return mStreamMeta.mLanguage;
-    }
-
-    @Override
-    public int getTrackType() {
-        return mTrackType;
-    }
-
-    public void setTrackType(int trackType) {
-        mTrackType = trackType;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + '{' + getInfoInline() + "}";
-    }
-
-    @Override
-    public String getInfoInline() {
-        StringBuilder out = new StringBuilder(128);
-        switch (mTrackType) {
-            case MEDIA_TRACK_TYPE_VIDEO:
-                out.append("VIDEO");
-                out.append(", ");
-                out.append(mStreamMeta.getCodecShortNameInline());
-                out.append(", ");
-                out.append(mStreamMeta.getBitrateInline());
-                out.append(", ");
-                out.append(mStreamMeta.getResolutionInline());
-                break;
-            case MEDIA_TRACK_TYPE_AUDIO:
-                out.append("AUDIO");
-                out.append(", ");
-                out.append(mStreamMeta.getCodecShortNameInline());
-                out.append(", ");
-                out.append(mStreamMeta.getBitrateInline());
-                out.append(", ");
-                out.append(mStreamMeta.getSampleRateInline());
-                break;
-            case MEDIA_TRACK_TYPE_TIMEDTEXT:
-                out.append("TIMEDTEXT");
-                out.append(", ");
-                out.append(mStreamMeta.mLanguage);
-                break;
-            case MEDIA_TRACK_TYPE_SUBTITLE:
-                out.append("SUBTITLE");
-                break;
-            default:
-                out.append("UNKNOWN");
-                break;
-        }
-        return out.toString();
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/pragma/DebugLog.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/pragma/DebugLog.java
deleted file mode 100644
index 7ccd89d..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/pragma/DebugLog.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2013 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.pragma;
-
-import java.util.Locale;
-
-
-import android.util.Log;
-
-@SuppressWarnings({"SameParameterValue", "WeakerAccess"})
-public class DebugLog {
-    public static final boolean ENABLE_ERROR = Pragma.ENABLE_VERBOSE;
-    public static final boolean ENABLE_INFO = Pragma.ENABLE_VERBOSE;
-    public static final boolean ENABLE_WARN = Pragma.ENABLE_VERBOSE;
-    public static final boolean ENABLE_DEBUG = Pragma.ENABLE_VERBOSE;
-    public static final boolean ENABLE_VERBOSE = Pragma.ENABLE_VERBOSE;
-
-    public static void e(String tag, String msg) {
-        if (ENABLE_ERROR) {
-            Log.e(tag, msg);
-        }
-    }
-
-    public static void e(String tag, String msg, Throwable tr) {
-        if (ENABLE_ERROR) {
-            Log.e(tag, msg, tr);
-        }
-    }
-
-    public static void efmt(String tag, String fmt, Object... args) {
-        if (ENABLE_ERROR) {
-            String msg = String.format(Locale.US, fmt, args);
-            Log.e(tag, msg);
-        }
-    }
-
-    public static void i(String tag, String msg) {
-        if (ENABLE_INFO) {
-            Log.i(tag, msg);
-        }
-    }
-
-    public static void i(String tag, String msg, Throwable tr) {
-        if (ENABLE_INFO) {
-            Log.i(tag, msg, tr);
-        }
-    }
-
-    public static void ifmt(String tag, String fmt, Object... args) {
-        if (ENABLE_INFO) {
-            String msg = String.format(Locale.US, fmt, args);
-            Log.i(tag, msg);
-        }
-    }
-
-    public static void w(String tag, String msg) {
-        if (ENABLE_WARN) {
-            Log.w(tag, msg);
-        }
-    }
-
-    public static void w(String tag, String msg, Throwable tr) {
-        if (ENABLE_WARN) {
-            Log.w(tag, msg, tr);
-        }
-    }
-
-    public static void wfmt(String tag, String fmt, Object... args) {
-        if (ENABLE_WARN) {
-            String msg = String.format(Locale.US, fmt, args);
-            Log.w(tag, msg);
-        }
-    }
-
-    public static void d(String tag, String msg) {
-        if (ENABLE_DEBUG) {
-            Log.d(tag, msg);
-        }
-    }
-
-    public static void d(String tag, String msg, Throwable tr) {
-        if (ENABLE_DEBUG) {
-            Log.d(tag, msg, tr);
-        }
-    }
-
-    public static void dfmt(String tag, String fmt, Object... args) {
-        if (ENABLE_DEBUG) {
-            String msg = String.format(Locale.US, fmt, args);
-            Log.d(tag, msg);
-        }
-    }
-
-    public static void v(String tag, String msg) {
-        if (ENABLE_VERBOSE) {
-            Log.v(tag, msg);
-        }
-    }
-
-    public static void v(String tag, String msg, Throwable tr) {
-        if (ENABLE_VERBOSE) {
-            Log.v(tag, msg, tr);
-        }
-    }
-
-    public static void vfmt(String tag, String fmt, Object... args) {
-        if (ENABLE_VERBOSE) {
-            String msg = String.format(Locale.US, fmt, args);
-            Log.v(tag, msg);
-        }
-    }
-
-    public static void printStackTrace(Throwable e) {
-        if (ENABLE_WARN) {
-            e.printStackTrace();
-        }
-    }
-
-    public static void printCause(Throwable e) {
-        if (ENABLE_WARN) {
-            Throwable cause = e.getCause();
-            if (cause != null)
-                e = cause;
-
-            printStackTrace(e);
-        }
-    }
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/pragma/Pragma.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/pragma/Pragma.java
deleted file mode 100644
index df26120..0000000
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/player/pragma/Pragma.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2013 Zhang Rui <bbcallen@gmail.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 tv.danmaku.ijk.media.player.pragma;
-
-/*-
- * configurated by app project
- */
-public class Pragma {
-    public static final boolean ENABLE_VERBOSE = true;
-}
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/FileMediaDataSource.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/FileMediaDataSource.java
index 0b007ff..fa38a7e 100644
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/FileMediaDataSource.java
+++ b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/FileMediaDataSource.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Bilibili
  * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,6 +18,8 @@
 package tv.danmaku.ijk.media.widget.media;
 
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.RandomAccessFile;
 
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IMediaController.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IMediaController.java
index 5e84c97..4d63274 100644
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IMediaController.java
+++ b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IMediaController.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Bilibili
  * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IRenderView.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IRenderView.java
index fd0164f..c8ae1e9 100644
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IRenderView.java
+++ b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IRenderView.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Bilibili
  * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IjkVideoView.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IjkVideoView.java
index aa3fd6a..ccf67e5 100644
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IjkVideoView.java
+++ b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/IjkVideoView.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Bilibili
  * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,30 +17,27 @@
 
 package tv.danmaku.ijk.media.widget.media;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.annotation.TargetApi;
 import android.content.Context;
-import android.graphics.Bitmap;
+import android.content.DialogInterface;
+import android.content.res.Resources;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.net.Uri;
 import android.os.Build;
-import android.preference.PreferenceManager;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
-import android.view.TextureView;
 import android.view.View;
 import android.widget.FrameLayout;
-import android.widget.ImageView;
 import android.widget.MediaController;
+import android.widget.TableLayout;
+import android.widget.TextView;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -50,22 +48,19 @@ import tv.danmaku.ijk.media.Settings;
 import tv.danmaku.ijk.media.player.AndroidMediaPlayer;
 import tv.danmaku.ijk.media.player.IMediaPlayer;
 import tv.danmaku.ijk.media.player.IjkMediaPlayer;
-import tv.danmaku.ijk.media.player.R;
+import tv.danmaku.ijk.media.player.IjkTimedText;
 import tv.danmaku.ijk.media.player.TextureMediaPlayer;
 import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
+import tv.danmaku.ijk.media.player.misc.IMediaFormat;
 import tv.danmaku.ijk.media.player.misc.ITrackInfo;
+import tv.danmaku.ijk.media.player.misc.IjkMediaFormat;
 
-/**
- * TODO
- * */
 public class IjkVideoView extends FrameLayout implements MediaController.MediaPlayerControl {
-    private String TAG = "VideoView";
-
+    private String TAG = "IjkVideoView";
     // settable by the client
-    protected Uri mUri;
-
+    private Uri mUri;
+    private String mManifestString;
     private Map<String, String> mHeaders;
-    public static String Player_KEY = "EasyPlayer is free!";
 
     // all possible internal states
     private static final int STATE_ERROR = -1;
@@ -87,23 +82,19 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
     // All the stuff we need for playing and showing a video
     private IRenderView.ISurfaceHolder mSurfaceHolder = null;
     protected IMediaPlayer mMediaPlayer = null;
-
     // private int         mAudioSession;
     private int mVideoWidth;
     private int mVideoHeight;
     private int mSurfaceWidth;
     private int mSurfaceHeight;
     private int mVideoRotationDegree;
-
     private IMediaController mMediaController;
     private IMediaPlayer.OnCompletionListener mOnCompletionListener;
     private IMediaPlayer.OnPreparedListener mOnPreparedListener;
+    private int mCurrentBufferPercentage;
     private IMediaPlayer.OnErrorListener mOnErrorListener;
     private IMediaPlayer.OnInfoListener mOnInfoListener;
-
-    private int mCurrentBufferPercentage;
     private int mSeekWhenPrepared;  // recording the seek position while preparing
-
     private boolean mCanPause = true;
     private boolean mCanSeekBack = true;
     private boolean mCanSeekForward = true;
@@ -119,17 +110,16 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
     private Context mAppContext;
     private Settings mSettings;
     private IRenderView mRenderView;
-
     private int mVideoSarNum;
     private int mVideoSarDen;
 
     private long mPrepareStartTime = 0;
     private long mPrepareEndTime = 0;
+
     private long mSeekStartTime = 0;
     private long mSeekEndTime = 0;
 
-    private ImageView mCover;
-    private boolean mShowing = true;
+    private TextView subtitleDisplay;
 
     public IjkVideoView(Context context) {
         super(context);
@@ -161,6 +151,7 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
         mAppContext = context.getApplicationContext();
         mSettings = new Settings(mAppContext);
 
+        initBackground();
         initRenders();
 
         mVideoWidth = 0;
@@ -173,6 +164,120 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
         // REMOVED: mPendingSubtitleTracks = new Vector<Pair<InputStream, MediaFormat>>();
         mCurrentState = STATE_IDLE;
         mTargetState = STATE_IDLE;
+
+        subtitleDisplay = new TextView(context);
+        subtitleDisplay.setTextSize(24);
+        subtitleDisplay.setGravity(Gravity.CENTER);
+        FrameLayout.LayoutParams layoutParams_txt = new FrameLayout.LayoutParams(
+                FrameLayout.LayoutParams.MATCH_PARENT,
+                FrameLayout.LayoutParams.WRAP_CONTENT,
+                Gravity.BOTTOM);
+        addView(subtitleDisplay, layoutParams_txt);
+    }
+
+    public void setRenderView(IRenderView renderView) {
+        if (mRenderView != null) {
+            if (mMediaPlayer != null)
+                mMediaPlayer.setDisplay(null);
+
+            View renderUIView = mRenderView.getView();
+            mRenderView.removeRenderCallback(mSHCallback);
+            mRenderView = null;
+            removeView(renderUIView);
+        }
+
+        if (renderView == null)
+            return;
+
+        mRenderView = renderView;
+        renderView.setAspectRatio(mCurrentAspectRatio);
+        if (mVideoWidth > 0 && mVideoHeight > 0)
+            renderView.setVideoSize(mVideoWidth, mVideoHeight);
+        if (mVideoSarNum > 0 && mVideoSarDen > 0)
+            renderView.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
+
+        View renderUIView = mRenderView.getView();
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+                FrameLayout.LayoutParams.WRAP_CONTENT,
+                FrameLayout.LayoutParams.WRAP_CONTENT,
+                Gravity.CENTER);
+        renderUIView.setLayoutParams(lp);
+        addView(renderUIView);
+
+        mRenderView.addRenderCallback(mSHCallback);
+        mRenderView.setVideoRotation(mVideoRotationDegree);
+    }
+
+    public void setRender(int render) {
+        switch (render) {
+            case RENDER_NONE:
+                setRenderView(null);
+                break;
+            case RENDER_TEXTURE_VIEW: {
+                TextureRenderView renderView = new TextureRenderView(getContext());
+                if (mMediaPlayer != null) {
+                    renderView.getSurfaceHolder().bindToMediaPlayer(mMediaPlayer);
+                    renderView.setVideoSize(mMediaPlayer.getVideoWidth(), mMediaPlayer.getVideoHeight());
+                    renderView.setVideoSampleAspectRatio(mMediaPlayer.getVideoSarNum(), mMediaPlayer.getVideoSarDen());
+                    renderView.setAspectRatio(mCurrentAspectRatio);
+                }
+                setRenderView(renderView);
+                break;
+            }
+            case RENDER_SURFACE_VIEW: {
+                SurfaceRenderView renderView = new SurfaceRenderView(getContext());
+                setRenderView(renderView);
+                break;
+            }
+            default:
+                Log.e(TAG, String.format(Locale.getDefault(), "invalid render %d\n", render));
+                break;
+        }
+    }
+
+    public void setHudView(TableLayout tableLayout) {
+    }
+
+    /**
+     * Sets video path.
+     *
+     * @param path the path of the video.
+     */
+    public void setVideoPath(String path) {
+        if (path.contains("adaptationSet")) {
+            mManifestString = path;
+            setVideoURI(Uri.parse("ijklas:"));
+        } else {
+            setVideoURI(Uri.parse(path));
+        }
+    }
+
+    /**
+     * Sets video URI.
+     *
+     * @param uri the URI of the video.
+     */
+    public void setVideoURI(Uri uri) {
+        setVideoURI(uri, null);
+    }
+
+    /**
+     * Sets video URI using specific headers.
+     *
+     * @param uri     the URI of the video.
+     * @param headers the headers for the URI request.
+     *                Note that the cross domain redirection is allowed by default, but that can be
+     *                changed with key/value pairs through the headers parameter with
+     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
+     *                to disallow or allow cross domain redirection.
+     */
+    private void setVideoURI(Uri uri, Map<String, String> headers) {
+        mUri = uri;
+        mHeaders = headers;
+        mSeekWhenPrepared = 0;
+        openVideo();
+        requestLayout();
+        invalidate();
     }
 
     // REMOVED: addSubtitleSource
@@ -180,7 +285,6 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
 
     public void stopPlayback() {
         if (mMediaPlayer != null) {
-            mMediaPlayer.record(null, 0);
             mMediaPlayer.stop();
             mMediaPlayer.release();
             mMediaPlayer = null;
@@ -197,7 +301,6 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
             // not ready for playback just yet, will try again later
             return;
         }
-
         // we shouldn't clear the target state, because somebody might have
         // called start() previously
         release(false);
@@ -207,28 +310,10 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
 
         try {
             mMediaPlayer = createPlayer(mSettings.getPlayer());
-            String scheme = mUri.getScheme();
-
-            if (scheme == null)
-                scheme = "";
-
-            if (mMediaPlayer instanceof IjkMediaPlayer) {
-                IjkMediaPlayer ijk = (IjkMediaPlayer) mMediaPlayer;
-
-                if (scheme.equalsIgnoreCase("rtsp")) {
-                    ijk.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "iformat", "rtsp");
-                } else if (scheme.equalsIgnoreCase("rtmp")) {
-                    ijk.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "iformat", "flv");
-                } else if (scheme.equalsIgnoreCase("http")) {
-                    if (mUri.getPath().endsWith(".m3u8")) {
-                        ijk.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "iformat", "hls");
-                    }
-                }
-            }
 
             // TODO: create SubtitleController in MediaPlayer, but we need
             // a context for the subtitle renderers
-//            final Context context = getContext();
+            final Context context = getContext();
             // REMOVED: SubtitleController
 
             // REMOVED: mAudioSession
@@ -239,7 +324,9 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
             mMediaPlayer.setOnInfoListener(mInfoListener);
             mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
             mMediaPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
+            mMediaPlayer.setOnTimedTextListener(mOnTimedTextListener);
             mCurrentBufferPercentage = 0;
+            String scheme = mUri.getScheme();
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
                     mSettings.getUsingMediaDataSource() &&
                     (TextUtils.isEmpty(scheme) || scheme.equalsIgnoreCase("file"))) {
@@ -250,12 +337,12 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
             } else {
                 mMediaPlayer.setDataSource(mUri.toString());
             }
-//            if (mShowing)
-                bindSurfaceHolder(mMediaPlayer, mSurfaceHolder);
+            bindSurfaceHolder(mMediaPlayer, mSurfaceHolder);
             mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
             mMediaPlayer.setScreenOnWhilePlaying(true);
             mPrepareStartTime = System.currentTimeMillis();
             mMediaPlayer.prepareAsync();
+
             // REMOVED: mPendingSubtitleTracks
 
             // we don't set the target state here either, but preserve the
@@ -281,7 +368,6 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
         if (mMediaController != null) {
             mMediaController.hide();
         }
-
         mMediaController = controller;
         attachMediaController();
     }
@@ -296,24 +382,23 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
         }
     }
 
-    IMediaPlayer.OnVideoSizeChangedListener mSizeChangedListener = new IMediaPlayer.OnVideoSizeChangedListener() {
-        public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sarNum, int sarDen) {
-            mVideoWidth = mp.getVideoWidth();
-            mVideoHeight = mp.getVideoHeight();
-            mVideoSarNum = mp.getVideoSarNum();
-            mVideoSarDen = mp.getVideoSarDen();
-
-            if (mVideoWidth != 0 && mVideoHeight != 0) {
-                if (mRenderView != null) {
-                    mRenderView.setVideoSize(mVideoWidth, mVideoHeight);
-                    mRenderView.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
+    IMediaPlayer.OnVideoSizeChangedListener mSizeChangedListener =
+            new IMediaPlayer.OnVideoSizeChangedListener() {
+                public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sarNum, int sarDen) {
+                    mVideoWidth = mp.getVideoWidth();
+                    mVideoHeight = mp.getVideoHeight();
+                    mVideoSarNum = mp.getVideoSarNum();
+                    mVideoSarDen = mp.getVideoSarDen();
+                    if (mVideoWidth != 0 && mVideoHeight != 0) {
+                        if (mRenderView != null) {
+                            mRenderView.setVideoSize(mVideoWidth, mVideoHeight);
+                            mRenderView.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
+                        }
+                        // REMOVED: getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+                        requestLayout();
+                    }
                 }
-
-                // REMOVED: getHolder().setFixedSize(mVideoWidth, mVideoHeight);
-                requestLayout();
-            }
-        }
-    };
+            };
 
     IMediaPlayer.OnPreparedListener mPreparedListener = new IMediaPlayer.OnPreparedListener() {
         public void onPrepared(IMediaPlayer mp) {
@@ -326,39 +411,33 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
             if (mOnPreparedListener != null) {
                 mOnPreparedListener.onPrepared(mMediaPlayer);
             }
-
             if (mMediaController != null) {
                 mMediaController.setEnabled(true);
             }
-
             mVideoWidth = mp.getVideoWidth();
             mVideoHeight = mp.getVideoHeight();
 
             int seekToPosition = mSeekWhenPrepared;  // mSeekWhenPrepared may be changed after seekTo() call
-
             if (seekToPosition != 0) {
                 seekTo(seekToPosition);
             }
-
             if (mVideoWidth != 0 && mVideoHeight != 0) {
                 //Log.i("@@@@", "video size: " + mVideoWidth +"/"+ mVideoHeight);
                 // REMOVED: getHolder().setFixedSize(mVideoWidth, mVideoHeight);
                 if (mRenderView != null) {
                     mRenderView.setVideoSize(mVideoWidth, mVideoHeight);
                     mRenderView.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
-
                     if (!mRenderView.shouldWaitForResize() || mSurfaceWidth == mVideoWidth && mSurfaceHeight == mVideoHeight) {
                         // We didn't actually change the size (it was already at the size
                         // we need), so we won't get a "surface changed" callback, so
                         // start the video here instead of in the callback.
-
                         if (mTargetState == STATE_PLAYING) {
                             start();
-
                             if (mMediaController != null) {
                                 mMediaController.show();
                             }
-                        } else if (!isPlaying() && (seekToPosition != 0 || getCurrentPosition() > 0)) {
+                        } else if (!isPlaying() &&
+                                (seekToPosition != 0 || getCurrentPosition() > 0)) {
                             if (mMediaController != null) {
                                 // Show the media controls when we're paused into a video and make 'em stick.
                                 mMediaController.show(0);
@@ -376,115 +455,146 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
         }
     };
 
-    private IMediaPlayer.OnCompletionListener mCompletionListener = new IMediaPlayer.OnCompletionListener() {
-        public void onCompletion(IMediaPlayer mp) {
-            mCurrentState = STATE_PLAYBACK_COMPLETED;
-            mTargetState = STATE_PLAYBACK_COMPLETED;
-
-            if (mMediaController != null) {
-                mMediaController.hide();
-            }
-
-            if (mOnCompletionListener != null) {
-                mOnCompletionListener.onCompletion(mMediaPlayer);
-            }
-        }
-    };
+    private IMediaPlayer.OnCompletionListener mCompletionListener =
+            new IMediaPlayer.OnCompletionListener() {
+                public void onCompletion(IMediaPlayer mp) {
+                    mCurrentState = STATE_PLAYBACK_COMPLETED;
+                    mTargetState = STATE_PLAYBACK_COMPLETED;
+                    if (mMediaController != null) {
+                        mMediaController.hide();
+                    }
+                    if (mOnCompletionListener != null) {
+                        mOnCompletionListener.onCompletion(mMediaPlayer);
+                    }
+                }
+            };
 
-    private IMediaPlayer.OnInfoListener mInfoListener = new IMediaPlayer.OnInfoListener() {
-        public boolean onInfo(IMediaPlayer mp, int arg1, int arg2) {
-            if (mOnInfoListener != null) {
-                mOnInfoListener.onInfo(mp, arg1, arg2);
-            }
+    private IMediaPlayer.OnInfoListener mInfoListener =
+            new IMediaPlayer.OnInfoListener() {
+                public boolean onInfo(IMediaPlayer mp, int arg1, int arg2) {
+                    if (mOnInfoListener != null) {
+                        mOnInfoListener.onInfo(mp, arg1, arg2);
+                    }
+                    switch (arg1) {
+                        case IMediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
+                            Log.d(TAG, "MEDIA_INFO_VIDEO_TRACK_LAGGING:");
+                            break;
+                        case IMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:
+                            Log.d(TAG, "MEDIA_INFO_VIDEO_RENDERING_START:");
+                            break;
+                        case IMediaPlayer.MEDIA_INFO_BUFFERING_START:
+                            Log.d(TAG, "MEDIA_INFO_BUFFERING_START:");
+                            break;
+                        case IMediaPlayer.MEDIA_INFO_BUFFERING_END:
+                            Log.d(TAG, "MEDIA_INFO_BUFFERING_END:");
+                            break;
+                        case IMediaPlayer.MEDIA_INFO_NETWORK_BANDWIDTH:
+                            Log.d(TAG, "MEDIA_INFO_NETWORK_BANDWIDTH: " + arg2);
+                            break;
+                        case IMediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
+                            Log.d(TAG, "MEDIA_INFO_BAD_INTERLEAVING:");
+                            break;
+                        case IMediaPlayer.MEDIA_INFO_NOT_SEEKABLE:
+                            Log.d(TAG, "MEDIA_INFO_NOT_SEEKABLE:");
+                            break;
+                        case IMediaPlayer.MEDIA_INFO_METADATA_UPDATE:
+                            Log.d(TAG, "MEDIA_INFO_METADATA_UPDATE:");
+                            break;
+                        case IMediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE:
+                            Log.d(TAG, "MEDIA_INFO_UNSUPPORTED_SUBTITLE:");
+                            break;
+                        case IMediaPlayer.MEDIA_INFO_SUBTITLE_TIMED_OUT:
+                            Log.d(TAG, "MEDIA_INFO_SUBTITLE_TIMED_OUT:");
+                            break;
+                        case IMediaPlayer.MEDIA_INFO_VIDEO_ROTATION_CHANGED:
+                            mVideoRotationDegree = arg2;
+                            Log.d(TAG, "MEDIA_INFO_VIDEO_ROTATION_CHANGED: " + arg2);
+                            if (mRenderView != null)
+                                mRenderView.setVideoRotation(arg2);
+                            break;
+                        case IMediaPlayer.MEDIA_INFO_AUDIO_RENDERING_START:
+                            Log.d(TAG, "MEDIA_INFO_AUDIO_RENDERING_START:");
+                            break;
+                    }
+                    return true;
+                }
+            };
+
+    private IMediaPlayer.OnErrorListener mErrorListener =
+            new IMediaPlayer.OnErrorListener() {
+                public boolean onError(IMediaPlayer mp, int framework_err, int impl_err) {
+                    Log.d(TAG, "Error: " + framework_err + "," + impl_err);
+                    mCurrentState = STATE_ERROR;
+                    mTargetState = STATE_ERROR;
+                    if (mMediaController != null) {
+                        mMediaController.hide();
+                    }
 
-            switch (arg1) {
-                case IMediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
-                    Log.d(TAG, "MEDIA_INFO_VIDEO_TRACK_LAGGING:");
-                    break;
-                case IMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:
-                    Log.d(TAG, "MEDIA_INFO_VIDEO_RENDERING_START:");
-                    mCover.animate().cancel();
-                    mCover.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            mCover.setVisibility(GONE);
-                            mCover.setAlpha(1.0f);
+                    /* If an error handler has been supplied, use it and finish. */
+                    if (mOnErrorListener != null) {
+                        if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) {
+                            return true;
                         }
-                    });
-                    break;
-                case IMediaPlayer.MEDIA_INFO_BUFFERING_START:
-                    Log.d(TAG, "MEDIA_INFO_BUFFERING_START:");
-                    break;
-                case IMediaPlayer.MEDIA_INFO_BUFFERING_END:
-                    Log.d(TAG, "MEDIA_INFO_BUFFERING_END:");
-                    break;
-                case IMediaPlayer.MEDIA_INFO_NETWORK_BANDWIDTH:
-                    Log.d(TAG, "MEDIA_INFO_NETWORK_BANDWIDTH: " + arg2);
-                    break;
-                case IMediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
-                    Log.d(TAG, "MEDIA_INFO_BAD_INTERLEAVING:");
-                    break;
-                case IMediaPlayer.MEDIA_INFO_NOT_SEEKABLE:
-                    Log.d(TAG, "MEDIA_INFO_NOT_SEEKABLE:");
-                    break;
-                case IMediaPlayer.MEDIA_INFO_METADATA_UPDATE:
-                    Log.d(TAG, "MEDIA_INFO_METADATA_UPDATE:");
-                    break;
-                case IMediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE:
-                    Log.d(TAG, "MEDIA_INFO_UNSUPPORTED_SUBTITLE:");
-                    break;
-                case IMediaPlayer.MEDIA_INFO_SUBTITLE_TIMED_OUT:
-                    Log.d(TAG, "MEDIA_INFO_SUBTITLE_TIMED_OUT:");
-                    break;
-                case IMediaPlayer.MEDIA_INFO_VIDEO_ROTATION_CHANGED:
-                    mVideoRotationDegree = arg2;
-                    Log.d(TAG, "MEDIA_INFO_VIDEO_ROTATION_CHANGED: " + arg2);
-                    if (mRenderView != null)
-                        mRenderView.setVideoRotation(arg2);
-                    break;
-                case IMediaPlayer.MEDIA_INFO_AUDIO_RENDERING_START:
-                    Log.d(TAG, "MEDIA_INFO_AUDIO_RENDERING_START:");
-                    break;
-            }
-            return true;
-        }
-    };
-
-    private IMediaPlayer.OnErrorListener mErrorListener = new IMediaPlayer.OnErrorListener() {
-        public boolean onError(IMediaPlayer mp, int framework_err, int impl_err) {
-            Log.d(TAG, "Error: " + framework_err + "," + impl_err);
-            mCurrentState = STATE_ERROR;
-            mTargetState = STATE_ERROR;
-            if (mMediaController != null) {
-                mMediaController.hide();
-            }
+                    }
 
-            /* If an error handler has been supplied, use it and finish. */
-            if (mOnErrorListener != null) {
-                if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) {
+                    /* Otherwise, pop up an error dialog so the user knows that
+                     * something bad has happened. Only try and pop up the dialog
+                     * if we're attached to a window. When we're going away and no
+                     * longer have a window, don't bother showing the user an error.
+                     */
+//                    if (getWindowToken() != null) {
+//                        Resources r = mAppContext.getResources();
+//                        int messageId;
+//
+//                        if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
+//                            messageId = R.string.VideoView_error_text_invalid_progressive_playback;
+//                        } else {
+//                            messageId = R.string.VideoView_error_text_unknown;
+//                        }
+//
+//                        new AlertDialog.Builder(getContext())
+//                                .setMessage(messageId)
+//                                .setPositiveButton(R.string.VideoView_error_button,
+//                                        new DialogInterface.OnClickListener() {
+//                                            public void onClick(DialogInterface dialog, int whichButton) {
+//                                            /* If we get here, there is no onError listener, so
+//                                             * at least inform them that the video is over.
+//                                             */
+//                                                if (mOnCompletionListener != null) {
+//                                                    mOnCompletionListener.onCompletion(mMediaPlayer);
+//                                                }
+//                                            }
+//                                        })
+//                                .setCancelable(false)
+//                                .show();
+//                    }
                     return true;
                 }
-            }
-            return true;
-        }
-    };
+            };
 
-    private IMediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new IMediaPlayer.OnBufferingUpdateListener() {
-        public void onBufferingUpdate(IMediaPlayer mp, int percent) {
-            mCurrentBufferPercentage = percent;
-        }
-    };
+    private IMediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
+            new IMediaPlayer.OnBufferingUpdateListener() {
+                public void onBufferingUpdate(IMediaPlayer mp, int percent) {
+                    mCurrentBufferPercentage = percent;
+                }
+            };
 
     private IMediaPlayer.OnSeekCompleteListener mSeekCompleteListener = new IMediaPlayer.OnSeekCompleteListener() {
+
         @Override
         public void onSeekComplete(IMediaPlayer mp) {
             mSeekEndTime = System.currentTimeMillis();
         }
     };
 
-    public void reStart(){
-        openVideo();
-    }
+    private IMediaPlayer.OnTimedTextListener mOnTimedTextListener = new IMediaPlayer.OnTimedTextListener() {
+        @Override
+        public void onTimedText(IMediaPlayer mp, IjkTimedText text) {
+            if (text != null) {
+                subtitleDisplay.setText(text.getText());
+            }
+        }
+    };
 
     /**
      * Register a callback to be invoked when the media file
@@ -543,7 +653,7 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
 
     IRenderView.IRenderCallback mSHCallback = new IRenderView.IRenderCallback() {
         @Override
-        public void onSurfaceChanged( IRenderView.ISurfaceHolder holder, int format, int w, int h) {
+        public void onSurfaceChanged(IRenderView.ISurfaceHolder holder, int format, int w, int h) {
             if (holder.getRenderView() != mRenderView) {
                 Log.e(TAG, "onSurfaceChanged: unmatched render callback\n");
                 return;
@@ -553,50 +663,30 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
             mSurfaceHeight = h;
             boolean isValidState = (mTargetState == STATE_PLAYING);
             boolean hasValidSize = !mRenderView.shouldWaitForResize() || (mVideoWidth == w && mVideoHeight == h);
-
             if (mMediaPlayer != null && isValidState && hasValidSize) {
                 if (mSeekWhenPrepared != 0) {
                     seekTo(mSeekWhenPrepared);
                 }
-
                 start();
             }
         }
 
         @Override
-        public void onSurfaceCreated( IRenderView.ISurfaceHolder holder, int width, int height) {
+        public void onSurfaceCreated(IRenderView.ISurfaceHolder holder, int width, int height) {
             if (holder.getRenderView() != mRenderView) {
                 Log.e(TAG, "onSurfaceCreated: unmatched render callback\n");
                 return;
             }
 
-            if (mCurrentState == STATE_PLAYING) {
-                mCover.animate().cancel();
-                mCover.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        mCover.setVisibility(GONE);
-                        mCover.setAlpha(1.0f);
-                    }
-                });
-            }
-
             mSurfaceHolder = holder;
-
-            if (mMediaPlayer != null) {
-//                if (mShowing)
+            if (mMediaPlayer != null)
                 bindSurfaceHolder(mMediaPlayer, holder);
-//                mCover.animate().setListener(null);
-//                mRenderView.getView().setAlpha(0);
-//                mRenderView.getView().animate().withLayer().alpha(1.0f);
-
-            } else {
+            else
                 openVideo();
-            }
         }
 
         @Override
-        public void onSurfaceDestroyed( IRenderView.ISurfaceHolder holder) {
+        public void onSurfaceDestroyed(IRenderView.ISurfaceHolder holder) {
             if (holder.getRenderView() != mRenderView) {
                 Log.e(TAG, "onSurfaceDestroyed: unmatched render callback\n");
                 return;
@@ -604,7 +694,6 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
 
             // after we return from this we can't use the surface any more
             mSurfaceHolder = null;
-
             // REMOVED: if (mMediaController != null) mMediaController.hide();
             // REMOVED: release(true);
             releaseWithoutStop();
@@ -624,50 +713,29 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
             mMediaPlayer.reset();
             mMediaPlayer.release();
             mMediaPlayer = null;
-
             // REMOVED: mPendingSubtitleTracks.clear();
             mCurrentState = STATE_IDLE;
-
             if (cleartargetstate) {
                 mTargetState = STATE_IDLE;
             }
-
             AudioManager am = (AudioManager) mAppContext.getSystemService(Context.AUDIO_SERVICE);
             am.abandonAudioFocus(null);
         }
     }
 
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-
-        final int delayMillis = 30 * 60 * 1000;
-
-        postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                setVideoURI(mUri);
-                toggleRender();
-                postDelayed(this, delayMillis);
-            }
-        }, delayMillis);
-    }
-
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         if (isInPlaybackState() && mMediaController != null) {
-            toggleMediaControlsVisibility();
-            return true;
+            toggleMediaControlsVisiblity();
         }
-
-        return super.onTouchEvent(ev);
+        return false;
     }
 
     @Override
     public boolean onTrackballEvent(MotionEvent ev) {
         if (isInPlaybackState() && mMediaController != null) {
-            toggleMediaControlsVisibility();
+            toggleMediaControlsVisiblity();
         }
-
         return false;
     }
 
@@ -680,9 +748,9 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
                 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) {
+            if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
+                    keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
                 if (mMediaPlayer.isPlaying()) {
                     pause();
                     mMediaController.show();
@@ -690,34 +758,29 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
                     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) {
+            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
+                    || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
                 if (mMediaPlayer.isPlaying()) {
                     pause();
                     mMediaController.show();
                 }
-
                 return true;
             } else {
-                toggleMediaControlsVisibility();
+                toggleMediaControlsVisiblity();
             }
         }
 
         return super.onKeyDown(keyCode, event);
     }
 
-    public void toggleMediaControlsVisibility() {
-        if (mMediaController == null)
-            return;
-
+    public void toggleMediaControlsVisiblity() {
         if (mMediaController.isShowing()) {
             mMediaController.hide();
         } else {
@@ -725,27 +788,12 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
         }
     }
 
-    public int getSurfaceWidth() {
-        if (mRenderView == null)
-            return 0;
-
-        return mRenderView.getView().getWidth();
-    }
-
-    public int getSurfaceHeight() {
-        if (mRenderView == null)
-            return 0;
-
-        return mRenderView.getView().getHeight();
-    }
-
     @Override
     public void start() {
         if (isInPlaybackState()) {
             mMediaPlayer.start();
             mCurrentState = STATE_PLAYING;
         }
-
         mTargetState = STATE_PLAYING;
     }
 
@@ -757,7 +805,6 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
                 mCurrentState = STATE_PAUSED;
             }
         }
-
         mTargetState = STATE_PAUSED;
     }
 
@@ -781,10 +828,8 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
     @Override
     public int getCurrentPosition() {
         if (isInPlaybackState()) {
-            long position = mMediaPlayer.getCurrentPosition();
-            return (int) position;
+            return (int) mMediaPlayer.getCurrentPosition();
         }
-
         return 0;
     }
 
@@ -809,13 +854,14 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
         if (mMediaPlayer != null) {
             return mCurrentBufferPercentage;
         }
-
         return 0;
     }
 
     public boolean isInPlaybackState() {
-        return (mMediaPlayer != null && mCurrentState != STATE_ERROR &&
-                mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING);
+        return (mMediaPlayer != null &&
+                mCurrentState != STATE_ERROR &&
+                mCurrentState != STATE_IDLE &&
+                mCurrentState != STATE_PREPARING);
     }
 
     @Override
@@ -854,12 +900,10 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
     private static final int[] s_allAspectRatio = {
             IRenderView.AR_ASPECT_FIT_PARENT,
             IRenderView.AR_ASPECT_FILL_PARENT,
-//            IRenderView.AR_ASPECT_WRAP_CONTENT,
-             IRenderView.AR_MATCH_PARENT,
-//            IRenderView.AR_16_9_FIT_PARENT,
-//            IRenderView.AR_4_3_FIT_PARENT
-    };
-
+            IRenderView.AR_ASPECT_WRAP_CONTENT,
+            // IRenderView.AR_MATCH_PARENT,
+            IRenderView.AR_16_9_FIT_PARENT,
+            IRenderView.AR_4_3_FIT_PARENT};
     private int mCurrentAspectRatioIndex = 0;
     private int mCurrentAspectRatio = s_allAspectRatio[0];
 
@@ -867,21 +911,9 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
         mCurrentAspectRatioIndex++;
         mCurrentAspectRatioIndex %= s_allAspectRatio.length;
 
-        switch (mCurrentAspectRatio) {
-            case IRenderView.AR_ASPECT_FIT_PARENT:
-                mCover.setScaleType(ImageView.ScaleType.FIT_CENTER);
-            case IRenderView.AR_ASPECT_FILL_PARENT:
-//            IRenderView.AR_ASPECT_WRAP_CONTENT,
-                mCover.setScaleType(ImageView.ScaleType.CENTER_CROP);
-            case IRenderView.AR_MATCH_PARENT:
-                mCover.setScaleType(ImageView.ScaleType.FIT_XY);
-        }
-
         mCurrentAspectRatio = s_allAspectRatio[mCurrentAspectRatioIndex];
-
         if (mRenderView != null)
             mRenderView.setAspectRatio(mCurrentAspectRatio);
-
         return mCurrentAspectRatio;
     }
 
@@ -892,41 +924,24 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
     public static final int RENDER_SURFACE_VIEW = 1;
     public static final int RENDER_TEXTURE_VIEW = 2;
 
-    private List<Integer> mAllRenders = new ArrayList<>();
+    private List<Integer> mAllRenders = new ArrayList<Integer>();
     private int mCurrentRenderIndex = 0;
     private int mCurrentRender = RENDER_NONE;
 
     private void initRenders() {
         mAllRenders.clear();
 
-        if (mSettings.getEnableTextureView() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
-            mAllRenders.add(RENDER_TEXTURE_VIEW);
         if (mSettings.getEnableSurfaceView())
             mAllRenders.add(RENDER_SURFACE_VIEW);
+        if (mSettings.getEnableTextureView() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+            mAllRenders.add(RENDER_TEXTURE_VIEW);
         if (mSettings.getEnableNoView())
             mAllRenders.add(RENDER_NONE);
 
         if (mAllRenders.isEmpty())
             mAllRenders.add(RENDER_SURFACE_VIEW);
-
         mCurrentRender = mAllRenders.get(mCurrentRenderIndex);
         setRender(mCurrentRender);
-
-        mCover = new ImageView(getContext());
-        addView(mCover);
-
-        switch (mCurrentAspectRatio) {
-            case IRenderView.AR_ASPECT_FIT_PARENT:
-                mCover.setScaleType(ImageView.ScaleType.FIT_CENTER);
-                break;
-            case IRenderView.AR_ASPECT_FILL_PARENT:
-//            IRenderView.AR_ASPECT_WRAP_CONTENT,
-                mCover.setScaleType(ImageView.ScaleType.CENTER_CROP);
-                break;
-            case IRenderView.AR_MATCH_PARENT:
-                mCover.setScaleType(ImageView.ScaleType.FIT_XY);
-                break;
-        }
     }
 
     public int toggleRender() {
@@ -940,23 +955,21 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
 
     public static String getRenderText(Context context, int render) {
         String text;
-
-        switch (render) {
-            case RENDER_NONE:
-                text = context.getString(R.string.VideoView_render_none);
-                break;
-            case RENDER_SURFACE_VIEW:
-                text = context.getString(R.string.VideoView_render_surface_view);
-                break;
-            case RENDER_TEXTURE_VIEW:
-                text = context.getString(R.string.VideoView_render_texture_view);
-                break;
-            default:
-                text = context.getString(R.string.N_A);
-                break;
-        }
-
-        return text;
+//        switch (render) {
+//            case RENDER_NONE:
+//                text = context.getString(R.string.VideoView_render_none);
+//                break;
+//            case RENDER_SURFACE_VIEW:
+//                text = context.getString(R.string.VideoView_render_surface_view);
+//                break;
+//            case RENDER_TEXTURE_VIEW:
+//                text = context.getString(R.string.VideoView_render_texture_view);
+//                break;
+//            default:
+//                text = context.getString(R.string.N_A);
+//                break;
+//        }
+        return "getRenderText";
     }
 
     //-------------------------
@@ -968,16 +981,38 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
 
         if (mRenderView != null)
             mRenderView.getView().invalidate();
-
         openVideo();
-
         return mSettings.getPlayer();
     }
 
+    public static String getPlayerText(Context context, int player) {
+//        String text;
+//        switch (player) {
+//            case Settings.PV_PLAYER__AndroidMediaPlayer:
+//                text = context.getString(R.string.VideoView_player_AndroidMediaPlayer);
+//                break;
+//            case Settings.PV_PLAYER__IjkMediaPlayer:
+//                text = context.getString(R.string.VideoView_player_IjkMediaPlayer);
+//                break;
+//            case Settings.PV_PLAYER__IjkExoMediaPlayer:
+//                text = context.getString(R.string.VideoView_player_IjkExoMediaPlayer);
+//                break;
+//            default:
+//                text = context.getString(R.string.N_A);
+//                break;
+//        }
+        return "getPlayerText";
+    }
+
     public IMediaPlayer createPlayer(int playerType) {
         IMediaPlayer mediaPlayer = null;
 
         switch (playerType) {
+//            case Settings.PV_PLAYER__IjkExoMediaPlayer: {
+//                IjkExoMediaPlayer IjkExoMediaPlayer = new IjkExoMediaPlayer(mAppContext);
+//                mediaPlayer = IjkExoMediaPlayer;
+//            }
+//            break;
             case Settings.PV_PLAYER__AndroidMediaPlayer: {
                 AndroidMediaPlayer androidMediaPlayer = new AndroidMediaPlayer();
                 mediaPlayer = androidMediaPlayer;
@@ -986,20 +1021,22 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
             case Settings.PV_PLAYER__IjkMediaPlayer:
             default: {
                 IjkMediaPlayer ijkMediaPlayer = null;
-
                 if (mUri != null) {
-                    ijkMediaPlayer = new IjkMediaPlayer(getContext().getApplicationContext(), Player_KEY);
+                    ijkMediaPlayer = new IjkMediaPlayer();
                     ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG);
 
+                    if (mManifestString != null) {
+                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "iformat", "ijklas");
+                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "find_stream_info", 0);
+                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "manifest_string", mManifestString);
+                    }
                     if (mSettings.getUsingMediaCodec()) {
                         ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
-
                         if (mSettings.getUsingMediaCodecAutoRotate()) {
                             ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
                         } else {
                             ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);
                         }
-
                         if (mSettings.getMediaCodecHandleResolutionChange()) {
                             ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 1);
                         } else {
@@ -1009,7 +1046,6 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
                         ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);
                     }
 
-//                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
                     if (mSettings.getUsingOpenSLES()) {
                         ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 1);
                     } else {
@@ -1017,32 +1053,17 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
                     }
 
                     String pixelFormat = mSettings.getPixelFormat();
-
                     if (TextUtils.isEmpty(pixelFormat)) {
                         ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
                     } else {
                         ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", pixelFormat);
                     }
+                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
+                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
 
-                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("USE_UDP_MODE", false) ? "udp":"tcp");
-                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", PreferenceManager.getDefaultSharedPreferences(getContext()).getLong("analyzeduration", 1000000L));//21s
-                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", PreferenceManager.getDefaultSharedPreferences(getContext()).getLong("probesize", 204800));//32byte
-                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "auto_convert", 0);
-                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "reconnect", 1);
-                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", PreferenceManager.getDefaultSharedPreferences(getContext()).getInt("timeout", 10));
-                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0);
-                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags","nobuffer");
-
-//                    // framedrop 是在视频帧处理不过来的时候丢弃一些帧达到同步的效果
-//                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 30);
-
-                    // 清空DNS,有時因爲在APP裏面要播放多種類型的視頻(如:MP4,直播,直播平臺保存的視頻,和其他http視頻), 有時會造成因爲DNS的問題而報10000問題的
-                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1);
+                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
 
-//                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "iformat", "hls");
-//                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1);
-
-//                    pause output until enough packets have been read after stalling
+                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
                 }
                 mediaPlayer = ijkMediaPlayer;
             }
@@ -1056,224 +1077,102 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
         return mediaPlayer;
     }
 
-    public String takePicture(String path) {
-        try {
-            int videoWidth = mVideoWidth;
-            int videoHeight = mVideoHeight;
-
-            if (videoWidth <= 0 || videoHeight <= 0) {
-                return path;
-            }
-
-            Bitmap bitmap = Bitmap.createBitmap(videoWidth, videoHeight, Bitmap.Config.ARGB_8888);
-
-            if (mRenderView instanceof TextureRenderView){
-                TextureRenderView render = (TextureRenderView) mRenderView;
-                render.getBitmap(bitmap);
-
-                saveBitmapInFile(path, bitmap);
-
-                bitmap.recycle();
-                return path;
-            }
-        } catch (OutOfMemoryError error) {
-            error.printStackTrace();
-        } catch (IllegalStateException e) {
-            e.printStackTrace();
-        }
-
-        return null;
-    }
-
-    private void saveBitmapInFile(String path, Bitmap bitmap) {
-        FileOutputStream fos = null;
-        try {
-            fos = new FileOutputStream(path);
-
-            // 压缩图像
-            bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
-        } catch (IOException e) {
-            e.printStackTrace();
-        } catch (OutOfMemoryError error) {
-            error.printStackTrace();
-        } finally {
-            if (fos != null) {
-                try {
-                    fos.close();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-    }
-
-    public void startRecord(String path,int seconds) {
-        if (mMediaPlayer == null){
-            throw new IllegalStateException("should in play state!");
-        }
-        if (TextUtils.isEmpty(path)){
-            throw new IllegalArgumentException("path should not be null!");
-        }
-        mMediaPlayer.record(path,seconds);
-    }
-
-    public void stopRecord() {
-        if (mMediaPlayer == null){
-            throw new IllegalStateException("should in play state!");
-        }
-
-        mMediaPlayer.record(null, 0);
-    }
-
-    public long getReceivedBytes() {
-        if (mMediaPlayer == null || !(mMediaPlayer instanceof IjkMediaPlayer))
-            return 0;
-
-        return  ((IjkMediaPlayer)mMediaPlayer).getReceivedBytes();
-    }
-
-    public long getVideoCachePackets() {
-        if (mMediaPlayer == null || !(mMediaPlayer instanceof IjkMediaPlayer))
-            return 0;
-
-        return  ((IjkMediaPlayer)mMediaPlayer).getReceivedVideoFrames();
-    }
-
-    public void setShowing(boolean showing) {
-        mShowing = showing;
-
-        if (mMediaPlayer != null){
-//            toggleRender();
-
-            if (mShowing) {
-//                bindSurfaceHolder(mMediaPlayer, mSurfaceHolder);
-//                mSurfaceHolder.getSurfaceHolder().setFixedSize(mSurfaceWidth,mSurfaceHeight);
-//                mRenderView.getView().layout(0,0,getWidth(),getHeight());
-
-                mRenderView.setAspectRatio(mCurrentAspectRatio);
-            } else {
-//                mMediaPlayer.setDisplay(null);
-                mRenderView.setAspectRatio(IRenderView.AR_1_1);
-//                mSurfaceHolder.getSurfaceHolder().setFixedSize(1,1);
-            }
-        }
-    }
-
-    public boolean isShowing() {
-        return mShowing;
-    }
-
-    public void setRenderView(IRenderView renderView) {
-        if (mRenderView != null) {
-            if (mRenderView instanceof TextureView){
-                Bitmap bmp = ((TextureView) mRenderView).getBitmap();
-                mCover.setImageBitmap(bmp);
-//                mCover.setVisibility(VISIBLE);
-            }
-
-//            if (mMediaPlayer != null)
-//                mMediaPlayer.setDisplay(null);
-
-            View renderUIView = mRenderView.getView();
-            mRenderView.removeRenderCallback(mSHCallback);
-            mRenderView = null;
-            removeView(renderUIView);
-        }
-
-        if (renderView == null)
-            return;
-
-        mRenderView = renderView;
-        renderView.setAspectRatio(mCurrentAspectRatio);
-
-        if (mVideoWidth > 0 && mVideoHeight > 0)
-            renderView.setVideoSize(mVideoWidth, mVideoHeight);
-        if (mVideoSarNum > 0 && mVideoSarDen > 0)
-            renderView.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
-
-        View renderUIView = mRenderView.getView();
-        LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER);
-        renderUIView.setLayoutParams(lp);
-        addView(renderUIView, 0);
-
-        mRenderView.addRenderCallback(mSHCallback);
-        mRenderView.setVideoRotation(mVideoRotationDegree);
-    }
-
-    public void setRender(int render) {
-        switch (render) {
-            case RENDER_NONE:
-                setRenderView(null);
-                break;
-            case RENDER_TEXTURE_VIEW: {
-                TextureRenderView renderView = new TextureRenderView(getContext());
-
-                if (mMediaPlayer != null) {
-                    renderView.getSurfaceHolder().bindToMediaPlayer(mMediaPlayer);
-                    renderView.setVideoSize(mMediaPlayer.getVideoWidth(), mMediaPlayer.getVideoHeight());
-                    renderView.setVideoSampleAspectRatio(mMediaPlayer.getVideoSarNum(), mMediaPlayer.getVideoSarDen());
-                    renderView.setAspectRatio(mCurrentAspectRatio);
-                }
-
-                setRenderView(renderView);
-                break;
-            }
-            case RENDER_SURFACE_VIEW: {
-                SurfaceRenderView renderView = new SurfaceRenderView(getContext());
-                setRenderView(renderView);
-                break;
-            }
-            default:
-                Log.e(TAG, String.format(Locale.getDefault(), "invalid render %d\n", render));
-                break;
-        }
-    }
+    //-------------------------
+    // Extend: Background
+    //-------------------------
 
-    /**
-     * Sets video path.
-     *
-     * @param path the path of the video.
-     */
-    public void setVideoPath(String path) {
-        setVideoURI(Uri.parse(path));
-    }
+    private boolean mEnableBackgroundPlay = false;
 
-    /**
-     * Sets video URI.
-     *
-     * @param uri the URI of the video.
-     */
-    public void setVideoURI(Uri uri) {
-        setVideoURI(uri, null);
+    private void initBackground() {
+//        mEnableBackgroundPlay = mSettings.getEnableBackgroundPlay();
+//        if (mEnableBackgroundPlay) {
+//            MediaPlayerService.intentToStart(getContext());
+//            mMediaPlayer = MediaPlayerService.getMediaPlayer();
+//            if (mHudViewHolder != null)
+//                mHudViewHolder.setMediaPlayer(mMediaPlayer);
+//        }
     }
 
-    /**
-     * Sets video URI using specific headers.
-     *
-     * @param uri     the URI of the video.
-     * @param headers the headers for the URI request.
-     *                Note that the cross domain redirection is allowed by default, but that can be
-     *                changed with key/value pairs through the headers parameter with
-     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
-     *                to disallow or allow cross domain redirection.
-     */
-    private void setVideoURI(Uri uri, Map<String, String> headers) {
-        mUri = uri;
-        mHeaders = headers;
-        mSeekWhenPrepared = 0;
-
-        openVideo();
-        requestLayout();
-        invalidate();
+    public boolean isBackgroundPlayEnabled() {
+        return mEnableBackgroundPlay;
     }
 
-    public int getVideoWidth(){
-        return mVideoWidth;
-    }
+//    public void enterBackground() {
+//        MediaPlayerService.setMediaPlayer(mMediaPlayer);
+//    }
+//
+//    public void stopBackgroundPlay() {
+//        MediaPlayerService.setMediaPlayer(null);
+//    }
 
-    public int getmVideoHeight(){
-        return mVideoHeight;
-    }
+    //-------------------------
+    // Extend: Background
+    //-------------------------
+//    public void showMediaInfo() {
+//        if (mMediaPlayer == null)
+//            return;
+//
+//        int selectedVideoTrack = MediaPlayerCompat.getSelectedTrack(mMediaPlayer, ITrackInfo.MEDIA_TRACK_TYPE_VIDEO);
+//        int selectedAudioTrack = MediaPlayerCompat.getSelectedTrack(mMediaPlayer, ITrackInfo.MEDIA_TRACK_TYPE_AUDIO);
+//        int selectedSubtitleTrack = MediaPlayerCompat.getSelectedTrack(mMediaPlayer, ITrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT);
+//
+//        TableLayoutBinder builder = new TableLayoutBinder(getContext());
+//        builder.appendSection(R.string.mi_player);
+//        builder.appendRow2(R.string.mi_player, MediaPlayerCompat.getName(mMediaPlayer));
+//        builder.appendSection(R.string.mi_media);
+//        builder.appendRow2(R.string.mi_resolution, buildResolution(mVideoWidth, mVideoHeight, mVideoSarNum, mVideoSarDen));
+//        builder.appendRow2(R.string.mi_length, buildTimeMilli(mMediaPlayer.getDuration()));
+//
+//        ITrackInfo trackInfos[] = mMediaPlayer.getTrackInfo();
+//        if (trackInfos != null) {
+//            int index = -1;
+//            for (ITrackInfo trackInfo : trackInfos) {
+//                index++;
+//
+//                int trackType = trackInfo.getTrackType();
+//                if (index == selectedVideoTrack) {
+//                    builder.appendSection(getContext().getString(R.string.mi_stream_fmt1, index) + " " + getContext().getString(R.string.mi__selected_video_track));
+//                } else if (index == selectedAudioTrack) {
+//                    builder.appendSection(getContext().getString(R.string.mi_stream_fmt1, index) + " " + getContext().getString(R.string.mi__selected_audio_track));
+//                } else if (index == selectedSubtitleTrack) {
+//                    builder.appendSection(getContext().getString(R.string.mi_stream_fmt1, index) + " " + getContext().getString(R.string.mi__selected_subtitle_track));
+//                } else {
+//                    builder.appendSection(getContext().getString(R.string.mi_stream_fmt1, index));
+//                }
+//                builder.appendRow2(R.string.mi_type, buildTrackType(trackType));
+//                builder.appendRow2(R.string.mi_language, buildLanguage(trackInfo.getLanguage()));
+//
+//                IMediaFormat mediaFormat = trackInfo.getFormat();
+//                if (mediaFormat == null) {
+//                } else if (mediaFormat instanceof IjkMediaFormat) {
+//                    switch (trackType) {
+//                        case ITrackInfo.MEDIA_TRACK_TYPE_VIDEO:
+//                            builder.appendRow2(R.string.mi_codec, mediaFormat.getString(IjkMediaFormat.KEY_IJK_CODEC_LONG_NAME_UI));
+//                            builder.appendRow2(R.string.mi_profile_level, mediaFormat.getString(IjkMediaFormat.KEY_IJK_CODEC_PROFILE_LEVEL_UI));
+//                            builder.appendRow2(R.string.mi_pixel_format, mediaFormat.getString(IjkMediaFormat.KEY_IJK_CODEC_PIXEL_FORMAT_UI));
+//                            builder.appendRow2(R.string.mi_resolution, mediaFormat.getString(IjkMediaFormat.KEY_IJK_RESOLUTION_UI));
+//                            builder.appendRow2(R.string.mi_frame_rate, mediaFormat.getString(IjkMediaFormat.KEY_IJK_FRAME_RATE_UI));
+//                            builder.appendRow2(R.string.mi_bit_rate, mediaFormat.getString(IjkMediaFormat.KEY_IJK_BIT_RATE_UI));
+//                            break;
+//                        case ITrackInfo.MEDIA_TRACK_TYPE_AUDIO:
+//                            builder.appendRow2(R.string.mi_codec, mediaFormat.getString(IjkMediaFormat.KEY_IJK_CODEC_LONG_NAME_UI));
+//                            builder.appendRow2(R.string.mi_profile_level, mediaFormat.getString(IjkMediaFormat.KEY_IJK_CODEC_PROFILE_LEVEL_UI));
+//                            builder.appendRow2(R.string.mi_sample_rate, mediaFormat.getString(IjkMediaFormat.KEY_IJK_SAMPLE_RATE_UI));
+//                            builder.appendRow2(R.string.mi_channels, mediaFormat.getString(IjkMediaFormat.KEY_IJK_CHANNEL_UI));
+//                            builder.appendRow2(R.string.mi_bit_rate, mediaFormat.getString(IjkMediaFormat.KEY_IJK_BIT_RATE_UI));
+//                            break;
+//                        default:
+//                            break;
+//                    }
+//                }
+//            }
+//        }
+//
+//        AlertDialog.Builder adBuilder = builder.buildAlertDialogBuilder();
+//        adBuilder.setTitle(R.string.media_information);
+//        adBuilder.setNegativeButton(R.string.close, null);
+//        adBuilder.show();
+//    }
 
     private String buildResolution(int width, int height, int sarNum, int sarDen) {
         StringBuilder sb = new StringBuilder();
@@ -1297,11 +1196,9 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
         long hours = total_seconds / 3600;
         long minutes = (total_seconds % 3600) / 60;
         long seconds = total_seconds % 60;
-
         if (duration <= 0) {
             return "--:--";
         }
-
         if (hours >= 100) {
             return String.format(Locale.US, "%d:%02d:%02d", hours, minutes, seconds);
         } else if (hours > 0) {
@@ -1312,22 +1209,23 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
     }
 
     private String buildTrackType(int type) {
-        Context context = getContext();
-        switch (type) {
-            case ITrackInfo.MEDIA_TRACK_TYPE_VIDEO:
-                return context.getString(R.string.TrackType_video);
-            case ITrackInfo.MEDIA_TRACK_TYPE_AUDIO:
-                return context.getString(R.string.TrackType_audio);
-            case ITrackInfo.MEDIA_TRACK_TYPE_SUBTITLE:
-                return context.getString(R.string.TrackType_subtitle);
-            case ITrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT:
-                return context.getString(R.string.TrackType_timedtext);
-            case ITrackInfo.MEDIA_TRACK_TYPE_METADATA:
-                return context.getString(R.string.TrackType_metadata);
-            case ITrackInfo.MEDIA_TRACK_TYPE_UNKNOWN:
-            default:
-                return context.getString(R.string.TrackType_unknown);
-        }
+//        Context context = getContext();
+//        switch (type) {
+//            case ITrackInfo.MEDIA_TRACK_TYPE_VIDEO:
+//                return context.getString(R.string.TrackType_video);
+//            case ITrackInfo.MEDIA_TRACK_TYPE_AUDIO:
+//                return context.getString(R.string.TrackType_audio);
+//            case ITrackInfo.MEDIA_TRACK_TYPE_SUBTITLE:
+//                return context.getString(R.string.TrackType_subtitle);
+//            case ITrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT:
+//                return context.getString(R.string.TrackType_timedtext);
+//            case ITrackInfo.MEDIA_TRACK_TYPE_METADATA:
+//                return context.getString(R.string.TrackType_metadata);
+//            case ITrackInfo.MEDIA_TRACK_TYPE_UNKNOWN:
+//            default:
+//                return context.getString(R.string.TrackType_unknown);
+//        }
+        return "buildTrackType";
     }
 
     private String buildLanguage(String language) {
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/MeasureHelper.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/MeasureHelper.java
index 696f9cd..b378e5b 100644
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/MeasureHelper.java
+++ b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/MeasureHelper.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Bilibili
  * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,12 +20,8 @@ package tv.danmaku.ijk.media.widget.media;
 import android.content.Context;
 import android.view.View;
 
-
 import java.lang.ref.WeakReference;
 
-import tv.danmaku.ijk.media.player.R;
-
-
 public final class MeasureHelper {
     private WeakReference<View> mWeakView;
 
@@ -140,9 +137,6 @@ public final class MeasureHelper {
                             height = (int) (width / displayAspectRatio);
                         }
                         break;
-                    case IRenderView.AR_1_1:
-                        width = height = 1;
-                        break;
                     case IRenderView.AR_ASPECT_WRAP_CONTENT:
                     default:
                         if (shouldBeWider) {
@@ -220,32 +214,31 @@ public final class MeasureHelper {
         mCurrentAspectRatio = aspectRatio;
     }
 
-
     public static String getAspectRatioText(Context context, int aspectRatio) {
         String text;
-        switch (aspectRatio) {
-            case IRenderView.AR_ASPECT_FIT_PARENT:
-                text = context.getString(R.string.VideoView_ar_aspect_fit_parent);
-                break;
-            case IRenderView.AR_ASPECT_FILL_PARENT:
-                text = context.getString(R.string.VideoView_ar_aspect_fill_parent);
-                break;
-            case IRenderView.AR_ASPECT_WRAP_CONTENT:
-                text = context.getString(R.string.VideoView_ar_aspect_wrap_content);
-                break;
-            case IRenderView.AR_MATCH_PARENT:
-                text = context.getString(R.string.VideoView_ar_match_parent);
-                break;
-            case IRenderView.AR_16_9_FIT_PARENT:
-                text = context.getString(R.string.VideoView_ar_16_9_fit_parent);
-                break;
-            case IRenderView.AR_4_3_FIT_PARENT:
-                text = context.getString(R.string.VideoView_ar_4_3_fit_parent);
-                break;
-            default:
-                text = context.getString(R.string.N_A);
-                break;
-        }
-        return text;
+//        switch (aspectRatio) {
+//            case IRenderView.AR_ASPECT_FIT_PARENT:
+//                text = context.getString(R.string.VideoView_ar_aspect_fit_parent);
+//                break;
+//            case IRenderView.AR_ASPECT_FILL_PARENT:
+//                text = context.getString(R.string.VideoView_ar_aspect_fill_parent);
+//                break;
+//            case IRenderView.AR_ASPECT_WRAP_CONTENT:
+//                text = context.getString(R.string.VideoView_ar_aspect_wrap_content);
+//                break;
+//            case IRenderView.AR_MATCH_PARENT:
+//                text = context.getString(R.string.VideoView_ar_match_parent);
+//                break;
+//            case IRenderView.AR_16_9_FIT_PARENT:
+//                text = context.getString(R.string.VideoView_ar_16_9_fit_parent);
+//                break;
+//            case IRenderView.AR_4_3_FIT_PARENT:
+//                text = context.getString(R.string.VideoView_ar_4_3_fit_parent);
+//                break;
+//            default:
+//                text = context.getString(R.string.N_A);
+//                break;
+//        }
+        return "getAspectRatioText";
     }
 }
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/MediaPlayerCompat.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/MediaPlayerCompat.java
index f7231a4..b4e1fa6 100644
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/MediaPlayerCompat.java
+++ b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/MediaPlayerCompat.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Bilibili
  * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/SurfaceRenderView.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/SurfaceRenderView.java
index 2d5b917..1f04448 100644
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/SurfaceRenderView.java
+++ b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/SurfaceRenderView.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Bilibili
  * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -35,7 +36,6 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import tv.danmaku.ijk.media.player.IMediaPlayer;
 import tv.danmaku.ijk.media.player.ISurfaceTextureHolder;
-import tv.danmaku.ijk.media.widget.media.IRenderView;
 
 public class SurfaceRenderView extends SurfaceView implements IRenderView {
     private MeasureHelper mMeasureHelper;
@@ -190,11 +190,11 @@ public class SurfaceRenderView extends SurfaceView implements IRenderView {
         private WeakReference<SurfaceRenderView> mWeakSurfaceView;
         private Map<IRenderCallback, Object> mRenderCallbackMap = new ConcurrentHashMap<IRenderCallback, Object>();
 
-        public SurfaceCallback(SurfaceRenderView surfaceView) {
+        public SurfaceCallback( SurfaceRenderView surfaceView) {
             mWeakSurfaceView = new WeakReference<SurfaceRenderView>(surfaceView);
         }
 
-        public void addRenderCallback(IRenderCallback callback) {
+        public void addRenderCallback( IRenderCallback callback) {
             mRenderCallbackMap.put(callback, callback);
 
             ISurfaceHolder surfaceHolder = null;
@@ -211,7 +211,7 @@ public class SurfaceRenderView extends SurfaceView implements IRenderView {
             }
         }
 
-        public void removeRenderCallback(IRenderCallback callback) {
+        public void removeRenderCallback( IRenderCallback callback) {
             mRenderCallbackMap.remove(callback);
         }
 
diff --git a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/TextureRenderView.java b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/TextureRenderView.java
index fee9005..16bacf4 100644
--- a/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/TextureRenderView.java
+++ b/library-ijkplayer/src/main/java/tv/danmaku/ijk/media/widget/media/TextureRenderView.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Bilibili
  * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +19,6 @@ package tv.danmaku.ijk.media.widget.media;
 
 import android.annotation.TargetApi;
 import android.content.Context;
-import android.graphics.Bitmap;
 import android.graphics.SurfaceTexture;
 import android.os.Build;
 import android.util.AttributeSet;
@@ -167,25 +167,21 @@ public class TextureRenderView extends TextureView implements IRenderView {
             }
         }
 
-        
         @Override
         public IRenderView getRenderView() {
             return mTextureView;
         }
 
-        
         @Override
         public SurfaceHolder getSurfaceHolder() {
             return null;
         }
 
-        
         @Override
         public SurfaceTexture getSurfaceTexture() {
             return mSurfaceTexture;
         }
 
-        
         @Override
         public Surface openSurface() {
             if (mSurfaceTexture == null)
@@ -210,7 +206,7 @@ public class TextureRenderView extends TextureView implements IRenderView {
 
     private SurfaceCallback mSurfaceCallback;
 
-    private static final class SurfaceCallback implements SurfaceTextureListener, ISurfaceTextureHost {
+    private static final class SurfaceCallback implements TextureView.SurfaceTextureListener, ISurfaceTextureHost {
         private SurfaceTexture mSurfaceTexture;
         private boolean mIsFormatChanged;
         private int mWidth;