├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── dbnavigator.xml ├── encodings.xml ├── misc.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── devyk │ │ └── av │ │ └── rtmppush │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── devyk │ │ │ └── av │ │ │ └── rtmppush │ │ │ ├── LiveActivity.kt │ │ │ ├── SPUtils.java │ │ │ ├── Utils.java │ │ │ └── base │ │ │ └── BaseActivity.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_live.xml │ │ └── address_dialog.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── camera_change.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── live.png │ │ ├── stop.png │ │ └── watemark.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── live_logo.jpeg │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── devyk │ └── av │ └── rtmppush │ └── ExampleUnitTest.kt ├── build.gradle ├── config.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── devyk │ │ └── av │ │ └── rtmp │ │ └── library │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── CMakeLists.txt │ │ ├── callback │ │ │ ├── JavaCallback.cpp │ │ │ └── JavaCallback.h │ │ ├── common │ │ │ ├── IObserver.cpp │ │ │ ├── IObserver.h │ │ │ ├── IPush.cpp │ │ │ ├── IPush.h │ │ │ ├── IThread.cpp │ │ │ ├── IThread.h │ │ │ ├── PushProxy.cpp │ │ │ └── PushProxy.h │ │ ├── jni │ │ │ └── native_rtmp_push.cpp │ │ ├── librtmp │ │ │ ├── include │ │ │ │ ├── amf.h │ │ │ │ ├── http.h │ │ │ │ ├── log.h │ │ │ │ └── rtmp.h │ │ │ └── libs │ │ │ │ ├── arm64-v8a │ │ │ │ └── librtmp.a │ │ │ │ └── armeabi-v7a │ │ │ │ └── librtmp.a │ │ └── push │ │ │ ├── AVQueue.cpp │ │ │ ├── AVQueue.h │ │ │ ├── RTMPPush.cpp │ │ │ └── RTMPPush.h │ ├── java │ │ └── com │ │ │ └── devyk │ │ │ └── av │ │ │ └── rtmp │ │ │ └── library │ │ │ ├── Contacts.kt │ │ │ ├── annotation │ │ │ └── RendererMode.kt │ │ │ ├── audio │ │ │ ├── AudioProcessor.kt │ │ │ └── AudioUtils.kt │ │ │ ├── black │ │ │ └── BlackListHelper.kt │ │ │ ├── callback │ │ │ ├── ICameraOpenListener.kt │ │ │ ├── IController.kt │ │ │ ├── IGLThreadConfig.kt │ │ │ ├── ILog.kt │ │ │ ├── IRenderer.kt │ │ │ ├── OnAudioDataListener.kt │ │ │ ├── OnAudioEncodeListener.kt │ │ │ ├── OnConnectListener.kt │ │ │ └── OnVideoEncodeListener.kt │ │ │ ├── camera │ │ │ ├── CameraData.kt │ │ │ ├── CameraHolder.kt │ │ │ ├── CameraRecorder.kt │ │ │ ├── CameraUtils.kt │ │ │ ├── EglHelper.kt │ │ │ ├── GLThread.kt │ │ │ ├── ShaderHelper.kt │ │ │ ├── Watermark.kt │ │ │ ├── exception │ │ │ │ ├── CameraDisabledException.kt │ │ │ │ ├── CameraHardwareException.kt │ │ │ │ ├── CameraNotSupportException.kt │ │ │ │ ├── NoCameraException.java │ │ │ │ └── NoCameraException.kt │ │ │ └── renderer │ │ │ │ ├── CameraRenderer.kt │ │ │ │ ├── DefaultRenderer.kt │ │ │ │ ├── EncodeRenderer.kt │ │ │ │ └── FboRenderer.kt │ │ │ ├── common │ │ │ ├── IThread.kt │ │ │ └── ThreadImpl.kt │ │ │ ├── config │ │ │ ├── AudioConfiguration.kt │ │ │ ├── CameraConfiguration.kt │ │ │ ├── RendererConfiguration.kt │ │ │ └── VideoConfiguration.kt │ │ │ ├── controller │ │ │ ├── AudioController.kt │ │ │ ├── StreamController.kt │ │ │ └── VideoController.kt │ │ │ ├── mediacodec │ │ │ ├── AudioEncoder.kt │ │ │ ├── AudioMediaCodec.kt │ │ │ ├── BaseAudioCodec.kt │ │ │ ├── BaseVideoEncoder.kt │ │ │ ├── IAudioCodec.kt │ │ │ ├── IVideoCodec.kt │ │ │ ├── VideoEncoder.kt │ │ │ └── VideoMediaCodec.kt │ │ │ ├── stream │ │ │ ├── AnnexbHelper.kt │ │ │ ├── PacketType.kt │ │ │ ├── amf │ │ │ │ ├── AmfArray.java │ │ │ │ ├── AmfBoolean.java │ │ │ │ ├── AmfData.java │ │ │ │ ├── AmfDecoder.java │ │ │ │ ├── AmfMap.java │ │ │ │ ├── AmfNull.java │ │ │ │ ├── AmfNumber.java │ │ │ │ ├── AmfObject.java │ │ │ │ ├── AmfString.java │ │ │ │ ├── AmfType.java │ │ │ │ ├── AmfUndefined.java │ │ │ │ └── Util.java │ │ │ ├── packer │ │ │ │ ├── DefaultPacker.kt │ │ │ │ ├── Packer.kt │ │ │ │ ├── flv │ │ │ │ │ └── FlvPackerHelper.java │ │ │ │ └── rtmp │ │ │ │ │ └── RtmpPacker.kt │ │ │ └── sender │ │ │ │ ├── Sender.kt │ │ │ │ └── rtmp │ │ │ │ └── RtmpSender.kt │ │ │ ├── utils │ │ │ ├── BitmapUtils.kt │ │ │ └── LogHelper.kt │ │ │ └── widget │ │ │ ├── AVLiveView.kt │ │ │ ├── CameraView.kt │ │ │ └── GLSurfaceView.kt │ └── res │ │ ├── layout │ │ └── include_live.xml │ │ ├── raw │ │ ├── fragment_shader.glsl │ │ ├── fragment_shader_camera.glsl │ │ ├── vertex_shader.glsl │ │ └── vertex_shader_matrix.glsl │ │ └── values │ │ ├── attrs.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── devyk │ └── av │ └── rtmp │ └── library │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # FILE 11 | file/ 12 | *.yuv 13 | *.h264 14 | *.pcm 15 | *.aac 16 | 17 | # Java class files 18 | *.class 19 | 20 | # Generated files 21 | bin/ 22 | gen/ 23 | out/ 24 | # Uncomment the following line in case you need and you don't have the release build type files in your app 25 | # release/ 26 | 27 | # Gradle files 28 | .gradle/ 29 | build/ 30 | 31 | # Local configuration file (sdk path, etc) 32 | local.properties 33 | 34 | # Proguard folder generated by Eclipse 35 | proguard/ 36 | 37 | # Log Files 38 | *.log 39 | 40 | # Android Studio Navigation editor temp files 41 | .navigation/ 42 | 43 | # Android Studio captures folder 44 | captures/ 45 | 46 | # IntelliJ 47 | *.iml 48 | .idea/workspace.xml 49 | .idea/tasks.xml 50 | .idea/gradle.xml 51 | .idea/assetWizardSettings.xml 52 | .idea/dictionaries 53 | .idea/libraries 54 | # Android Studio 3 in .gitignore file. 55 | .idea/caches 56 | .idea/modules.xml 57 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 58 | .idea/navEditor.xml 59 | 60 | # Keystore files 61 | # Uncomment the following lines if you do not want to check your keystore files in. 62 | #*.jks 63 | #*.keystore 64 | 65 | # External native build folder generated in Android Studio 2.2 and later 66 | .externalNativeBuild 67 | .cxx/ 68 | 69 | # Google Services (e.g. APIs or Firebase) 70 | # google-services.json 71 | 72 | # Freeline 73 | freeline.py 74 | freeline/ 75 | freeline_project_description.json 76 | 77 | # fastlane 78 | fastlane/report.xml 79 | fastlane/Preview.html 80 | fastlane/screenshots 81 | fastlane/test_output 82 | fastlane/readme.md 83 | 84 | # Version control 85 | vcs.xml 86 | 87 | # lint 88 | lint/intermediates/ 89 | lint/generated/ 90 | lint/outputs/ 91 | lint/tmp/ 92 | # lint/reports/ -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 21 | 22 | 26 | 27 | 28 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 42 | 48 | 49 | 53 | 54 | 55 | 57 | 58 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Android 10 | 11 | 12 | Code style issuesJava 13 | 14 | 15 | Control flow issuesJava 16 | 17 | 18 | CorrectnessLintAndroid 19 | 20 | 21 | Declaration redundancyJava 22 | 23 | 24 | Gradle 25 | 26 | 27 | GradleMigrationKotlin 28 | 29 | 30 | InternationalizationLintAndroid 31 | 32 | 33 | Java 34 | 35 | 36 | Java 5Java language level migration aidsJava 37 | 38 | 39 | Java language level migration aidsJava 40 | 41 | 42 | Kotlin 43 | 44 | 45 | LintAndroid 46 | 47 | 48 | MigrationKotlin 49 | 50 | 51 | PerformanceLintAndroid 52 | 53 | 54 | Probable bugsGradle 55 | 56 | 57 | Resource managementJava 58 | 59 | 60 | SecurityLintAndroid 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 72 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | android { 8 | compileSdkVersion rootProject.ext.android["compileSdkVersion"] 9 | buildToolsVersion rootProject.ext.android["buildToolsVersion"] 10 | 11 | compileOptions { 12 | targetCompatibility JavaVersion.VERSION_1_8 13 | sourceCompatibility JavaVersion.VERSION_1_8 14 | } 15 | 16 | defaultConfig { 17 | applicationId "com.devyk.av.rtmppush" 18 | minSdkVersion rootProject.ext.android["minSdkVersion"] 19 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 20 | versionCode rootProject.ext.android["versionCode"] 21 | versionName rootProject.ext.android["versionName"] 22 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 23 | 24 | ndk { 25 | // 设置编译的 SO 库架构 26 | // abiFilters 'armeabi' //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a' 27 | abiFilters 'arm64-v8a', 'armeabi-v7a' 28 | } 29 | 30 | } 31 | buildTypes { 32 | release { 33 | minifyEnabled false 34 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 35 | } 36 | } 37 | 38 | // 在Android代码块中添加如下配置:(可优化最上图中transformClassDexBuilderForDebug的时间) 39 | dexOptions { 40 | preDexLibraries true 41 | maxProcessCount 8 42 | } 43 | 44 | lintOptions { 45 | abortOnError false 46 | } 47 | 48 | 49 | } 50 | 51 | dependencies { 52 | implementation fileTree(dir: 'libs', include: ['*.jar']) 53 | //test 54 | testImplementation rootProject.ext.testDeps["junit"] 55 | 56 | //androidx 57 | api rootProject.ext.androidx["appcompat"] 58 | 59 | //kotlin 60 | api rootProject.ext.kotlin["core-ktx"] 61 | api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 62 | 63 | //rx 64 | api rootProject.ext.rxs["rxJava"] 65 | api rootProject.ext.rxs["rxAndroid"] 66 | api rootProject.ext.rxs["rxpermissions2"] 67 | // implementation project(path: ':library') 68 | 69 | implementation 'com.devyk.av.rtmp.library:AVRtmpPushSDK:1.0.0' 70 | 71 | } 72 | 73 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/devyk/av/rtmppush/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmppush 2 | 3 | import androidx.test.InstrumentationRegistry 4 | import androidx.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.devyk.av.rtmppush", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/devyk/av/rtmppush/Utils.java: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmppush; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | /** 7 | *
 8 |  *     author  : devyk on 2020-07-16 22:32
 9 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
10 |  *     github  : https://github.com/yangkun19921001
11 |  *     mailbox : yang1001yk@gmail.com
12 |  *     desc    : This is Utils
13 |  * 
14 | */ 15 | class Utils { 16 | private static Application sApp; 17 | 18 | public static Context getApp() { 19 | return sApp; 20 | } 21 | 22 | public static void init(Application application) { 23 | sApp = application; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/devyk/av/rtmppush/base/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.ikavedit.base 2 | 3 | import android.annotation.SuppressLint 4 | import android.graphics.Color 5 | import android.os.Bundle 6 | import android.os.SystemClock 7 | import android.view.Choreographer 8 | import android.view.View 9 | import android.view.Window 10 | import android.view.WindowManager 11 | import android.widget.Chronometer 12 | import android.widget.Toast 13 | import androidx.appcompat.app.AppCompatActivity 14 | import com.devyk.av.rtmppush.R 15 | import com.devyk.av.rtmppush.SPUtils 16 | import com.tbruyelle.rxpermissions2.RxPermissions 17 | 18 | /** 19 | *
 20 |  *     author  : devyk on 2020-05-24 23:40
 21 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 22 |  *     github  : https://github.com/yangkun19921001
 23 |  *     mailbox : yang1001yk@gmail.com
 24 |  *     desc    : This is BaseActivity
 25 |  * 
26 | */ 27 | 28 | abstract class BaseActivity : AppCompatActivity() { 29 | public var TAG = javaClass.simpleName; 30 | override fun onCreate(savedInstanceState: Bundle?) { 31 | super.onCreate(savedInstanceState) 32 | onContentViewBefore() 33 | 34 | if (getLayoutId() is Int){ 35 | setContentView(getLayoutId() as Int) 36 | }else if (getLayoutId() is View){ 37 | setContentView(getLayoutId() as View) 38 | } 39 | checkPermission() 40 | init(); 41 | initListener(); 42 | initData(); 43 | 44 | 45 | } 46 | 47 | /** 48 | * 在 setContentView 之前需要做的初始化 49 | */ 50 | protected open fun onContentViewBefore() { 51 | 52 | } 53 | 54 | abstract fun initListener() 55 | 56 | abstract fun initData() 57 | 58 | abstract fun init() 59 | 60 | abstract fun getLayoutId(): T 61 | 62 | 63 | protected fun setNotTitleBar() { 64 | val window = window 65 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) 66 | window.getDecorView().setSystemUiVisibility( 67 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 68 | or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 69 | or View.SYSTEM_UI_FLAG_LAYOUT_STABLE 70 | ) 71 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) 72 | window.setStatusBarColor(Color.TRANSPARENT) 73 | window.setNavigationBarColor(Color.TRANSPARENT) 74 | //去掉标题栏 75 | supportRequestWindowFeature(Window.FEATURE_NO_TITLE) 76 | } 77 | 78 | 79 | /** 80 | * 检查权限 81 | */ 82 | @SuppressLint("CheckResult") 83 | protected fun checkPermission() { 84 | if (SPUtils.getInstance().getBoolean(getString(R.string.OPEN_PERMISSIONS))) return 85 | var rxPermissions = RxPermissions(this); 86 | rxPermissions.requestEach( 87 | android.Manifest.permission.READ_EXTERNAL_STORAGE, 88 | android.Manifest.permission.RECORD_AUDIO, 89 | android.Manifest.permission.CAMERA, 90 | android.Manifest.permission.WRITE_EXTERNAL_STORAGE 91 | ).subscribe { 92 | if (it.granted) { 93 | SPUtils.getInstance().put(getString(R.string.OPEN_PERMISSIONS), true) 94 | Toast.makeText(this, getString(R.string.GET_PERMISSION_ERROR), Toast.LENGTH_SHORT).show(); 95 | } else if (it.shouldShowRequestPermissionRationale) { 96 | Toast.makeText(this, getString(R.string.GET_PERMISSION_ERROR), Toast.LENGTH_SHORT).show(); 97 | SPUtils.getInstance().put(getString(R.string.OPEN_PERMISSIONS), false) 98 | } 99 | } 100 | } 101 | 102 | 103 | public fun startTime(timer: Chronometer) { 104 | var hour = ((SystemClock.elapsedRealtime() - timer.getBase()) / 1000 / 60).toInt(); 105 | timer.setFormat("0${hour}:%s"); 106 | timer.start() 107 | } 108 | 109 | public fun cleanTime(timer: Chronometer) { 110 | timer?.setBase(SystemClock.elapsedRealtime()); 111 | timer?.stop() 112 | } 113 | 114 | 115 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 | 68 | 70 | 72 | 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_live.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 23 | 24 | 25 | 32 | 37 | 38 | 39 | 40 | 41 | 50 | 51 | 56 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/layout/address_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 26 | 27 |