Просмотр исходного кода

Merge pull request #102 from yangchong211/feature-4.0.0

Feature 4.0.0
杨充 4 лет назад
Родитель
Сommit
9d59f95353

+ 18 - 0
VideoGradle/video.gradle

@@ -0,0 +1,18 @@
+ext {
+
+    androidBuildToolsVersion = "29.0.0"
+    androidMinSdkVersion = 17
+    androidTargetSdkVersion = 29
+    androidCompileSdkVersion = 29
+
+
+    constraintLayoutVersion = '1.1.3'
+    appcompatVersion = '1.2.0'
+
+    /**主app-start*/
+    AppDependencies = [
+            constraintLayout    : "androidx.constraintlayout:constraintlayout:${constraintLayoutVersion}",
+            appcompat           : "androidx.appcompat:appcompat:${appcompatVersion}",
+    ]
+
+}

+ 1 - 0
VideoTool/.gitignore

@@ -0,0 +1 @@
+/build

+ 33 - 0
VideoTool/build.gradle

@@ -0,0 +1,33 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 29
+    buildToolsVersion "29.0.3"
+
+    defaultConfig {
+        minSdkVersion 16
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles 'consumer-rules.pro'
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    implementation 'androidx.appcompat:appcompat:1.2.0'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+}

+ 0 - 0
VideoTool/consumer-rules.pro


+ 21 - 0
VideoTool/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 27 - 0
VideoTool/src/androidTest/java/com/yc/videotool/ExampleInstrumentedTest.java

@@ -0,0 +1,27 @@
+package com.yc.videotool;
+
+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.videotool.test", appContext.getPackageName());
+    }
+}

+ 2 - 0
VideoTool/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.yc.videotool" />

+ 9 - 0
VideoTool/src/main/java/com/yc/videotool/Tool.java

@@ -0,0 +1,9 @@
+package com.yc.videotool;
+
+public final class Tool {
+
+    /**
+     * 工具基础库介绍
+     */
+
+}

+ 17 - 0
VideoTool/src/test/java/com/yc/videotool/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package com.yc.videotool;
+
+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);
+    }
+}

+ 7 - 5
VideoView/build.gradle

@@ -1,11 +1,13 @@
 apply plugin: 'com.android.library'
+apply from: rootProject.projectDir.absolutePath + "/VideoGradle/video.gradle"
+
 
 android {
-    compileSdkVersion 29
-    buildToolsVersion '29.0.0'
+    compileSdkVersion project.ext.androidCompileSdkVersion
+    buildToolsVersion project.ext.androidBuildToolsVersion
     defaultConfig {
-        minSdkVersion 17
-        targetSdkVersion 29
+        minSdkVersion project.ext.androidMinSdkVersion
+        targetSdkVersion project.ext.androidTargetSdkVersion
         versionCode 35
         versionName "3.0.5"
     }
@@ -20,7 +22,7 @@ android {
 
 dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
-    implementation 'androidx.appcompat:appcompat:1.2.0'
+    implementation project.ext.AppDependencies['appcompat']
 }
 
 /** 以下开始是将Android Library上传到jcenter的相关配置**/

+ 79 - 61
read/09.视频深度优化处理.md

@@ -1,84 +1,102 @@
 # 视频优化处理
 #### 目录介绍
+- 00.视频优化有哪些
+- 01.播放的完整流程
+- 02.播放痛点分析
+- 03.视频监控手段
+- 04.播放成功率优化
+- 05.播放性能优化
 
 
 
 
 
-### 01.播放的完整流程
-播放器加载一个网络url,首先要进行网络请求,网络如何优化,涉及到网络优化的方方面面。
-网络拉取回来数据之后,识别一下当前视频的具体封装格式,这个可以正式流式视频,也可以是普通视频,优化的手段有点不同。
-识别到具体的封装格式,按照封装格式的要求,开始解析封装格式,解析其中的音频流、视频流、字幕流等等。
-音频流要解码成音频原始数据,视频流要解码成视频原始数据。
-解码过程中注意音视频同步。
-音频播放,同时视频开始渲染。
-
-
+### 00.视频优化有哪些
+- ![image](https://img-blog.csdnimg.cn/20210401171515103.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzAwMjc1,size_16,color_FFFFFF,t_70)
 
-### 02.播放痛点
-- 根据我们平时的开发实践,我们总结出播放过程中常见的几类问题:
-
-播放失败率高
-播放首帧慢
-播放卡顿
-播放器占用CPU、内存过高
 
-- 面对这些问题,我们急切需要知道两方面的数据:
 
-怎么监控这些问题
-怎么解决这类问题
-
-这两个问题是有有递进关系的,“怎么监控这些问题”就是为了更好地“解决这类问题”。
-
-
-
-### 03.监控手段
-1、网络加载监控
-播放视频首要的是网络加载,网络请求是一个复杂的过程,全链路的点太多,将全链路的所有点收集起来,可以在播放器中加上网络的全链路监控:
+### 01.播放的完整流程
+- 播放流程图
+    - 待完善
+- 播放流程如下
+    - 播放器加载一个网络url,首先要进行网络请求,网络如何优化,涉及到网络优化的方方面面。
+    - 网络拉取回来数据之后,识别一下当前视频的具体封装格式,这个可以正式流式视频,也可以是普通视频,优化的手段有点不同。
+    - 识别到具体的封装格式,按照封装格式的要求,开始解析封装格式,解析其中的音频流、视频流、字幕流等等。
+    - 音频流要解码成音频原始数据,视频流要解码成视频原始数据。
+    - 解码过程中注意音视频同步。
+    - 音频播放,同时视频开始渲染。
 
-这样我们对网络的整体加载情况有了全面的把握,发生网络加载问题,也知道是哪个点出现了问题,分析解决问题有了更加全的数据。
-2、播放器全链路监控
-开篇就分析了播放器的完整流程,其实开发者也非常需要当前播放器的运行状态:
-播放器的工作状态也可以拆解一下:
 
-播放器发生状态异常,开发者可以明确获知播放器当前所处的状态。
-每个状态都可能发生异常,发生异常都有具体的原因。利用播放器状态、播放器出错情况构建一个较为完善的播放监控体系。
-3、播放器流畅度监控
-播放卡顿,就是播放过程中发生loading,UI直接显示转圈,这对用户体验的损害是巨大的,用户在不断的吐槽中默默地卸载了我们的app。卡顿的主要原因是网络状况不好,很小的一部分原因是源的问题。
 
-卡顿的次数
-卡顿的时长
-卡顿时的网速
+### 02.播放痛点分析
+- 根据我们平时的开发实践,我们总结出播放过程中常见的几类问题:
+    - 播放失败率高
+    - 播放首帧慢
+    - 播放卡顿
+    - 播放器占用CPU、内存过高
+- 面对这些问题,我们急切需要知道两方面的数据:
+    - 怎么监控这些问题
+    - 怎么解决这类问题
+- 这两个问题是有有递进关系的,“怎么监控这些问题”就是为了更好地“解决这类问题”。
 
-单次播放平均卡顿次数和卡顿时间是我们衡量播放流畅度的重要指标。
-如果是源的问题,例如出现播放视频的时候,进度条在走,但是画面不走,就是视频解码出现问题,但是又没有出错,只是解码出的数据有问题。
-解码出的数据有问题,有两种情况:原始数据就存在问题,这种情况下基本无法优化;另一种情况下是解码线程异常。
 
-MediaCodec发生异常
-解码线程异常错误
 
-监控发生问题时系统codec的具体状态,然后上报,便于分析问题。
+### 03.视频监控手段
+- 1、网络加载监控
+    - 播放视频首要的是网络加载,网络请求是一个复杂的过程,全链路的点太多,将全链路的所有点收集起来,可以在播放器中加上网络的全链路监控:
+    - 这样我们对网络的整体加载情况有了全面的把握,发生网络加载问题,也知道是哪个点出现了问题,分析解决问题有了更加全的数据。
+- 2、播放器全链路监控
+    - 播放器的工作状态也可以拆解一下:播放器发生状态异常,开发者可以明确获知播放器当前所处的状态。
+    - 每个状态都可能发生异常,发生异常都有具体的原因。利用播放器状态、播放器出错情况构建一个较为完善的播放监控体系。
+- 3、播放器流畅度监控
+    - 播放卡顿,就是播放过程中发生loading,UI直接显示转圈,这对用户体验的损害是巨大的,用户在不断的吐槽中默默地卸载了我们的app。卡顿的主要原因是网络状况不好,很小的一部分原因是源的问题。
+        - 卡顿的次数
+        - 卡顿的时长
+        - 卡顿时的网速
+    - 单次播放平均卡顿次数和卡顿时间是我们衡量播放流畅度的重要指标。
+    - 如果是源的问题,例如出现播放视频的时候,进度条在走,但是画面不走,就是视频解码出现问题,但是又没有出错,只是解码出的数据有问题。
+    - 解码出的数据有问题,有两种情况:原始数据就存在问题,这种情况下基本无法优化;另一种情况下是解码线程异常。
+        - MediaCodec发生异常
+        - 解码线程异常错误
+        - 监控发生问题时系统codec的具体状态,然后上报,便于分析问题。
 
 
 
 ### 04.播放成功率优化
-播放失败的原因很多,使用播放器播放视频,最终都会在Player.onError回调中通知开发者播放失败了,最多返回一个错误码,对应一个播放错误。
-总结而言,播放错误主要分为下面几类:
-
-**网络加载错误:**网络请求发生问题,可能是网络请求的任何一个阶段。
-**视频格式识别错误:**不支持当前的格式,或者当前格式识别出错。
-**解码出错:**不支持当前视频、音频解码导致的出错,或者系统codec异常导致的问题。
-**文件的IO异常:**读取缓存文件发生问题。
-
-网络加载错误一般要视情况而定,网络超时要做好超时重试机制。
-视频格式支持使用ffmpeg能解决基本上所有的视频格式的识别和处理工作。
-MediaCodec解码受到手机硬件的制约,解码有时候会出错,出错可以切换到软解码。
-
-
-
-
-
-
+- 播放失败的原因很多
+    - 使用播放器播放视频,最终都会在Player.onError回调中通知开发者播放失败了,最多返回一个错误码,对应一个播放错误。
+- 总结而言,播放错误主要分为下面几类:
+    - **网络加载错误:**网络请求发生问题,可能是网络请求的任何一个阶段。
+    - **视频格式识别错误:**不支持当前的格式,或者当前格式识别出错。
+    - **解码出错:**不支持当前视频、音频解码导致的出错,或者系统codec异常导致的问题。
+    - **文件的IO异常:**读取缓存文件发生问题。
+- 还有一些其他
+    - 网络加载错误一般要视情况而定,网络超时要做好超时重试机制。重试机制如何理解??
+    - 视频格式支持使用ffmpeg能解决基本上所有的视频格式的识别和处理工作。
+    - MediaCodec解码受到手机硬件的制约,解码有时候会出错,出错可以切换到软解码。
+
+
+
+### 05.播放性能优化
+- 1、复用链接:
+    - 平时刷信息流视频的时候,其实很多视频的域名都是相同的,这些链接都是可以复用的,网络建连的时间需要30ms到200ms不等,如果能复用链接,这部分的时间是可以节省下来的。
+- 2、预加载
+    - 一个播放器实例持有的数据非常大,player初始化的时候会初始化MediaCodec,MediaCodec对应底层的AVCodec,操作底层的/dev/codec-node,Android系统规定了系统最大持有的MediaCodec实例是16个,当然每个手机会有所不同,但总的来说不会有大的不同,就是MediaCodec的实例个数是有限的,不可能无限创建实例。
+    - 预加载多个播放器实例的时候,就会创建多个codec实例,超过codec实现限制,系统codec就无法正常工作,极易造成OOM或者ANR。
+    - 平时解决问题的时候经常发现media.codec进程导致SystemServer卡死的。一般都是media.codec使用不当造成的。
+- 3、指定封装格式和解码格式:
+    - 针对一些视频,我们已经明确知道它们的封装格式和音视频的编解码格式,那我们就可以提前告知播放器这些信息,播放器直接使用特定的封装格式去嗅探,直接起特定的解码器去解码。
+    - 例如信息流视频基本上都是MP4的封装格式,H264的视频编码,AAC的音频编码。这样我们可以节省嗅探和MediaCodec检索的时间。
+- 4、流式视频优化
+    - 除了MP4视频,还有一些流式点播的视频,例如HLS格式,这些视频是一个一个的ts分片组成的。针对这些视频首帧的优化,我建议直接将前几个ts的分片的数据压缩,例如针对一个3s的ts视频,原来的分辨率是1280 * 720,现在可以压缩到320 * 180的大小,数据量大大降低,这样首帧就能快速加载下来。
+- 6、边下边播
+    - 在播放视频的时候,最好能边播放边缓存到本地,这样我二次打开这个视频的时候,就可以不用请求了,直接复用本地的数据。边下边播可以使用本地代理来完成。
+
+
+
+### 参考博客
+- 播放器性能优化之路:https://juejin.cn/post/6898867991161602061
 
 
 

+ 1 - 0
settings.gradle

@@ -20,3 +20,4 @@ include ':VideoCache'
 //视频播放器
 include ':VideoPlayer'
 include ':Demo'
+include ':VideoTool'