├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ ├── live.png │ │ │ │ ├── stop.png │ │ │ │ ├── watemark.png │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── camera_change.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── live_logo.jpeg │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── layout │ │ │ │ ├── address_dialog.xml │ │ │ │ └── activity_live.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ └── drawable │ │ │ │ └── ic_launcher_background.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── devyk │ │ │ │ └── av │ │ │ │ └── rtmppush │ │ │ │ ├── Utils.java │ │ │ │ └── base │ │ │ │ └── BaseActivity.kt │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── devyk │ │ │ └── av │ │ │ └── rtmppush │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── com │ │ └── devyk │ │ └── av │ │ └── rtmppush │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle ├── library ├── .gitignore ├── src │ ├── main │ │ ├── cpp │ │ │ ├── common │ │ │ │ ├── IPush.cpp │ │ │ │ ├── IObserver.cpp │ │ │ │ ├── IObserver.h │ │ │ │ ├── IThread.cpp │ │ │ │ ├── IThread.h │ │ │ │ ├── IPush.h │ │ │ │ ├── PushProxy.cpp │ │ │ │ └── PushProxy.h │ │ │ ├── librtmp │ │ │ │ ├── libs │ │ │ │ │ ├── arm64-v8a │ │ │ │ │ │ └── librtmp.a │ │ │ │ │ └── armeabi-v7a │ │ │ │ │ │ └── librtmp.a │ │ │ │ └── include │ │ │ │ │ ├── http.h │ │ │ │ │ └── log.h │ │ │ ├── push │ │ │ │ ├── AVQueue.h │ │ │ │ ├── AVQueue.cpp │ │ │ │ └── RTMPPush.h │ │ │ ├── callback │ │ │ │ ├── JavaCallback.h │ │ │ │ └── JavaCallback.cpp │ │ │ ├── CMakeLists.txt │ │ │ └── jni │ │ │ │ └── native_rtmp_push.cpp │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ └── attrs.xml │ │ │ ├── raw │ │ │ │ ├── fragment_shader.glsl │ │ │ │ ├── vertex_shader.glsl │ │ │ │ ├── fragment_shader_camera.glsl │ │ │ │ └── vertex_shader_matrix.glsl │ │ │ └── layout │ │ │ │ └── include_live.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── devyk │ │ │ └── av │ │ │ └── rtmp │ │ │ └── library │ │ │ ├── camera │ │ │ ├── exception │ │ │ │ ├── NoCameraException.java │ │ │ │ ├── NoCameraException.kt │ │ │ │ ├── CameraDisabledException.kt │ │ │ │ ├── CameraHardwareException.kt │ │ │ │ └── CameraNotSupportException.kt │ │ │ ├── renderer │ │ │ │ └── DefaultRenderer.kt │ │ │ ├── Watermark.kt │ │ │ ├── CameraData.kt │ │ │ ├── CameraRecorder.kt │ │ │ ├── EglHelper.kt │ │ │ ├── ShaderHelper.kt │ │ │ └── GLThread.kt │ │ │ ├── callback │ │ │ ├── OnAudioDataListener.kt │ │ │ ├── OnVideoEncodeListener.kt │ │ │ ├── ICameraOpenListener.kt │ │ │ ├── ILog.kt │ │ │ ├── OnAudioEncodeListener.kt │ │ │ ├── OnConnectListener.kt │ │ │ ├── IRenderer.kt │ │ │ ├── IGLThreadConfig.kt │ │ │ └── IController.kt │ │ │ ├── stream │ │ │ ├── sender │ │ │ │ ├── Sender.kt │ │ │ │ └── rtmp │ │ │ │ │ └── RtmpSender.kt │ │ │ ├── PacketType.kt │ │ │ ├── amf │ │ │ │ ├── AmfData.java │ │ │ │ ├── AmfNull.java │ │ │ │ ├── AmfUndefined.java │ │ │ │ ├── AmfType.java │ │ │ │ ├── AmfBoolean.java │ │ │ │ ├── AmfDecoder.java │ │ │ │ ├── AmfNumber.java │ │ │ │ ├── AmfMap.java │ │ │ │ ├── AmfArray.java │ │ │ │ ├── AmfString.java │ │ │ │ ├── AmfObject.java │ │ │ │ └── Util.java │ │ │ └── packer │ │ │ │ ├── Packer.kt │ │ │ │ ├── DefaultPacker.kt │ │ │ │ └── rtmp │ │ │ │ └── RtmpPacker.kt │ │ │ ├── Contacts.kt │ │ │ ├── mediacodec │ │ │ ├── IAudioCodec.kt │ │ │ ├── IVideoCodec.kt │ │ │ ├── AudioEncoder.kt │ │ │ ├── VideoEncoder.kt │ │ │ ├── BaseAudioCodec.kt │ │ │ ├── AudioMediaCodec.kt │ │ │ └── VideoMediaCodec.kt │ │ │ ├── common │ │ │ ├── IThread.kt │ │ │ └── ThreadImpl.kt │ │ │ ├── annotation │ │ │ └── RendererMode.kt │ │ │ ├── utils │ │ │ ├── LogHelper.kt │ │ │ └── BitmapUtils.kt │ │ │ ├── black │ │ │ └── BlackListHelper.kt │ │ │ ├── controller │ │ │ ├── VideoController.kt │ │ │ └── AudioController.kt │ │ │ ├── config │ │ │ ├── CameraConfiguration.kt │ │ │ ├── RendererConfiguration.kt │ │ │ ├── VideoConfiguration.kt │ │ │ └── AudioConfiguration.kt │ │ │ ├── audio │ │ │ ├── AudioProcessor.kt │ │ │ └── AudioUtils.kt │ │ │ └── widget │ │ │ └── GLSurfaceView.kt │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── devyk │ │ │ └── av │ │ │ └── rtmp │ │ │ └── library │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── devyk │ │ └── av │ │ └── rtmp │ │ └── library │ │ └── ExampleInstrumentedTest.java ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── encodings.xml ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── runConfigurations.xml └── misc.xml ├── gradle.properties ├── .gitignore ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':library' 2 | -------------------------------------------------------------------------------- /library/src/main/cpp/common/IPush.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 阳坤 on 2020-07-03. 3 | // 4 | 5 | #include "IPush.h" 6 | -------------------------------------------------------------------------------- /library/src/main/cpp/common/IObserver.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 阳坤 on 2020-07-03. 3 | // 4 | 5 | #include "IObserver.h" 6 | -------------------------------------------------------------------------------- /library/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | library 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/live.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-hdpi/live.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-hdpi/stop.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/watemark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-hdpi/watemark.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/live_logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-xhdpi/live_logo.jpeg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/camera_change.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-hdpi/camera_change.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /library/src/main/cpp/librtmp/libs/arm64-v8a/librtmp.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/library/src/main/cpp/librtmp/libs/arm64-v8a/librtmp.a -------------------------------------------------------------------------------- /library/src/main/cpp/librtmp/libs/armeabi-v7a/librtmp.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangkun19921001/AVRtmpPushSDK/HEAD/library/src/main/cpp/librtmp/libs/armeabi-v7a/librtmp.a -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/camera/exception/NoCameraException.java: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.camera.exception; 2 | 3 | public class NoCameraException extends Exception { 4 | } -------------------------------------------------------------------------------- /library/src/main/res/raw/fragment_shader.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | varying vec2 ft_Position; 3 | uniform sampler2D sTexture; 4 | void main() { 5 | gl_FragColor=texture2D(sTexture, ft_Position); 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 随播 3 | 4 | 权限是否已经开启 5 | 权限获取成功! 6 | 7 | -------------------------------------------------------------------------------- /library/src/main/res/raw/vertex_shader.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 v_Position; 2 | attribute vec2 f_Position; 3 | varying vec2 ft_Position; 4 | void main() { 5 | ft_Position = f_Position; 6 | gl_Position = v_Position; 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /library/src/main/cpp/common/IObserver.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 阳坤 on 2020-07-03. 3 | // 4 | 5 | #ifndef RTMPPUSH_IOBSERVER_H 6 | #define RTMPPUSH_IOBSERVER_H 7 | 8 | 9 | 10 | class IObserver { 11 | 12 | }; 13 | 14 | 15 | 16 | #endif //RTMPPUSH_IOBSERVER_H 17 | -------------------------------------------------------------------------------- /library/src/main/res/raw/fragment_shader_camera.glsl: -------------------------------------------------------------------------------- 1 | #extension GL_OES_EGL_image_external : require 2 | precision mediump float; 3 | varying vec2 ft_Position; 4 | uniform samplerExternalOES sTexture; 5 | void main() { 6 | gl_FragColor=texture2D(sTexture, ft_Position); 7 | } 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jul 03 10:42:37 CST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip 7 | -------------------------------------------------------------------------------- /library/src/main/res/raw/vertex_shader_matrix.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 v_Position; 2 | attribute vec2 f_Position; 3 | varying vec2 ft_Position; 4 | uniform mat4 u_Matrix; 5 | void main() { 6 | ft_Position = f_Position; 7 | gl_Position = v_Position * u_Matrix; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/callback/OnAudioDataListener.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.callback 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-07-16 10:30
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is OnAudioDataListener
10 |  * 
11 | */ -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/camera/exception/NoCameraException.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.camera.exception 2 | /** 3 | *
 4 |  *     author  : devyk on 2020-05-28 23:32
 5 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 6 |  *     github  : https://github.com/yangkun19921001
 7 |  *     mailbox : yang1001yk@gmail.com
 8 |  *     desc    : This is NoCameraException
 9 |  * 
10 | */ -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/callback/OnVideoEncodeListener.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.callback 2 | 3 | import android.media.MediaCodec 4 | import android.media.MediaFormat 5 | import java.nio.ByteBuffer 6 | 7 | /** 8 | * 编码回调 9 | */ 10 | interface OnVideoEncodeListener { 11 | abstract fun onVideoEncode(bb: ByteBuffer?, bi: MediaCodec.BufferInfo?) 12 | fun onVideoOutformat(outputFormat: MediaFormat?) 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /library/src/main/cpp/common/IThread.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 阳坤 on 2020-07-03. 3 | // 4 | 5 | #include "IThread.h" 6 | 7 | 8 | void *_main(void *pVoid) { 9 | IThread *thread = static_cast(pVoid); 10 | //交于子类实现 11 | thread->main(); 12 | return 0; 13 | } 14 | 15 | 16 | void IThread::start() { 17 | pthread_create(&this->pId, 0, _main, this); 18 | } 19 | 20 | void IThread::stop() { 21 | // pthread_join(pId,0); 22 | } 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/test/java/com/devyk/av/rtmppush/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmppush 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/camera/exception/CameraDisabledException.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.camera.exception 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-05-28 23:31
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is CameraDisabledException
10 |  * 
11 | */ 12 | class CameraDisabledException : Exception() -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/callback/ICameraOpenListener.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.callback 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-07-08 21:35
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is ICameraOpenListener
10 |  * 
11 | */ 12 | 13 | public interface ICameraOpenListener { 14 | fun onCameraOpen() 15 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/camera/exception/CameraHardwareException.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.camera.exception 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-05-29 15:04
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is CameraHardwareException
10 |  * 
11 | */ 12 | class CameraHardwareException(t: Throwable) : Exception(t) -------------------------------------------------------------------------------- /library/src/test/java/com/devyk/av/rtmp/library/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/camera/exception/CameraNotSupportException.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.camera.exception 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-05-28 23:26
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is CameraNotSupportException
10 |  * 
11 | */ 12 | public class CameraNotSupportException :Exception(){ 13 | 14 | } -------------------------------------------------------------------------------- /library/src/main/cpp/common/IThread.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 阳坤 on 2020-07-03. 3 | // 4 | 5 | #ifndef RTMPPUSH_ITHREAD_H 6 | #define RTMPPUSH_ITHREAD_H 7 | 8 | 9 | #include 10 | 11 | 12 | /** 13 | * 线程控制的基类 14 | */ 15 | class IThread { 16 | 17 | public: 18 | 19 | /** 20 | * 线程 ID 21 | */ 22 | pthread_t pId; 23 | 24 | public: 25 | virtual void start(); 26 | 27 | virtual void stop(); 28 | 29 | virtual void main() = 0; 30 | 31 | 32 | }; 33 | 34 | 35 | #endif //RTMPPUSH_ITHREAD_H 36 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/stream/sender/Sender.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.stream.sender 2 | 3 | import com.devyk.av.rtmp.library.stream.PacketType 4 | 5 | /** 6 | *
 7 |  *     author  : devyk on 2020-07-16 21:26
 8 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 9 |  *     github  : https://github.com/yangkun19921001
10 |  *     mailbox : yang1001yk@gmail.com
11 |  *     desc    : This is Sender
12 |  * 
13 | */ 14 | public interface Sender{ 15 | fun onData(data: ByteArray, type: PacketType) 16 | fun onData(sps: ByteArray,pps: ByteArray, type: PacketType){} 17 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/Contacts.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-07-15 21:44
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is Contacts
10 |  * 
11 | */ 12 | public object Contacts { 13 | public var TAG = "AVRtmpPush" 14 | //rtmp 初始化失败 15 | var RTMP_INIT_ERROR = -9 16 | //设置 rtmp url 失败 17 | var RTMP_SET_URL_ERROR = -10 18 | //连接服务器失败 19 | var RTMP_CONNECT_ERROR = -11 20 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/callback/ILog.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.callback 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-07-15 21:26
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is ILog
10 |  * 
11 | */ 12 | public interface ILog { 13 | fun i(tag: String = javaClass.simpleName, info: String?); 14 | fun e(tag: String = javaClass.simpleName, info: String?); 15 | fun w(tag: String = javaClass.simpleName, info: String?); 16 | fun d(tag: String = javaClass.simpleName, info: String?); 17 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/mediacodec/IAudioCodec.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.mediacodec 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-06-13 23:55
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is ICodec
10 |  * 
11 | */ 12 | public interface IAudioCodec{ 13 | 14 | 15 | /** 16 | * 准备编码 17 | */ 18 | fun start() 19 | 20 | /** 21 | * 将数据送入编解码器 22 | */ 23 | fun enqueueCodec(input: ByteArray?); 24 | 25 | /** 26 | * 停止编码 27 | */ 28 | fun stop(); 29 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/stream/PacketType.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.stream 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-07-16 21:29
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is PacketType
10 |  * 
11 | */ 12 | public enum class PacketType { 13 | FIRST_AUDIO(1), 14 | FIRST_VIDEO(2), 15 | SPS_PPS(3), 16 | AUDIO(4), 17 | KEY_FRAME(5), 18 | VIDEO(6); 19 | 20 | 21 | var type = -1; 22 | constructor(types: Int){ 23 | type = types 24 | } 25 | 26 | 27 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/callback/OnAudioEncodeListener.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.callback 2 | 3 | import android.media.MediaCodec 4 | import android.media.MediaFormat 5 | import java.nio.ByteBuffer 6 | 7 | /** 8 | *
 9 |  *     author  : devyk on 2020-06-13 16:09
10 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
11 |  *     github  : https://github.com/yangkun19921001
12 |  *     mailbox : yang1001yk@gmail.com
13 |  *     desc    : This is OnAudioEncodeListener
14 |  * 
15 | */ 16 | public interface OnAudioEncodeListener { 17 | fun onAudioEncode(bb: ByteBuffer, bi: MediaCodec.BufferInfo) 18 | fun onAudioOutformat(outputFormat: MediaFormat?) 19 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /library/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/callback/OnConnectListener.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.callback 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-07-16 23:10
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is OnConnectListener
10 |  * 
11 | */ 12 | public interface OnConnectListener { 13 | /** 14 | * 开始链接 15 | */ 16 | fun onConnecting() 17 | 18 | /** 19 | * 连接成功 20 | */ 21 | fun onConnected() 22 | 23 | /** 24 | * 推送失败 25 | */ 26 | fun onFail(message:String) 27 | 28 | /** 29 | * 关闭 30 | */ 31 | fun onClose() 32 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /library/src/main/res/layout/include_live.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 19 | -------------------------------------------------------------------------------- /library/src/main/cpp/push/AVQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by yangw on 2018-9-14. 3 | // 4 | 5 | #ifndef AVLIVEPUSHER_QUEUE_H 6 | #define AVLIVEPUSHER_QUEUE_H 7 | 8 | #include "queue" 9 | #include "pthread.h" 10 | #include 11 | 12 | extern "C" 13 | { 14 | #include "../librtmp/include/rtmp.h" 15 | }; 16 | 17 | 18 | class AVQueue { 19 | 20 | public: 21 | std::queue queuePacket; 22 | pthread_mutex_t mutexPacket; 23 | pthread_cond_t condPacket; 24 | 25 | public: 26 | AVQueue(); 27 | ~AVQueue(); 28 | 29 | int putRtmpPacket(RTMPPacket *packet); 30 | 31 | RTMPPacket* getRtmpPacket(); 32 | 33 | void clearQueue(); 34 | 35 | void notifyQueue(); 36 | 37 | 38 | }; 39 | 40 | 41 | #endif //AVLIVEPUSHER_QUEUE_H 42 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/common/IThread.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.common 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-07-15 20:42
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is IThread
10 |  * 
11 | */ 12 | public interface IThread { 13 | 14 | /** 15 | * 开始执行线程 16 | */ 17 | fun start(main:()->Unit) 18 | 19 | /** 20 | * 停止执行 21 | */ 22 | fun stop() 23 | 24 | /** 25 | *设置是否暂停 26 | */ 27 | fun setPause(pause: Boolean) 28 | 29 | /** 30 | * 停止 31 | */ 32 | fun isPause(): Boolean 33 | 34 | /** 35 | * 是否运行 36 | */ 37 | fun isRuning(): Boolean 38 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /library/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 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/callback/IRenderer.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.camera_recorder.callback 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-07-06 11:05
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is IRenderer
10 |  *
11 |  *
12 |  *     OpenGL ES 坐标系:
13 |  *     @see ![](https://devyk.oss-cn-qingdao.aliyuncs.com/blog/20200706174743.png)
14 |  * 
15 | */ 16 | public interface IRenderer { 17 | /** 18 | * 当 Surface 创建的时候 19 | */ 20 | public fun onSurfaceCreate(width: Int, height: Int); 21 | 22 | /** 23 | * 当 surface 窗口改变的时候 24 | */ 25 | public fun onSurfaceChange(width: Int, height: Int); 26 | 27 | /** 28 | * 绘制的时候 29 | */ 30 | public fun onDraw(); 31 | } -------------------------------------------------------------------------------- /library/src/androidTest/java/com/devyk/av/rtmp/library/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library; 2 | 3 | import android.content.Context; 4 | import androidx.test.InstrumentationRegistry; 5 | import androidx.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.devyk.av.rtmp.library.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/annotation/RendererMode.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.annotation 2 | 3 | import androidx.annotation.IntDef 4 | import com.devyk.av.rtmp.library.widget.GLSurfaceView 5 | import java.lang.annotation.Retention 6 | import java.lang.annotation.RetentionPolicy 7 | 8 | /** 9 | *
10 |  *     author  : devyk on 2020-07-06 11:35
11 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
12 |  *     github  : https://github.com/yangkun19921001
13 |  *     mailbox : yang1001yk@gmail.com
14 |  *     desc    : This is RendererMode 用于 OpenGL ES 渲染模式  @link com.devyk.av.camera_recorder.widget.base.GLSurfaceView
15 |  * 
16 | */ 17 | @IntDef(GLSurfaceView.RENDERERMODE_WHEN_DIRTY, GLSurfaceView.RENDERERMODE_CONTINUOUSLY) 18 | @Target(AnnotationTarget.VALUE_PARAMETER) //用于参数上 19 | @Retention(RetentionPolicy.SOURCE) //编译器 20 | annotation class RendererMode {} -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/callback/IGLThreadConfig.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.camera_recorder.callback 2 | 3 | import android.view.Surface 4 | import javax.microedition.khronos.egl.EGLContext 5 | 6 | /** 7 | *
 8 |  *     author  : devyk on 2020-07-08 20:51
 9 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
10 |  *     github  : https://github.com/yangkun19921001
11 |  *     mailbox : yang1001yk@gmail.com
12 |  *     desc    : This is IGLThreadConfig ELThread 需要的配置
13 |  * 
14 | */ 15 | public interface IGLThreadConfig { 16 | /** 17 | * 拿到渲染器 18 | */ 19 | fun getRenderer(): IRenderer? 20 | 21 | /** 22 | * 拿到渲染的 Surface 23 | */ 24 | fun getSurface(): Surface? 25 | 26 | /** 27 | * 拿到 EGL 环境的上下文 28 | */ 29 | fun getEGLContext(): EGLContext? 30 | 31 | /** 32 | * 拿到渲染模式 33 | */ 34 | fun getRendererMode(): Int 35 | 36 | 37 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/camera/renderer/DefaultRenderer.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.camera.renderer 2 | 3 | import android.opengl.GLES20 4 | import com.devyk.av.camera_recorder.callback.IRenderer 5 | 6 | /** 7 | *
 8 |  *     author  : devyk on 2020-07-06 11:57
 9 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
10 |  *     github  : https://github.com/yangkun19921001
11 |  *     mailbox : yang1001yk@gmail.com
12 |  *     desc    : This is DefaultRenderer 渲染
13 |  * 
14 | */ 15 | public class DefaultRenderer : IRenderer { 16 | override fun onSurfaceCreate(width: Int, height: Int) { 17 | } 18 | 19 | override fun onSurfaceChange(width: Int, height: Int) { 20 | //清屏 21 | GLES20.glViewport(0, 0, width, height) 22 | } 23 | 24 | override fun onDraw() { 25 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) 26 | GLES20.glClearColor(0f, 1f, 0f, 1f) 27 | } 28 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/mediacodec/IVideoCodec.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.mediacodec 2 | 3 | import android.media.MediaCodec 4 | 5 | import com.devyk.av.rtmp.library.config.VideoConfiguration 6 | 7 | import java.nio.ByteBuffer 8 | 9 | /** 10 | *
11 |  *     author  : devyk on 2020-06-15 21:42
12 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
13 |  *     github  : https://github.com/yangkun19921001
14 |  *     mailbox : yang1001yk@gmail.com
15 |  *     desc    : This is ICodec
16 |  * 
17 | */ 18 | 19 | public interface IVideoCodec { 20 | 21 | 22 | 23 | /** 24 | * 初始化编码器 25 | */ 26 | fun prepare(videoConfiguration: VideoConfiguration = VideoConfiguration.createDefault()){}; 27 | 28 | /** 29 | * start 编码 30 | */ 31 | fun start(); 32 | 33 | /** 34 | * 停止编码 35 | */ 36 | fun stop(); 37 | 38 | /** 39 | * 返回编码好的 H264 数据 40 | */ 41 | abstract fun onVideoEncode(bb: ByteBuffer?, mBufferInfo: MediaCodec.BufferInfo) 42 | 43 | 44 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/stream/amf/AmfData.java: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.stream.amf; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | 7 | /** 8 | * @Title: AmfData 9 | * @Package com.jimfengfly.rtmppublisher.amf 10 | * @Description: 11 | * @Author Jim 12 | * @Date 2016/11/28 13 | * @Time 上午11:40 14 | * @Version 15 | */ 16 | 17 | public interface AmfData { 18 | /** 19 | * Write/Serialize this AMF data intance (Object/string/integer etc) to 20 | * the specified OutputStream 21 | */ 22 | void writeTo(OutputStream out) throws IOException; 23 | 24 | /** 25 | * Read and parse bytes from the specified input stream to populate this 26 | * AMFData instance (deserialize) 27 | * 28 | * @return the amount of bytes read 29 | */ 30 | void readFrom(InputStream in) throws IOException; 31 | 32 | /** @return the amount of bytes required for this object */ 33 | int getSize(); 34 | 35 | /** @return the bytes of this object */ 36 | byte[] getBytes(); 37 | } 38 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/utils/LogHelper.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.utils 2 | 3 | import android.os.Build 4 | import android.util.Log 5 | import com.devyk.av.rtmp.library.callback.ILog 6 | 7 | /** 8 | *
 9 |  *     author  : devyk on 2020-06-02 00:07
10 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
11 |  *     github  : https://github.com/yangkun19921001
12 |  *     mailbox : yang1001yk@gmail.com
13 |  *     desc    : This is LogHelper
14 |  * 
15 | */ 16 | public object LogHelper : ILog { 17 | 18 | var isShowLog = false 19 | 20 | 21 | override fun i(tag: String, info: String?) { 22 | if (isShowLog) 23 | Log.i(tag, info) 24 | 25 | } 26 | 27 | override fun e(tag: String, info: String?) { 28 | if (isShowLog) 29 | Log.e(tag, info) 30 | } 31 | 32 | override fun w(tag: String, info: String?) { 33 | if (isShowLog) 34 | Log.w(tag, info) 35 | } 36 | 37 | override fun d(tag: String, info: String?) { 38 | if (isShowLog) 39 | Log.d(tag, info) 40 | } 41 | } -------------------------------------------------------------------------------- /library/src/main/cpp/common/IPush.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 阳坤 on 2020-07-03. 3 | // 4 | 5 | #ifndef RTMPPUSH_IPUSH_H 6 | #define RTMPPUSH_IPUSH_H 7 | 8 | 9 | #include "IThread.h" 10 | 11 | class IPush : public IThread { 12 | 13 | public: 14 | /** 15 | * 开启线程 16 | */ 17 | virtual void start() = 0; 18 | 19 | /** 20 | * 停止推流 21 | */ 22 | virtual void stop() = 0; 23 | 24 | /** 25 | * 子线程入口 26 | */ 27 | virtual void main() = 0; 28 | 29 | /** 30 | * 推送视频第一帧 SPS PPS 数据 31 | * @param sps 32 | * @param sps_len 33 | * @param pps 34 | * @param pps_len 35 | */ 36 | virtual void pushSpsPps(uint8_t *sps, int sps_len, uint8_t *pps, int pps_len) = 0; 37 | 38 | /** 39 | * 推送音频数据 40 | * @param audio 41 | * @param len 42 | */ 43 | virtual void pushAudioData(uint8_t *audio, int len,int type) = 0; 44 | 45 | /** 46 | * 推送视频数据 47 | * @param video 48 | * @param len 49 | * @param keyframe 50 | */ 51 | virtual void pushVideoData(uint8_t *video, int len, int type) = 0; 52 | }; 53 | 54 | 55 | #endif //RTMPPUSH_IPUSH_H 56 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/camera/Watermark.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.camera 2 | 3 | import android.graphics.Bitmap 4 | 5 | /** 6 | *
 7 |  *     author  : devyk on 2020-07-18 19:43
 8 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 9 |  *     github  : https://github.com/yangkun19921001
10 |  *     mailbox : yang1001yk@gmail.com
11 |  *     desc    : This is Watermark
12 |  * 
13 | */ 14 | class Watermark { 15 | 16 | var markImg: Bitmap? = null 17 | var txt: String? = null 18 | var textColor = -1 19 | var textSize = -1 20 | 21 | var floatArray: FloatArray? = null 22 | 23 | 24 | constructor( 25 | markImg: Bitmap 26 | , floatArray: FloatArray? 27 | ) { 28 | this.markImg = markImg 29 | this.floatArray = floatArray 30 | } 31 | 32 | constructor( 33 | txt: String, 34 | txtColor: Int, 35 | txtSize: Int 36 | , floatArray: FloatArray? 37 | ) { 38 | this.txt = txt 39 | this.textSize = txtSize 40 | this.textColor = txtColor 41 | this.floatArray = floatArray 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /library/src/main/cpp/callback/JavaCallback.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 阳坤 on 2020-07-17. 3 | // 4 | 5 | #ifndef RTMPPUSH_JAVACALLBACK_H 6 | #define RTMPPUSH_JAVACALLBACK_H 7 | 8 | #define THREAD_MAIN 1 9 | #define THREAD_CHILD 2 10 | 11 | 12 | //rtmp 初始化失败 13 | #define RTMP_INIT_ERROR -9 14 | //设置 rtmp url 失败 15 | #define RTMP_SET_URL_ERROR -10 16 | //连接服务器失败 17 | #define RTMP_CONNECT_ERROR -11 18 | //RTMP 关闭成功 19 | #define RTMP_CLOSE -12 20 | 21 | 22 | 23 | #include 24 | 25 | class JavaCallback { 26 | 27 | public: 28 | JNIEnv *jniEnv = 0; 29 | JavaVM *javaVM = 0; 30 | jobject jobject1; 31 | 32 | jmethodID jmid_connecting; 33 | jmethodID jmid_success; 34 | jmethodID jmid_close; 35 | jmethodID jmid_fail; 36 | 37 | public: 38 | JavaCallback(JavaVM *vm, JNIEnv *env, jobject obj); 39 | 40 | ~JavaCallback(); 41 | 42 | /** 43 | * 开始链接 44 | */ 45 | void onConnecting(int threadType); 46 | 47 | /** 48 | * 链接成功 49 | */ 50 | void onConnectSuccess(); 51 | 52 | /** 53 | * 链接失败 54 | */ 55 | void onConnectFail(int errorCode); 56 | void onClose(int errorCode); 57 | 58 | }; 59 | 60 | 61 | #endif //RTMPPUSH_JAVACALLBACK_H 62 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/stream/amf/AmfNull.java: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.stream.amf; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | 7 | /** 8 | * @Title: AmfNull 9 | * @Package com.jimfengfly.rtmppublisher.amf 10 | * @Description: 11 | * @Author Jim 12 | * @Date 2016/11/28 13 | * @Time 下午12:51 14 | * @Version 15 | */ 16 | 17 | public class AmfNull implements AmfData { 18 | public static final int SIZE = 1; 19 | 20 | @Override 21 | public void writeTo(OutputStream out) throws IOException { 22 | out.write(AmfType.NULL.getValue()); 23 | } 24 | 25 | @Override 26 | public void readFrom(InputStream in) throws IOException { 27 | // Skip data type byte (we assume it's already read) 28 | } 29 | 30 | public static void writeNullTo(OutputStream out) throws IOException { 31 | out.write(AmfType.NULL.getValue()); 32 | } 33 | 34 | @Override 35 | public int getSize() { 36 | return SIZE; 37 | } 38 | 39 | @Override 40 | public byte[] getBytes() { 41 | byte[] data = new byte[1]; 42 | data[0] = AmfType.NULL.getValue(); 43 | return data; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/camera/CameraData.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.camera 2 | 3 | /** 4 | *
 5 |  *     author  : devyk on 2020-05-28 23:18
 6 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 7 |  *     github  : https://github.com/yangkun19921001
 8 |  *     mailbox : yang1001yk@gmail.com
 9 |  *     desc    : This is CameraData
10 |  * 
11 | */ 12 | class CameraData { 13 | 14 | var cameraID: Int = 0 //camera的id 15 | var cameraFacing: Int = 0 //区分前后摄像头 16 | var cameraWidth: Int = 0 //camera的宽度 17 | var cameraHeight: Int = 0 //camera的高度 18 | var hasLight: Boolean = false 19 | var orientation: Int = 0 20 | var supportTouchFocus: Boolean = false 21 | var touchFocusMode: Boolean = false 22 | 23 | constructor(id: Int, facing: Int, width: Int, height: Int) { 24 | cameraID = id 25 | cameraFacing = facing 26 | cameraWidth = width 27 | cameraHeight = height 28 | } 29 | 30 | constructor(id: Int, facing: Int) { 31 | cameraID = id 32 | cameraFacing = facing 33 | } 34 | 35 | companion object { 36 | val FACING_FRONT = 1 37 | val FACING_BACK = 2 38 | } 39 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/stream/amf/AmfUndefined.java: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.stream.amf; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | 7 | /** 8 | * @Title: AmfUndefined 9 | * @Package com.jimfengfly.rtmppublisher.amf 10 | * @Description: 11 | * @Author Jim 12 | * @Date 2016/11/28 13 | * @Time 下午12:53 14 | * @Version 15 | */ 16 | 17 | public class AmfUndefined implements AmfData { 18 | public static final int SIZE = 1; 19 | 20 | @Override 21 | public void writeTo(OutputStream out) throws IOException { 22 | out.write(AmfType.UNDEFINED.getValue()); 23 | } 24 | 25 | @Override 26 | public void readFrom(InputStream in) throws IOException { 27 | // Skip data type byte (we assume it's already read) 28 | } 29 | 30 | public static void writeUndefinedTo(OutputStream out) throws IOException { 31 | out.write(AmfType.UNDEFINED.getValue()); 32 | } 33 | 34 | @Override 35 | public int getSize() { 36 | return SIZE; 37 | } 38 | 39 | @Override 40 | public byte[] getBytes() { 41 | byte[] data = new byte[1]; 42 | data[0] = AmfType.UNDEFINED.getValue(); 43 | return data; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | # AndroidX package structure to make it clearer which packages are bundled with the 20 | # Android operating system, and which are packaged with your app's APK 21 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 22 | android.useAndroidX=true 23 | # Automatically convert third-party libraries to use AndroidX 24 | android.enableJetifier=true 25 | 26 | # Kotlin code style for this project: "official" or "obsolete": 27 | kotlin.code.style=official 28 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/stream/packer/Packer.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.stream.packer 2 | 3 | import com.devyk.av.rtmp.library.stream.PacketType 4 | import android.media.MediaCodec 5 | import java.nio.ByteBuffer 6 | 7 | 8 | /** 9 | *
10 |  *     author  : devyk on 2020-07-16 21:24
11 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
12 |  *     github  : https://github.com/yangkun19921001
13 |  *     mailbox : yang1001yk@gmail.com
14 |  *     desc    : This is Packer 对音视频数据打包
15 |  * 
16 | */ 17 | public interface Packer { 18 | interface OnPacketListener { 19 | fun onPacket(byteArray: ByteArray, packetType: PacketType) 20 | fun onPacket(sps: ByteArray?,pps: ByteArray?, packetType: PacketType){} 21 | } 22 | 23 | /** 24 | * 设置打包监听器 25 | */ 26 | fun setPacketListener(packetListener: OnPacketListener) 27 | 28 | /** 29 | *处理视频硬编编码器输出的数据 30 | */ 31 | fun onVideoData(bb: ByteBuffer?, bi: MediaCodec.BufferInfo?) 32 | 33 | /** 34 | * 处理音频硬编编码器输出的数据 35 | * */ 36 | fun onAudioData(bb: ByteBuffer, bi: MediaCodec.BufferInfo) 37 | 38 | /** 39 | * 处理视频 SPS PPS 数据 40 | */ 41 | fun onVideoSpsPpsData(sps: ByteArray, pps: ByteArray, spsPps: PacketType) { 42 | 43 | } 44 | 45 | 46 | fun start(); 47 | fun stop(); 48 | } 49 | -------------------------------------------------------------------------------- /library/src/main/cpp/common/PushProxy.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 阳坤 on 2020-07-17. 3 | // 4 | 5 | #include "PushProxy.h" 6 | 7 | 8 | IPush *PushProxy::getPushEngine() { 9 | return this->rtmpPush; 10 | } 11 | 12 | PushProxy::PushProxy() { 13 | } 14 | 15 | 16 | PushProxy *PushProxy::getInstance() { 17 | static PushProxy proxy[1]; 18 | return &proxy[0]; 19 | } 20 | 21 | void PushProxy::init(const char *url, JavaCallback **javaCallback) { 22 | this->url = url; 23 | this->javaCallback = *javaCallback; 24 | this->rtmpPush = new RTMPPush(url, javaCallback); 25 | } 26 | 27 | void PushProxy::start() { 28 | getPushEngine()->start(); 29 | } 30 | 31 | void PushProxy::stop() { 32 | if (getPushEngine()) { 33 | getPushEngine()->stop(); 34 | delete (this->getPushEngine()); 35 | } 36 | 37 | if (javaCallback) { 38 | delete (javaCallback); 39 | } 40 | 41 | 42 | 43 | } 44 | 45 | void PushProxy::pushSpsPps(uint8_t *sps, int sps_len, uint8_t *pps, int pps_len) { 46 | getPushEngine()->pushSpsPps(sps, sps_len, pps, pps_len); 47 | } 48 | 49 | 50 | 51 | void PushProxy::pushVideoData(uint8_t *video, int len, int keyframe) { 52 | getPushEngine()->pushVideoData(video, len, keyframe); 53 | } 54 | 55 | void PushProxy::pushAudioData(uint8_t *audio, int len, int type) { 56 | getPushEngine()->pushAudioData(audio, len,type); 57 | } 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/stream/amf/AmfType.java: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.stream.amf; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @Title: AmfType 8 | * @Package com.jimfengfly.rtmppublisher.amf 9 | * @Description: 10 | * @Author Jim 11 | * @Date 2016/11/28 12 | * @Time 上午11:13 13 | * @Version 14 | */ 15 | 16 | public enum AmfType { 17 | /** Number (encoded as IEEE 64-bit double precision floating point number) */ 18 | NUMBER(0x00), 19 | /** Boolean (Encoded as a single byte of value 0x00 or 0x01) */ 20 | BOOLEAN(0x01), 21 | /** String (ASCII encoded) */ 22 | STRING(0x02), 23 | /** Object - set of key/value pairs */ 24 | OBJECT(0x03), 25 | NULL(0x05), 26 | UNDEFINED(0x06), 27 | MAP(0x08), 28 | ARRAY(0x0A); 29 | private byte value; 30 | private static final Map quickLookupMap = new HashMap(); 31 | 32 | static { 33 | for (AmfType amfType : AmfType.values()) { 34 | quickLookupMap.put(amfType.getValue(), amfType); 35 | } 36 | } 37 | 38 | private AmfType(int intValue) { 39 | this.value = (byte) intValue; 40 | } 41 | 42 | public byte getValue() { 43 | return value; 44 | } 45 | 46 | public static AmfType valueOf(byte amfTypeByte) { 47 | return quickLookupMap.get(amfTypeByte); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/mediacodec/AudioEncoder.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.mediacodec 2 | 3 | import android.media.MediaCodec 4 | import android.media.MediaFormat 5 | import com.devyk.av.rtmp.library.callback.OnAudioEncodeListener 6 | import com.devyk.av.rtmp.library.config.AudioConfiguration 7 | import java.nio.ByteBuffer 8 | 9 | /** 10 | *
11 |  *     author  : devyk on 2020-06-13 16:08
12 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
13 |  *     github  : https://github.com/yangkun19921001
14 |  *     mailbox : yang1001yk@gmail.com
15 |  *     desc    : This is AudioEncoder AAC 编码
16 |  * 
17 | */ 18 | 19 | class AudioEncoder(private val mAudioConfiguration: AudioConfiguration?) : BaseAudioCodec(mAudioConfiguration) { 20 | 21 | override fun onAudioOutformat(outputFormat: MediaFormat?) { 22 | mListener?.onAudioOutformat(outputFormat) 23 | } 24 | 25 | public var mListener: OnAudioEncodeListener? = null 26 | 27 | override fun onAudioData(bb: ByteBuffer, bi: MediaCodec.BufferInfo) { 28 | mListener?.onAudioEncode(bb, bi) 29 | } 30 | 31 | fun setOnAudioEncodeListener(listener: OnAudioEncodeListener?) { 32 | mListener = listener 33 | } 34 | 35 | 36 | override fun start() { 37 | super.start() 38 | } 39 | 40 | override fun stop() { 41 | super.stop() 42 | mListener = null 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/mediacodec/VideoEncoder.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.mediacodec 2 | 3 | import android.media.MediaCodec 4 | import android.media.MediaFormat 5 | import com.devyk.av.rtmp.library.callback.OnVideoEncodeListener 6 | import com.devyk.av.rtmp.library.config.VideoConfiguration 7 | 8 | import java.nio.ByteBuffer 9 | 10 | /** 11 | *
12 |  *     author  : devyk on 2020-07-09 22:57
13 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
14 |  *     github  : https://github.com/yangkun19921001
15 |  *     mailbox : yang1001yk@gmail.com
16 |  *     desc    : This is H264Encoder
17 |  * 
18 | */ 19 | public open class VideoEncoder : BaseVideoEncoder() { 20 | 21 | 22 | override fun onVideoOutformat(outputFormat: MediaFormat?) { 23 | mListener?.onVideoOutformat(outputFormat) 24 | } 25 | 26 | override fun prepare(videoConfiguration: VideoConfiguration) { 27 | super.prepare(videoConfiguration) 28 | } 29 | 30 | 31 | private var mListener: OnVideoEncodeListener? = null 32 | 33 | /** 34 | * 视频编码完成的回调 35 | */ 36 | override fun onVideoEncode(bb: ByteBuffer?, bi: MediaCodec.BufferInfo) { 37 | mListener?.onVideoEncode(bb!!, bi) 38 | } 39 | 40 | /** 41 | * 设置编码回调 42 | */ 43 | fun setOnVideoEncodeListener(listener: OnVideoEncodeListener) { 44 | mListener = listener 45 | } 46 | 47 | 48 | } -------------------------------------------------------------------------------- /library/src/main/cpp/common/PushProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 阳坤 on 2020-07-17. 3 | // 4 | 5 | #ifndef RTMPPUSH_PUSHPROXY_H 6 | #define RTMPPUSH_PUSHPROXY_H 7 | 8 | #include "../push/RTMPPush.h" 9 | #include "IPush.h" 10 | 11 | class PushProxy { 12 | 13 | private: 14 | 15 | RTMPPush *rtmpPush = 0; 16 | /** 17 | * 拿到推流的实体类 18 | * @return 19 | */ 20 | IPush *getPushEngine(); 21 | 22 | 23 | public: 24 | PushProxy(); 25 | 26 | static PushProxy * getInstance(); 27 | 28 | 29 | 30 | 31 | void init(const char*url,JavaCallback ** javaCallback); 32 | 33 | const char *url = 0; 34 | JavaCallback *javaCallback = 0; 35 | 36 | 37 | 38 | /** 39 | * 开启线程 40 | */ 41 | void start() ; 42 | 43 | /** 44 | * 停止推流 45 | */ 46 | void stop() ; 47 | 48 | 49 | 50 | /** 51 | * 推送视频第一帧 SPS PPS 数据 52 | * @param sps 53 | * @param sps_len 54 | * @param pps 55 | * @param pps_len 56 | */ 57 | void pushSpsPps(uint8_t *sps, int sps_len, uint8_t *pps, int pps_len) ; 58 | 59 | /** 60 | * 推送音频数据 61 | * @param audio 62 | * @param len 63 | */ 64 | void pushAudioData(uint8_t *audio, int len,int type) ; 65 | 66 | /** 67 | * 推送视频数据 68 | * @param video 69 | * @param len 70 | * @param keyframe 71 | */ 72 | void pushVideoData(uint8_t *video, int len, int keyframe) ; 73 | 74 | }; 75 | 76 | 77 | #endif //RTMPPUSH_PUSHPROXY_H 78 | -------------------------------------------------------------------------------- /library/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | #配置 librtmp 库的路径 4 | set(LIBRTMP_ROOT_PATH ${CMAKE_SOURCE_DIR}/librtmp) 5 | set(JNI_ROOT_PATH ${CMAKE_SOURCE_DIR}/jni) 6 | set(PUSH_ROOT_PATH ${CMAKE_SOURCE_DIR}/push) 7 | set(COMMON_ROOT_PATH ${CMAKE_SOURCE_DIR}/common) 8 | set(CALLBACK_ROOT_PATH ${CMAKE_SOURCE_DIR}/callback) 9 | 10 | #librtmp H 文件 11 | include_directories(${LIBRTMP_ROOT_PATH}/include) 12 | #push H 文件 13 | include_directories(${PUSH_ROOT_PATH}) 14 | #JNI H 文件 15 | include_directories(${JNI_ROOT_PATH}) 16 | #核心库 H 文件 17 | include_directories(${COMMON_ROOT_PATH}) 18 | #Java callback 19 | include_directories(${CALLBACK_ROOT_PATH}) 20 | 21 | 22 | #jni cpp 文件 23 | FILE(GLOB JNI_ALL_CPP ${JNI_ROOT_PATH}/*.cpp) 24 | #push cpp 文件 25 | FILE(GLOB PUSH_ALL_CPP ${PUSH_ROOT_PATH}/*.cpp) 26 | #核心库 cpp 文件 27 | FILE(GLOB COMMON_ALL_CPP ${COMMON_ROOT_PATH}/*.cpp) 28 | #callback 29 | FILE(GLOB CALLBACK_ALL_CPP ${CALLBACK_ROOT_PATH}/*.cpp) 30 | 31 | 32 | add_library( 33 | AVRtmpPush 34 | SHARED 35 | ${JNI_ALL_CPP} 36 | ${PUSH_ALL_CPP} 37 | ${COMMON_ALL_CPP} 38 | ${CALLBACK_ALL_CPP} 39 | ) 40 | 41 | #librtmp 静态库 42 | add_library(rtmp STATIC IMPORTED) 43 | set_target_properties(rtmp PROPERTIES IMPORTED_LOCATION ${LIBRTMP_ROOT_PATH}/libs/${CMAKE_ANDROID_ARCH_ABI}/librtmp.a) 44 | 45 | 46 | 47 | 48 | find_library(log-lib log) 49 | 50 | target_link_libraries( 51 | AVRtmpPush 52 | rtmp 53 | ${log-lib} 54 | ) -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/black/BlackListHelper.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.black 2 | 3 | import android.os.Build 4 | import android.text.TextUtils 5 | import java.util.* 6 | 7 | /** 8 | *
 9 |  *     author  : devyk on 2020-06-14 22:11
10 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
11 |  *     github  : https://github.com/yangkun19921001
12 |  *     mailbox : yang1001yk@gmail.com
13 |  *     desc    : This is BlackListHelper
14 |  * 
15 | */ 16 | 17 | object BlackListHelper { 18 | private val BLACKLISTED_AEC_MODELS = arrayOf("Nexus 5")// Nexus 5 19 | 20 | private val BLACKLISTED_FPS_MODELS = arrayOf("OPPO R9", "Nexus 6P") 21 | 22 | 23 | fun deviceInAecBlacklisted(): Boolean { 24 | val blackListedModels = Arrays.asList(*BLACKLISTED_AEC_MODELS) 25 | for (blackModel in blackListedModels) { 26 | val model = Build.MODEL 27 | if (!TextUtils.isEmpty(model) && model.contains(blackModel)) { 28 | return true 29 | } 30 | } 31 | return false 32 | } 33 | 34 | fun deviceInFpsBlacklisted(): Boolean { 35 | val blackListedModels = Arrays.asList(*BLACKLISTED_FPS_MODELS) 36 | for (blackModel in blackListedModels) { 37 | val model = Build.MODEL 38 | if (!TextUtils.isEmpty(model) && model.contains(blackModel)) { 39 | return true 40 | } 41 | } 42 | return false 43 | } 44 | } -------------------------------------------------------------------------------- /library/src/main/java/com/devyk/av/rtmp/library/common/ThreadImpl.kt: -------------------------------------------------------------------------------- 1 | package com.devyk.av.rtmp.library.common 2 | 3 | import com.devyk.av.rtmp.library.utils.LogHelper 4 | 5 | /** 6 | *
 7 |  *     author  : devyk on 2020-07-15 20:48
 8 |  *     blog    : https://juejin.im/user/578259398ac2470061f3a3fb/posts
 9 |  *     github  : https://github.com/yangkun19921001
10 |  *     mailbox : yang1001yk@gmail.com
11 |  *     desc    : This is ThreadImpl
12 |  * 
13 | */ 14 | public open class ThreadImpl : IThread { 15 | 16 | private var isPause = false 17 | 18 | private var isRuning = false 19 | 20 | private var TAG = javaClass.simpleName 21 | 22 | 23 | override fun start(main: () -> Unit) { 24 | if (isRuning())return 25 | isRuning = true 26 | isPause = false 27 | Thread { 28 | main() 29 | LogHelper.d(TAG, "thread start!") 30 | }.start() 31 | } 32 | 33 | /** 34 | * 线程停止 35 | */ 36 | override fun stop() { 37 | isRuning = false 38 | isPause = true 39 | LogHelper.d(TAG, "thread stop!") 40 | } 41 | 42 | /** 43 | * 设置停止 44 | */ 45 | override fun setPause(pause: Boolean) { 46 | this.isPause = pause 47 | LogHelper.d(TAG, "thread pause:${pause}!") 48 | } 49 | 50 | /** 51 | * 是否停止 52 | */ 53 | override fun isPause(): Boolean = isPause 54 | 55 | 56 | /** 57 | * 是否执行 58 | */ 59 | override fun isRuning(): Boolean = isRuning 60 | 61 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/address_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 26 | 27 |