Преглед на файлове

完善视频player的代码注释

杨充 преди 4 години
родител
ревизия
1361d5bc36
променени са 16 файла, в които са добавени 898 реда и са изтрити 387 реда
  1. 130 30
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/exo/ExoMediaPlayer.java
  2. 0 18
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/exo/ExoMediaPlayerFactory.java
  3. 21 6
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/exo/ExoMediaSourceHelper.java
  4. 26 0
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/exo/ExoPlayerFactory.java
  5. 0 264
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/ijk/IjkPlayer.java
  6. 27 5
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/ijk/IjkPlayerFactory.java
  7. 478 0
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/ijk/IjkVideoPlayer.java
  8. 15 0
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/ijk/RawDataSourceProvider.java
  9. 124 5
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/media/AndroidMediaPlayer.java
  10. 23 1
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/media/MediaPlayerFactory.java
  11. 43 11
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/inter/AbstractPlayer.java
  12. 2 1
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/render/TextureRenderView.java
  13. 6 0
      VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/ui/view/BasisVideoController.java
  14. 0 26
      VideoUi/src/androidTest/java/com/yc/videoui/ExampleInstrumentedTest.java
  15. 0 17
      VideoUi/src/test/java/com/yc/videoui/ExampleUnitTest.java
  16. 3 3
      app/src/main/java/org/yczbj/ycvideoplayer/activity/TypeActivity.java

+ 130 - 30
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/exo/ExoMediaPlayer.java

@@ -1,5 +1,6 @@
 package org.yczbj.ycvideoplayerlib.player.impl.exo;
 
+import android.app.Application;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.os.Handler;
@@ -14,6 +15,7 @@ import com.google.android.exoplayer2.PlaybackParameters;
 import com.google.android.exoplayer2.Player;
 import com.google.android.exoplayer2.RenderersFactory;
 import com.google.android.exoplayer2.SimpleExoPlayer;
+import com.google.android.exoplayer2.Timeline;
 import com.google.android.exoplayer2.analytics.AnalyticsCollector;
 import com.google.android.exoplayer2.source.MediaSource;
 import com.google.android.exoplayer2.source.MediaSourceEventListener;
@@ -27,19 +29,26 @@ import com.google.android.exoplayer2.util.Util;
 import com.google.android.exoplayer2.video.VideoListener;
 import org.yczbj.ycvideoplayerlib.player.inter.AbstractPlayer;
 import org.yczbj.ycvideoplayerlib.player.manager.VideoViewManager;
+import org.yczbj.ycvideoplayerlib.tool.toast.BaseToast;
 
 import java.util.Map;
 
-
+/**
+ * <pre>
+ *     @author yangchong
+ *     blog  : https://github.com/yangchong211
+ *     time  : 2018/11/9
+ *     desc  : exo视频播放器实现类
+ *     revise:
+ * </pre>
+ */
 public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Player.EventListener {
 
     protected Context mAppContext;
     protected SimpleExoPlayer mInternalPlayer;
     protected MediaSource mMediaSource;
     protected ExoMediaSourceHelper mMediaSourceHelper;
-
     private PlaybackParameters mSpeedPlaybackParameters;
-
     private int mLastReportedPlaybackState = Player.STATE_IDLE;
     private boolean mLastReportedPlayWhenReady = false;
     private boolean mIsPreparing;
@@ -50,7 +59,11 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
     private TrackSelector mTrackSelector;
 
     public ExoMediaPlayer(Context context) {
-        mAppContext = context.getApplicationContext();
+        if (context instanceof Application){
+            mAppContext = context;
+        } else {
+            mAppContext = context.getApplicationContext();
+        }
         mMediaSourceHelper = ExoMediaSourceHelper.getInstance(context);
     }
 
@@ -73,7 +86,13 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
         if (VideoViewManager.getConfig().mIsEnableLog && mTrackSelector instanceof MappingTrackSelector) {
             mInternalPlayer.addAnalyticsListener(new EventLogger((MappingTrackSelector) mTrackSelector, "ExoPlayer"));
         }
+        initListener();
+    }
 
+    /**
+     * exo视频播放器监听listener
+     */
+    private void initListener() {
         mInternalPlayer.addListener(this);
         mInternalPlayer.addVideoListener(this);
     }
@@ -90,8 +109,19 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
         mLoadControl = loadControl;
     }
 
+    /**
+     * 设置播放地址
+     *
+     * @param path    播放地址
+     * @param headers 播放地址请求头
+     */
     @Override
     public void setDataSource(String path, Map<String, String> headers) {
+        // 设置dataSource
+        if(path==null || path.length()==0){
+            BaseToast.showRoundRectToast("视频链接不能为空");
+            return;
+        }
         mMediaSource = mMediaSourceHelper.getMediaSource(path, headers);
     }
 
@@ -100,38 +130,56 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
         //no support
     }
 
+    /**
+     * 准备开始播放(异步)
+     */
+    @Override
+    public void prepareAsync() {
+        if (mInternalPlayer == null){
+            return;
+        }
+        if (mMediaSource == null){
+            return;
+        }
+        if (mSpeedPlaybackParameters != null) {
+            mInternalPlayer.setPlaybackParameters(mSpeedPlaybackParameters);
+        }
+        mIsPreparing = true;
+        mMediaSource.addEventListener(new Handler(), mMediaSourceEventListener);
+        mInternalPlayer.prepare(mMediaSource);
+    }
+
+    /**
+     * 播放
+     */
     @Override
     public void start() {
-        if (mInternalPlayer == null)
+        if (mInternalPlayer == null){
             return;
+        }
         mInternalPlayer.setPlayWhenReady(true);
     }
 
+    /**
+     * 暂停
+     */
     @Override
     public void pause() {
-        if (mInternalPlayer == null)
+        if (mInternalPlayer == null){
             return;
+        }
         mInternalPlayer.setPlayWhenReady(false);
     }
 
+    /**
+     * 停止
+     */
     @Override
     public void stop() {
-        if (mInternalPlayer == null)
+        if (mInternalPlayer == null){
             return;
-        mInternalPlayer.stop();
-    }
-
-    @Override
-    public void prepareAsync() {
-        if (mInternalPlayer == null)
-            return;
-        if (mMediaSource == null) return;
-        if (mSpeedPlaybackParameters != null) {
-            mInternalPlayer.setPlaybackParameters(mSpeedPlaybackParameters);
         }
-        mIsPreparing = true;
-        mMediaSource.addEventListener(new Handler(), mMediaSourceEventListener);
-        mInternalPlayer.prepare(mMediaSource);
+        mInternalPlayer.stop();
     }
 
     private MediaSourceEventListener mMediaSourceEventListener = new MediaSourceEventListener() {
@@ -143,6 +191,9 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
         }
     };
 
+    /**
+     * 重置播放器
+     */
     @Override
     public void reset() {
         if (mInternalPlayer != null) {
@@ -155,10 +206,14 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
         }
     }
 
+    /**
+     * 是否正在播放
+     */
     @Override
     public boolean isPlaying() {
-        if (mInternalPlayer == null)
+        if (mInternalPlayer == null){
             return false;
+        }
         int state = mInternalPlayer.getPlaybackState();
         switch (state) {
             case Player.STATE_BUFFERING:
@@ -171,13 +226,20 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
         }
     }
 
+    /**
+     * 调整进度
+     */
     @Override
     public void seekTo(long time) {
-        if (mInternalPlayer == null)
+        if (mInternalPlayer == null){
             return;
+        }
         mInternalPlayer.seekTo(time);
     }
 
+    /**
+     * 释放播放器
+     */
     @Override
     public void release() {
         if (mInternalPlayer != null) {
@@ -201,25 +263,39 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
         mSpeedPlaybackParameters = null;
     }
 
+    /**
+     * 获取当前播放的位置
+     */
     @Override
     public long getCurrentPosition() {
-        if (mInternalPlayer == null)
+        if (mInternalPlayer == null){
             return 0;
+        }
         return mInternalPlayer.getCurrentPosition();
     }
 
+    /**
+     * 获取视频总时长
+     */
     @Override
     public long getDuration() {
-        if (mInternalPlayer == null)
+        if (mInternalPlayer == null){
             return 0;
+        }
         return mInternalPlayer.getDuration();
     }
 
+    /**
+     * 获取缓冲百分比
+     */
     @Override
     public int getBufferedPercentage() {
         return mInternalPlayer == null ? 0 : mInternalPlayer.getBufferedPercentage();
     }
 
+    /**
+     * 设置渲染视频的View,主要用于SurfaceView
+     */
     @Override
     public void setSurface(Surface surface) {
         if (mInternalPlayer != null) {
@@ -229,22 +305,31 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
 
     @Override
     public void setDisplay(SurfaceHolder holder) {
-        if (holder == null)
+        if (holder == null){
             setSurface(null);
-        else
+        } else{
             setSurface(holder.getSurface());
+        }
     }
 
+    /**
+     * 设置音量
+     */
     @Override
     public void setVolume(float leftVolume, float rightVolume) {
-        if (mInternalPlayer != null)
+        if (mInternalPlayer != null){
             mInternalPlayer.setVolume((leftVolume + rightVolume) / 2);
+        }
     }
 
+    /**
+     * 设置是否循环播放
+     */
     @Override
     public void setLooping(boolean isLooping) {
-        if (mInternalPlayer != null)
+        if (mInternalPlayer != null){
             mInternalPlayer.setRepeatMode(isLooping ? Player.REPEAT_MODE_ALL : Player.REPEAT_MODE_OFF);
+        }
     }
 
     @Override
@@ -253,6 +338,9 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
         mInternalPlayer.setPlayWhenReady(true);
     }
 
+    /**
+     * 设置播放速度
+     */
     @Override
     public void setSpeed(float speed) {
         PlaybackParameters playbackParameters = new PlaybackParameters(speed);
@@ -262,6 +350,9 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
         }
     }
 
+    /**
+     * 获取播放速度
+     */
     @Override
     public float getSpeed() {
         if (mSpeedPlaybackParameters != null) {
@@ -270,6 +361,9 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
         return 1f;
     }
 
+    /**
+     * 获取当前缓冲的网速
+     */
     @Override
     public long getTcpSpeed() {
         // no support
@@ -278,8 +372,12 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
 
     @Override
     public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
-        if (mPlayerEventListener == null) return;
-        if (mIsPreparing) return;
+        if (mPlayerEventListener == null){
+            return;
+        }
+        if (mIsPreparing){
+            return;
+        }
         if (mLastReportedPlayWhenReady != playWhenReady || mLastReportedPlaybackState != playbackState) {
             switch (playbackState) {
                 case Player.STATE_BUFFERING:
@@ -295,6 +393,8 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
                 case Player.STATE_ENDED:
                     mPlayerEventListener.onCompletion();
                     break;
+                default:
+                    break;
             }
             mLastReportedPlaybackState = playbackState;
             mLastReportedPlayWhenReady = playWhenReady;

+ 0 - 18
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/exo/ExoMediaPlayerFactory.java

@@ -1,18 +0,0 @@
-package org.yczbj.ycvideoplayerlib.player.impl.exo;
-
-import android.content.Context;
-
-import org.yczbj.ycvideoplayerlib.player.factory.PlayerFactory;
-
-
-public class ExoMediaPlayerFactory extends PlayerFactory<ExoMediaPlayer> {
-
-    public static ExoMediaPlayerFactory create() {
-        return new ExoMediaPlayerFactory();
-    }
-
-    @Override
-    public ExoMediaPlayer createPlayer(Context context) {
-        return new ExoMediaPlayer(context);
-    }
-}

+ 21 - 6
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/exo/ExoMediaSourceHelper.java

@@ -1,5 +1,6 @@
 package org.yczbj.ycvideoplayerlib.player.impl.exo;
 
+import android.app.Application;
 import android.content.Context;
 import android.net.Uri;
 import android.text.TextUtils;
@@ -28,17 +29,29 @@ import java.io.File;
 import java.lang.reflect.Field;
 import java.util.Map;
 
+/**
+ * <pre>
+ *     @author yangchong
+ *     blog  : https://github.com/yangchong211
+ *     time  : 2018/11/9
+ *     desc  : exo视频播放器帮助类
+ *     revise:
+ * </pre>
+ */
 public final class ExoMediaSourceHelper {
 
     private static ExoMediaSourceHelper sInstance;
-
     private final String mUserAgent;
     private Context mAppContext;
     private HttpDataSource.Factory mHttpDataSourceFactory;
     private Cache mCache;
 
     private ExoMediaSourceHelper(Context context) {
-        mAppContext = context.getApplicationContext();
+        if (context instanceof Application){
+            mAppContext = context;
+        } else {
+            mAppContext = context.getApplicationContext();
+        }
         mUserAgent = Util.getUserAgent(mAppContext, mAppContext.getApplicationInfo().name);
     }
 
@@ -68,8 +81,8 @@ public final class ExoMediaSourceHelper {
     public MediaSource getMediaSource(String uri, Map<String, String> headers, boolean isCache) {
         Uri contentUri = Uri.parse(uri);
         if ("rtmp".equals(contentUri.getScheme())) {
-            return new ProgressiveMediaSource.Factory(new RtmpDataSourceFactory(null))
-                    .createMediaSource(contentUri);
+            RtmpDataSourceFactory rtmpDataSourceFactory = new RtmpDataSourceFactory(null);
+            return new ProgressiveMediaSource.Factory(rtmpDataSourceFactory).createMediaSource(contentUri);
         }
         int contentType = inferContentType(uri);
         DataSource.Factory factory;
@@ -119,8 +132,10 @@ public final class ExoMediaSourceHelper {
 
     private Cache newCache() {
         return new SimpleCache(
-                new File(mAppContext.getExternalCacheDir(), "exo-video-cache"),//缓存目录
-                new LeastRecentlyUsedCacheEvictor(512 * 1024 * 1024),//缓存大小,默认512M,使用LRU算法实现
+                //缓存目录
+                new File(mAppContext.getExternalCacheDir(), "exo-video-cache"),
+                //缓存大小,默认512M,使用LRU算法实现
+                new LeastRecentlyUsedCacheEvictor(512 * 1024 * 1024),
                 new ExoDatabaseProvider(mAppContext));
     }
 

+ 26 - 0
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/exo/ExoPlayerFactory.java

@@ -0,0 +1,26 @@
+package org.yczbj.ycvideoplayerlib.player.impl.exo;
+
+import android.content.Context;
+
+import org.yczbj.ycvideoplayerlib.player.factory.PlayerFactory;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     blog  : https://github.com/yangchong211
+ *     time  : 2018/11/9
+ *     desc  : exo视频播放器Factory
+ *     revise:
+ * </pre>
+ */
+public class ExoPlayerFactory extends PlayerFactory<ExoMediaPlayer> {
+
+    public static ExoPlayerFactory create() {
+        return new ExoPlayerFactory();
+    }
+
+    @Override
+    public ExoMediaPlayer createPlayer(Context context) {
+        return new ExoMediaPlayer(context);
+    }
+}

+ 0 - 264
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/ijk/IjkPlayer.java

@@ -1,264 +0,0 @@
-package org.yczbj.ycvideoplayerlib.player.impl.ijk;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-
-
-import org.yczbj.ycvideoplayerlib.player.inter.AbstractPlayer;
-import org.yczbj.ycvideoplayerlib.player.manager.VideoViewManager;
-
-import java.util.Map;
-
-import tv.danmaku.ijk.media.player.IMediaPlayer;
-import tv.danmaku.ijk.media.player.IjkMediaPlayer;
-
-public class IjkPlayer extends AbstractPlayer {
-
-    protected IjkMediaPlayer mMediaPlayer;
-    private int mBufferedPercent;
-    private Context mAppContext;
-
-    public IjkPlayer(Context context) {
-        mAppContext = context;
-    }
-
-    @Override
-    public void initPlayer() {
-        mMediaPlayer = new IjkMediaPlayer();
-        //native日志
-        IjkMediaPlayer.native_setLogLevel(VideoViewManager.getConfig().mIsEnableLog ? IjkMediaPlayer.IJK_LOG_INFO : IjkMediaPlayer.IJK_LOG_SILENT);
-        setOptions();
-        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
-        mMediaPlayer.setOnErrorListener(onErrorListener);
-        mMediaPlayer.setOnCompletionListener(onCompletionListener);
-        mMediaPlayer.setOnInfoListener(onInfoListener);
-        mMediaPlayer.setOnBufferingUpdateListener(onBufferingUpdateListener);
-        mMediaPlayer.setOnPreparedListener(onPreparedListener);
-        mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
-        mMediaPlayer.setOnNativeInvokeListener(new IjkMediaPlayer.OnNativeInvokeListener() {
-            @Override
-            public boolean onNativeInvoke(int i, Bundle bundle) {
-                return true;
-            }
-        });
-    }
-
-
-    @Override
-    public void setOptions() {
-    }
-
-    @Override
-    public void setDataSource(String path, Map<String, String> headers) {
-        try {
-            Uri uri = Uri.parse(path);
-            if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())) {
-                RawDataSourceProvider rawDataSourceProvider = RawDataSourceProvider.create(mAppContext, uri);
-                mMediaPlayer.setDataSource(rawDataSourceProvider);
-            } else {
-                //处理UA问题
-                if (headers != null) {
-                    String userAgent = headers.get("User-Agent");
-                    if (!TextUtils.isEmpty(userAgent)) {
-                        mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "user_agent", userAgent);
-                    }
-                }
-                mMediaPlayer.setDataSource(mAppContext, uri, headers);
-            }
-        } catch (Exception e) {
-            mPlayerEventListener.onError();
-        }
-    }
-
-    @Override
-    public void setDataSource(AssetFileDescriptor fd) {
-        try {
-            mMediaPlayer.setDataSource(new RawDataSourceProvider(fd));
-        } catch (Exception e) {
-            mPlayerEventListener.onError();
-        }
-    }
-
-    @Override
-    public void pause() {
-        try {
-            mMediaPlayer.pause();
-        } catch (IllegalStateException e) {
-            mPlayerEventListener.onError();
-        }
-    }
-
-    @Override
-    public void start() {
-        try {
-            mMediaPlayer.start();
-        } catch (IllegalStateException e) {
-            mPlayerEventListener.onError();
-        }
-    }
-
-    @Override
-    public void stop() {
-        try {
-            mMediaPlayer.stop();
-        } catch (IllegalStateException e) {
-            mPlayerEventListener.onError();
-        }
-    }
-
-    @Override
-    public void prepareAsync() {
-        try {
-            mMediaPlayer.prepareAsync();
-        } catch (IllegalStateException e) {
-            mPlayerEventListener.onError();
-        }
-    }
-
-    @Override
-    public void reset() {
-        mMediaPlayer.reset();
-        mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
-        setOptions();
-    }
-
-    @Override
-    public boolean isPlaying() {
-        return mMediaPlayer.isPlaying();
-    }
-
-    @Override
-    public void seekTo(long time) {
-        try {
-            mMediaPlayer.seekTo((int) time);
-        } catch (IllegalStateException e) {
-            mPlayerEventListener.onError();
-        }
-    }
-
-    @Override
-    public void release() {
-        mMediaPlayer.setOnErrorListener(null);
-        mMediaPlayer.setOnCompletionListener(null);
-        mMediaPlayer.setOnInfoListener(null);
-        mMediaPlayer.setOnBufferingUpdateListener(null);
-        mMediaPlayer.setOnPreparedListener(null);
-        mMediaPlayer.setOnVideoSizeChangedListener(null);
-        new Thread() {
-            @Override
-            public void run() {
-                try {
-                    mMediaPlayer.release();
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-        }.start();
-    }
-
-    @Override
-    public long getCurrentPosition() {
-        return mMediaPlayer.getCurrentPosition();
-    }
-
-    @Override
-    public long getDuration() {
-        return mMediaPlayer.getDuration();
-    }
-
-    @Override
-    public int getBufferedPercentage() {
-        return mBufferedPercent;
-    }
-
-    @Override
-    public void setSurface(Surface surface) {
-        mMediaPlayer.setSurface(surface);
-    }
-
-    @Override
-    public void setDisplay(SurfaceHolder holder) {
-        mMediaPlayer.setDisplay(holder);
-    }
-
-    @Override
-    public void setVolume(float v1, float v2) {
-        mMediaPlayer.setVolume(v1, v2);
-    }
-
-    @Override
-    public void setLooping(boolean isLooping) {
-        mMediaPlayer.setLooping(isLooping);
-    }
-
-    @Override
-    public void setSpeed(float speed) {
-        mMediaPlayer.setSpeed(speed);
-    }
-
-    @Override
-    public float getSpeed() {
-        return mMediaPlayer.getSpeed(0);
-    }
-
-    @Override
-    public long getTcpSpeed() {
-        return mMediaPlayer.getTcpSpeed();
-    }
-
-    private IMediaPlayer.OnErrorListener onErrorListener = new IMediaPlayer.OnErrorListener() {
-        @Override
-        public boolean onError(IMediaPlayer iMediaPlayer, int framework_err, int impl_err) {
-            mPlayerEventListener.onError();
-            return true;
-        }
-    };
-
-    private IMediaPlayer.OnCompletionListener onCompletionListener = new IMediaPlayer.OnCompletionListener() {
-        @Override
-        public void onCompletion(IMediaPlayer iMediaPlayer) {
-            mPlayerEventListener.onCompletion();
-        }
-    };
-
-    private IMediaPlayer.OnInfoListener onInfoListener = new IMediaPlayer.OnInfoListener() {
-        @Override
-        public boolean onInfo(IMediaPlayer iMediaPlayer, int what, int extra) {
-            mPlayerEventListener.onInfo(what, extra);
-            return true;
-        }
-    };
-
-    private IMediaPlayer.OnBufferingUpdateListener onBufferingUpdateListener = new IMediaPlayer.OnBufferingUpdateListener() {
-        @Override
-        public void onBufferingUpdate(IMediaPlayer iMediaPlayer, int percent) {
-            mBufferedPercent = percent;
-        }
-    };
-
-
-    private IMediaPlayer.OnPreparedListener onPreparedListener = new IMediaPlayer.OnPreparedListener() {
-        @Override
-        public void onPrepared(IMediaPlayer iMediaPlayer) {
-            mPlayerEventListener.onPrepared();
-        }
-    };
-
-    private IMediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener = new IMediaPlayer.OnVideoSizeChangedListener() {
-        @Override
-        public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int i, int i1, int i2, int i3) {
-            int videoWidth = iMediaPlayer.getVideoWidth();
-            int videoHeight = iMediaPlayer.getVideoHeight();
-            if (videoWidth != 0 && videoHeight != 0) {
-                mPlayerEventListener.onVideoSizeChanged(videoWidth, videoHeight);
-            }
-        }
-    };
-}

+ 27 - 5
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/ijk/IjkPlayerFactory.java

@@ -1,18 +1,40 @@
-package org.yczbj.ycvideoplayerlib.player.impl.ijk;
+/*
+Copyright 2017 yangchong211(github.com/yangchong211)
 
-import android.content.Context;
+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 org.yczbj.ycvideoplayerlib.player.impl.ijk;
+import android.content.Context;
 import org.yczbj.ycvideoplayerlib.player.factory.PlayerFactory;
 
 
-public class IjkPlayerFactory extends PlayerFactory<IjkPlayer> {
+/**
+ * <pre>
+ *     @author yangchong
+ *     blog  : https://github.com/yangchong211
+ *     time  : 2018/11/9
+ *     desc  : ijk视频播放器Factory
+ *     revise:
+ * </pre>
+ */
+public class IjkPlayerFactory extends PlayerFactory<IjkVideoPlayer> {
 
     public static IjkPlayerFactory create() {
         return new IjkPlayerFactory();
     }
 
     @Override
-    public IjkPlayer createPlayer(Context context) {
-        return new IjkPlayer(context);
+    public IjkVideoPlayer createPlayer(Context context) {
+        return new IjkVideoPlayer(context);
     }
 }

+ 478 - 0
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/ijk/IjkVideoPlayer.java

@@ -0,0 +1,478 @@
+/*
+Copyright 2017 yangchong211(github.com/yangchong211)
+
+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 org.yczbj.ycvideoplayerlib.player.impl.ijk;
+
+import android.app.Application;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.AudioManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import org.yczbj.ycvideoplayerlib.player.inter.AbstractPlayer;
+import org.yczbj.ycvideoplayerlib.player.manager.VideoViewManager;
+import org.yczbj.ycvideoplayerlib.tool.toast.BaseToast;
+import org.yczbj.ycvideoplayerlib.tool.utils.VideoLogUtils;
+
+import java.util.Map;
+import tv.danmaku.ijk.media.player.IMediaPlayer;
+import tv.danmaku.ijk.media.player.IjkMediaPlayer;
+import tv.danmaku.ijk.media.player.IjkTimedText;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     blog  : https://github.com/yangchong211
+ *     time  : 2018/11/9
+ *     desc  : ijk视频播放器实现类
+ *     revise:
+ * </pre>
+ */
+public class IjkVideoPlayer extends AbstractPlayer {
+
+    protected IjkMediaPlayer mMediaPlayer;
+    private int mBufferedPercent;
+    private Context mAppContext;
+
+    public IjkVideoPlayer(Context context) {
+        if (context instanceof Application){
+            mAppContext = context;
+        } else {
+            mAppContext = context.getApplicationContext();
+        }
+    }
+
+    @Override
+    public void initPlayer() {
+        mMediaPlayer = new IjkMediaPlayer();
+        //native日志
+        IjkMediaPlayer.native_setLogLevel(VideoViewManager.getConfig().mIsEnableLog
+                ? IjkMediaPlayer.IJK_LOG_INFO : IjkMediaPlayer.IJK_LOG_SILENT);
+        setOptions();
+        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+        initListener();
+    }
+
+    @Override
+    public void setOptions() {
+        int player = IjkMediaPlayer.OPT_CATEGORY_PLAYER;
+        int codec = IjkMediaPlayer.OPT_CATEGORY_CODEC;
+        int format = IjkMediaPlayer.OPT_CATEGORY_FORMAT;
+
+        //设置ijkPlayer播放器的硬件解码相关参数
+        //设置播放前的最大探测时间
+        mMediaPlayer.setOption(format, "analyzemaxduration", 100L);
+        //设置播放前的探测时间 1,达到首屏秒开效果
+        mMediaPlayer.setOption(format, "analyzeduration", 1L);
+        //播放前的探测Size,默认是1M, 改小一点会出画面更快
+        mMediaPlayer.setOption(format, "probesize", 10240L);
+        //设置是否开启变调isModifyTone?0:1
+        mMediaPlayer.setOption(player,"soundtouch",0);
+        //每处理一个packet之后刷新io上下文
+        mMediaPlayer.setOption(format, "flush_packets", 1L);
+        //是否开启预缓冲,一般直播项目会开启,达到秒开的效果,不过带来了播放丢帧卡顿的体验
+        mMediaPlayer.setOption(player, "packet-buffering", 0L);
+        //播放重连次数
+        mMediaPlayer.setOption(player, "reconnect", 5);
+        //最大缓冲大小,单位kb
+        mMediaPlayer.setOption(player, "max-buffer-size", 10240L);
+        //跳帧处理,放CPU处理较慢时,进行跳帧处理,保证播放流程,画面和声音同步
+        mMediaPlayer.setOption(player, "framedrop", 1L);
+        //最大fps
+        mMediaPlayer.setOption(player, "max-fps", 30L);
+        //SeekTo设置优化
+        mMediaPlayer.setOption(player, "enable-accurate-seek", 1L);
+        mMediaPlayer.setOption(player, "opensles", 0);
+        mMediaPlayer.setOption(player, "overlay-format",
+                IjkMediaPlayer.SDL_FCC_RV32);
+        mMediaPlayer.setOption(player, "framedrop", 1);
+        mMediaPlayer.setOption(player, "start-on-prepared", 0);
+        mMediaPlayer.setOption(format, "http-detect-range-support", 0);
+        //设置是否开启环路过滤: 0开启,画面质量高,解码开销大,48关闭,画面质量差点,解码开销小
+        mMediaPlayer.setOption(codec, "skip_loop_filter", 48);
+
+        //jkPlayer支持硬解码和软解码。
+        //软解码时不会旋转视频角度这时需要你通过onInfo的what == IMediaPlayer.MEDIA_INFO_VIDEO_ROTATION_CHANGED去获取角度,自己旋转画面。
+        //或者开启硬解硬解码,不过硬解码容易造成黑屏无声(硬件兼容问题),下面是设置硬解码相关的代码
+        mMediaPlayer.setOption(player, "mediacodec", 0);
+        mMediaPlayer.setOption(player, "mediacodec-auto-rotate", 1);
+        mMediaPlayer.setOption(player, "mediacodec-handle-resolution-change", 1);
+    }
+
+    /**
+     * ijk视频播放器监听listener
+     */
+    private void initListener() {
+        // 设置监听,可以查看ijk中的IMediaPlayer源码监听事件
+        // 设置视频错误监听器
+        mMediaPlayer.setOnErrorListener(onErrorListener);
+        // 设置视频播放完成监听事件
+        mMediaPlayer.setOnCompletionListener(onCompletionListener);
+        // 设置视频信息监听器
+        mMediaPlayer.setOnInfoListener(onInfoListener);
+        // 设置视频缓冲更新监听事件
+        mMediaPlayer.setOnBufferingUpdateListener(onBufferingUpdateListener);
+        // 设置准备视频播放监听事件
+        mMediaPlayer.setOnPreparedListener(onPreparedListener);
+        // 设置视频大小更改监听器
+        mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
+        // 设置视频seek完成监听事件
+        mMediaPlayer.setOnSeekCompleteListener(onSeekCompleteListener);
+        // 设置时间文本监听器
+        mMediaPlayer.setOnTimedTextListener(onTimedTextListener);
+        mMediaPlayer.setOnNativeInvokeListener(new IjkMediaPlayer.OnNativeInvokeListener() {
+            @Override
+            public boolean onNativeInvoke(int i, Bundle bundle) {
+                return true;
+            }
+        });
+    }
+
+    /**
+     * 设置播放地址
+     *
+     * @param path    播放地址
+     * @param headers 播放地址请求头
+     */
+    @Override
+    public void setDataSource(String path, Map<String, String> headers) {
+        // 设置dataSource
+        if(path==null || path.length()==0){
+            BaseToast.showRoundRectToast("视频链接不能为空");
+            return;
+        }
+        try {
+            //解析path
+            Uri uri = Uri.parse(path);
+            if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())) {
+                RawDataSourceProvider rawDataSourceProvider = RawDataSourceProvider.create(mAppContext, uri);
+                mMediaPlayer.setDataSource(rawDataSourceProvider);
+            } else {
+                //处理UA问题
+                if (headers != null) {
+                    String userAgent = headers.get("User-Agent");
+                    if (!TextUtils.isEmpty(userAgent)) {
+                        mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "user_agent", userAgent);
+                    }
+                }
+                mMediaPlayer.setDataSource(mAppContext, uri, headers);
+            }
+        } catch (Exception e) {
+            mPlayerEventListener.onError();
+        }
+    }
+
+    /**
+     * 用于播放raw和asset里面的视频文件
+     */
+    @Override
+    public void setDataSource(AssetFileDescriptor fd) {
+        try {
+            mMediaPlayer.setDataSource(new RawDataSourceProvider(fd));
+        } catch (Exception e) {
+            mPlayerEventListener.onError();
+        }
+    }
+
+    /**
+     * 设置渲染视频的View,主要用于TextureView
+     * @param surface                           surface
+     */
+    @Override
+    public void setSurface(Surface surface) {
+        mMediaPlayer.setSurface(surface);
+    }
+
+    /**
+     * 准备开始播放(异步)
+     */
+    @Override
+    public void prepareAsync() {
+        try {
+            mMediaPlayer.prepareAsync();
+        } catch (IllegalStateException e) {
+            mPlayerEventListener.onError();
+        }
+    }
+
+    /**
+     * 暂停
+     */
+    @Override
+    public void pause() {
+        try {
+            mMediaPlayer.pause();
+        } catch (IllegalStateException e) {
+            mPlayerEventListener.onError();
+        }
+    }
+
+    /**
+     * 播放
+     */
+    @Override
+    public void start() {
+        try {
+            mMediaPlayer.start();
+        } catch (IllegalStateException e) {
+            mPlayerEventListener.onError();
+        }
+    }
+
+    /**
+     * 停止
+     */
+    @Override
+    public void stop() {
+        try {
+            mMediaPlayer.stop();
+        } catch (IllegalStateException e) {
+            mPlayerEventListener.onError();
+        }
+    }
+
+    /**
+     * 重置播放器
+     */
+    @Override
+    public void reset() {
+        mMediaPlayer.reset();
+        mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
+        setOptions();
+    }
+
+    /**
+     * 是否正在播放
+     */
+    @Override
+    public boolean isPlaying() {
+        return mMediaPlayer.isPlaying();
+    }
+
+
+    /**
+     * 调整进度
+     */
+    @Override
+    public void seekTo(long time) {
+        try {
+            mMediaPlayer.seekTo((int) time);
+        } catch (IllegalStateException e) {
+            mPlayerEventListener.onError();
+        }
+    }
+
+    /**
+     * 释放播放器
+     */
+    @Override
+    public void release() {
+        mMediaPlayer.setOnErrorListener(null);
+        mMediaPlayer.setOnCompletionListener(null);
+        mMediaPlayer.setOnInfoListener(null);
+        mMediaPlayer.setOnBufferingUpdateListener(null);
+        mMediaPlayer.setOnPreparedListener(null);
+        mMediaPlayer.setOnVideoSizeChangedListener(null);
+        new Thread() {
+            @Override
+            public void run() {
+                try {
+                    mMediaPlayer.release();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }.start();
+    }
+
+    /**
+     * 获取当前播放的位置
+     */
+    @Override
+    public long getCurrentPosition() {
+        return mMediaPlayer.getCurrentPosition();
+    }
+
+    /**
+     * 获取视频总时长
+     */
+    @Override
+    public long getDuration() {
+        return mMediaPlayer.getDuration();
+    }
+
+    /**
+     * 获取缓冲百分比
+     */
+    @Override
+    public int getBufferedPercentage() {
+        return mBufferedPercent;
+    }
+
+    /**
+     * 设置渲染视频的View,主要用于SurfaceView
+     */
+    @Override
+    public void setDisplay(SurfaceHolder holder) {
+        mMediaPlayer.setDisplay(holder);
+    }
+
+    /**
+     * 设置音量
+     */
+    @Override
+    public void setVolume(float v1, float v2) {
+        mMediaPlayer.setVolume(v1, v2);
+    }
+
+    /**
+     * 设置是否循环播放
+     */
+    @Override
+    public void setLooping(boolean isLooping) {
+        mMediaPlayer.setLooping(isLooping);
+    }
+
+    /**
+     * 设置播放速度
+     */
+    @Override
+    public void setSpeed(float speed) {
+        mMediaPlayer.setSpeed(speed);
+    }
+
+    /**
+     * 获取播放速度
+     */
+    @Override
+    public float getSpeed() {
+        return mMediaPlayer.getSpeed(0);
+    }
+
+    /**
+     * 获取当前缓冲的网速
+     */
+    @Override
+    public long getTcpSpeed() {
+        return mMediaPlayer.getTcpSpeed();
+    }
+
+    /**
+     * 设置视频错误监听器
+     * int MEDIA_INFO_VIDEO_RENDERING_START = 3;//视频准备渲染
+     * int MEDIA_INFO_BUFFERING_START = 701;//开始缓冲
+     * int MEDIA_INFO_BUFFERING_END = 702;//缓冲结束
+     * int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;//视频选择信息
+     * int MEDIA_ERROR_SERVER_DIED = 100;//视频中断,一般是视频源异常或者不支持的视频类型。
+     * int MEDIA_ERROR_IJK_PLAYER = -10000,//一般是视频源有问题或者数据格式不支持,比如音频不是AAC之类的
+     * int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;//数据错误没有有效的回收
+     */
+    private IMediaPlayer.OnErrorListener onErrorListener = new IMediaPlayer.OnErrorListener() {
+        @Override
+        public boolean onError(IMediaPlayer iMediaPlayer, int framework_err, int impl_err) {
+            mPlayerEventListener.onError();
+            VideoLogUtils.d("IjkVideoPlayer----listener---------onError ——> STATE_ERROR ———— what:" + framework_err + ", extra: " + impl_err);
+            return true;
+        }
+    };
+
+    /**
+     * 设置视频播放完成监听事件
+     */
+    private IMediaPlayer.OnCompletionListener onCompletionListener = new IMediaPlayer.OnCompletionListener() {
+        @Override
+        public void onCompletion(IMediaPlayer iMediaPlayer) {
+            mPlayerEventListener.onCompletion();
+            VideoLogUtils.d("IjkVideoPlayer----listener---------onCompletion ——> STATE_COMPLETED");
+        }
+    };
+
+
+    /**
+     * 设置视频信息监听器
+     */
+    private IMediaPlayer.OnInfoListener onInfoListener = new IMediaPlayer.OnInfoListener() {
+        @Override
+        public boolean onInfo(IMediaPlayer iMediaPlayer, int what, int extra) {
+            mPlayerEventListener.onInfo(what, extra);
+            VideoLogUtils.d("IjkVideoPlayer----listener---------onInfo ——> ———— what:" + what + ", extra: " + extra);
+            return true;
+        }
+    };
+
+    /**
+     * 设置视频缓冲更新监听事件
+     */
+    private IMediaPlayer.OnBufferingUpdateListener onBufferingUpdateListener = new IMediaPlayer.OnBufferingUpdateListener() {
+        @Override
+        public void onBufferingUpdate(IMediaPlayer iMediaPlayer, int percent) {
+            mBufferedPercent = percent;
+        }
+    };
+
+
+    /**
+     * 设置准备视频播放监听事件
+     */
+    private IMediaPlayer.OnPreparedListener onPreparedListener = new IMediaPlayer.OnPreparedListener() {
+        @Override
+        public void onPrepared(IMediaPlayer iMediaPlayer) {
+            mPlayerEventListener.onPrepared();
+            VideoLogUtils.d("IjkVideoPlayer----listener---------onPrepared ——> STATE_PREPARED");
+        }
+    };
+
+    /**
+     * 设置视频大小更改监听器
+     */
+    private IMediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener = new IMediaPlayer.OnVideoSizeChangedListener() {
+        @Override
+        public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int width, int height,
+                                       int sar_num, int sar_den) {
+            int videoWidth = iMediaPlayer.getVideoWidth();
+            int videoHeight = iMediaPlayer.getVideoHeight();
+            if (videoWidth != 0 && videoHeight != 0) {
+                mPlayerEventListener.onVideoSizeChanged(videoWidth, videoHeight);
+            }
+            VideoLogUtils.d("IjkVideoPlayer----listener---------onVideoSizeChanged ——> WIDTH:" + width + ", HEIGHT:" + height);
+        }
+    };
+
+    /**
+     * 设置时间文本监听器
+     */
+    private IMediaPlayer.OnTimedTextListener onTimedTextListener = new IMediaPlayer.OnTimedTextListener() {
+        @Override
+        public void onTimedText(IMediaPlayer iMediaPlayer, IjkTimedText ijkTimedText) {
+
+        }
+    };
+
+    /**
+     * 设置视频seek完成监听事件
+     */
+    private IMediaPlayer.OnSeekCompleteListener onSeekCompleteListener = new IMediaPlayer.OnSeekCompleteListener() {
+        @Override
+        public void onSeekComplete(IMediaPlayer iMediaPlayer) {
+
+        }
+    };
+
+
+}

+ 15 - 0
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/ijk/RawDataSourceProvider.java

@@ -1,3 +1,18 @@
+/*
+Copyright 2017 yangchong211(github.com/yangchong211)
+
+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 org.yczbj.ycvideoplayerlib.player.impl.ijk;
 
 import android.content.Context;

+ 124 - 5
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/media/AndroidMediaPlayer.java

@@ -1,5 +1,21 @@
+/*
+Copyright 2017 yangchong211(github.com/yangchong211)
+
+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 org.yczbj.ycvideoplayerlib.player.impl.media;
 
+import android.app.Application;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.media.AudioManager;
@@ -9,10 +25,19 @@ import android.os.Build;
 import android.view.Surface;
 import android.view.SurfaceHolder;
 import org.yczbj.ycvideoplayerlib.player.inter.AbstractPlayer;
+import org.yczbj.ycvideoplayerlib.tool.toast.BaseToast;
+
 import java.util.Map;
 
+
 /**
- * 封装系统的MediaPlayer,不推荐,系统的MediaPlayer兼容性较差,建议使用IjkPlayer或者ExoPlayer
+ * <pre>
+ *     @author yangchong
+ *     blog  : https://github.com/yangchong211
+ *     time  : 2018/11/9
+ *     desc  : 不推荐,系统的MediaPlayer兼容性较差,建议使用IjkPlayer或者ExoPlayer
+ *     revise:
+ * </pre>
  */
 public class AndroidMediaPlayer extends AbstractPlayer {
 
@@ -22,13 +47,24 @@ public class AndroidMediaPlayer extends AbstractPlayer {
     private boolean mIsPreparing;
 
     public AndroidMediaPlayer(Context context) {
-        mAppContext = context.getApplicationContext();
+        if (context instanceof Application){
+            mAppContext = context;
+        } else {
+            mAppContext = context.getApplicationContext();
+        }
     }
 
     @Override
     public void initPlayer() {
         mMediaPlayer = new MediaPlayer();
         setOptions();
+        initListener();
+    }
+
+    /**
+     * MediaPlayer视频播放器监听listener
+     */
+    private void initListener() {
         mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
         mMediaPlayer.setOnErrorListener(onErrorListener);
         mMediaPlayer.setOnCompletionListener(onCompletionListener);
@@ -38,15 +74,30 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
     }
 
+    /**
+     * 设置播放地址
+     *
+     * @param path    播放地址
+     * @param headers 播放地址请求头
+     */
     @Override
     public void setDataSource(String path, Map<String, String> headers) {
+        // 设置dataSource
+        if(path==null || path.length()==0){
+            BaseToast.showRoundRectToast("视频链接不能为空");
+            return;
+        }
         try {
-            mMediaPlayer.setDataSource(mAppContext, Uri.parse(path), headers);
+            Uri uri = Uri.parse(path);
+            mMediaPlayer.setDataSource(mAppContext, uri, headers);
         } catch (Exception e) {
             mPlayerEventListener.onError();
         }
     }
 
+    /**
+     * 用于播放raw和asset里面的视频文件
+     */
     @Override
     public void setDataSource(AssetFileDescriptor fd) {
         try {
@@ -56,6 +107,9 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         }
     }
 
+    /**
+     * 播放
+     */
     @Override
     public void start() {
         try {
@@ -65,6 +119,9 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         }
     }
 
+    /**
+     * 暂停
+     */
     @Override
     public void pause() {
         try {
@@ -74,6 +131,9 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         }
     }
 
+    /**
+     * 停止
+     */
     @Override
     public void stop() {
         try {
@@ -93,6 +153,9 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         }
     }
 
+    /**
+     * 重置播放器
+     */
     @Override
     public void reset() {
         mMediaPlayer.reset();
@@ -101,11 +164,17 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         mMediaPlayer.setVolume(1, 1);
     }
 
+    /**
+     * 是否正在播放
+     */
     @Override
     public boolean isPlaying() {
         return mMediaPlayer.isPlaying();
     }
 
+    /**
+     * 调整进度
+     */
     @Override
     public void seekTo(long time) {
         try {
@@ -115,6 +184,9 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         }
     }
 
+    /**
+     * 释放播放器
+     */
     @Override
     public void release() {
         mMediaPlayer.setOnErrorListener(null);
@@ -135,21 +207,35 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         }.start();
     }
 
+    /**
+     * 获取当前播放的位置
+     */
     @Override
     public long getCurrentPosition() {
         return mMediaPlayer.getCurrentPosition();
     }
 
+    /**
+     * 获取视频总时长
+     */
     @Override
     public long getDuration() {
         return mMediaPlayer.getDuration();
     }
 
+    /**
+     * 获取缓冲百分比
+     * @return                                  获取缓冲百分比
+     */
     @Override
     public int getBufferedPercentage() {
         return mBufferedPercent;
     }
 
+    /**
+     * 设置渲染视频的View,主要用于TextureView
+     * @param surface                           surface
+     */
     @Override
     public void setSurface(Surface surface) {
         try {
@@ -159,6 +245,10 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         }
     }
 
+    /**
+     * 设置渲染视频的View,主要用于SurfaceView
+     * @param holder                            holder
+     */
     @Override
     public void setDisplay(SurfaceHolder holder) {
         try {
@@ -168,20 +258,41 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         }
     }
 
+    /**
+     * 设置音量
+     * @param v1                                v1
+     * @param v2                                v2
+     */
     @Override
     public void setVolume(float v1, float v2) {
-        mMediaPlayer.setVolume(v1, v2);
+        try {
+            mMediaPlayer.setVolume(v1, v2);
+        } catch (Exception e){
+            mPlayerEventListener.onError();
+        }
     }
 
+    /**
+     * 设置是否循环播放
+     * @param isLooping                         布尔值
+     */
     @Override
     public void setLooping(boolean isLooping) {
-        mMediaPlayer.setLooping(isLooping);
+        try {
+            mMediaPlayer.setLooping(isLooping);
+        } catch (Exception e){
+            mPlayerEventListener.onError();
+        }
     }
 
     @Override
     public void setOptions() {
     }
 
+    /**
+     * 设置播放速度
+     * @param speed                             速度
+     */
     @Override
     public void setSpeed(float speed) {
         // only support above Android M
@@ -194,6 +305,10 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         }
     }
 
+    /**
+     * 获取播放速度
+     * @return                                  播放速度
+     */
     @Override
     public float getSpeed() {
         // only support above Android M
@@ -207,6 +322,10 @@ public class AndroidMediaPlayer extends AbstractPlayer {
         return 1f;
     }
 
+    /**
+     * 获取当前缓冲的网速
+     * @return                                  获取网络
+     */
     @Override
     public long getTcpSpeed() {
         // no support

+ 23 - 1
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/impl/media/MediaPlayerFactory.java

@@ -1,11 +1,33 @@
+/*
+Copyright 2017 yangchong211(github.com/yangchong211)
+
+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 org.yczbj.ycvideoplayerlib.player.impl.media;
 
 import android.content.Context;
 
 import org.yczbj.ycvideoplayerlib.player.factory.PlayerFactory;
 
+
 /**
- * 创建{@link AndroidMediaPlayer}的工厂类,不推荐,系统的MediaPlayer兼容性较差,建议使用IjkPlayer或者ExoPlayer
+ * <pre>
+ *     @author yangchong
+ *     blog  : https://github.com/yangchong211
+ *     time  : 2018/11/9
+ *     desc  : 不推荐,系统的MediaPlayer兼容性较差,建议使用IjkPlayer或者ExoPlayer
+ *     revise:
+ * </pre>
  */
 public class MediaPlayerFactory extends PlayerFactory<AndroidMediaPlayer> {
 

+ 43 - 11
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/inter/AbstractPlayer.java

@@ -38,12 +38,13 @@ public abstract class AbstractPlayer {
 
     /**
      * 初始化播放器实例
+     * 视频播放器第一步:创建视频播放器
      */
     public abstract void initPlayer();
 
     /**
      * 设置播放地址
-     *
+     * 视频播放器第二步:设置数据
      * @param path    播放地址
      * @param headers 播放地址请求头
      */
@@ -54,6 +55,19 @@ public abstract class AbstractPlayer {
      */
     public abstract void setDataSource(AssetFileDescriptor fd);
 
+    /**
+     * 设置渲染视频的View,主要用于TextureView
+     * 视频播放器第三步:设置surface
+     * @param surface                           surface
+     */
+    public abstract void setSurface(Surface surface);
+
+    /**
+     * 准备开始播放(异步)
+     * 视频播放器第四步:开始加载【异步】
+     */
+    public abstract void prepareAsync();
+
     /**
      * 播放
      */
@@ -69,11 +83,6 @@ public abstract class AbstractPlayer {
      */
     public abstract void stop();
 
-    /**
-     * 准备开始播放(异步)
-     */
-    public abstract void prepareAsync();
-
     /**
      * 重置播放器
      */
@@ -81,6 +90,7 @@ public abstract class AbstractPlayer {
 
     /**
      * 是否正在播放
+     * @return                                  是否正在播放
      */
     public abstract boolean isPlaying();
 
@@ -96,36 +106,38 @@ public abstract class AbstractPlayer {
 
     /**
      * 获取当前播放的位置
+     * @return                                  获取当前播放的位置
      */
     public abstract long getCurrentPosition();
 
     /**
      * 获取视频总时长
+     * @return                                  获取视频总时长
      */
     public abstract long getDuration();
 
     /**
      * 获取缓冲百分比
+     * @return                                  获取缓冲百分比
      */
     public abstract int getBufferedPercentage();
 
-    /**
-     * 设置渲染视频的View,主要用于TextureView
-     */
-    public abstract void setSurface(Surface surface);
-
     /**
      * 设置渲染视频的View,主要用于SurfaceView
+     * @param holder                            holder
      */
     public abstract void setDisplay(SurfaceHolder holder);
 
     /**
      * 设置音量
+     * @param v1                                v1
+     * @param v2                                v2
      */
     public abstract void setVolume(float v1, float v2);
 
     /**
      * 设置是否循环播放
+     * @param isLooping                         布尔值
      */
     public abstract void setLooping(boolean isLooping);
 
@@ -136,16 +148,19 @@ public abstract class AbstractPlayer {
 
     /**
      * 设置播放速度
+     * @param speed                             速度
      */
     public abstract void setSpeed(float speed);
 
     /**
      * 获取播放速度
+     * @return                                  播放速度
      */
     public abstract float getSpeed();
 
     /**
      * 获取当前缓冲的网速
+     * @return                                  获取网络
      */
     public abstract long getTcpSpeed();
 
@@ -158,14 +173,31 @@ public abstract class AbstractPlayer {
 
     public interface PlayerEventListener {
 
+        /**
+         * 异常
+         */
         void onError();
 
+        /**
+         * 完成
+         */
         void onCompletion();
 
+        /**
+         * 视频信息
+         * @param what                          what
+         * @param extra                         extra
+         */
         void onInfo(int what, int extra);
 
+        /**
+         * 准备
+         */
         void onPrepared();
 
+        /**
+         * 视频size变化监听
+         */
         void onVideoSizeChanged(int width, int height);
 
     }

+ 2 - 1
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/player/render/TextureRenderView.java

@@ -26,9 +26,10 @@ public class TextureRenderView extends TextureView implements IRenderView, Textu
 
     public TextureRenderView(Context context) {
         super(context);
+        init(context);
     }
 
-    {
+    private void init(Context context){
         mMeasureHelper = new MeasureHelper();
         setSurfaceTextureListener(this);
     }

+ 6 - 0
VideoPlayer/src/main/java/org/yczbj/ycvideoplayerlib/ui/view/BasisVideoController.java

@@ -98,28 +98,34 @@ public class BasisVideoController extends GestureVideoController implements View
         setEnableInNormal(true);
         //滑动调节亮度,音量,进度,默认开启
         setGestureEnabled(true);
+
         //添加与加载视图界面view,准备播放界面
         CustomPrepareView prepareView = new CustomPrepareView(mContext);
         thumb = prepareView.getThumb();
         prepareView.setClickStart();
         this.addControlComponent(prepareView);
+
         //添加自动完成播放界面view
         CustomCompleteView completeView = new CustomCompleteView(mContext);
         completeView.setVisibility(GONE);
         this.addControlComponent(completeView);
+
         //添加错误界面view
         CustomErrorView errorView = new CustomErrorView(mContext);
         errorView.setVisibility(GONE);
         this.addControlComponent(errorView);
+
         //添加标题栏
         CustomTitleView titleView = new CustomTitleView(mContext);
         titleView.setVisibility(VISIBLE);
         this.addControlComponent(titleView);
+
         //添加底部播放控制条
         CustomBottomView vodControlView = new CustomBottomView(mContext);
         //是否显示底部进度条。默认显示
         vodControlView.showBottomProgress(true);
         this.addControlComponent(vodControlView);
+
         //添加滑动控制视图
         CustomGestureView gestureControlView = new CustomGestureView(mContext);
         this.addControlComponent(gestureControlView);

+ 0 - 26
VideoUi/src/androidTest/java/com/yc/videoui/ExampleInstrumentedTest.java

@@ -1,26 +0,0 @@
-package com.yc.videoui;
-
-import android.content.Context;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.*;
-
-/**
- * Instrumented test, which will execute on an Android device.
- *
- * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
-    @Test
-    public void useAppContext() {
-        // Context of the app under test.
-        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        assertEquals("com.yc.videoui.test", appContext.getPackageName());
-    }
-}

+ 0 - 17
VideoUi/src/test/java/com/yc/videoui/ExampleUnitTest.java

@@ -1,17 +0,0 @@
-package com.yc.videoui;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
- */
-public class ExampleUnitTest {
-    @Test
-    public void addition_isCorrect() {
-        assertEquals(4, 2 + 2);
-    }
-}

+ 3 - 3
app/src/main/java/org/yczbj/ycvideoplayer/activity/TypeActivity.java

@@ -20,7 +20,7 @@ import org.yczbj.ycvideoplayer.surface.TestSurfaceActivity;
 import org.yczbj.ycvideoplayer.tiny.TestFullActivity;
 import org.yczbj.ycvideoplayer.tiny.TinyScreenActivity;
 import org.yczbj.ycvideoplayerlib.config.ConstantKeys;
-import org.yczbj.ycvideoplayerlib.player.impl.exo.ExoMediaPlayerFactory;
+import org.yczbj.ycvideoplayerlib.player.impl.exo.ExoPlayerFactory;
 import org.yczbj.ycvideoplayerlib.player.impl.ijk.IjkPlayerFactory;
 import org.yczbj.ycvideoplayerlib.player.impl.media.MediaPlayerFactory;
 import org.yczbj.ycvideoplayerlib.player.factory.PlayerFactory;
@@ -65,7 +65,7 @@ public class TypeActivity extends AppCompatActivity implements View.OnClickListe
 
         //检测当前是用的哪个播放器
         Object factory = PlayerUtils.getCurrentPlayerFactory();
-        if (factory instanceof ExoMediaPlayerFactory) {
+        if (factory instanceof ExoPlayerFactory) {
             mTvTitle.setText("视频内核:" + " (ExoPlayer)");
             setTitle(getResources().getString(R.string.app_name) + " (ExoPlayer)");
         } else if (factory instanceof IjkPlayerFactory) {
@@ -191,7 +191,7 @@ public class TypeActivity extends AppCompatActivity implements View.OnClickListe
                     mTvTitle.setText("视频内核:" + " (IjkPlayer)");
                     break;
                 case ConstantKeys.VideoPlayerType.TYPE_EXO:
-                    playerFactory = ExoMediaPlayerFactory.create();
+                    playerFactory = ExoPlayerFactory.create();
                     mTvTitle.setText("视频内核:" + " (ExoPlayer)");
                     break;
                 case ConstantKeys.VideoPlayerType.TYPE_NATIVE: