Sfoglia il codice sorgente

优化视频播放器

yangchong 3 anni fa
parent
commit
c9afcb7cb2

+ 20 - 10
AudioPlayer/src/main/java/com/yc/audioplayer/bean/AudioPlayData.java

@@ -5,21 +5,31 @@ package com.yc.audioplayer.bean;
  */
 public class AudioPlayData {
 
+    /**
+     * 默认是普通级别
+     */
     public AudioTtsPriority mPriority = AudioTtsPriority.NORMAL_PRIORITY;
-
     /**
      * 是否播放tts,如果是文案则表示true,如果是资源文件则表示false
      * true,使用TtsPlayer播放
      * false,使用MediaPlayer播放
      */
     public boolean mPlayTts = true;
-
+    /**
+     * tts文本内容
+     */
     private String mTts;
-
+    /**
+     * 资源id
+     */
     private int mRawId;
-
+    /**
+     * 当前data
+     */
     private AudioPlayData mCurrent;
-
+    /**
+     * 下一个data
+     */
     private AudioPlayData mNext;
 
     private AudioPlayData() {
@@ -103,11 +113,11 @@ public class AudioPlayData {
     @Override
     public String toString() {
         return "AudioPlayData{" +
-            "priority=" + mPriority +
-            ", mTts='" + mTts + '\'' +
-            ", mRawId=" + mRawId +
-            ", mNext=" + mNext +
-            '}';
+                "priority=" + mPriority +
+                ", mTts='" + mTts + '\'' +
+                ", mRawId=" + mRawId +
+                ", mNext=" + mNext +
+                '}';
     }
 
 }

+ 3 - 0
AudioPlayer/src/main/java/com/yc/audioplayer/deque/AudioTtsDeque.java

@@ -19,6 +19,9 @@ import java.util.concurrent.locks.ReentrantLock;
  */
 public class AudioTtsDeque {
 
+    /**
+     * 创建锁对象
+     */
     private final Lock mLock = new ReentrantLock();
     private final Condition mNotEmpty = mLock.newCondition();
     private final LinkedBlockingDeque<AudioPlayData> mHighDeque = new LinkedBlockingDeque<>();

+ 18 - 18
Demo/build.gradle

@@ -69,25 +69,25 @@ dependencies {
     implementation 'com.github.ctiao:DanmakuFlameMaster:0.9.25'
     implementation 'com.github.ctiao:ndkbitmap-armv7a:0.9.21'
 
-//    implementation 'com.github.yangchong211.YCVideoPlayer:VideoPlayer:1.1.0'
-//    implementation 'com.github.yangchong211.YCVideoPlayer:VideoKernel:1.1.0'
-//    implementation 'com.github.yangchong211.YCVideoPlayer:VideoView:1.1.0'
-//    implementation 'com.github.yangchong211.YCVideoPlayer:MusicPlayer:1.1.0'
-//    implementation 'com.github.yangchong211.YCVideoPlayer:VideoM3u8:1.1.0'
-//    implementation 'com.github.yangchong211.YCVideoPlayer:VideoSqlLite:1.1.0'
-//    implementation 'com.github.yangchong211.YCVideoPlayer:AudioPlayer:1.1.0'
-//    implementation 'com.github.yangchong211.YCVideoPlayer:VideoTool:1.1.0'
-//    implementation 'com.github.yangchong211.YCVideoPlayer:VideoCache:1.1.0'
+    implementation 'com.github.yangchong211.YCVideoPlayer:VideoPlayer:1.1.0'
+    implementation 'com.github.yangchong211.YCVideoPlayer:VideoKernel:1.1.0'
+    implementation 'com.github.yangchong211.YCVideoPlayer:VideoView:1.1.0'
+    implementation 'com.github.yangchong211.YCVideoPlayer:MusicPlayer:1.1.0'
+    implementation 'com.github.yangchong211.YCVideoPlayer:VideoM3u8:1.1.0'
+    implementation 'com.github.yangchong211.YCVideoPlayer:VideoSqlLite:1.1.0'
+    implementation 'com.github.yangchong211.YCVideoPlayer:AudioPlayer:1.1.0'
+    implementation 'com.github.yangchong211.YCVideoPlayer:VideoTool:1.1.0'
+    implementation 'com.github.yangchong211.YCVideoPlayer:VideoCache:1.1.0'
 
-    implementation project(path: ':VideoCache')
-    implementation project(path: ':VideoPlayer')
-    implementation project(path: ':VideoKernel')
-    implementation project(path: ':VideoView')
-    implementation project(path: ':MusicPlayer')
-    implementation project(path: ':VideoM3u8')
-    implementation project(path: ':VideoSqlLite')
-    implementation project(path: ':AudioPlayer')
-    implementation project(path: ':VideoTool')
+//    implementation project(path: ':VideoCache')
+//    implementation project(path: ':VideoPlayer')
+//    implementation project(path: ':VideoKernel')
+//    implementation project(path: ':VideoView')
+//    implementation project(path: ':MusicPlayer')
+//    implementation project(path: ':VideoM3u8')
+//    implementation project(path: ':VideoSqlLite')
+//    implementation project(path: ':AudioPlayer')
+//    implementation project(path: ':VideoTool')
 
     //自己封装的库,都有对应的案例项目【欢迎star】:https://github.com/yangchong211
     implementation 'cn.yc:YCStatusBarLib:1.5.0'

+ 2 - 2
Demo/src/main/java/com/yc/ycvideoplayer/video/ad/AdActivity.java

@@ -102,8 +102,8 @@ public class AdActivity extends AppCompatActivity implements View.OnClickListene
         mVideoPlayer.setController(controller);
         HttpProxyCacheServer cacheServer = ProxyVideoCacheManager.getProxy(this);
         String proxyUrl = cacheServer.getProxyUrl(URL_AD);
-        HttpProxyCacheServer server = new HttpProxyCacheServer(this);
-        String proxyVideoUrl = server.getProxyUrl(URL_AD);
+        //HttpProxyCacheServer server = new HttpProxyCacheServer(this);
+        //String proxyVideoUrl = server.getProxyUrl(URL_AD);
 
 
         mVideoPlayer.setUrl(proxyUrl);

+ 36 - 5
VideoCache/src/main/java/com/yc/videocache/HttpProxyCacheServer.java

@@ -45,7 +45,6 @@ import static com.yc.videocache.Preconditions.checkNotNull;
  * // should return single instance of HttpProxyCacheServer shared for whole app.
  * }
  * </code></pre>
- *
  */
 public class HttpProxyCacheServer {
 
@@ -66,15 +65,21 @@ public class HttpProxyCacheServer {
     private HttpProxyCacheServer(Config config) {
         this.config = checkNotNull(config);
         try {
+            //使用Socket将本地的一个端口作为服务器,这个端口号自动生成
             InetAddress inetAddress = InetAddress.getByName(PROXY_HOST);
             this.serverSocket = new ServerSocket(0, 8, inetAddress);
+            //设置端口号
             this.port = serverSocket.getLocalPort();
+            Logger.debug("server socket port is : " + port);
             IgnoreHostProxySelector.install(PROXY_HOST, port);
             CountDownLatch startSignal = new CountDownLatch(1);
+            //开启一个线程然后调用start执行
             this.waitConnectionThread = new Thread(new WaitRequestsRunnable(startSignal));
             this.waitConnectionThread.start();
-            startSignal.await(); // freeze thread, wait for server starts
+            // freeze thread, wait for server starts
+            startSignal.await();
         } catch (IOException | InterruptedException e) {
+            //如果是执行好异常,则停止线程池
             socketProcessor.shutdown();
             throw new IllegalStateException("Error starting local proxy server", e);
         }
@@ -212,23 +217,44 @@ public class HttpProxyCacheServer {
 
     private void waitForRequest() {
         try {
+            //执行一个循环,这个循环的条件就是当前线程没有被中断
             while (!Thread.currentThread().isInterrupted()) {
+                //accept()方法,这是一个阻塞方法,对Socket不太了解的可以先去了解下
+                //当有访问这个ServerSocket的端口时,这是就会返回一个Socket对象,通过这个对象就可以与客户端进行通信
+                //这个Socket可以理解为就是视频播放器那边传过来的,我们把视频数据从这个Socket中返回,那视频就可以播放了。
                 Socket socket = serverSocket.accept();
                 Logger.debug("Accept new socket " + socket);
-                socketProcessor.submit(new SocketProcessorRunnable(socket));
+                //常见一个任务
+                SocketProcessorRunnable socketProcessorRunnable = new SocketProcessorRunnable(socket);
+                //提交任务
+                //socketProcess是一个线程池,把这个socket对象放进了线程中
+                socketProcessor.submit(socketProcessorRunnable);
             }
         } catch (IOException e) {
             onError(new ProxyCacheException("Error during waiting connection", e));
         }
     }
 
+    /**
+     * @param socket socket通信
+     */
     private void processSocket(Socket socket) {
         try {
+            //这里就是获取socket流中请求头的信息,然后创建了一个GetRequest对象并返回
             GetRequest request = GetRequest.read(socket.getInputStream());
             Logger.debug("Request to cache proxy:" + request);
+            //request.uri是我们传给播放器的代理url,这里获取的是真正的url
             String url = ProxyCacheUtils.decode(request.uri);
-            HttpProxyCacheServerClients clients = getClients(url);
-            clients.processRequest(request, socket);
+            //这个url是分为两种情况的,一种是ping的时候传的url,另一种就是真正请求资源的url路径了,获取代理路径的时候就会去ping
+            if (Pinger.isPingRequest(url)) {
+                Pinger.responseToPing(socket);
+            } else {
+                //获取远程的视频资源
+                HttpProxyCacheServerClients clients = getClients(url);
+                clients.processRequest(request, socket);
+            }
+            //HttpProxyCacheServerClients clients = getClients(url);
+            //clients.processRequest(request, socket);
         } catch (SocketException e) {
             // There is no way to determine that client closed connection http://stackoverflow.com/a/10241044/999458
             // So just to prevent log flooding don't log stacktrace
@@ -357,6 +383,7 @@ public class HttpProxyCacheServer {
         }
 
         /**
+         * 视频文件的缓存路径
          * Overrides default cache folder to be used for caching files.
          * <p>
          * By default AndroidVideoCache uses
@@ -374,6 +401,7 @@ public class HttpProxyCacheServer {
         }
 
         /**
+         * 生成的缓存视频文件的名字,传进来的对象实现FileNameGenerator这个类就可以了
          * Overrides default cache file name generator {@link Md5FileNameGenerator} .
          *
          * @param fileNameGenerator a new file name generator.
@@ -385,6 +413,7 @@ public class HttpProxyCacheServer {
         }
 
         /**
+         * 设置缓存文件的大小,单位是bytes,默认是512M
          * Sets max cache size in bytes.
          * <p>
          * All files that exceeds limit will be deleted using LRU strategy.
@@ -401,6 +430,7 @@ public class HttpProxyCacheServer {
         }
 
         /**
+         * 设置缓存文件的个数,缓存的策略只能是大小和个数中的一个
          * Sets max cache files count.
          * All files that exceeds limit will be deleted using LRU strategy.
          * Note this method overrides result of calling {@link #maxCacheSize(long)}
@@ -414,6 +444,7 @@ public class HttpProxyCacheServer {
         }
 
         /**
+         * 缓存策略也可以自己定义,实现DiskUsage就可以了,看自己需要
          * Set custom DiskUsage logic for handling when to keep or clean cache.
          *
          * @param diskUsage a disk usage strategy, cant be {@code null}.

+ 3 - 3
VideoCache/src/main/java/com/yc/videocache/Pinger.java

@@ -25,7 +25,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
  * Pings {@link HttpProxyCacheServer} to make sure it works.
  */
 
-class Pinger {
+public class Pinger {
 
     private static final String PING_REQUEST = "ping";
     private static final String PING_RESPONSE = "ping ok";
@@ -77,11 +77,11 @@ class Pinger {
         }
     }
 
-    boolean isPingRequest(String request) {
+    public static boolean isPingRequest(String request) {
         return PING_REQUEST.equals(request);
     }
 
-    void responseToPing(Socket socket) throws IOException {
+    public static void responseToPing(Socket socket) throws IOException {
         OutputStream out = socket.getOutputStream();
         out.write("HTTP/1.1 200 OK\n\n".getBytes());
         out.write(PING_RESPONSE.getBytes());

+ 5 - 4
VideoCache/src/main/java/com/yc/videocache/cache/PreloadManager.java

@@ -22,19 +22,19 @@ public class PreloadManager {
     /**
      * 单线程池,按照添加顺序依次执行{@link PreloadTask}
      */
-    private ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
+    private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
 
     /**
      * 保存正在预加载的{@link PreloadTask}
      */
-    private LinkedHashMap<String, PreloadTask> mPreloadTasks = new LinkedHashMap<>();
+    private final LinkedHashMap<String, PreloadTask> mPreloadTasks = new LinkedHashMap<>();
 
     /**
      * 标识是否需要预加载
      */
     private boolean mIsStartPreload = true;
 
-    private HttpProxyCacheServer mHttpProxyCacheServer;
+    private final HttpProxyCacheServer mHttpProxyCacheServer;
 
     /**
      * 预加载的大小,每个视频预加载512KB,这个参数可根据实际情况调整
@@ -73,7 +73,7 @@ public class PreloadManager {
         mPreloadTasks.put(rawUrl, task);
 
         if (mIsStartPreload) {
-            //开始预加载
+            //开始预加载,执行任务
             task.executeOn(mExecutorService);
         }
     }
@@ -96,6 +96,7 @@ public class PreloadManager {
         //再判断是否有临时缓存文件,如果已经存在临时缓存文件,并且临时缓存文件超过了预加载大小,则表示已经预加载完成了
         File tempCacheFile = mHttpProxyCacheServer.getTempCacheFile(rawUrl);
         if (tempCacheFile.exists()) {
+            //每个视频预加载512KB
             return tempCacheFile.length() >= PRELOAD_LENGTH;
         }
 

+ 9 - 3
VideoCache/src/main/java/com/yc/videocache/cache/PreloadTask.java

@@ -40,7 +40,7 @@ public class PreloadTask implements Runnable {
     @Override
     public void run() {
         if (!mIsCanceled) {
-            start();
+            startPreload();
         }
         mIsExecuted = false;
         mIsCanceled = false;
@@ -49,12 +49,16 @@ public class PreloadTask implements Runnable {
     /**
      * 开始预加载
      */
-    private void start() {
+    private void startPreload() {
         Logger.info("开始预加载:" + mPosition);
         HttpURLConnection connection = null;
         try {
+            //重点内容
             //获取HttpProxyCacheServer的代理地址
+            //urlPath指的是网络上的视频路径,返回的proxyUrl是一个代理路径
+            //得到这个代理路径后,接下来就只需要将这个路径设置给播放器就完成了。
             String proxyUrl = mCacheServer.getProxyUrl(mRawUrl);
+
             URL url = new URL(proxyUrl);
             connection = (HttpURLConnection) url.openConnection();
             connection.setConnectTimeout(5_000);
@@ -71,7 +75,8 @@ public class PreloadTask implements Runnable {
                     break;
                 }
             }
-            if (read == -1) { //这种情况一般是预加载出错了,删掉缓存
+            if (read == -1) {
+                //这种情况一般是预加载出错了,删掉缓存
                 Logger.info("预加载失败:" +  mPosition);
                 File cacheFile = mCacheServer.getCacheFile(mRawUrl);
                 if (cacheFile.exists()) {
@@ -96,6 +101,7 @@ public class PreloadTask implements Runnable {
         }
         mIsExecuted = true;
         executorService.submit(this);
+        //executorService.execute(this);
     }
 
     /**

+ 1 - 1
VideoCache/src/main/java/com/yc/videocache/cache/ProxyVideoCacheManager.java

@@ -46,6 +46,6 @@ public class ProxyVideoCacheManager {
         File path = sharedProxy.getCacheFile(url);
         return StorageUtils.deleteFile(pathTmp.getAbsolutePath()) &&
                 StorageUtils.deleteFile(path.getAbsolutePath());
-
     }
+
 }

+ 1 - 1
VideoM3u8/src/main/java/com/yc/m3u8/manager/M3u8InfoManger.java

@@ -28,7 +28,7 @@ public class M3u8InfoManger {
     private static final int WHAT_ON_SUCCESS = 1102;
 
     @SuppressLint("HandlerLeak")
-    private Handler mHandler = new Handler() {
+    private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {

+ 3 - 1
VideoM3u8/src/main/java/com/yc/m3u8/task/M3u8DownloadTask.java

@@ -1,5 +1,6 @@
 package com.yc.m3u8.task;
 
+import android.annotation.SuppressLint;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Message;
@@ -89,7 +90,8 @@ public class M3u8DownloadTask {
      */
     private Timer netSpeedTimer;
     private ExecutorService executor;//线程池
-    private Handler mHandler = new Handler() {
+    @SuppressLint("HandlerLeak")
+    private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {

+ 1 - 1
VideoSqlLite/src/main/java/com/yc/videosqllite/cache/VideoMapCache.java

@@ -17,7 +17,7 @@ public class VideoMapCache {
     /**
      * 缓存
      */
-    private InterCache<String, VideoLocation> mCache;
+    private final InterCache<String, VideoLocation> mCache;
     private final SafeKeyGenerator safeKeyGenerator;
 
     public VideoMapCache(){

+ 1 - 1
VideoSqlLite/src/main/java/com/yc/videosqllite/model/VideoLocation.java

@@ -205,7 +205,7 @@ public class VideoLocation implements Serializable , Cloneable{
         return hashCode(values);
     }
 
-    public static int hashCode(Object a[]) {
+    private int hashCode(Object a[]) {
         if (a == null){
             return 0;
         }

+ 23 - 7
VideoView/src/main/java/com/yc/videoview/abs/AbsFloatView.java

@@ -15,27 +15,43 @@ public abstract class AbsFloatView implements IFloatView {
 
     /**
      * 更新x和y
-     * @param x                     x
-     * @param y                     y
+     *
+     * @param x x
+     * @param y y
      */
-    public void updateXY(int x, int y) {}
+    public void updateXY(int x, int y) {
+    }
 
     /**
      * 更新x
-     * @param x                     x
+     *
+     * @param x x
      */
-    public void updateX(int x) {}
+    public void updateX(int x) {
+    }
 
     /**
      * 更新y
-     * @param y                     y
+     *
+     * @param y y
      */
-    public void updateY(int y) {}
+    public void updateY(int y) {
+    }
 
+    /**
+     * 获取x
+     *
+     * @return 默认是0
+     */
     public int getX() {
         return 0;
     }
 
+    /**
+     * 获取y
+     *
+     * @return 默认是0
+     */
     public int getY() {
         return 0;
     }

+ 7 - 1
VideoView/src/main/java/com/yc/videoview/impl/FloatPhoneImpl.java

@@ -30,8 +30,10 @@ public class FloatPhoneImpl extends AbsFloatView {
     public FloatPhoneImpl(Context applicationContext) {
         mContext = applicationContext;
         //创建WindowManager
+        //WindowManager负责窗口的动态操作,比如窗口的增、删、改。
         mWindowManager = (WindowManager)
                 applicationContext.getSystemService(Context.WINDOW_SERVICE);
+        //负责窗口的静态属性,比如窗口的标题、背景、输入法模式、屏幕方向等等。
         mLayoutParams = new WindowManager.LayoutParams();
     }
 
@@ -69,7 +71,10 @@ public class FloatPhoneImpl extends AbsFloatView {
         mLayoutParams.format = PixelFormat.TRANSPARENT;
         //设置类型
         mLayoutParams.type = layoutType;
+        //动画
         mLayoutParams.windowAnimations = 0;
+        //token,指标识窗口
+        //mLayoutParams.token;
         mView = view;
     }
 
@@ -90,6 +95,7 @@ public class FloatPhoneImpl extends AbsFloatView {
                 //将悬浮窗控件添加到WindowManager
                 mWindowManager.addView(mView, mLayoutParams);
             } else {
+                //先申请权限,然后在addView进来
                 PermissionActivity.request(mContext, new PermissionActivity.PermissionListener() {
                     @Override
                     public void onSuccess() {
@@ -108,7 +114,7 @@ public class FloatPhoneImpl extends AbsFloatView {
 
     @Override
     public void dismiss() {
-        if (mView!=null){
+        if (mView != null) {
             mWindowManager.removeView(mView);
         }
     }