├── .gitignore
├── LICENSE
├── README.md
├── README_en.md
├── app
├── .gitignore
├── build.gradle
├── libs
│ └── rtmpx-1.0.3.aar
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── rtmpx
│ │ └── app
│ │ ├── config
│ │ └── Const.java
│ │ ├── ui
│ │ ├── MainActivity.java
│ │ └── PublishPreferenceActivity.java
│ │ ├── utils
│ │ └── Utils.java
│ │ └── widget
│ │ ├── FocusView.java
│ │ └── VerticalSeekBar.java
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ ├── ic_baseline_brightness_6_24.xml
│ ├── ic_baseline_cameraswitch_24.xml
│ ├── ic_baseline_lock_24.xml
│ ├── ic_baseline_lock_open_24.xml
│ ├── ic_baseline_settings_24.xml
│ ├── ic_circle_solid.xml
│ ├── ic_circle_stroke.xml
│ ├── ic_circle_stroke_0_8dp.xml
│ ├── ic_divider_0_5dp.xml
│ ├── ic_launcher_background.xml
│ ├── ic_sun_24dp.xml
│ ├── round_corner_grey_5dp.xml
│ └── selector_exposure_lock_unlock.xml
│ ├── layout
│ ├── activity_main.xml
│ ├── activity_publish_setting.xml
│ ├── vr_view_exposure.xml
│ └── vr_view_focus.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── 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-night
│ └── themes.xml
│ ├── values-zh-rCN
│ └── values.xml
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── themes.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── rtmpx_library
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── cpp
│ ├── CMakeLists.txt
│ ├── flvmuxer
│ │ ├── xiecc_rtmp.c
│ │ └── xiecc_rtmp.h
│ ├── librtmp-jni.c
│ ├── librtmp-jni.h
│ ├── librtmp
│ │ ├── COPYING
│ │ ├── Makefile
│ │ ├── amf.c
│ │ ├── amf.h
│ │ ├── bytes.h
│ │ ├── dh.h
│ │ ├── dhgroups.h
│ │ ├── handshake.h
│ │ ├── hashswf.c
│ │ ├── http.h
│ │ ├── librtmp.3
│ │ ├── librtmp.3.html
│ │ ├── librtmp.pc.in
│ │ ├── log.c
│ │ ├── log.h
│ │ ├── parseurl.c
│ │ ├── rtmp.c
│ │ ├── rtmp.h
│ │ └── rtmp_sys.h
│ ├── rtmpmuxer.c
│ ├── yuv
│ │ ├── libyuv.h
│ │ └── libyuv
│ │ │ ├── basic_types.h
│ │ │ ├── compare.h
│ │ │ ├── compare_row.h
│ │ │ ├── convert.h
│ │ │ ├── convert_argb.h
│ │ │ ├── convert_from.h
│ │ │ ├── convert_from_argb.h
│ │ │ ├── cpu_id.h
│ │ │ ├── macros_msa.h
│ │ │ ├── mjpeg_decoder.h
│ │ │ ├── planar_functions.h
│ │ │ ├── rotate.h
│ │ │ ├── rotate_argb.h
│ │ │ ├── rotate_row.h
│ │ │ ├── row.h
│ │ │ ├── scale.h
│ │ │ ├── scale_argb.h
│ │ │ ├── scale_row.h
│ │ │ ├── version.h
│ │ │ └── video_common.h
│ └── yuv_convert.cpp
│ ├── java
│ └── com
│ │ └── rtmpx
│ │ └── library
│ │ ├── camera
│ │ ├── ICamera.java
│ │ ├── ICameraPreviewCallback.java
│ │ └── widget
│ │ │ └── CameraXImplView.java
│ │ ├── config
│ │ ├── Config.java
│ │ └── Const.java
│ │ ├── encode
│ │ ├── AudioEncoder.java
│ │ ├── Encoder.java
│ │ └── VideoEncoder.java
│ │ ├── publish
│ │ ├── IPublishListener.java
│ │ ├── PublisherX.java
│ │ └── RTMPPublisher.java
│ │ ├── record
│ │ ├── audio
│ │ │ └── AudioRecorder.java
│ │ └── video
│ │ │ └── VideoRecorder.java
│ │ ├── rtmp
│ │ ├── RTMPFrame.java
│ │ ├── RTMPMuxer.java
│ │ └── RtmpClient.java
│ │ ├── utils
│ │ └── ConvertUtils.java
│ │ └── yuv
│ │ ├── YuvFrame.java
│ │ └── YuvHelper.java
│ └── jniLibs
│ ├── arm64-v8a
│ └── libyuv.so
│ └── armeabi-v7a
│ └── libyuv.so
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 | /.idea/
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RTMPX
2 |
3 | [English doc][1]
4 |
5 | [1]: https://github.com/luohaohaha/RTMPX/blob/dev/README_en.md
6 |
7 | RTMPX是一个android的rtmp推流库,采集使用camerax,支持60fps,编码使用mediacodec硬编码,推流使用了librtmp。
8 |
9 | https://user-images.githubusercontent.com/3376376/145600890-4abd9b30-ba70-4f04-b1ca-1409be121838.mp4
10 |
11 |
12 | https://user-images.githubusercontent.com/3376376/145600918-9c88f7b4-5ed5-4bde-9ec9-36c10fa07d81.mp4
13 |
14 |
15 | ### 支持的功能
16 | - [x] 60帧预览、推流(理论上支持更高,只要手机支持,目前pixel2最高设置240fps,但是没效果)
17 | - [x] 边推流边录制(保存到本地)
18 |
19 | ### 已知问题
20 | - [x] 部分机型在竖屏推流60fps的时候性能不够,导致libyuv旋转需要很长时间(例如pixel2,I帧旋转要12ms),导致达不到60fps
21 | - [x] 等你发现
22 |
23 | ### 待优化
24 | - [ ] 添加注释
25 | - [ ] 支持滤镜
26 | - [ ] 竖屏libyuv旋转时长优化
27 |
28 | ### 怎么使用(参考示例app)
29 | #### 1. 依赖
30 |
31 | ##### 1) 下载aar(这种集成aar文件的方式,camerax库是必须依赖)
32 | ```
33 | def camerax_version = "1.0.0"
34 | // CameraX core library using camera2 implementation
35 | implementation "androidx.camera:camera-camera2:$camerax_version"
36 | // CameraX Lifecycle Library
37 | implementation "androidx.camera:camera-lifecycle:$camerax_version"
38 | // CameraX View class
39 | implementation "androidx.camera:camera-view:1.0.0-alpha24"
40 | ```
41 | or
42 |
43 | ##### 2) mavenCentral远程依赖
44 | ```
45 | implementation 'io.github.luohaohaha:rtmpx:latest'
46 | ```
47 |
48 |
49 | #### 2. 将CameraXImplView 放入布局
50 |
51 | ```
52 | ...
53 |
57 | ...
58 | ```
59 |
60 | #### 3. 设置推流配置
61 | ```
62 | Config config = new Config.ConfigBuilder()
63 | .withBitRate(1000 * 5000) //码率
64 | .withPublishUrl("rtmp://192.168.50.170:18888/test/live") //推流url
65 | .withFrameRate(60)//帧率
66 | .withVideoWidth(1080)//视频宽
67 | .withVideoHeight(1920) //视频高
68 | .withRecordVideo(false)//是否录制
69 | .withRecordVideoPath("sdcard/dump.mp4")//录制文件保存文件
70 | .build();
71 | ```
72 |
73 | #### 4. 绑定预览控件
74 |
75 | ```
76 | CameraXImplView mPreview = findViewById(R.id.preview);
77 | mPreview.setPreviewRange(mConfig.getFrameRate(),mConfig.getFrameRate());
78 | mPreview.setTargetResolution(mConfig.getVideoWidth(), mConfig.getVideoHeight());
79 |
80 | PublisherX mPublisher = new PublisherX(mConfig);
81 | mPublisher.bindCamera(mPreview);
82 | mPublisher.setPublishListener(this);
83 |
84 | ```
85 |
86 | #### 5. 开启预览 & 开始推流 / 停止预览 & 停止推流
87 |
88 | ```
89 | mPreview.startPreview();
90 | mPublisher.startPublish();
91 | ```
92 |
93 | or
94 |
95 | ```
96 | mPreview.stopPreview();
97 | mPublisher.stopPublish();
98 | ```
99 |
100 |
101 |
102 |
103 | ### IPublishListener 回调
104 |
105 | ```
106 | /**
107 | * rtmp连接中
108 | */
109 | void onConnecting();
110 |
111 | /**
112 | * rtmp 连接建立成功
113 | */
114 | void onConnected();
115 |
116 | /**
117 | * rtmp 连接失败
118 | * @param code error code 失败错误码
119 | */
120 | void onConnectedFailed(int code);
121 |
122 | /**
123 | * 开始推流
124 | */
125 | void onStartPublish();
126 |
127 | /**
128 | * 结束推流
129 | */
130 | void onStopPublish();
131 |
132 | /**
133 | * 开始录制
134 | */
135 | void onStartRecord();
136 |
137 | /**
138 | * 结束录制
139 | */
140 | void onStopRecord();
141 |
142 | /**
143 | * 发送平均帧率统计(带宽不足的情况下会低于设置帧率)
144 | * @param fps avg fps
145 | */
146 | void onFpsStatistic(int fps);
147 |
148 | /**
149 | * rtmp 断开连接
150 | */
151 | void onRtmpDisconnect();
152 | ```
153 |
154 |
155 |
156 | ## Thanks
157 | [LibRtmp-Client-for-Android][2]
158 |
159 | [2]: https://github.com/ant-media/LibRtmp-Client-for-Android
160 |
161 |
--------------------------------------------------------------------------------
/README_en.md:
--------------------------------------------------------------------------------
1 | # RTMPX
2 |
3 |
4 | RTMPX is an android rtmp streaming library. It uses camerax for acquisition and supports 60fps. The encoding uses mediacodec hard coding, and the streaming uses librtmp.
5 |
6 |
7 |
8 | https://user-images.githubusercontent.com/3376376/145600890-4abd9b30-ba70-4f04-b1ca-1409be121838.mp4
9 |
10 |
11 | https://user-images.githubusercontent.com/3376376/145600918-9c88f7b4-5ed5-4bde-9ec9-36c10fa07d81.mp4
12 |
13 |
14 | ### Features
15 | - [x] 60-frame preview and streaming (theoretically support higher, as long as the phone supports it, the current pixel2 is set to 240fps, but it has no effect)
16 | - [x] Streaming while recording (save to local)
17 |
18 | ### Known issues
19 | - [x] Some models have insufficient performance when pushing 60fps in the vertical screen, which causes libyuv rotation to take a long time (for example, pixel2, I frame rotation takes 12ms), resulting in failure to reach 60fps
20 | - [x] Waiting for you to find out
21 |
22 | ### To be optimized
23 | - [ ] add notes
24 | - [ ] support filters
25 | - [ ] optimization of vertical screen libyuv rotation
26 |
27 | ### How to use(Refer to sample app)
28 | #### 1. Depend
29 |
30 | ##### 1) Download aar (this way of integrating aar files, the camerax library is a must)
31 | ```
32 | def camerax_version = "1.0.0"
33 | // CameraX core library using camera2 implementation
34 | implementation "androidx.camera:camera-camera2:$camerax_version"
35 | // CameraX Lifecycle Library
36 | implementation "androidx.camera:camera-lifecycle:$camerax_version"
37 | // CameraX View class
38 | implementation "androidx.camera:camera-view:1.0.0-alpha24"
39 | ```
40 | or
41 |
42 | ##### 2) mavenCentral()
43 | ```
44 | implementation 'io.github.luohaohaha:rtmpx:latest'
45 | ```
46 |
47 |
48 | #### 2. Put CameraXImplView in the xml layout
49 |
50 | ```
51 | ...
52 |
56 | ...
57 | ```
58 |
59 | #### 3. set publish config
60 | ```
61 | Config config = new Config.ConfigBuilder()
62 | .withBitRate(1000 * 5000) //bitrate
63 | .withPublishUrl("rtmp://192.168.50.170:18888/test/live") //publish url
64 | .withFrameRate(60)//fps
65 | .withVideoWidth(1080)//width
66 | .withVideoHeight(1920) //height
67 | .withRecordVideo(false)//record video
68 | .withRecordVideoPath("sdcard/dump.mp4")//path
69 | .build();
70 | ```
71 |
72 | #### 4. bind camera preview
73 |
74 | ```
75 | CameraXImplView mPreview = findViewById(R.id.preview);
76 | mPreview.setPreviewRange(mConfig.getFrameRate(),mConfig.getFrameRate());
77 | mPreview.setTargetResolution(mConfig.getVideoWidth(), mConfig.getVideoHeight());
78 |
79 | PublisherX mPublisher = new PublisherX(mConfig);
80 | mPublisher.bindCamera(mPreview);
81 | mPublisher.setPublishListener(this);
82 |
83 | ```
84 |
85 | #### 5. start preview & start publish
86 |
87 | ```
88 | mPreview.startPreview();
89 | mPublisher.startPublish();
90 | ```
91 |
92 | or
93 |
94 | ```
95 | mPreview.stopPreview();
96 | mPublisher.stopPublish();
97 | ```
98 |
99 |
100 |
101 |
102 | ### IPublishListener Callback
103 |
104 | ```
105 | /**
106 | * rtmp is connecting
107 | */
108 | void onConnecting();
109 |
110 | /**
111 | * rtmp connection is successful
112 | */
113 | void onConnected();
114 |
115 | /**
116 | * rtmp connection failed
117 | * @param code error code
118 | */
119 | void onConnectedFailed(int code);
120 |
121 | /**
122 | * Start publishing
123 | */
124 | void onStartPublish();
125 |
126 | /**
127 | * Stop publishing
128 | */
129 | void onStopPublish();
130 |
131 | /**
132 | * Start recording
133 | */
134 | void onStartRecord();
135 |
136 | /**
137 | * Stop recording
138 | */
139 | void onStopRecord();
140 |
141 | /**
142 | * fps statistics
143 | * @param fps avg fps
144 | */
145 | void onFpsStatistic(int fps);
146 |
147 | /**
148 | * rtmp disconnect
149 | */
150 | void onRtmpDisconnect();
151 | ```
152 |
153 |
154 |
155 | ## Thanks
156 | [LibRtmp-Client-for-Android][1]
157 |
158 | [1]: https://github.com/ant-media/LibRtmp-Client-for-Android
159 |
160 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | }
4 |
5 | android {
6 | compileSdkVersion 30
7 | buildToolsVersion "30.0.3"
8 |
9 | defaultConfig {
10 | applicationId "com.rtmpx.app"
11 | minSdkVersion 21
12 | targetSdkVersion 29
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | compileOptions {
25 | sourceCompatibility JavaVersion.VERSION_1_8
26 | targetCompatibility JavaVersion.VERSION_1_8
27 | }
28 |
29 | repositories {
30 | flatDir {
31 | dirs 'libs'
32 | }
33 | }
34 | }
35 |
36 | dependencies {
37 |
38 | implementation 'com.google.android.material:material:1.4.0'
39 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
40 | // implementation project(path: ':rtmpx_library')
41 | implementation 'io.github.luohaohaha:rtmpx:1.0.3'
42 |
43 |
44 | /* implementation(name:"rtmpx-${version}", ext:'aar')
45 |
46 | def camerax_version = "1.0.0"
47 | // CameraX core library using camera2 implementation
48 | implementation "androidx.camera:camera-camera2:$camerax_version"
49 | // CameraX Lifecycle Library
50 | implementation "androidx.camera:camera-lifecycle:$camerax_version"
51 | // CameraX View class
52 | implementation "androidx.camera:camera-view:1.0.0-alpha24"*/
53 | }
--------------------------------------------------------------------------------
/app/libs/rtmpx-1.0.3.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/app/libs/rtmpx-1.0.3.aar
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rtmpx/app/config/Const.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.app.config;
2 |
3 | /**
4 | * Project: RTMPX
5 | * Package: com.rtmpx.app.config
6 | * ClassName: Const
7 | * Description: TODO
8 | * Date: 2023-01-17 19:21
9 | *
10 | * Author luohao
11 | * Version 1.0
12 | * since JDK 1.6
13 | *
14 | */
15 | public class Const {
16 |
17 | public static final String PREFERENCE_PUBLISH_CONFIG = "PublishConfig";
18 | public static final String PREFERENCE_SAVE_CONFIG = "PublishSaveConfig";
19 | public static final String BITRATE = "bitrate";
20 | public static final String PUBLISH_URL = "publishUrl";
21 | public static final String FRAME_RATE = "frameRate";
22 | public static final String WIDTH = "width";
23 | public static final String HEIGHT = "height";
24 | public static final String RECORD = "record";
25 | public static final String RECORD_PATH = "recordPath";
26 | public static final String RESULT = "result";
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rtmpx/app/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.app.utils;
2 |
3 | import android.content.Context;
4 | import android.util.DisplayMetrics;
5 | import android.view.Display;
6 | import android.view.MotionEvent;
7 | import android.view.View;
8 | import android.view.WindowManager;
9 |
10 | import java.lang.reflect.Method;
11 |
12 | public class Utils {
13 |
14 | public static int dip2px(Context context, int dp) {
15 | final float density = context.getResources().getDisplayMetrics().density;
16 | return (int) ((float) dp * density + 0.5f);
17 | }
18 |
19 | private static final DisplayMetrics getRealDisplayMetricsForAndroid40(Context context) {
20 | if (context == null) return null;
21 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
22 | Display display = windowManager.getDefaultDisplay();
23 | DisplayMetrics dm = new DisplayMetrics();
24 |
25 | Class c;
26 | try {
27 | c = Class.forName("android.view.Display");
28 | Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
29 | method.invoke(display, dm);
30 | } catch (Exception e) {
31 | e.printStackTrace();
32 | }
33 | return dm;
34 | }
35 |
36 | public static int getScreenWidth(Context context) {
37 | if (context == null) return -1;
38 | DisplayMetrics displaymetrics = getRealDisplayMetricsForAndroid40(context);
39 | return displaymetrics.widthPixels;
40 | }
41 |
42 | public static int getScreenHeight(Context context) {
43 | if (context == null) return -1;
44 | DisplayMetrics displaymetrics = getRealDisplayMetricsForAndroid40(context);
45 | return displaymetrics.heightPixels;
46 | }
47 |
48 | public static void autoClickOnce(View view) {
49 | if (null == view)
50 | return;
51 | view.post(() -> autoClickOnce(view, getScreenWidth(view.getContext()) / 2, getScreenHeight(view.getContext()) / 2));
52 | }
53 |
54 | public static void autoClickOnce(View view, float x, float y) {
55 | if (null == view)
56 | return;
57 | long downTime = System.currentTimeMillis();
58 | long upTime = downTime + 200;
59 | view.dispatchTouchEvent(obtainEvent(downTime, upTime, x, y, MotionEvent.ACTION_DOWN));
60 | view.dispatchTouchEvent(obtainEvent(downTime, upTime, x, y, MotionEvent.ACTION_UP));
61 | }
62 |
63 | private static MotionEvent obtainEvent(long downTime, long eventTime, float x, float y, int action) {
64 | return MotionEvent.obtain(downTime, eventTime, action, x, y, 0);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rtmpx/app/widget/VerticalSeekBar.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.app.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.os.Build;
6 | import android.util.AttributeSet;
7 | import android.view.MotionEvent;
8 |
9 | import androidx.appcompat.widget.AppCompatSeekBar;
10 |
11 | /**
12 | * Project: android_client
13 | * Package: com.sqtech.client.widget
14 | * ClassName: VerticalSeekBar
15 | * Description: TODO
16 | * Date: 2020/12/17 11:24 AM
17 | *
18 | * Author LuoHao
19 | * Version 1.0
20 | * since JDK 1.6
21 | *
22 | */
23 | public class VerticalSeekBar extends AppCompatSeekBar {
24 |
25 | private int max, min;
26 |
27 | private OnSeekBarChangeListener mSeekBarChangeListener;
28 |
29 | public VerticalSeekBar(Context context) {
30 | super(context);
31 | }
32 |
33 | public VerticalSeekBar(Context context, AttributeSet attrs) {
34 | super(context, attrs);
35 | }
36 |
37 | public VerticalSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
38 | super(context, attrs, defStyleAttr);
39 | }
40 |
41 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
42 | super.onSizeChanged(h, w, oldh, oldw);
43 | }
44 |
45 | @Override
46 | protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
47 | super.onMeasure(heightMeasureSpec, widthMeasureSpec);
48 | setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
49 | }
50 |
51 | protected void onDraw(Canvas c) {
52 | c.rotate(-90);
53 | c.translate(-getHeight(), 0);
54 | super.onDraw(c);
55 | }
56 |
57 | @Override
58 | public synchronized void setProgress(int progress) {
59 | super.setProgress(progress);
60 | onSizeChanged(getWidth(), getHeight(), 0, 0);
61 | }
62 |
63 | public synchronized void setSupportMax(int max) {
64 | this.max = max;
65 | try {
66 | super.setMax(max);
67 | } catch (Exception e) {
68 | e.printStackTrace();
69 | }
70 | }
71 |
72 | public synchronized void setSupportMin(int min) {
73 | this.min = min;
74 | try {
75 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
76 | super.setMin(min);
77 | }
78 | } catch (Exception e) {
79 | e.printStackTrace();
80 | }
81 | }
82 |
83 | @Override
84 | public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {
85 | super.setOnSeekBarChangeListener(l);
86 | this.mSeekBarChangeListener = l;
87 | }
88 |
89 | @Override
90 | public boolean onTouchEvent(MotionEvent event) {
91 | if (!isEnabled()) {
92 | return false;
93 | }
94 | switch (event.getAction()) {
95 | case MotionEvent.ACTION_DOWN:
96 | if(null != mSeekBarChangeListener){
97 | mSeekBarChangeListener.onStartTrackingTouch(this);
98 | }
99 | case MotionEvent.ACTION_MOVE:
100 | float y = event.getY();
101 | int height = getHeight();
102 | int progress = 0;
103 | final int range = max - min;
104 | float scale = y / height;
105 | progress -= scale * range + min;
106 | setProgress(progress);
107 | onSizeChanged(getWidth(), getHeight(), 0, 0);
108 | break;
109 | case MotionEvent.ACTION_UP:
110 | case MotionEvent.ACTION_CANCEL:
111 | if(null != mSeekBarChangeListener){
112 | mSeekBarChangeListener.onStopTrackingTouch(this);
113 | }
114 | break;
115 | }
116 | return true;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_brightness_6_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_cameraswitch_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_lock_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_lock_open_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_settings_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_circle_solid.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_circle_stroke.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_circle_stroke_0_8dp.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_divider_0_5dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sun_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_corner_grey_5dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_exposure_lock_unlock.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
21 |
22 |
28 |
29 |
37 |
38 |
43 |
44 |
45 |
52 |
53 |
61 |
62 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_publish_setting.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
26 |
27 |
38 |
39 |
40 |
47 |
48 |
54 |
55 |
65 |
66 |
67 |
74 |
75 |
81 |
82 |
93 |
94 |
95 |
102 |
103 |
109 |
110 |
120 |
121 |
122 |
129 |
130 |
136 |
137 |
143 |
144 |
145 |
153 |
154 |
160 |
161 |
170 |
171 |
172 |
177 |
178 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/vr_view_exposure.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
18 |
19 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/vr_view_focus.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
23 |
24 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/values.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | app
4 | 码率(kbps)
5 | 请输入推流码率
6 | 推流地址
7 | 请输入推流地址
8 | 推流帧率
9 | 请输入推流帧率
10 | 推流分辨率
11 | 请输入推流分辨率(如:1080x1920)
12 | 录制开关
13 | 是否录制
14 | 录制路径
15 | 请输入录制路径
16 | 保存
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Application
3 | Bitrate(kbps)
4 | Please enter the publish bitrate
5 | Publish url
6 | Please enter the publish address
7 | Publish frame rate
8 | Please enter the publish rate
9 | Publish resolution
10 | Please enter the publish resolution (eg: 1080x1920)
11 | Record switch
12 | whether to record
13 | Record path
14 | Please enter the record path
15 | Save
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath "com.android.tools.build:gradle:4.2.1"
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | google()
18 | mavenCentral()
19 | jcenter() // Warning: this repository is going to shut down soon
20 | }
21 | }
22 |
23 | task clean(type: Delete) {
24 | delete rootProject.buildDir
25 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 |
19 | android.injected.testOnly=false
20 | version=1.0.3
21 | versionCode=3
22 |
23 | signing.keyId=AC245F5F
24 | signing.password=8790141lh
25 | signing.secretKeyRingFile=/Volumes/MacDev/maven/private.pgp
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Jul 21 23:18:16 CST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/rtmpx_library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/rtmpx_library/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | }
4 | //apply from: './publish.gradle'
5 |
6 | android {
7 | compileSdkVersion 30
8 | buildToolsVersion "30.0.3"
9 | def propCode = "${versionCode}".toInteger()
10 | defaultConfig {
11 | minSdkVersion 21
12 | targetSdkVersion 30
13 | versionCode propCode
14 | versionName "${version}"
15 |
16 | ndk {
17 | abiFilters "armeabi-v7a", "arm64-v8a"
18 | }
19 |
20 | externalNativeBuild {
21 | cmake {
22 | arguments "-DANDROID_STL=c++_shared"
23 | }
24 | }
25 | }
26 |
27 | buildTypes {
28 | release {
29 | minifyEnabled false
30 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
31 | }
32 | }
33 | compileOptions {
34 | sourceCompatibility JavaVersion.VERSION_1_8
35 | targetCompatibility JavaVersion.VERSION_1_8
36 | }
37 |
38 | externalNativeBuild {
39 | cmake {
40 | path "src/main/cpp/CMakeLists.txt"
41 | }
42 | }
43 |
44 | packagingOptions {
45 | pickFirst '**/*.so'
46 | }
47 | }
48 |
49 | dependencies {
50 |
51 | implementation "androidx.appcompat:appcompat:1.3.0"
52 | def camerax_version = "1.0.0"
53 | // CameraX core library using camera2 implementation
54 | implementation "androidx.camera:camera-camera2:$camerax_version"
55 | // CameraX Lifecycle Library
56 | implementation "androidx.camera:camera-lifecycle:$camerax_version"
57 | // CameraX View class
58 | implementation "androidx.camera:camera-view:1.0.0-alpha24"
59 | }
60 |
61 | task buildReleaseAAR(type: Copy) {
62 | def libPath = '../app/libs/'
63 | from('build/outputs/aar')
64 | into(libPath)
65 | include('rtmpx_library-release.aar')
66 | rename('rtmpx_library-release.aar', 'rtmpx-' + "${version}" + '.aar')
67 | }
68 |
69 | buildReleaseAAR.dependsOn('assembleRelease')
70 |
71 |
--------------------------------------------------------------------------------
/rtmpx_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
--------------------------------------------------------------------------------
/rtmpx_library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # For more information about using CMake with Android Studio, read the
2 | # documentation: https://d.android.com/studio/projects/add-native-code.html
3 |
4 | # Sets the minimum version of CMake required to build the native library.
5 |
6 | cmake_minimum_required(VERSION 3.4.1)
7 |
8 | # Creates and names a library, sets it as either STATIC
9 | # or SHARED, and provides the relative paths to its source code.
10 | # You can define multiple libraries, and CMake builds them for you.
11 | # Gradle automatically packages shared libraries with your APK.
12 |
13 | add_library( # Sets the name of the library.
14 | rtmpx
15 |
16 | # Sets the library as a shared library.
17 | SHARED
18 |
19 | # Provides a relative path to your source file(s).
20 | flvmuxer/xiecc_rtmp.c
21 | flvmuxer/xiecc_rtmp.c
22 | librtmp/amf.c
23 | librtmp/hashswf.c
24 | librtmp/log.c
25 | librtmp/parseurl.c
26 | librtmp/rtmp.c
27 | librtmp-jni.c
28 | rtmpmuxer.c
29 | yuv_convert.cpp
30 | )
31 |
32 |
33 | include_directories(
34 | ${CMAKE_SOURCE_DIR}/flvmuxer
35 | ${CMAKE_SOURCE_DIR}/librtmp
36 | ${CMAKE_SOURCE_DIR}/yuv/libyuv
37 | ${CMAKE_SOURCE_DIR}/yuv
38 | ${CMAKE_SOURCE_DIR}
39 | ) #包含的头文件,依赖的so库都会提供头文件共使用,必须列出来
40 |
41 | add_definitions(-DNO_CRYPTO)
42 |
43 |
44 | # Searches for a specified prebuilt library and stores the path as a
45 | # variable. Because CMake includes system libraries in the search path by
46 | # default, you only need to specify the name of the public NDK library
47 | # you want to add. CMake verifies that the library exists before
48 | # completing its build.
49 |
50 | add_library(yuv SHARED IMPORTED)
51 | set_target_properties(yuv PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libyuv.so)
52 |
53 | find_library( # Sets the name of the path variable.
54 | log-lib
55 |
56 | # Specifies the name of the NDK library that
57 | # you want CMake to locate.
58 | log)
59 |
60 | # Specifies libraries CMake should link to your target library. You
61 | # can link multiple libraries, such as libraries you define in this
62 | # build script, prebuilt third-party libraries, or system libraries.
63 |
64 |
65 | target_link_libraries( # Specifies the target library.
66 | rtmpx
67 | yuv
68 | # Links the target library to the log library
69 | # included in the NDK.
70 | ${log-lib})
71 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/flvmuxer/xiecc_rtmp.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by faraklit on 08.02.2016.
3 | //
4 |
5 | #ifndef _XRTMP_H_
6 | #define _XRTMP_H_
7 | #include
8 | #include
9 |
10 | #ifdef __cplusplus
11 | extern "C"{
12 | #endif
13 |
14 | #define RTMP_STREAM_PROPERTY_PUBLIC 0x00000001
15 | #define RTMP_STREAM_PROPERTY_ALARM 0x00000002
16 | #define RTMP_STREAM_PROPERTY_RECORD 0x00000004
17 |
18 |
19 | int rtmp_open_for_write(const char *url, uint32_t video_width, uint32_t video_height,uint32_t frame_rate);
20 |
21 | void rtmp_close();
22 |
23 | int rtmp_is_connected();
24 |
25 | // @brief send audio frame
26 | // @param [in] rtmp_sender handler
27 | // @param [in] data : AACAUDIODATA
28 | // @param [in] size : AACAUDIODATA size
29 | // @param [in] dts_us : decode timestamp of frame
30 | int rtmp_sender_write_audio_frame(uint8_t *data,
31 | int size,
32 | uint64_t dts_us,
33 | uint32_t abs_ts);
34 |
35 | // @brief send video frame, now only H264 supported
36 | // @param [in] rtmp_sender handler
37 | // @param [in] data : video data, (Full frames are required)
38 | // @param [in] size : video data size
39 | // @param [in] dts_us : decode timestamp of frame
40 | // @param [in] key : key frame indicate, [0: non key] [1: key]
41 | int rtmp_sender_write_video_frame(uint8_t *data,
42 | int size,
43 | uint64_t dts_us,
44 | int key,
45 | uint32_t abs_ts);
46 |
47 | int rtmp_read_date(uint8_t* data, int size);
48 |
49 | void flv_file_open(const char *filename);
50 |
51 | void flv_file_close();
52 |
53 | void write_flv_header(bool is_have_audio, bool is_have_video);
54 |
55 | #ifdef __cplusplus
56 | }
57 | #endif
58 | #endif
59 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/librtmp-jni.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "librtmp-jni.h"
3 | #include "rtmp.h"
4 | #include
5 | //
6 | // Created by faraklit on 01.01.2016.
7 | //
8 |
9 |
10 | #define LOG_TAG "rtmp-jni"
11 |
12 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
13 |
14 | //RTMP *rtmp = NULL;
15 |
16 | JNIEXPORT jlong JNICALL
17 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeAlloc(JNIEnv* env, jobject thiz) {
18 | RTMP *rtmp = RTMP_Alloc();
19 | return (jlong)rtmp;
20 | }
21 |
22 | /*
23 | * Class: net_butterflytv_rtmp_client_RtmpClient
24 | * Method: open
25 | * Signature: (Ljava/lang/String;)I
26 | */
27 | JNIEXPORT jint JNICALL
28 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeOpen(JNIEnv* env, jobject thiz, jstring url_,
29 | jboolean isPublishMode, jlong rtmpPointer,
30 | jint sendTimeoutInMs, jint receiveTimeoutInMs) {
31 |
32 | const char *url = (*env)->GetStringUTFChars(env, url_, NULL);
33 | RTMP *rtmp = (RTMP *) rtmpPointer;
34 | // rtmp = RTMP_Alloc();
35 | if (rtmp == NULL) {
36 | throwIllegalStateException(env, "RTMP open called without allocating rtmp object");
37 | return RTMP_ERROR_IGNORED;
38 | }
39 |
40 | RTMP_Init(rtmp);
41 | rtmp->Link.receiveTimeoutInMs = receiveTimeoutInMs;
42 | rtmp->Link.sendTimeoutInMs = sendTimeoutInMs;
43 | RTMPResult ret = RTMP_SetupURL(rtmp, url);
44 |
45 | if (ret != RTMP_SUCCESS) {
46 | RTMP_Free(rtmp);
47 | return ret;
48 | }
49 | if (isPublishMode) {
50 | RTMP_EnableWrite(rtmp);
51 | }
52 |
53 | ret = RTMP_Connect(rtmp, NULL);
54 | if (ret != RTMP_SUCCESS) {
55 | RTMP_Free(rtmp);
56 | return ret;
57 | }
58 | ret = RTMP_ConnectStream(rtmp, 0);
59 |
60 | if (ret != RTMP_SUCCESS) {
61 | RTMP_Free(rtmp);
62 | return ret;
63 | }
64 | (*env)->ReleaseStringUTFChars(env, url_, url);
65 | return RTMP_SUCCESS;
66 | }
67 |
68 | /*
69 | * Class: net_butterflytv_rtmp_client_RtmpClient
70 | * Method: read
71 | * Signature: ([CI)I
72 | */
73 | JNIEXPORT jint JNICALL
74 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeRead(JNIEnv* env, jobject thiz, jbyteArray data_,
75 | jint offset, jint size, jlong rtmpPointer) {
76 |
77 | RTMP *rtmp = (RTMP *) rtmpPointer;
78 | if (rtmp == NULL) {
79 | throwIllegalStateException(env, "RTMP open function has to be called before read");
80 | return RTMP_ERROR_IGNORED;
81 | }
82 |
83 | int connected = RTMP_IsConnected(rtmp);
84 | if (!connected) {
85 | return RTMP_ERROR_CONNECTION_LOST;
86 | }
87 |
88 | char* data = malloc(size);
89 |
90 | int readCount = RTMP_Read(rtmp, data, size);
91 |
92 | if (readCount > 0) {
93 | (*env)->SetByteArrayRegion(env, data_, offset, readCount, data); // copy
94 | }
95 | free(data);
96 | return readCount;
97 | }
98 |
99 | /*
100 | * Class: net_butterflytv_rtmp_client_RtmpClient
101 | * Method: write
102 | * Signature: ([CI)I
103 | */
104 | JNIEXPORT jint JNICALL
105 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeWrite(JNIEnv* env, jobject thiz, jbyteArray data,
106 | jint offset, jint size, jlong rtmpPointer) {
107 |
108 | RTMP *rtmp = (RTMP *) rtmpPointer;
109 | if (rtmp == NULL) {
110 | throwIllegalStateException(env, "RTMP open function has to be called before write");
111 | return RTMP_ERROR_IGNORED;
112 | }
113 |
114 | int connected = RTMP_IsConnected(rtmp);
115 | if (!connected) {
116 | return RTMP_ERROR_CONNECTION_LOST;
117 | }
118 |
119 | jbyte* buf = malloc(size);
120 | (*env)->GetByteArrayRegion(env, data, offset, size, buf);
121 | int result = RTMP_Write(rtmp, buf, size);
122 | free(buf);
123 | return result;
124 | }
125 |
126 | /*
127 | * Class: net_butterflytv_rtmp_client_RtmpClient
128 | * Method: seek
129 | * Signature: (I)I
130 | */
131 | JNIEXPORT jint JNICALL
132 | Java_com_rtmpx_library_rtmp_RtmpClient_seek(JNIEnv* env, jobject thiz, jint seekTime) {
133 | return 0;
134 | }
135 |
136 | /*
137 | * Class: net_butterflytv_rtmp_client_RtmpClient
138 | * Method: pause
139 | * Signature: (I)I
140 | */
141 | JNIEXPORT jint JNICALL
142 | Java_com_rtmpx_library_rtmp_RtmpClient_nativePause(JNIEnv* env, jobject thiz, jboolean pause,
143 | jlong rtmpPointer) {
144 |
145 | RTMP *rtmp = (RTMP *) rtmpPointer;
146 | if (rtmp == NULL) {
147 | throwIllegalStateException(env, "RTMP open function has to be called before pause");
148 | return RTMP_ERROR_IGNORED;
149 | }
150 |
151 | return RTMP_Pause(rtmp, pause);
152 | }
153 |
154 | /*
155 | * Class: net_butterflytv_rtmp_client_RtmpClient
156 | * Method: close
157 | * Signature: ()I
158 | */
159 | JNIEXPORT void JNICALL
160 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeClose(JNIEnv* env, jobject thiz, jlong rtmpPointer) {
161 |
162 | RTMP *rtmp = (RTMP *) rtmpPointer;
163 | if (rtmp != NULL) {
164 | RTMP_Close(rtmp);
165 | RTMP_Free(rtmp);
166 | }
167 | }
168 |
169 |
170 | JNIEXPORT jboolean JNICALL
171 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeIsConnected(JNIEnv* env, jobject thiz, jlong rtmpPointer) {
172 | RTMP *rtmp = (RTMP *) rtmpPointer;
173 | if (rtmp == NULL) {
174 | return false;
175 | }
176 | int connected = RTMP_IsConnected(rtmp);
177 | return connected ? true : false;
178 | }
179 |
180 | jint throwIllegalStateException (JNIEnv* env, char* message)
181 | {
182 | jclass exception = (*env)->FindClass(env, "java/lang/IllegalStateException");
183 | return (*env)->ThrowNew(env, exception, message);
184 | }
185 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/librtmp-jni.h:
--------------------------------------------------------------------------------
1 | /* DO NOT EDIT THIS FILE - it is machine generated */
2 | #include
3 | #include
4 | #include "flvmuxer/xiecc_rtmp.h"
5 | /* Header for class com_rtmpx_library_rtmp_RtmpClient */
6 |
7 | #ifndef _Included_com_rtmpx_library_rtmp_RtmpClient
8 | #define _Included_com_rtmpx_library_rtmp_RtmpClient
9 | #ifdef __cplusplus
10 | extern "C" {
11 | #endif
12 |
13 | /*
14 | * Class: com_rtmpx_library_rtmp_RtmpClient
15 | * Method: open
16 | * Signature: (Ljava/lang/String;)I
17 | */
18 | JNIEXPORT jint JNICALL
19 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeOpen(JNIEnv* env, jobject thiz,
20 | jstring url, jboolean isPublishMode,
21 | jlong rtmpPointer, jint sendTimeoutInMs,
22 | jint receiveTimeoutInMs);
23 |
24 | /*
25 | * Class: com_rtmpx_library_rtmp_RtmpClient
26 | * Method: read
27 | * Signature: ([CI)I
28 | */
29 | JNIEXPORT jint JNICALL
30 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeRead(JNIEnv* env, jobject thiz,
31 | jbyteArray data, jint offset, jint size,
32 | jlong rtmpPointer);
33 |
34 | /*
35 | * Class: com_rtmpx_library_rtmp_RtmpClient
36 | * Method: write
37 | * Signature: ([CI)I
38 | */
39 | JNIEXPORT jint JNICALL
40 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeWrite(JNIEnv* env, jobject thiz, jbyteArray data,
41 | jint offset, jint size, jlong rtmpPointer);
42 |
43 | /*
44 | * Class: com_rtmpx_library_rtmp_RtmpClient
45 | * Method: seek
46 | * Signature: (I)I
47 | */
48 | JNIEXPORT jint JNICALL
49 | Java_com_rtmpx_library_rtmp_RtmpClient_seek(JNIEnv* env, jobject thiz, jint seekTime);
50 |
51 | /*
52 | * Class: com_rtmpx_library_rtmp_RtmpClient
53 | * Method: pause
54 | * Signature: (I)I
55 | */
56 | JNIEXPORT jint JNICALL
57 | Java_com_rtmpx_library_rtmp_RtmpClient_nativePause(JNIEnv* env, jobject thiz, jboolean pause,
58 | jlong rtmpPointer);
59 |
60 | /*
61 | * Class: com_rtmpx_library_rtmp_RtmpClient
62 | * Method: close
63 | * Signature: ()I
64 | */
65 | JNIEXPORT void JNICALL
66 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeClose(JNIEnv* env, jobject thiz, jlong rtmpPointer);
67 |
68 | JNIEXPORT jboolean JNICALL
69 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeIsConnected(JNIEnv* env, jobject thiz, jlong rtmpPointer);
70 |
71 | JNIEXPORT void JNICALL
72 | Java_com_rtmpx_library_rtmp_RTMPMuxer_write_1flv_1header(JNIEnv* env, jobject thiz,
73 | jboolean is_have_audio, jboolean is_have_video) {
74 | write_flv_header(is_have_audio, is_have_video);
75 | }
76 |
77 | JNIEXPORT void JNICALL
78 | Java_com_rtmpx_library_rtmp_RTMPMuxer_file_1open(JNIEnv* env, jobject thiz, jstring filename) {
79 | const char *cfilename = (*env)->GetStringUTFChars(env, filename, NULL);
80 |
81 | flv_file_open(cfilename);
82 |
83 | (*env)->ReleaseStringUTFChars(env, filename, cfilename);
84 | }
85 |
86 | JNIEXPORT void JNICALL
87 | Java_com_rtmpx_library_rtmp_RTMPMuxer_file_1close(JNIEnv* env, jobject thiz) {
88 |
89 | flv_file_close();
90 |
91 | }
92 |
93 | JNIEXPORT jlong JNICALL
94 | Java_com_rtmpx_library_rtmp_RtmpClient_nativeAlloc(JNIEnv* env, jobject thiz);
95 |
96 | JNIEXPORT jint JNICALL
97 | Java_com_rtmpx_library_rtmp_RTMPMuxer_read(JNIEnv* env, jobject thiz, jbyteArray data,
98 | jint offset, jint size);
99 |
100 | JNIEXPORT jboolean JNICALL
101 | Java_com_rtmpx_library_rtmp_RTMPMuxer_isConnected(JNIEnv* env, jobject thiz);
102 |
103 | jint throwIllegalStateException (JNIEnv* env, char* message);
104 |
105 | #ifdef __cplusplus
106 | }
107 | #endif
108 | #endif
109 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/librtmp/Makefile:
--------------------------------------------------------------------------------
1 | VERSION=v2.4
2 |
3 | prefix=/usr/local
4 |
5 | incdir=$(prefix)/include/librtmp
6 | bindir=$(prefix)/bin
7 | libdir=$(prefix)/lib
8 | mandir=$(prefix)/man
9 | BINDIR=$(DESTDIR)$(bindir)
10 | INCDIR=$(DESTDIR)$(incdir)
11 | LIBDIR=$(DESTDIR)$(libdir)
12 | MANDIR=$(DESTDIR)$(mandir)
13 |
14 | CC=$(CROSS_COMPILE)gcc
15 | LD=$(CROSS_COMPILE)ld
16 | AR=$(CROSS_COMPILE)ar
17 |
18 | SYS=posix
19 | CRYPTO=OPENSSL
20 | #CRYPTO=GNUTLS
21 | DEF_POLARSSL=-DUSE_POLARSSL
22 | DEF_OPENSSL=-DUSE_OPENSSL
23 | DEF_GNUTLS=-DUSE_GNUTLS
24 | DEF_=-DNO_CRYPTO
25 | REQ_GNUTLS=gnutls
26 | REQ_OPENSSL=libssl,libcrypto
27 | LIBZ=-lz
28 | LIBS_posix=
29 | LIBS_darwin=
30 | LIBS_mingw=-lws2_32 -lwinmm -lgdi32
31 | LIB_GNUTLS=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ)
32 | LIB_OPENSSL=-lssl -lcrypto $(LIBZ)
33 | LIB_POLARSSL=-lpolarssl $(LIBZ)
34 | PRIVATE_LIBS=$(LIBS_$(SYS))
35 | CRYPTO_LIB=$(LIB_$(CRYPTO)) $(PRIVATE_LIBS)
36 | CRYPTO_REQ=$(REQ_$(CRYPTO))
37 | CRYPTO_DEF=$(DEF_$(CRYPTO))
38 |
39 | SO_VERSION=0
40 | SOX_posix=so
41 | SOX_darwin=dylib
42 | SOX_mingw=dll
43 | SOX=$(SOX_$(SYS))
44 | SO_posix=.$(SOX).$(SO_VERSION)
45 | SO_darwin=.$(SO_VERSION).$(SOX)
46 | SO_mingw=-$(SO_VERSION).$(SOX)
47 | SO_EXT=$(SO_$(SYS))
48 |
49 | SODIR_posix=$(LIBDIR)
50 | SODIR_darwin=$(LIBDIR)
51 | SODIR_mingw=$(BINDIR)
52 | SODIR=$(SODIR_$(SYS))
53 |
54 | SO_LDFLAGS_posix=-shared -Wl,-soname,$@
55 | SO_LDFLAGS_darwin=-dynamiclib -twolevel_namespace -undefined dynamic_lookup \
56 | -fno-common -headerpad_max_install_names -install_name $(libdir)/$@
57 | SO_LDFLAGS_mingw=-shared -Wl,--out-implib,librtmp.dll.a
58 | SO_LDFLAGS=$(SO_LDFLAGS_$(SYS))
59 |
60 | INSTALL_IMPLIB_posix=
61 | INSTALL_IMPLIB_darwin=
62 | INSTALL_IMPLIB_mingw=cp librtmp.dll.a $(LIBDIR)
63 | INSTALL_IMPLIB=$(INSTALL_IMPLIB_$(SYS))
64 |
65 | SHARED=yes
66 | SODEF_yes=-fPIC
67 | SOLIB_yes=librtmp$(SO_EXT)
68 | SOINST_yes=install_so
69 | SO_DEF=$(SODEF_$(SHARED))
70 | SO_LIB=$(SOLIB_$(SHARED))
71 | SO_INST=$(SOINST_$(SHARED))
72 |
73 | DEF=-DRTMPDUMP_VERSION=\"$(VERSION)\" $(CRYPTO_DEF) $(XDEF)
74 | OPT=-O2
75 | CFLAGS=-Wall $(XCFLAGS) $(INC) $(DEF) $(OPT) $(SO_DEF)
76 | LDFLAGS=$(XLDFLAGS)
77 |
78 |
79 | OBJS=rtmp.o log.o amf.o hashswf.o parseurl.o
80 |
81 | all: librtmp.a $(SO_LIB)
82 |
83 | clean:
84 | rm -f *.o *.a *.$(SOX) *$(SO_EXT) librtmp.pc
85 |
86 | librtmp.a: $(OBJS)
87 | $(AR) rs $@ $?
88 |
89 | librtmp$(SO_EXT): $(OBJS)
90 | $(CC) $(SO_LDFLAGS) $(LDFLAGS) -o $@ $^ $> $(CRYPTO_LIB)
91 | ln -sf $@ librtmp.$(SOX)
92 |
93 | log.o: log.c log.h Makefile
94 | rtmp.o: rtmp.c rtmp.h rtmp_sys.h handshake.h dh.h log.h amf.h Makefile
95 | amf.o: amf.c amf.h bytes.h log.h Makefile
96 | hashswf.o: hashswf.c http.h rtmp.h rtmp_sys.h Makefile
97 | parseurl.o: parseurl.c rtmp.h rtmp_sys.h log.h Makefile
98 |
99 | librtmp.pc: librtmp.pc.in Makefile
100 | sed -e "s;@prefix@;$(prefix);" -e "s;@libdir@;$(libdir);" \
101 | -e "s;@VERSION@;$(VERSION);" \
102 | -e "s;@CRYPTO_REQ@;$(CRYPTO_REQ);" \
103 | -e "s;@PRIVATE_LIBS@;$(PRIVATE_LIBS);" librtmp.pc.in > $@
104 |
105 | install: install_base $(SO_INST)
106 |
107 | install_base: librtmp.a librtmp.pc
108 | -mkdir -p $(INCDIR) $(LIBDIR)/pkgconfig $(MANDIR)/man3 $(SODIR)
109 | cp amf.h http.h log.h rtmp.h $(INCDIR)
110 | cp librtmp.a $(LIBDIR)
111 | cp librtmp.pc $(LIBDIR)/pkgconfig
112 | cp librtmp.3 $(MANDIR)/man3
113 |
114 | install_so: librtmp$(SO_EXT)
115 | cp librtmp$(SO_EXT) $(SODIR)
116 | $(INSTALL_IMPLIB)
117 | cd $(SODIR); ln -sf librtmp$(SO_EXT) librtmp.$(SOX)
118 |
119 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/librtmp/amf.h:
--------------------------------------------------------------------------------
1 | #ifndef __AMF_H__
2 | #define __AMF_H__
3 | /*
4 | * Copyright (C) 2005-2008 Team XBMC
5 | * http://www.xbmc.org
6 | * Copyright (C) 2008-2009 Andrej Stepanchuk
7 | * Copyright (C) 2009-2010 Howard Chu
8 | *
9 | * This file is part of librtmp.
10 | *
11 | * librtmp is free software; you can redistribute it and/or modify
12 | * it under the terms of the GNU Lesser General Public License as
13 | * published by the Free Software Foundation; either version 2.1,
14 | * or (at your option) any later version.
15 | *
16 | * librtmp is distributed in the hope that it will be useful,
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * You should have received a copy of the GNU Lesser General Public License
22 | * along with librtmp see the file COPYING. If not, write to
23 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 | * Boston, MA 02110-1301, USA.
25 | * http://www.gnu.org/copyleft/lgpl.html
26 | */
27 |
28 | #include
29 |
30 | #ifndef TRUE
31 | #define TRUE 1
32 | #define FALSE 0
33 | #endif
34 |
35 | #ifdef __cplusplus
36 | extern "C"
37 | {
38 | #endif
39 |
40 | typedef enum
41 | { AMF_NUMBER = 0, AMF_BOOLEAN, AMF_STRING, AMF_OBJECT,
42 | AMF_MOVIECLIP, /* reserved, not used */
43 | AMF_NULL, AMF_UNDEFINED, AMF_REFERENCE, AMF_ECMA_ARRAY, AMF_OBJECT_END,
44 | AMF_STRICT_ARRAY, AMF_DATE, AMF_LONG_STRING, AMF_UNSUPPORTED,
45 | AMF_RECORDSET, /* reserved, not used */
46 | AMF_XML_DOC, AMF_TYPED_OBJECT,
47 | AMF_AVMPLUS, /* switch to AMF3 */
48 | AMF_INVALID = 0xff
49 | } AMFDataType;
50 |
51 | typedef enum
52 | { AMF3_UNDEFINED = 0, AMF3_NULL, AMF3_FALSE, AMF3_TRUE,
53 | AMF3_INTEGER, AMF3_DOUBLE, AMF3_STRING, AMF3_XML_DOC, AMF3_DATE,
54 | AMF3_ARRAY, AMF3_OBJECT, AMF3_XML, AMF3_BYTE_ARRAY
55 | } AMF3DataType;
56 |
57 | typedef struct AVal
58 | {
59 | char *av_val;
60 | int av_len;
61 | } AVal;
62 | #define AVC(str) {str,sizeof(str)-1}
63 | #define AVMATCH(a1,a2) ((a1)->av_len == (a2)->av_len && !memcmp((a1)->av_val,(a2)->av_val,(a1)->av_len))
64 |
65 | struct AMFObjectProperty;
66 |
67 | typedef struct AMFObject
68 | {
69 | int o_num;
70 | struct AMFObjectProperty *o_props;
71 | } AMFObject;
72 |
73 | typedef struct AMFObjectProperty
74 | {
75 | AVal p_name;
76 | AMFDataType p_type;
77 | union
78 | {
79 | double p_number;
80 | AVal p_aval;
81 | AMFObject p_object;
82 | } p_vu;
83 | int16_t p_UTCoffset;
84 | } AMFObjectProperty;
85 |
86 | char *AMF_EncodeString(char *output, char *outend, const AVal * str);
87 | char *AMF_EncodeNumber(char *output, char *outend, double dVal);
88 | char *AMF_EncodeInt16(char *output, char *outend, short nVal);
89 | char *AMF_EncodeInt24(char *output, char *outend, int nVal);
90 | char *AMF_EncodeInt32(char *output, char *outend, int nVal);
91 | char *AMF_EncodeBoolean(char *output, char *outend, int bVal);
92 |
93 | /* Shortcuts for AMFProp_Encode */
94 | char *AMF_EncodeNamedString(char *output, char *outend, const AVal * name, const AVal * value);
95 | char *AMF_EncodeNamedNumber(char *output, char *outend, const AVal * name, double dVal);
96 | char *AMF_EncodeNamedBoolean(char *output, char *outend, const AVal * name, int bVal);
97 |
98 | unsigned short AMF_DecodeInt16(const char *data);
99 | unsigned int AMF_DecodeInt24(const char *data);
100 | unsigned int AMF_DecodeInt32(const char *data);
101 | void AMF_DecodeString(const char *data, AVal * str);
102 | void AMF_DecodeLongString(const char *data, AVal * str);
103 | int AMF_DecodeBoolean(const char *data);
104 | double AMF_DecodeNumber(const char *data);
105 |
106 | char *AMF_Encode(AMFObject * obj, char *pBuffer, char *pBufEnd);
107 | char *AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd);
108 | char *AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd);
109 |
110 | int AMF_Decode(AMFObject * obj, const char *pBuffer, int nSize,
111 | int bDecodeName);
112 | int AMF_DecodeArray(AMFObject * obj, const char *pBuffer, int nSize,
113 | int nArrayLen, int bDecodeName);
114 | int AMF3_Decode(AMFObject * obj, const char *pBuffer, int nSize,
115 | int bDecodeName);
116 | void AMF_Dump(AMFObject * obj);
117 | void AMF_Reset(AMFObject * obj);
118 |
119 | void AMF_AddProp(AMFObject * obj, const AMFObjectProperty * prop);
120 | int AMF_CountProp(AMFObject * obj);
121 | AMFObjectProperty *AMF_GetProp(AMFObject * obj, const AVal * name,
122 | int nIndex);
123 |
124 | AMFDataType AMFProp_GetType(AMFObjectProperty * prop);
125 | void AMFProp_SetNumber(AMFObjectProperty * prop, double dval);
126 | void AMFProp_SetBoolean(AMFObjectProperty * prop, int bflag);
127 | void AMFProp_SetString(AMFObjectProperty * prop, AVal * str);
128 | void AMFProp_SetObject(AMFObjectProperty * prop, AMFObject * obj);
129 |
130 | void AMFProp_GetName(AMFObjectProperty * prop, AVal * name);
131 | void AMFProp_SetName(AMFObjectProperty * prop, AVal * name);
132 | double AMFProp_GetNumber(AMFObjectProperty * prop);
133 | int AMFProp_GetBoolean(AMFObjectProperty * prop);
134 | void AMFProp_GetString(AMFObjectProperty * prop, AVal * str);
135 | void AMFProp_GetObject(AMFObjectProperty * prop, AMFObject * obj);
136 |
137 | int AMFProp_IsValid(AMFObjectProperty * prop);
138 |
139 | char *AMFProp_Encode(AMFObjectProperty * prop, char *pBuffer, char *pBufEnd);
140 | int AMF3Prop_Decode(AMFObjectProperty * prop, const char *pBuffer,
141 | int nSize, int bDecodeName);
142 | int AMFProp_Decode(AMFObjectProperty * prop, const char *pBuffer,
143 | int nSize, int bDecodeName);
144 |
145 | void AMFProp_Dump(AMFObjectProperty * prop);
146 | void AMFProp_Reset(AMFObjectProperty * prop);
147 |
148 | typedef struct AMF3ClassDef
149 | {
150 | AVal cd_name;
151 | char cd_externalizable;
152 | char cd_dynamic;
153 | int cd_num;
154 | AVal *cd_props;
155 | } AMF3ClassDef;
156 |
157 | void AMF3CD_AddProp(AMF3ClassDef * cd, AVal * prop);
158 | AVal *AMF3CD_GetProp(AMF3ClassDef * cd, int idx);
159 |
160 | #ifdef __cplusplus
161 | }
162 | #endif
163 |
164 | #endif /* __AMF_H__ */
165 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/librtmp/bytes.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2005-2008 Team XBMC
3 | * http://www.xbmc.org
4 | * Copyright (C) 2008-2009 Andrej Stepanchuk
5 | * Copyright (C) 2009-2010 Howard Chu
6 | *
7 | * This file is part of librtmp.
8 | *
9 | * librtmp is free software; you can redistribute it and/or modify
10 | * it under the terms of the GNU Lesser General Public License as
11 | * published by the Free Software Foundation; either version 2.1,
12 | * or (at your option) any later version.
13 | *
14 | * librtmp is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public License
20 | * along with librtmp see the file COPYING. If not, write to
21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 | * Boston, MA 02110-1301, USA.
23 | * http://www.gnu.org/copyleft/lgpl.html
24 | */
25 |
26 | #ifndef __BYTES_H__
27 | #define __BYTES_H__
28 |
29 | #include
30 |
31 | #ifdef _WIN32
32 | /* Windows is little endian only */
33 | #define __LITTLE_ENDIAN 1234
34 | #define __BIG_ENDIAN 4321
35 | #define __BYTE_ORDER __LITTLE_ENDIAN
36 | #define __FLOAT_WORD_ORDER __BYTE_ORDER
37 |
38 | typedef unsigned char uint8_t;
39 |
40 | #else /* !_WIN32 */
41 |
42 | #include
43 |
44 | #if defined(BYTE_ORDER) && !defined(__BYTE_ORDER)
45 | #define __BYTE_ORDER BYTE_ORDER
46 | #endif
47 |
48 | #if defined(BIG_ENDIAN) && !defined(__BIG_ENDIAN)
49 | #define __BIG_ENDIAN BIG_ENDIAN
50 | #endif
51 |
52 | #if defined(LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN)
53 | #define __LITTLE_ENDIAN LITTLE_ENDIAN
54 | #endif
55 |
56 | #endif /* !_WIN32 */
57 |
58 | /* define default endianness */
59 | #ifndef __LITTLE_ENDIAN
60 | #define __LITTLE_ENDIAN 1234
61 | #endif
62 |
63 | #ifndef __BIG_ENDIAN
64 | #define __BIG_ENDIAN 4321
65 | #endif
66 |
67 | #ifndef __BYTE_ORDER
68 | #warning "Byte order not defined on your system, assuming little endian!"
69 | #define __BYTE_ORDER __LITTLE_ENDIAN
70 | #endif
71 |
72 | /* ok, we assume to have the same float word order and byte order if float word order is not defined */
73 | #ifndef __FLOAT_WORD_ORDER
74 | #warning "Float word order not defined, assuming the same as byte order!"
75 | #define __FLOAT_WORD_ORDER __BYTE_ORDER
76 | #endif
77 |
78 | #if !defined(__BYTE_ORDER) || !defined(__FLOAT_WORD_ORDER)
79 | #error "Undefined byte or float word order!"
80 | #endif
81 |
82 | #if __FLOAT_WORD_ORDER != __BIG_ENDIAN && __FLOAT_WORD_ORDER != __LITTLE_ENDIAN
83 | #error "Unknown/unsupported float word order!"
84 | #endif
85 |
86 | #if __BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN
87 | #error "Unknown/unsupported byte order!"
88 | #endif
89 |
90 | #endif
91 |
92 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/librtmp/http.h:
--------------------------------------------------------------------------------
1 | #ifndef __RTMP_HTTP_H__
2 | #define __RTMP_HTTP_H__
3 | /*
4 | * Copyright (C) 2010 Howard Chu
5 | * Copyright (C) 2010 Antti Ajanki
6 | *
7 | * This file is part of librtmp.
8 | *
9 | * librtmp is free software; you can redistribute it and/or modify
10 | * it under the terms of the GNU Lesser General Public License as
11 | * published by the Free Software Foundation; either version 2.1,
12 | * or (at your option) any later version.
13 | *
14 | * librtmp is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public License
20 | * along with librtmp see the file COPYING. If not, write to
21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 | * Boston, MA 02110-1301, USA.
23 | * http://www.gnu.org/copyleft/lgpl.html
24 | */
25 |
26 | typedef enum {
27 | HTTPRES_OK, /* result OK */
28 | HTTPRES_OK_NOT_MODIFIED, /* not modified since last request */
29 | HTTPRES_NOT_FOUND, /* not found */
30 | HTTPRES_BAD_REQUEST, /* client error */
31 | HTTPRES_SERVER_ERROR, /* server reported an error */
32 | HTTPRES_REDIRECTED, /* resource has been moved */
33 | HTTPRES_LOST_CONNECTION /* connection lost while waiting for data */
34 | } HTTPResult;
35 |
36 | struct HTTP_ctx {
37 | char *date;
38 | int size;
39 | int status;
40 | void *data;
41 | };
42 |
43 | typedef size_t (HTTP_read_callback)(void *ptr, size_t size, size_t nmemb, void *stream);
44 |
45 | HTTPResult HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb);
46 |
47 | #endif
48 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/librtmp/librtmp.pc.in:
--------------------------------------------------------------------------------
1 | prefix=@prefix@
2 | exec_prefix=${prefix}
3 | libdir=@libdir@
4 | incdir=${prefix}/include
5 |
6 | Name: librtmp
7 | Description: RTMP implementation
8 | Version: @VERSION@
9 | Requires: @CRYPTO_REQ@
10 | URL: http://rtmpdump.mplayerhq.hu
11 | Libs: -L${libdir} -lrtmp -lz
12 | Libs.private: @PRIVATE_LIBS@
13 | Cflags: -I${incdir}
14 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/librtmp/log.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008-2009 Andrej Stepanchuk
3 | * Copyright (C) 2009-2010 Howard Chu
4 | *
5 | * This file is part of librtmp.
6 | *
7 | * librtmp is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU Lesser General Public License as
9 | * published by the Free Software Foundation; either version 2.1,
10 | * or (at your option) any later version.
11 | *
12 | * librtmp is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with librtmp see the file COPYING. If not, write to
19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 | * Boston, MA 02110-1301, USA.
21 | * http://www.gnu.org/copyleft/lgpl.html
22 | */
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "rtmp_sys.h"
31 | #include "log.h"
32 |
33 | #define MAX_PRINT_LEN 2048
34 |
35 | RTMP_LogLevel RTMP_debuglevel = RTMP_LOGERROR;
36 |
37 | static int neednl;
38 |
39 | static FILE *fmsg;
40 |
41 | static RTMP_LogCallback rtmp_log_default, *cb = rtmp_log_default;
42 |
43 | static const char *levels[] = {
44 | "CRIT", "ERROR", "WARNING", "INFO",
45 | "DEBUG", "DEBUG2"
46 | };
47 |
48 | static void rtmp_log_default(int level, const char *format, va_list vl)
49 | {
50 | char str[MAX_PRINT_LEN]="";
51 |
52 | vsnprintf(str, MAX_PRINT_LEN-1, format, vl);
53 |
54 | /* Filter out 'no-name' */
55 | if ( RTMP_debuglevel RTMP_debuglevel )
108 | return;
109 |
110 | ptr = line;
111 |
112 | for(i=0; i> 4)];
114 | *ptr++ = hexdig[0x0f & data[i]];
115 | if ((i & 0x0f) == 0x0f) {
116 | *ptr = '\0';
117 | ptr = line;
118 | RTMP_Log(level, "%s", line);
119 | } else {
120 | *ptr++ = ' ';
121 | }
122 | }
123 | if (i & 0x0f) {
124 | *ptr = '\0';
125 | RTMP_Log(level, "%s", line);
126 | }
127 | }
128 |
129 | void RTMP_LogHexString(int level, const uint8_t *data, unsigned long len)
130 | {
131 | #define BP_OFFSET 9
132 | #define BP_GRAPH 60
133 | #define BP_LEN 80
134 | char line[BP_LEN];
135 | unsigned long i;
136 |
137 | if ( !data || level > RTMP_debuglevel )
138 | return;
139 |
140 | /* in case len is zero */
141 | line[0] = '\0';
142 |
143 | for ( i = 0 ; i < len ; i++ ) {
144 | int n = i & 15;
145 | unsigned off;
146 |
147 | if( !n ) {
148 | if( i ) RTMP_Log( level, "%s", line );
149 | memset( line, ' ', sizeof(line)-2 );
150 | line[sizeof(line)-2] = '\0';
151 |
152 | off = i % 0x0ffffU;
153 |
154 | line[2] = hexdig[0x0f & (off >> 12)];
155 | line[3] = hexdig[0x0f & (off >> 8)];
156 | line[4] = hexdig[0x0f & (off >> 4)];
157 | line[5] = hexdig[0x0f & off];
158 | line[6] = ':';
159 | }
160 |
161 | off = BP_OFFSET + n*3 + ((n >= 8)?1:0);
162 | line[off] = hexdig[0x0f & ( data[i] >> 4 )];
163 | line[off+1] = hexdig[0x0f & data[i]];
164 |
165 | off = BP_GRAPH + n + ((n >= 8)?1:0);
166 |
167 | if ( isprint( data[i] )) {
168 | line[BP_GRAPH + n] = data[i];
169 | } else {
170 | line[BP_GRAPH + n] = '.';
171 | }
172 | }
173 |
174 | RTMP_Log( level, "%s", line );
175 | }
176 |
177 | /* These should only be used by apps, never by the library itself */
178 | void RTMP_LogPrintf(const char *format, ...)
179 | {
180 | char str[MAX_PRINT_LEN]="";
181 | int len;
182 | va_list args;
183 | va_start(args, format);
184 | len = vsnprintf(str, MAX_PRINT_LEN-1, format, args);
185 | va_end(args);
186 |
187 | if ( RTMP_debuglevel==RTMP_LOGCRIT )
188 | return;
189 |
190 | if ( !fmsg ) fmsg = stderr;
191 |
192 | if (neednl) {
193 | putc('\n', fmsg);
194 | neednl = 0;
195 | }
196 |
197 | if (len > MAX_PRINT_LEN-1)
198 | len = MAX_PRINT_LEN-1;
199 | fprintf(fmsg, "%s", str);
200 | if (str[len-1] == '\n')
201 | fflush(fmsg);
202 | }
203 |
204 | void RTMP_LogStatus(const char *format, ...)
205 | {
206 | char str[MAX_PRINT_LEN]="";
207 | va_list args;
208 | va_start(args, format);
209 | vsnprintf(str, MAX_PRINT_LEN-1, format, args);
210 | va_end(args);
211 |
212 | if ( RTMP_debuglevel==RTMP_LOGCRIT )
213 | return;
214 |
215 | if ( !fmsg ) fmsg = stderr;
216 |
217 | fprintf(fmsg, "%s", str);
218 | fflush(fmsg);
219 | neednl = 1;
220 | }
221 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/librtmp/log.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008-2009 Andrej Stepanchuk
3 | * Copyright (C) 2009-2010 Howard Chu
4 | *
5 | * This file is part of librtmp.
6 | *
7 | * librtmp is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU Lesser General Public License as
9 | * published by the Free Software Foundation; either version 2.1,
10 | * or (at your option) any later version.
11 | *
12 | * librtmp is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with librtmp see the file COPYING. If not, write to
19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 | * Boston, MA 02110-1301, USA.
21 | * http://www.gnu.org/copyleft/lgpl.html
22 | */
23 |
24 | #ifndef __RTMP_LOG_H__
25 | #define __RTMP_LOG_H__
26 |
27 | #include
28 | #include
29 | #include
30 |
31 | #ifdef __cplusplus
32 | extern "C" {
33 | #endif
34 | /* Enable this to get full debugging output */
35 | /* #define _DEBUG */
36 |
37 | #ifdef _DEBUG
38 | #undef NODEBUG
39 | #endif
40 |
41 | typedef enum
42 | { RTMP_LOGCRIT=0, RTMP_LOGERROR, RTMP_LOGWARNING, RTMP_LOGINFO,
43 | RTMP_LOGDEBUG, RTMP_LOGDEBUG2, RTMP_LOGALL
44 | } RTMP_LogLevel;
45 |
46 | extern RTMP_LogLevel RTMP_debuglevel;
47 |
48 | typedef void (RTMP_LogCallback)(int level, const char *fmt, va_list);
49 | void RTMP_LogSetCallback(RTMP_LogCallback *cb);
50 | void RTMP_LogSetOutput(FILE *file);
51 | #ifdef __GNUC__
52 | void RTMP_LogPrintf(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
53 | void RTMP_LogStatus(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
54 | void RTMP_Log(int level, const char *format, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
55 | #else
56 | void RTMP_LogPrintf(const char *format, ...);
57 | void RTMP_LogStatus(const char *format, ...);
58 | void RTMP_Log(int level, const char *format, ...);
59 | #endif
60 | void RTMP_LogHex(int level, const uint8_t *data, unsigned long len);
61 | void RTMP_LogHexString(int level, const uint8_t *data, unsigned long len);
62 | void RTMP_LogSetLevel(RTMP_LogLevel lvl);
63 | RTMP_LogLevel RTMP_LogGetLevel(void);
64 |
65 | #ifdef __cplusplus
66 | }
67 | #endif
68 |
69 | #endif
70 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/librtmp/rtmp_sys.h:
--------------------------------------------------------------------------------
1 | #ifndef __RTMP_SYS_H__
2 | #define __RTMP_SYS_H__
3 | /*
4 | * Copyright (C) 2010 Howard Chu
5 | *
6 | * This file is part of librtmp.
7 | *
8 | * librtmp is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU Lesser General Public License as
10 | * published by the Free Software Foundation; either version 2.1,
11 | * or (at your option) any later version.
12 | *
13 | * librtmp is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Lesser General Public License
19 | * along with librtmp see the file COPYING. If not, write to
20 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 | * Boston, MA 02110-1301, USA.
22 | * http://www.gnu.org/copyleft/lgpl.html
23 | */
24 |
25 | #ifdef _WIN32
26 |
27 | #include
28 | #include
29 |
30 | #ifdef _MSC_VER /* MSVC */
31 | #define snprintf _snprintf
32 | #define strcasecmp stricmp
33 | #define strncasecmp strnicmp
34 | #define vsnprintf _vsnprintf
35 | #endif
36 |
37 | #define GetSockError() WSAGetLastError()
38 | #define SetSockError(e) WSASetLastError(e)
39 | #define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
40 | #define EWOULDBLOCK WSAETIMEDOUT /* we don't use nonblocking, but we do use timeouts */
41 | #define sleep(n) Sleep(n*1000)
42 | #define msleep(n) Sleep(n)
43 | #define SET_RCVTIMEO(tv,s) int tv = s*1000
44 | #else /* !_WIN32 */
45 | #include
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #define GetSockError() errno
54 | #define SetSockError(e) errno = e
55 | #undef closesocket
56 | #define closesocket(s) close(s)
57 | #define msleep(n) usleep(n*1000)
58 | #define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0}
59 | #endif
60 |
61 | #include "rtmp.h"
62 |
63 | #ifdef USE_POLARSSL
64 | #include
65 | #include
66 | #include
67 | #include
68 | #if POLARSSL_VERSION_NUMBER < 0x01010000
69 | #define havege_random havege_rand
70 | #endif
71 | #if POLARSSL_VERSION_NUMBER >= 0x01020000
72 | #define SSL_SET_SESSION(S,resume,timeout,ctx) ssl_set_session(S,ctx)
73 | #else
74 | #define SSL_SET_SESSION(S,resume,timeout,ctx) ssl_set_session(S,resume,timeout,ctx)
75 | #endif
76 | typedef struct tls_ctx {
77 | havege_state hs;
78 | ssl_session ssn;
79 | } tls_ctx;
80 | typedef struct tls_server_ctx {
81 | havege_state *hs;
82 | x509_cert cert;
83 | rsa_context key;
84 | ssl_session ssn;
85 | const char *dhm_P, *dhm_G;
86 | } tls_server_ctx;
87 |
88 | #define TLS_CTX tls_ctx *
89 | #define TLS_client(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\
90 | ssl_set_endpoint(s, SSL_IS_CLIENT); ssl_set_authmode(s, SSL_VERIFY_NONE);\
91 | ssl_set_rng(s, havege_random, &ctx->hs);\
92 | ssl_set_ciphersuites(s, ssl_default_ciphersuites);\
93 | SSL_SET_SESSION(s, 1, 600, &ctx->ssn)
94 | #define TLS_server(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\
95 | ssl_set_endpoint(s, SSL_IS_SERVER); ssl_set_authmode(s, SSL_VERIFY_NONE);\
96 | ssl_set_rng(s, havege_random, ((tls_server_ctx*)ctx)->hs);\
97 | ssl_set_ciphersuites(s, ssl_default_ciphersuites);\
98 | SSL_SET_SESSION(s, 1, 600, &((tls_server_ctx*)ctx)->ssn);\
99 | ssl_set_own_cert(s, &((tls_server_ctx*)ctx)->cert, &((tls_server_ctx*)ctx)->key);\
100 | ssl_set_dh_param(s, ((tls_server_ctx*)ctx)->dhm_P, ((tls_server_ctx*)ctx)->dhm_G)
101 | #define TLS_setfd(s,fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd)
102 | #define TLS_connect(s) ssl_handshake(s)
103 | #define TLS_accept(s) ssl_handshake(s)
104 | #define TLS_read(s,b,l) ssl_read(s,(unsigned char *)b,l)
105 | #define TLS_write(s,b,l) ssl_write(s,(unsigned char *)b,l)
106 | #define TLS_shutdown(s) ssl_close_notify(s)
107 | #define TLS_close(s) ssl_free(s); free(s)
108 |
109 | #elif defined(USE_GNUTLS)
110 | #include
111 | typedef struct tls_ctx {
112 | gnutls_certificate_credentials_t cred;
113 | gnutls_priority_t prios;
114 | } tls_ctx;
115 | #define TLS_CTX tls_ctx *
116 | #define TLS_client(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_CLIENT); gnutls_priority_set(s, ctx->prios); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx->cred)
117 | #define TLS_server(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_SERVER); gnutls_priority_set_direct(s, "NORMAL", NULL); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx)
118 | #define TLS_setfd(s,fd) gnutls_transport_set_ptr(s, (gnutls_transport_ptr_t)(long)fd)
119 | #define TLS_connect(s) gnutls_handshake(s)
120 | #define TLS_accept(s) gnutls_handshake(s)
121 | #define TLS_read(s,b,l) gnutls_record_recv(s,b,l)
122 | #define TLS_write(s,b,l) gnutls_record_send(s,b,l)
123 | #define TLS_shutdown(s) gnutls_bye(s, GNUTLS_SHUT_RDWR)
124 | #define TLS_close(s) gnutls_deinit(s)
125 |
126 | #else /* USE_OPENSSL */
127 | #define TLS_CTX SSL_CTX *
128 | #define TLS_client(ctx,s) s = SSL_new(ctx)
129 | #define TLS_server(ctx,s) s = SSL_new(ctx)
130 | #define TLS_setfd(s,fd) SSL_set_fd(s,fd)
131 | #define TLS_connect(s) SSL_connect(s)
132 | #define TLS_accept(s) SSL_accept(s)
133 | #define TLS_read(s,b,l) SSL_read(s,b,l)
134 | #define TLS_write(s,b,l) SSL_write(s,b,l)
135 | #define TLS_shutdown(s) SSL_shutdown(s)
136 | #define TLS_close(s) SSL_free(s)
137 |
138 | #endif
139 | #endif
140 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/rtmpmuxer.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "flvmuxer/xiecc_rtmp.h"
6 |
7 |
8 | /**
9 | * if it returns bigger than 0 it is successful
10 | */
11 | JNIEXPORT jint JNICALL
12 | Java_com_rtmpx_library_rtmp_RTMPMuxer_open(JNIEnv* env, jobject thiz, jstring url_,
13 | jint video_width, jint video_height,jint frame_rate) {
14 | const char *url = (*env)->GetStringUTFChars(env, url_, NULL);
15 |
16 | int result = rtmp_open_for_write(url, video_width, video_height,frame_rate);
17 |
18 | (*env)->ReleaseStringUTFChars(env, url_, url);
19 | return result;
20 | }
21 |
22 | JNIEXPORT jint JNICALL
23 | Java_com_rtmpx_library_rtmp_RTMPMuxer_writeAudio(JNIEnv* env, jobject thiz, jbyteArray data_,
24 | jint offset, jint length, jlong timestamp) {
25 | jbyte *data = (*env)->GetByteArrayElements(env, data_, NULL);
26 |
27 | jint result = rtmp_sender_write_audio_frame(&data[offset], length, timestamp, 0);
28 |
29 | (*env)->ReleaseByteArrayElements(env, data_, data, JNI_ABORT);
30 | return result;
31 | }
32 |
33 | JNIEXPORT jint JNICALL
34 | Java_com_rtmpx_library_rtmp_RTMPMuxer_writeVideo(JNIEnv* env, jobject thiz, jbyteArray data_,
35 | jint offset, jint length, jlong timestamp) {
36 | jbyte *data = (*env)->GetByteArrayElements(env, data_, NULL);
37 |
38 | jint result = rtmp_sender_write_video_frame(&data[offset], length, timestamp, 0, 0);
39 |
40 | (*env)->ReleaseByteArrayElements(env, data_, data, JNI_ABORT);
41 |
42 | return result;
43 | }
44 |
45 | JNIEXPORT jint JNICALL
46 | Java_com_rtmpx_library_rtmp_RTMPMuxer_close(JNIEnv* env, jobject thiz) {
47 | rtmp_close();
48 |
49 | return 0;
50 |
51 | }
52 |
53 | JNIEXPORT jboolean JNICALL
54 | Java_com_rtmpx_library_rtmp_RTMPMuxer_isConnected(JNIEnv* env, jobject thiz) {
55 | return rtmp_is_connected() ? true : false;
56 | }
57 |
58 | JNIEXPORT jint JNICALL
59 | Java_com_rtmpx_library_rtmp_RTMPMuxer_read(JNIEnv* env, jobject thiz, jbyteArray data_,
60 | jint offset, jint size) {
61 |
62 | char* data = malloc(size);
63 |
64 | int readCount = rtmp_read_date(data, size);
65 |
66 | if (readCount > 0) {
67 | (*env)->SetByteArrayRegion(env, data_, offset, readCount, data); // copy
68 | }
69 | free(data);
70 |
71 | return readCount;
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_H_
12 | #define INCLUDE_LIBYUV_H_
13 |
14 | #include "libyuv/basic_types.h"
15 | #include "libyuv/compare.h"
16 | #include "libyuv/convert.h"
17 | #include "libyuv/convert_argb.h"
18 | #include "libyuv/convert_from.h"
19 | #include "libyuv/convert_from_argb.h"
20 | #include "libyuv/cpu_id.h"
21 | #include "libyuv/mjpeg_decoder.h"
22 | #include "libyuv/planar_functions.h"
23 | #include "libyuv/rotate.h"
24 | #include "libyuv/rotate_argb.h"
25 | #include "libyuv/row.h"
26 | #include "libyuv/scale.h"
27 | #include "libyuv/scale_argb.h"
28 | #include "libyuv/scale_row.h"
29 | #include "libyuv/version.h"
30 | #include "libyuv/video_common.h"
31 |
32 | #endif // INCLUDE_LIBYUV_H_
33 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv/basic_types.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_BASIC_TYPES_H_
12 | #define INCLUDE_LIBYUV_BASIC_TYPES_H_
13 |
14 | #include // For size_t and NULL
15 |
16 | #if !defined(INT_TYPES_DEFINED) && !defined(GG_LONGLONG)
17 | #define INT_TYPES_DEFINED
18 |
19 | #if defined(_MSC_VER) && (_MSC_VER < 1600)
20 | #include // for uintptr_t on x86
21 | typedef unsigned __int64 uint64_t;
22 | typedef __int64 int64_t;
23 | typedef unsigned int uint32_t;
24 | typedef int int32_t;
25 | typedef unsigned short uint16_t;
26 | typedef short int16_t;
27 | typedef unsigned char uint8_t;
28 | typedef signed char int8_t;
29 | #else
30 | #include // for uintptr_t and C99 types
31 | #endif // defined(_MSC_VER) && (_MSC_VER < 1600)
32 | // Types are deprecated. Enable this macro for legacy types.
33 | #ifdef LIBYUV_LEGACY_TYPES
34 | typedef uint64_t uint64;
35 | typedef int64_t int64;
36 | typedef uint32_t uint32;
37 | typedef int32_t int32;
38 | typedef uint16_t uint16;
39 | typedef int16_t int16;
40 | typedef uint8_t uint8;
41 | typedef int8_t int8;
42 | #endif // LIBYUV_LEGACY_TYPES
43 | #endif // INT_TYPES_DEFINED
44 |
45 | #if !defined(LIBYUV_API)
46 | #if defined(_WIN32) || defined(__CYGWIN__)
47 | #if defined(LIBYUV_BUILDING_SHARED_LIBRARY)
48 | #define LIBYUV_API __declspec(dllexport)
49 | #elif defined(LIBYUV_USING_SHARED_LIBRARY)
50 | #define LIBYUV_API __declspec(dllimport)
51 | #else
52 | #define LIBYUV_API
53 | #endif // LIBYUV_BUILDING_SHARED_LIBRARY
54 | #elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__APPLE__) && \
55 | (defined(LIBYUV_BUILDING_SHARED_LIBRARY) || \
56 | defined(LIBYUV_USING_SHARED_LIBRARY))
57 | #define LIBYUV_API __attribute__((visibility("default")))
58 | #else
59 | #define LIBYUV_API
60 | #endif // __GNUC__
61 | #endif // LIBYUV_API
62 |
63 | // TODO(fbarchard): Remove bool macros.
64 | #define LIBYUV_BOOL int
65 | #define LIBYUV_FALSE 0
66 | #define LIBYUV_TRUE 1
67 |
68 | #endif // INCLUDE_LIBYUV_BASIC_TYPES_H_
69 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv/compare.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_COMPARE_H_
12 | #define INCLUDE_LIBYUV_COMPARE_H_
13 |
14 | #include "libyuv/basic_types.h"
15 |
16 | #ifdef __cplusplus
17 | namespace libyuv {
18 | extern "C" {
19 | #endif
20 |
21 | // Compute a hash for specified memory. Seed of 5381 recommended.
22 | LIBYUV_API
23 | uint32_t HashDjb2(const uint8_t* src, uint64_t count, uint32_t seed);
24 |
25 | // Hamming Distance
26 | LIBYUV_API
27 | uint64_t ComputeHammingDistance(const uint8_t* src_a,
28 | const uint8_t* src_b,
29 | int count);
30 |
31 | // Scan an opaque argb image and return fourcc based on alpha offset.
32 | // Returns FOURCC_ARGB, FOURCC_BGRA, or 0 if unknown.
33 | LIBYUV_API
34 | uint32_t ARGBDetect(const uint8_t* argb,
35 | int stride_argb,
36 | int width,
37 | int height);
38 |
39 | // Sum Square Error - used to compute Mean Square Error or PSNR.
40 | LIBYUV_API
41 | uint64_t ComputeSumSquareError(const uint8_t* src_a,
42 | const uint8_t* src_b,
43 | int count);
44 |
45 | LIBYUV_API
46 | uint64_t ComputeSumSquareErrorPlane(const uint8_t* src_a,
47 | int stride_a,
48 | const uint8_t* src_b,
49 | int stride_b,
50 | int width,
51 | int height);
52 |
53 | static const int kMaxPsnr = 128;
54 |
55 | LIBYUV_API
56 | double SumSquareErrorToPsnr(uint64_t sse, uint64_t count);
57 |
58 | LIBYUV_API
59 | double CalcFramePsnr(const uint8_t* src_a,
60 | int stride_a,
61 | const uint8_t* src_b,
62 | int stride_b,
63 | int width,
64 | int height);
65 |
66 | LIBYUV_API
67 | double I420Psnr(const uint8_t* src_y_a,
68 | int stride_y_a,
69 | const uint8_t* src_u_a,
70 | int stride_u_a,
71 | const uint8_t* src_v_a,
72 | int stride_v_a,
73 | const uint8_t* src_y_b,
74 | int stride_y_b,
75 | const uint8_t* src_u_b,
76 | int stride_u_b,
77 | const uint8_t* src_v_b,
78 | int stride_v_b,
79 | int width,
80 | int height);
81 |
82 | LIBYUV_API
83 | double CalcFrameSsim(const uint8_t* src_a,
84 | int stride_a,
85 | const uint8_t* src_b,
86 | int stride_b,
87 | int width,
88 | int height);
89 |
90 | LIBYUV_API
91 | double I420Ssim(const uint8_t* src_y_a,
92 | int stride_y_a,
93 | const uint8_t* src_u_a,
94 | int stride_u_a,
95 | const uint8_t* src_v_a,
96 | int stride_v_a,
97 | const uint8_t* src_y_b,
98 | int stride_y_b,
99 | const uint8_t* src_u_b,
100 | int stride_u_b,
101 | const uint8_t* src_v_b,
102 | int stride_v_b,
103 | int width,
104 | int height);
105 |
106 | #ifdef __cplusplus
107 | } // extern "C"
108 | } // namespace libyuv
109 | #endif
110 |
111 | #endif // INCLUDE_LIBYUV_COMPARE_H_
112 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv/compare_row.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_COMPARE_ROW_H_
12 | #define INCLUDE_LIBYUV_COMPARE_ROW_H_
13 |
14 | #include "libyuv/basic_types.h"
15 |
16 | #ifdef __cplusplus
17 | namespace libyuv {
18 | extern "C" {
19 | #endif
20 |
21 | #if defined(__pnacl__) || defined(__CLR_VER) || \
22 | (defined(__native_client__) && defined(__x86_64__)) || \
23 | (defined(__i386__) && !defined(__SSE__) && !defined(__clang__))
24 | #define LIBYUV_DISABLE_X86
25 | #endif
26 | #if defined(__native_client__)
27 | #define LIBYUV_DISABLE_NEON
28 | #endif
29 | // MemorySanitizer does not support assembly code yet. http://crbug.com/344505
30 | #if defined(__has_feature)
31 | #if __has_feature(memory_sanitizer)
32 | #define LIBYUV_DISABLE_X86
33 | #endif
34 | #endif
35 | // Visual C 2012 required for AVX2.
36 | #if defined(_M_IX86) && !defined(__clang__) && defined(_MSC_VER) && \
37 | _MSC_VER >= 1700
38 | #define VISUALC_HAS_AVX2 1
39 | #endif // VisualStudio >= 2012
40 |
41 | // clang >= 3.4.0 required for AVX2.
42 | #if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))
43 | #if (__clang_major__ > 3) || (__clang_major__ == 3 && (__clang_minor__ >= 4))
44 | #define CLANG_HAS_AVX2 1
45 | #endif // clang >= 3.4
46 | #endif // __clang__
47 |
48 | // The following are available for Visual C and GCC:
49 | #if !defined(LIBYUV_DISABLE_X86) && \
50 | (defined(__x86_64__) || defined(__i386__) || defined(_M_IX86))
51 | #define HAS_HASHDJB2_SSE41
52 | #define HAS_SUMSQUAREERROR_SSE2
53 | #define HAS_HAMMINGDISTANCE_SSE42
54 | #endif
55 |
56 | // The following are available for Visual C and clangcl 32 bit:
57 | #if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) && \
58 | (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2))
59 | #define HAS_HASHDJB2_AVX2
60 | #define HAS_SUMSQUAREERROR_AVX2
61 | #endif
62 |
63 | // The following are available for GCC and clangcl 64 bit:
64 | #if !defined(LIBYUV_DISABLE_X86) && \
65 | (defined(__x86_64__) || (defined(__i386__) && !defined(_MSC_VER)))
66 | #define HAS_HAMMINGDISTANCE_SSSE3
67 | #endif
68 |
69 | // The following are available for GCC and clangcl 64 bit:
70 | #if !defined(LIBYUV_DISABLE_X86) && defined(CLANG_HAS_AVX2) && \
71 | (defined(__x86_64__) || (defined(__i386__) && !defined(_MSC_VER)))
72 | #define HAS_HAMMINGDISTANCE_AVX2
73 | #endif
74 |
75 | // The following are available for Neon:
76 | #if !defined(LIBYUV_DISABLE_NEON) && \
77 | (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__))
78 | #define HAS_SUMSQUAREERROR_NEON
79 | #define HAS_HAMMINGDISTANCE_NEON
80 | #endif
81 |
82 | #if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa)
83 | #define HAS_HAMMINGDISTANCE_MSA
84 | #define HAS_SUMSQUAREERROR_MSA
85 | #endif
86 |
87 | #if !defined(LIBYUV_DISABLE_MMI) && defined(_MIPS_ARCH_LOONGSON3A)
88 | #define HAS_HAMMINGDISTANCE_MMI
89 | #define HAS_SUMSQUAREERROR_MMI
90 | #endif
91 |
92 | uint32_t HammingDistance_C(const uint8_t* src_a,
93 | const uint8_t* src_b,
94 | int count);
95 | uint32_t HammingDistance_SSE42(const uint8_t* src_a,
96 | const uint8_t* src_b,
97 | int count);
98 | uint32_t HammingDistance_SSSE3(const uint8_t* src_a,
99 | const uint8_t* src_b,
100 | int count);
101 | uint32_t HammingDistance_AVX2(const uint8_t* src_a,
102 | const uint8_t* src_b,
103 | int count);
104 | uint32_t HammingDistance_NEON(const uint8_t* src_a,
105 | const uint8_t* src_b,
106 | int count);
107 | uint32_t HammingDistance_MSA(const uint8_t* src_a,
108 | const uint8_t* src_b,
109 | int count);
110 | uint32_t HammingDistance_MMI(const uint8_t* src_a,
111 | const uint8_t* src_b,
112 | int count);
113 | uint32_t SumSquareError_C(const uint8_t* src_a,
114 | const uint8_t* src_b,
115 | int count);
116 | uint32_t SumSquareError_SSE2(const uint8_t* src_a,
117 | const uint8_t* src_b,
118 | int count);
119 | uint32_t SumSquareError_AVX2(const uint8_t* src_a,
120 | const uint8_t* src_b,
121 | int count);
122 | uint32_t SumSquareError_NEON(const uint8_t* src_a,
123 | const uint8_t* src_b,
124 | int count);
125 | uint32_t SumSquareError_MSA(const uint8_t* src_a,
126 | const uint8_t* src_b,
127 | int count);
128 | uint32_t SumSquareError_MMI(const uint8_t* src_a,
129 | const uint8_t* src_b,
130 | int count);
131 |
132 | uint32_t HashDjb2_C(const uint8_t* src, int count, uint32_t seed);
133 | uint32_t HashDjb2_SSE41(const uint8_t* src, int count, uint32_t seed);
134 | uint32_t HashDjb2_AVX2(const uint8_t* src, int count, uint32_t seed);
135 |
136 | #ifdef __cplusplus
137 | } // extern "C"
138 | } // namespace libyuv
139 | #endif
140 |
141 | #endif // INCLUDE_LIBYUV_COMPARE_ROW_H_
142 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv/convert_from.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_CONVERT_FROM_H_
12 | #define INCLUDE_LIBYUV_CONVERT_FROM_H_
13 |
14 | #include "libyuv/basic_types.h"
15 | #include "libyuv/rotate.h"
16 |
17 | #ifdef __cplusplus
18 | namespace libyuv {
19 | extern "C" {
20 | #endif
21 |
22 | // See Also convert.h for conversions from formats to I420.
23 |
24 | // Convert 8 bit YUV to 10 bit.
25 | #define H420ToH010 I420ToI010
26 | LIBYUV_API
27 | int I420ToI010(const uint8_t* src_y,
28 | int src_stride_y,
29 | const uint8_t* src_u,
30 | int src_stride_u,
31 | const uint8_t* src_v,
32 | int src_stride_v,
33 | uint16_t* dst_y,
34 | int dst_stride_y,
35 | uint16_t* dst_u,
36 | int dst_stride_u,
37 | uint16_t* dst_v,
38 | int dst_stride_v,
39 | int width,
40 | int height);
41 |
42 | LIBYUV_API
43 | int I420ToI422(const uint8_t* src_y,
44 | int src_stride_y,
45 | const uint8_t* src_u,
46 | int src_stride_u,
47 | const uint8_t* src_v,
48 | int src_stride_v,
49 | uint8_t* dst_y,
50 | int dst_stride_y,
51 | uint8_t* dst_u,
52 | int dst_stride_u,
53 | uint8_t* dst_v,
54 | int dst_stride_v,
55 | int width,
56 | int height);
57 |
58 | LIBYUV_API
59 | int I420ToI444(const uint8_t* src_y,
60 | int src_stride_y,
61 | const uint8_t* src_u,
62 | int src_stride_u,
63 | const uint8_t* src_v,
64 | int src_stride_v,
65 | uint8_t* dst_y,
66 | int dst_stride_y,
67 | uint8_t* dst_u,
68 | int dst_stride_u,
69 | uint8_t* dst_v,
70 | int dst_stride_v,
71 | int width,
72 | int height);
73 |
74 | // Copy to I400. Source can be I420, I422, I444, I400, NV12 or NV21.
75 | LIBYUV_API
76 | int I400Copy(const uint8_t* src_y,
77 | int src_stride_y,
78 | uint8_t* dst_y,
79 | int dst_stride_y,
80 | int width,
81 | int height);
82 |
83 | LIBYUV_API
84 | int I420ToNV12(const uint8_t* src_y,
85 | int src_stride_y,
86 | const uint8_t* src_u,
87 | int src_stride_u,
88 | const uint8_t* src_v,
89 | int src_stride_v,
90 | uint8_t* dst_y,
91 | int dst_stride_y,
92 | uint8_t* dst_uv,
93 | int dst_stride_uv,
94 | int width,
95 | int height);
96 |
97 | LIBYUV_API
98 | int I420ToNV21(const uint8_t* src_y,
99 | int src_stride_y,
100 | const uint8_t* src_u,
101 | int src_stride_u,
102 | const uint8_t* src_v,
103 | int src_stride_v,
104 | uint8_t* dst_y,
105 | int dst_stride_y,
106 | uint8_t* dst_vu,
107 | int dst_stride_vu,
108 | int width,
109 | int height);
110 |
111 | LIBYUV_API
112 | int I420ToYUY2(const uint8_t* src_y,
113 | int src_stride_y,
114 | const uint8_t* src_u,
115 | int src_stride_u,
116 | const uint8_t* src_v,
117 | int src_stride_v,
118 | uint8_t* dst_yuy2,
119 | int dst_stride_yuy2,
120 | int width,
121 | int height);
122 |
123 | LIBYUV_API
124 | int I420ToUYVY(const uint8_t* src_y,
125 | int src_stride_y,
126 | const uint8_t* src_u,
127 | int src_stride_u,
128 | const uint8_t* src_v,
129 | int src_stride_v,
130 | uint8_t* dst_uyvy,
131 | int dst_stride_uyvy,
132 | int width,
133 | int height);
134 |
135 | // Convert I420 to specified format.
136 | // "dst_sample_stride" is bytes in a row for the destination. Pass 0 if the
137 | // buffer has contiguous rows. Can be negative. A multiple of 16 is optimal.
138 | LIBYUV_API
139 | int ConvertFromI420(const uint8_t* y,
140 | int y_stride,
141 | const uint8_t* u,
142 | int u_stride,
143 | const uint8_t* v,
144 | int v_stride,
145 | uint8_t* dst_sample,
146 | int dst_sample_stride,
147 | int width,
148 | int height,
149 | uint32_t fourcc);
150 |
151 | #ifdef __cplusplus
152 | } // extern "C"
153 | } // namespace libyuv
154 | #endif
155 |
156 | #endif // INCLUDE_LIBYUV_CONVERT_FROM_H_
157 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv/cpu_id.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_CPU_ID_H_
12 | #define INCLUDE_LIBYUV_CPU_ID_H_
13 |
14 | #include "libyuv/basic_types.h"
15 |
16 | #ifdef __cplusplus
17 | namespace libyuv {
18 | extern "C" {
19 | #endif
20 |
21 | // Internal flag to indicate cpuid requires initialization.
22 | static const int kCpuInitialized = 0x1;
23 |
24 | // These flags are only valid on ARM processors.
25 | static const int kCpuHasARM = 0x2;
26 | static const int kCpuHasNEON = 0x4;
27 | // 0x8 reserved for future ARM flag.
28 |
29 | // These flags are only valid on x86 processors.
30 | static const int kCpuHasX86 = 0x10;
31 | static const int kCpuHasSSE2 = 0x20;
32 | static const int kCpuHasSSSE3 = 0x40;
33 | static const int kCpuHasSSE41 = 0x80;
34 | static const int kCpuHasSSE42 = 0x100; // unused at this time.
35 | static const int kCpuHasAVX = 0x200;
36 | static const int kCpuHasAVX2 = 0x400;
37 | static const int kCpuHasERMS = 0x800;
38 | static const int kCpuHasFMA3 = 0x1000;
39 | static const int kCpuHasF16C = 0x2000;
40 | static const int kCpuHasGFNI = 0x4000;
41 | static const int kCpuHasAVX512BW = 0x8000;
42 | static const int kCpuHasAVX512VL = 0x10000;
43 | static const int kCpuHasAVX512VBMI = 0x20000;
44 | static const int kCpuHasAVX512VBMI2 = 0x40000;
45 | static const int kCpuHasAVX512VBITALG = 0x80000;
46 | static const int kCpuHasAVX512VPOPCNTDQ = 0x100000;
47 |
48 | // These flags are only valid on MIPS processors.
49 | static const int kCpuHasMIPS = 0x200000;
50 | static const int kCpuHasMSA = 0x400000;
51 | static const int kCpuHasMMI = 0x800000;
52 |
53 | // Optional init function. TestCpuFlag does an auto-init.
54 | // Returns cpu_info flags.
55 | LIBYUV_API
56 | int InitCpuFlags(void);
57 |
58 | // Detect CPU has SSE2 etc.
59 | // Test_flag parameter should be one of kCpuHas constants above.
60 | // Returns non-zero if instruction set is detected
61 | static __inline int TestCpuFlag(int test_flag) {
62 | LIBYUV_API extern int cpu_info_;
63 | #ifdef __ATOMIC_RELAXED
64 | int cpu_info = __atomic_load_n(&cpu_info_, __ATOMIC_RELAXED);
65 | #else
66 | int cpu_info = cpu_info_;
67 | #endif
68 | return (!cpu_info ? InitCpuFlags() : cpu_info) & test_flag;
69 | }
70 |
71 | // Internal function for parsing /proc/cpuinfo.
72 | LIBYUV_API
73 | int ArmCpuCaps(const char* cpuinfo_name);
74 | LIBYUV_API
75 | int MipsCpuCaps(const char* cpuinfo_name);
76 |
77 | // For testing, allow CPU flags to be disabled.
78 | // ie MaskCpuFlags(~kCpuHasSSSE3) to disable SSSE3.
79 | // MaskCpuFlags(-1) to enable all cpu specific optimizations.
80 | // MaskCpuFlags(1) to disable all cpu specific optimizations.
81 | // MaskCpuFlags(0) to reset state so next call will auto init.
82 | // Returns cpu_info flags.
83 | LIBYUV_API
84 | int MaskCpuFlags(int enable_flags);
85 |
86 | // Sets the CPU flags to |cpu_flags|, bypassing the detection code. |cpu_flags|
87 | // should be a valid combination of the kCpuHas constants above and include
88 | // kCpuInitialized. Use this method when running in a sandboxed process where
89 | // the detection code might fail (as it might access /proc/cpuinfo). In such
90 | // cases the cpu_info can be obtained from a non sandboxed process by calling
91 | // InitCpuFlags() and passed to the sandboxed process (via command line
92 | // parameters, IPC...) which can then call this method to initialize the CPU
93 | // flags.
94 | // Notes:
95 | // - when specifying 0 for |cpu_flags|, the auto initialization is enabled
96 | // again.
97 | // - enabling CPU features that are not supported by the CPU will result in
98 | // undefined behavior.
99 | // TODO(fbarchard): consider writing a helper function that translates from
100 | // other library CPU info to libyuv CPU info and add a .md doc that explains
101 | // CPU detection.
102 | static __inline void SetCpuFlags(int cpu_flags) {
103 | LIBYUV_API extern int cpu_info_;
104 | #ifdef __ATOMIC_RELAXED
105 | __atomic_store_n(&cpu_info_, cpu_flags, __ATOMIC_RELAXED);
106 | #else
107 | cpu_info_ = cpu_flags;
108 | #endif
109 | }
110 |
111 | // Low level cpuid for X86. Returns zeros on other CPUs.
112 | // eax is the info type that you want.
113 | // ecx is typically the cpu number, and should normally be zero.
114 | LIBYUV_API
115 | void CpuId(int info_eax, int info_ecx, int* cpu_info);
116 |
117 | #ifdef __cplusplus
118 | } // extern "C"
119 | } // namespace libyuv
120 | #endif
121 |
122 | #endif // INCLUDE_LIBYUV_CPU_ID_H_
123 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv/mjpeg_decoder.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_MJPEG_DECODER_H_
12 | #define INCLUDE_LIBYUV_MJPEG_DECODER_H_
13 |
14 | #include "libyuv/basic_types.h"
15 |
16 | #ifdef __cplusplus
17 | // NOTE: For a simplified public API use convert.h MJPGToI420().
18 |
19 | struct jpeg_common_struct;
20 | struct jpeg_decompress_struct;
21 | struct jpeg_source_mgr;
22 |
23 | namespace libyuv {
24 |
25 | #ifdef __cplusplus
26 | extern "C" {
27 | #endif
28 |
29 | LIBYUV_BOOL ValidateJpeg(const uint8_t* sample, size_t sample_size);
30 |
31 | #ifdef __cplusplus
32 | } // extern "C"
33 | #endif
34 |
35 | static const uint32_t kUnknownDataSize = 0xFFFFFFFF;
36 |
37 | enum JpegSubsamplingType {
38 | kJpegYuv420,
39 | kJpegYuv422,
40 | kJpegYuv444,
41 | kJpegYuv400,
42 | kJpegUnknown
43 | };
44 |
45 | struct Buffer {
46 | const uint8_t* data;
47 | int len;
48 | };
49 |
50 | struct BufferVector {
51 | Buffer* buffers;
52 | int len;
53 | int pos;
54 | };
55 |
56 | struct SetJmpErrorMgr;
57 |
58 | // MJPEG ("Motion JPEG") is a pseudo-standard video codec where the frames are
59 | // simply independent JPEG images with a fixed huffman table (which is omitted).
60 | // It is rarely used in video transmission, but is common as a camera capture
61 | // format, especially in Logitech devices. This class implements a decoder for
62 | // MJPEG frames.
63 | //
64 | // See http://tools.ietf.org/html/rfc2435
65 | class LIBYUV_API MJpegDecoder {
66 | public:
67 | typedef void (*CallbackFunction)(void* opaque,
68 | const uint8_t* const* data,
69 | const int* strides,
70 | int rows);
71 |
72 | static const int kColorSpaceUnknown;
73 | static const int kColorSpaceGrayscale;
74 | static const int kColorSpaceRgb;
75 | static const int kColorSpaceYCbCr;
76 | static const int kColorSpaceCMYK;
77 | static const int kColorSpaceYCCK;
78 |
79 | MJpegDecoder();
80 | ~MJpegDecoder();
81 |
82 | // Loads a new frame, reads its headers, and determines the uncompressed
83 | // image format.
84 | // Returns LIBYUV_TRUE if image looks valid and format is supported.
85 | // If return value is LIBYUV_TRUE, then the values for all the following
86 | // getters are populated.
87 | // src_len is the size of the compressed mjpeg frame in bytes.
88 | LIBYUV_BOOL LoadFrame(const uint8_t* src, size_t src_len);
89 |
90 | // Returns width of the last loaded frame in pixels.
91 | int GetWidth();
92 |
93 | // Returns height of the last loaded frame in pixels.
94 | int GetHeight();
95 |
96 | // Returns format of the last loaded frame. The return value is one of the
97 | // kColorSpace* constants.
98 | int GetColorSpace();
99 |
100 | // Number of color components in the color space.
101 | int GetNumComponents();
102 |
103 | // Sample factors of the n-th component.
104 | int GetHorizSampFactor(int component);
105 |
106 | int GetVertSampFactor(int component);
107 |
108 | int GetHorizSubSampFactor(int component);
109 |
110 | int GetVertSubSampFactor(int component);
111 |
112 | // Public for testability.
113 | int GetImageScanlinesPerImcuRow();
114 |
115 | // Public for testability.
116 | int GetComponentScanlinesPerImcuRow(int component);
117 |
118 | // Width of a component in bytes.
119 | int GetComponentWidth(int component);
120 |
121 | // Height of a component.
122 | int GetComponentHeight(int component);
123 |
124 | // Width of a component in bytes with padding for DCTSIZE. Public for testing.
125 | int GetComponentStride(int component);
126 |
127 | // Size of a component in bytes.
128 | int GetComponentSize(int component);
129 |
130 | // Call this after LoadFrame() if you decide you don't want to decode it
131 | // after all.
132 | LIBYUV_BOOL UnloadFrame();
133 |
134 | // Decodes the entire image into a one-buffer-per-color-component format.
135 | // dst_width must match exactly. dst_height must be <= to image height; if
136 | // less, the image is cropped. "planes" must have size equal to at least
137 | // GetNumComponents() and they must point to non-overlapping buffers of size
138 | // at least GetComponentSize(i). The pointers in planes are incremented
139 | // to point to after the end of the written data.
140 | // TODO(fbarchard): Add dst_x, dst_y to allow specific rect to be decoded.
141 | LIBYUV_BOOL DecodeToBuffers(uint8_t** planes, int dst_width, int dst_height);
142 |
143 | // Decodes the entire image and passes the data via repeated calls to a
144 | // callback function. Each call will get the data for a whole number of
145 | // image scanlines.
146 | // TODO(fbarchard): Add dst_x, dst_y to allow specific rect to be decoded.
147 | LIBYUV_BOOL DecodeToCallback(CallbackFunction fn,
148 | void* opaque,
149 | int dst_width,
150 | int dst_height);
151 |
152 | // The helper function which recognizes the jpeg sub-sampling type.
153 | static JpegSubsamplingType JpegSubsamplingTypeHelper(
154 | int* subsample_x,
155 | int* subsample_y,
156 | int number_of_components);
157 |
158 | private:
159 | void AllocOutputBuffers(int num_outbufs);
160 | void DestroyOutputBuffers();
161 |
162 | LIBYUV_BOOL StartDecode();
163 | LIBYUV_BOOL FinishDecode();
164 |
165 | void SetScanlinePointers(uint8_t** data);
166 | LIBYUV_BOOL DecodeImcuRow();
167 |
168 | int GetComponentScanlinePadding(int component);
169 |
170 | // A buffer holding the input data for a frame.
171 | Buffer buf_;
172 | BufferVector buf_vec_;
173 |
174 | jpeg_decompress_struct* decompress_struct_;
175 | jpeg_source_mgr* source_mgr_;
176 | SetJmpErrorMgr* error_mgr_;
177 |
178 | // LIBYUV_TRUE iff at least one component has scanline padding. (i.e.,
179 | // GetComponentScanlinePadding() != 0.)
180 | LIBYUV_BOOL has_scanline_padding_;
181 |
182 | // Temporaries used to point to scanline outputs.
183 | int num_outbufs_; // Outermost size of all arrays below.
184 | uint8_t*** scanlines_;
185 | int* scanlines_sizes_;
186 | // Temporary buffer used for decoding when we can't decode directly to the
187 | // output buffers. Large enough for just one iMCU row.
188 | uint8_t** databuf_;
189 | int* databuf_strides_;
190 | };
191 |
192 | } // namespace libyuv
193 |
194 | #endif // __cplusplus
195 | #endif // INCLUDE_LIBYUV_MJPEG_DECODER_H_
196 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv/rotate.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_ROTATE_H_
12 | #define INCLUDE_LIBYUV_ROTATE_H_
13 |
14 | #include "libyuv/basic_types.h"
15 |
16 | #ifdef __cplusplus
17 | namespace libyuv {
18 | extern "C" {
19 | #endif
20 |
21 | // Supported rotation.
22 | typedef enum RotationMode {
23 | kRotate0 = 0, // No rotation.
24 | kRotate90 = 90, // Rotate 90 degrees clockwise.
25 | kRotate180 = 180, // Rotate 180 degrees.
26 | kRotate270 = 270, // Rotate 270 degrees clockwise.
27 |
28 | // Deprecated.
29 | kRotateNone = 0,
30 | kRotateClockwise = 90,
31 | kRotateCounterClockwise = 270,
32 | } RotationModeEnum;
33 |
34 | // Rotate I420 frame.
35 | LIBYUV_API
36 | int I420Rotate(const uint8_t* src_y,
37 | int src_stride_y,
38 | const uint8_t* src_u,
39 | int src_stride_u,
40 | const uint8_t* src_v,
41 | int src_stride_v,
42 | uint8_t* dst_y,
43 | int dst_stride_y,
44 | uint8_t* dst_u,
45 | int dst_stride_u,
46 | uint8_t* dst_v,
47 | int dst_stride_v,
48 | int width,
49 | int height,
50 | enum RotationMode mode);
51 |
52 | // Rotate I444 frame.
53 | LIBYUV_API
54 | int I444Rotate(const uint8_t* src_y,
55 | int src_stride_y,
56 | const uint8_t* src_u,
57 | int src_stride_u,
58 | const uint8_t* src_v,
59 | int src_stride_v,
60 | uint8_t* dst_y,
61 | int dst_stride_y,
62 | uint8_t* dst_u,
63 | int dst_stride_u,
64 | uint8_t* dst_v,
65 | int dst_stride_v,
66 | int width,
67 | int height,
68 | enum RotationMode mode);
69 |
70 | // Rotate NV12 input and store in I420.
71 | LIBYUV_API
72 | int NV12ToI420Rotate(const uint8_t* src_y,
73 | int src_stride_y,
74 | const uint8_t* src_uv,
75 | int src_stride_uv,
76 | uint8_t* dst_y,
77 | int dst_stride_y,
78 | uint8_t* dst_u,
79 | int dst_stride_u,
80 | uint8_t* dst_v,
81 | int dst_stride_v,
82 | int width,
83 | int height,
84 | enum RotationMode mode);
85 |
86 | // Rotate a plane by 0, 90, 180, or 270.
87 | LIBYUV_API
88 | int RotatePlane(const uint8_t* src,
89 | int src_stride,
90 | uint8_t* dst,
91 | int dst_stride,
92 | int width,
93 | int height,
94 | enum RotationMode mode);
95 |
96 | // Rotate planes by 90, 180, 270. Deprecated.
97 | LIBYUV_API
98 | void RotatePlane90(const uint8_t* src,
99 | int src_stride,
100 | uint8_t* dst,
101 | int dst_stride,
102 | int width,
103 | int height);
104 |
105 | LIBYUV_API
106 | void RotatePlane180(const uint8_t* src,
107 | int src_stride,
108 | uint8_t* dst,
109 | int dst_stride,
110 | int width,
111 | int height);
112 |
113 | LIBYUV_API
114 | void RotatePlane270(const uint8_t* src,
115 | int src_stride,
116 | uint8_t* dst,
117 | int dst_stride,
118 | int width,
119 | int height);
120 |
121 | // Rotations for when U and V are interleaved.
122 | // These functions take one input pointer and
123 | // split the data into two buffers while
124 | // rotating them. Deprecated.
125 | LIBYUV_API
126 | void RotateUV90(const uint8_t* src,
127 | int src_stride,
128 | uint8_t* dst_a,
129 | int dst_stride_a,
130 | uint8_t* dst_b,
131 | int dst_stride_b,
132 | int width,
133 | int height);
134 |
135 | LIBYUV_API
136 | void RotateUV180(const uint8_t* src,
137 | int src_stride,
138 | uint8_t* dst_a,
139 | int dst_stride_a,
140 | uint8_t* dst_b,
141 | int dst_stride_b,
142 | int width,
143 | int height);
144 |
145 | LIBYUV_API
146 | void RotateUV270(const uint8_t* src,
147 | int src_stride,
148 | uint8_t* dst_a,
149 | int dst_stride_a,
150 | uint8_t* dst_b,
151 | int dst_stride_b,
152 | int width,
153 | int height);
154 |
155 | // The 90 and 270 functions are based on transposes.
156 | // Doing a transpose with reversing the read/write
157 | // order will result in a rotation by +- 90 degrees.
158 | // Deprecated.
159 | LIBYUV_API
160 | void TransposePlane(const uint8_t* src,
161 | int src_stride,
162 | uint8_t* dst,
163 | int dst_stride,
164 | int width,
165 | int height);
166 |
167 | LIBYUV_API
168 | void TransposeUV(const uint8_t* src,
169 | int src_stride,
170 | uint8_t* dst_a,
171 | int dst_stride_a,
172 | uint8_t* dst_b,
173 | int dst_stride_b,
174 | int width,
175 | int height);
176 |
177 | #ifdef __cplusplus
178 | } // extern "C"
179 | } // namespace libyuv
180 | #endif
181 |
182 | #endif // INCLUDE_LIBYUV_ROTATE_H_
183 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv/rotate_argb.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_ROTATE_ARGB_H_
12 | #define INCLUDE_LIBYUV_ROTATE_ARGB_H_
13 |
14 | #include "libyuv/basic_types.h"
15 | #include "libyuv/rotate.h" // For RotationMode.
16 |
17 | #ifdef __cplusplus
18 | namespace libyuv {
19 | extern "C" {
20 | #endif
21 |
22 | // Rotate ARGB frame
23 | LIBYUV_API
24 | int ARGBRotate(const uint8_t* src_argb,
25 | int src_stride_argb,
26 | uint8_t* dst_argb,
27 | int dst_stride_argb,
28 | int src_width,
29 | int src_height,
30 | enum RotationMode mode);
31 |
32 | #ifdef __cplusplus
33 | } // extern "C"
34 | } // namespace libyuv
35 | #endif
36 |
37 | #endif // INCLUDE_LIBYUV_ROTATE_ARGB_H_
38 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv/scale.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_SCALE_H_
12 | #define INCLUDE_LIBYUV_SCALE_H_
13 |
14 | #include "libyuv/basic_types.h"
15 |
16 | #ifdef __cplusplus
17 | namespace libyuv {
18 | extern "C" {
19 | #endif
20 |
21 | // Supported filtering.
22 | typedef enum FilterMode {
23 | kFilterNone = 0, // Point sample; Fastest.
24 | kFilterLinear = 1, // Filter horizontally only.
25 | kFilterBilinear = 2, // Faster than box, but lower quality scaling down.
26 | kFilterBox = 3 // Highest quality.
27 | } FilterModeEnum;
28 |
29 | // Scale a YUV plane.
30 | LIBYUV_API
31 | void ScalePlane(const uint8_t* src,
32 | int src_stride,
33 | int src_width,
34 | int src_height,
35 | uint8_t* dst,
36 | int dst_stride,
37 | int dst_width,
38 | int dst_height,
39 | enum FilterMode filtering);
40 |
41 | LIBYUV_API
42 | void ScalePlane_16(const uint16_t* src,
43 | int src_stride,
44 | int src_width,
45 | int src_height,
46 | uint16_t* dst,
47 | int dst_stride,
48 | int dst_width,
49 | int dst_height,
50 | enum FilterMode filtering);
51 |
52 | // Scales a YUV 4:2:0 image from the src width and height to the
53 | // dst width and height.
54 | // If filtering is kFilterNone, a simple nearest-neighbor algorithm is
55 | // used. This produces basic (blocky) quality at the fastest speed.
56 | // If filtering is kFilterBilinear, interpolation is used to produce a better
57 | // quality image, at the expense of speed.
58 | // If filtering is kFilterBox, averaging is used to produce ever better
59 | // quality image, at further expense of speed.
60 | // Returns 0 if successful.
61 |
62 | LIBYUV_API
63 | int I420Scale(const uint8_t* src_y,
64 | int src_stride_y,
65 | const uint8_t* src_u,
66 | int src_stride_u,
67 | const uint8_t* src_v,
68 | int src_stride_v,
69 | int src_width,
70 | int src_height,
71 | uint8_t* dst_y,
72 | int dst_stride_y,
73 | uint8_t* dst_u,
74 | int dst_stride_u,
75 | uint8_t* dst_v,
76 | int dst_stride_v,
77 | int dst_width,
78 | int dst_height,
79 | enum FilterMode filtering);
80 |
81 | LIBYUV_API
82 | int I420Scale_16(const uint16_t* src_y,
83 | int src_stride_y,
84 | const uint16_t* src_u,
85 | int src_stride_u,
86 | const uint16_t* src_v,
87 | int src_stride_v,
88 | int src_width,
89 | int src_height,
90 | uint16_t* dst_y,
91 | int dst_stride_y,
92 | uint16_t* dst_u,
93 | int dst_stride_u,
94 | uint16_t* dst_v,
95 | int dst_stride_v,
96 | int dst_width,
97 | int dst_height,
98 | enum FilterMode filtering);
99 |
100 | // Scales a YUV 4:4:4 image from the src width and height to the
101 | // dst width and height.
102 | // If filtering is kFilterNone, a simple nearest-neighbor algorithm is
103 | // used. This produces basic (blocky) quality at the fastest speed.
104 | // If filtering is kFilterBilinear, interpolation is used to produce a better
105 | // quality image, at the expense of speed.
106 | // If filtering is kFilterBox, averaging is used to produce ever better
107 | // quality image, at further expense of speed.
108 | // Returns 0 if successful.
109 |
110 | LIBYUV_API
111 | int I444Scale(const uint8_t* src_y,
112 | int src_stride_y,
113 | const uint8_t* src_u,
114 | int src_stride_u,
115 | const uint8_t* src_v,
116 | int src_stride_v,
117 | int src_width,
118 | int src_height,
119 | uint8_t* dst_y,
120 | int dst_stride_y,
121 | uint8_t* dst_u,
122 | int dst_stride_u,
123 | uint8_t* dst_v,
124 | int dst_stride_v,
125 | int dst_width,
126 | int dst_height,
127 | enum FilterMode filtering);
128 |
129 | LIBYUV_API
130 | int I444Scale_16(const uint16_t* src_y,
131 | int src_stride_y,
132 | const uint16_t* src_u,
133 | int src_stride_u,
134 | const uint16_t* src_v,
135 | int src_stride_v,
136 | int src_width,
137 | int src_height,
138 | uint16_t* dst_y,
139 | int dst_stride_y,
140 | uint16_t* dst_u,
141 | int dst_stride_u,
142 | uint16_t* dst_v,
143 | int dst_stride_v,
144 | int dst_width,
145 | int dst_height,
146 | enum FilterMode filtering);
147 |
148 | #ifdef __cplusplus
149 | // Legacy API. Deprecated.
150 | LIBYUV_API
151 | int Scale(const uint8_t* src_y,
152 | const uint8_t* src_u,
153 | const uint8_t* src_v,
154 | int src_stride_y,
155 | int src_stride_u,
156 | int src_stride_v,
157 | int src_width,
158 | int src_height,
159 | uint8_t* dst_y,
160 | uint8_t* dst_u,
161 | uint8_t* dst_v,
162 | int dst_stride_y,
163 | int dst_stride_u,
164 | int dst_stride_v,
165 | int dst_width,
166 | int dst_height,
167 | LIBYUV_BOOL interpolate);
168 |
169 | // For testing, allow disabling of specialized scalers.
170 | LIBYUV_API
171 | void SetUseReferenceImpl(LIBYUV_BOOL use);
172 | #endif // __cplusplus
173 |
174 | #ifdef __cplusplus
175 | } // extern "C"
176 | } // namespace libyuv
177 | #endif
178 |
179 | #endif // INCLUDE_LIBYUV_SCALE_H_
180 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv/scale_argb.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_SCALE_ARGB_H_
12 | #define INCLUDE_LIBYUV_SCALE_ARGB_H_
13 |
14 | #include "libyuv/basic_types.h"
15 | #include "libyuv/scale.h" // For FilterMode
16 |
17 | #ifdef __cplusplus
18 | namespace libyuv {
19 | extern "C" {
20 | #endif
21 |
22 | LIBYUV_API
23 | int ARGBScale(const uint8_t* src_argb,
24 | int src_stride_argb,
25 | int src_width,
26 | int src_height,
27 | uint8_t* dst_argb,
28 | int dst_stride_argb,
29 | int dst_width,
30 | int dst_height,
31 | enum FilterMode filtering);
32 |
33 | // Clipped scale takes destination rectangle coordinates for clip values.
34 | LIBYUV_API
35 | int ARGBScaleClip(const uint8_t* src_argb,
36 | int src_stride_argb,
37 | int src_width,
38 | int src_height,
39 | uint8_t* dst_argb,
40 | int dst_stride_argb,
41 | int dst_width,
42 | int dst_height,
43 | int clip_x,
44 | int clip_y,
45 | int clip_width,
46 | int clip_height,
47 | enum FilterMode filtering);
48 |
49 | // Scale with YUV conversion to ARGB and clipping.
50 | LIBYUV_API
51 | int YUVToARGBScaleClip(const uint8_t* src_y,
52 | int src_stride_y,
53 | const uint8_t* src_u,
54 | int src_stride_u,
55 | const uint8_t* src_v,
56 | int src_stride_v,
57 | uint32_t src_fourcc,
58 | int src_width,
59 | int src_height,
60 | uint8_t* dst_argb,
61 | int dst_stride_argb,
62 | uint32_t dst_fourcc,
63 | int dst_width,
64 | int dst_height,
65 | int clip_x,
66 | int clip_y,
67 | int clip_width,
68 | int clip_height,
69 | enum FilterMode filtering);
70 |
71 | #ifdef __cplusplus
72 | } // extern "C"
73 | } // namespace libyuv
74 | #endif
75 |
76 | #endif // INCLUDE_LIBYUV_SCALE_ARGB_H_
77 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv/libyuv/version.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef INCLUDE_LIBYUV_VERSION_H_
12 | #define INCLUDE_LIBYUV_VERSION_H_
13 |
14 | #define LIBYUV_VERSION 1759
15 |
16 | #endif // INCLUDE_LIBYUV_VERSION_H_
17 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/cpp/yuv_convert.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "libyuv.h"
5 |
6 |
7 | extern "C" JNIEXPORT void JNICALL
8 | Java_com_rtmpx_library_yuv_YuvHelper_rotate(JNIEnv *env, jclass thiz, jobject y, jobject u,
9 | jobject v, jint yStride, jint uStride, jint vStride,
10 | jobject yOut, jobject uOut, jobject vOut,
11 | jint yOutStride, jint uOutStride, jint vOutStride,
12 | jint width, jint height, jint rotationMode) {
13 |
14 | uint8_t *yNative = (uint8_t *) env->GetDirectBufferAddress(y);
15 | uint8_t *uNative = (uint8_t *) env->GetDirectBufferAddress(u);
16 | uint8_t *vNative = (uint8_t *) env->GetDirectBufferAddress(v);
17 |
18 | uint8_t *yOutNative = (uint8_t *) env->GetDirectBufferAddress(yOut);
19 | uint8_t *uOutNative = (uint8_t *) env->GetDirectBufferAddress(uOut);
20 | uint8_t *vOutNative = (uint8_t *) env->GetDirectBufferAddress(vOut);
21 |
22 | libyuv::I420Rotate(yNative, yStride,
23 | uNative, uStride,
24 | vNative, vStride,
25 | yOutNative, yOutStride,
26 | uOutNative, uOutStride,
27 | vOutNative, vOutStride,
28 | width, height,
29 | libyuv::RotationMode(rotationMode));
30 | }
31 |
32 | extern "C" JNIEXPORT void JNICALL
33 | Java_com_rtmpx_library_yuv_YuvHelper_convertToI420(JNIEnv *env, jclass thiz, jobject y, jobject u,
34 | jobject v, jint yStride, jint uStride,
35 | jint vStride, jint srcPixelStrideUv,
36 | jobject yOut, jobject uOut, jobject vOut,
37 | jint yOutStride, jint uOutStride, jint vOutStride,
38 | jint width, jint height) {
39 |
40 | uint8_t *yNative = (uint8_t *) env->GetDirectBufferAddress(y);
41 | uint8_t *uNative = (uint8_t *) env->GetDirectBufferAddress(u);
42 | uint8_t *vNative = (uint8_t *) env->GetDirectBufferAddress(v);
43 |
44 | uint8_t *yOutNative = (uint8_t *) env->GetDirectBufferAddress(yOut);
45 | uint8_t *uOutNative = (uint8_t *) env->GetDirectBufferAddress(uOut);
46 | uint8_t *vOutNative = (uint8_t *) env->GetDirectBufferAddress(vOut);
47 |
48 | libyuv::Android420ToI420(yNative, yStride,
49 | uNative, uStride,
50 | vNative, vStride,
51 | srcPixelStrideUv,
52 | yOutNative, yOutStride,
53 | uOutNative, uOutStride,
54 | vOutNative, vOutStride,
55 | width, height);
56 | }
57 | extern "C"
58 | JNIEXPORT void JNICALL
59 | Java_com_rtmpx_library_yuv_YuvHelper_I420ToNV12(JNIEnv *env, jclass clazz,
60 | jbyteArray i420_src, jint width,
61 | jint height, jbyteArray nv12_dst) {
62 | jbyte *src_i420_data = env->GetByteArrayElements(i420_src, NULL);
63 | jbyte *dst_nv12_data = env->GetByteArrayElements(nv12_dst, NULL);
64 | jint src_y_size = width * height;
65 | jint src_u_size = (width >> 1) * (height >> 1);
66 |
67 | jbyte *src_nv12_y_data = dst_nv12_data;
68 | jbyte *src_nv12_uv_data = dst_nv12_data + src_y_size;
69 |
70 | jbyte *src_i420_y_data = src_i420_data;
71 | jbyte *src_i420_u_data = src_i420_data + src_y_size;
72 | jbyte *src_i420_v_data = src_i420_data + src_y_size + src_u_size;
73 |
74 | libyuv::I420ToNV12(
75 | (const uint8_t *) src_i420_y_data, width,
76 | (const uint8_t *) src_i420_u_data, width >> 1,
77 | (const uint8_t *) src_i420_v_data, width >> 1,
78 | (uint8_t *) src_nv12_y_data, width,
79 | (uint8_t *) src_nv12_uv_data, width,
80 | width, height);
81 |
82 |
83 | env->ReleaseByteArrayElements(i420_src, src_i420_data, 0);
84 | env->ReleaseByteArrayElements(nv12_dst, dst_nv12_data, 0);
85 |
86 | }
87 |
88 |
89 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/camera/ICamera.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.camera;
2 |
3 | import android.graphics.Rect;
4 | import android.util.Size;
5 |
6 | import java.io.File;
7 |
8 | public interface ICamera {
9 | /**
10 | * Start preview
11 | */
12 | void startPreview();
13 |
14 | /**
15 | * Stop preview
16 | */
17 | void stopPreview();
18 |
19 | /**
20 | * Whether to support zoom
21 | *
22 | * @return camera support zoom or not
23 | */
24 | default boolean supportZoom() {
25 | return true;
26 | }
27 |
28 | /**
29 | * Get the camera's maximum variable focal length
30 | *
31 | * @return camera max zoom level
32 | */
33 | float getMaxZoom();
34 |
35 | /**
36 | * Obtain the minimum variable focal length of the camera
37 | *
38 | * @return camera min zoom level
39 | */
40 | float getMinZoom();
41 |
42 | /**
43 | * Get the current focal length of the camera
44 | *
45 | * @return camera current zoom level
46 | */
47 | float getZoom();
48 |
49 | /**
50 | * Set zoom
51 | *
52 | * @param level 变焦等级 0 ~ {@link #getMaxZoom()}
53 | */
54 | void setZoom(float level);
55 |
56 | /**
57 | * Get the minimum exposure level
58 | *
59 | * @return camera min exposure level
60 | */
61 | int getMinExposureCompensation();
62 |
63 | /**
64 | * Get the maximum exposure level
65 | *
66 | * @return camera max exposure level
67 | */
68 | int getMaxExposureCompensation();
69 |
70 | /**
71 | *Get exposure level
72 | *
73 | * @return camera current exposure level
74 | */
75 | int getExposureCompensation();
76 |
77 | /**
78 | * Set the exposure level
79 | *
80 | * @param value {@link #getMinExposureCompensation()} ~ {@link #getMaxExposureCompensation()}
81 | */
82 | void setExposureCompensation(int value);
83 |
84 | /**
85 | * Set auto exposure
86 | *
87 | * @param toggle true ——> auto false——>manual
88 | */
89 | void setAutoExposure(boolean toggle);
90 |
91 | /**
92 | * Auto exposure {@link #setAutoExposure(boolean)}
93 | *
94 | * @return camera auto exposure or not
95 | */
96 | boolean autoExposure();
97 |
98 | /**
99 | * auto focus
100 | */
101 | void autoFocus();
102 |
103 | /**
104 | * Manual focus
105 | *
106 | * @param rect Focus area
107 | */
108 | void manualFocus(Rect rect);
109 |
110 | /**
111 | * Get camera id
112 | *
113 | * @return current camera id
114 | */
115 | int getCameraId();
116 |
117 | /**
118 | * Switch camera
119 | *
120 | * @param cameraId 相机id {@link #getCameraId()}
121 | */
122 | void switchCamera(int cameraId);
123 |
124 | /**
125 | * Set preview callback
126 | *
127 | * @param previewCallback
128 | */
129 | void setPreviewCallback(ICameraPreviewCallback previewCallback);
130 |
131 | /**
132 | * freed
133 | */
134 | void release();
135 |
136 | }
137 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/camera/ICameraPreviewCallback.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.camera;
2 |
3 | import androidx.camera.core.ImageProxy;
4 |
5 | public abstract class ICameraPreviewCallback {
6 |
7 | /**
8 | * get a preview frame raw data
9 | * @param image
10 | * @param rotation
11 | */
12 | public void onPreviewFrame(ImageProxy image, int rotation) {
13 | handleImage(image,rotation);
14 | image.close();
15 | }
16 |
17 | /**
18 | * handle a preview frame must close image
19 | * @param image
20 | * @param rotation
21 | */
22 | public abstract void handleImage(ImageProxy image, int rotation);
23 | }
24 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/config/Config.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.config;
2 |
3 | import static com.rtmpx.library.config.Const.RTMP_DEFAULT_BITRATE;
4 | import static com.rtmpx.library.config.Const.RTMP_DEFAULT_FRAME_RATE;
5 | import static com.rtmpx.library.config.Const.RTMP_DEFAULT_VIDEO_HEIGHT;
6 | import static com.rtmpx.library.config.Const.RTMP_DEFAULT_VIDEO_WIDTH;
7 | import static com.rtmpx.library.config.Const.RTMP_I_FRAME_INTERVAL;
8 | import static com.rtmpx.library.config.Const.RTMP_TEST_PUSH_URL;
9 |
10 | public class Config {
11 | /**
12 | * bitrate
13 | */
14 | private int mBitRate = RTMP_DEFAULT_BITRATE;//default 2m
15 | /**
16 | * fps frame rate
17 | */
18 | private int mFrameRate = RTMP_DEFAULT_FRAME_RATE; //default 30fps
19 | /**
20 | * GOP
21 | */
22 | private int mIFrameInterval = RTMP_I_FRAME_INTERVAL; //default 2s
23 | /**
24 | * preview width
25 | */
26 | private int mVideoWidth = RTMP_DEFAULT_VIDEO_WIDTH;
27 |
28 | /**
29 | * preview height
30 | */
31 | private int mVideoHeight = RTMP_DEFAULT_VIDEO_HEIGHT;
32 |
33 | /**
34 | * publish url
35 | */
36 | private String mPublishUrl = RTMP_TEST_PUSH_URL;
37 |
38 | /**
39 | * video record
40 | */
41 | private boolean mRecordVideo = false;
42 | /**
43 | * video save path
44 | */
45 | private String mRecordVideoPath;
46 |
47 |
48 | private Config() {
49 |
50 | }
51 |
52 | public int getBitRate() {
53 | return mBitRate;
54 | }
55 |
56 | public int getFrameRate() {
57 | return mFrameRate;
58 | }
59 |
60 | public int getIFrameInterval() {
61 | return mIFrameInterval;
62 | }
63 |
64 | public int getVideoWidth() {
65 | return mVideoWidth;
66 | }
67 |
68 | public int getVideoHeight() {
69 | return mVideoHeight;
70 | }
71 |
72 | public String getPublishUrl() {
73 | return mPublishUrl;
74 | }
75 |
76 | public boolean isRecordVideo() {
77 | return mRecordVideo;
78 | }
79 |
80 | public String getRecordVideoPath() {
81 | return mRecordVideoPath;
82 | }
83 |
84 |
85 | public static final class ConfigBuilder {
86 | /**
87 | * bitrate
88 | */
89 | private int mBitRate = RTMP_DEFAULT_BITRATE;//default 2m
90 | /**
91 | * fps frame rate
92 | */
93 | private int mFrameRate = RTMP_DEFAULT_FRAME_RATE; //default 30fps
94 | /**
95 | * GOP
96 | */
97 | private int mIFrameInterval = RTMP_I_FRAME_INTERVAL; //default 10s
98 | /**
99 | * preview width
100 | */
101 | private int mVideoWidth = RTMP_DEFAULT_VIDEO_WIDTH;
102 |
103 | /**
104 | * preview height
105 | */
106 | private int mVideoHeight = RTMP_DEFAULT_VIDEO_HEIGHT;
107 |
108 | /**
109 | * publish url
110 | */
111 | private String mPublishUrl = RTMP_TEST_PUSH_URL;
112 |
113 | /**
114 | * video record
115 | */
116 | private boolean mRecordVideo = false;
117 | /**
118 | * video save path
119 | */
120 | private String mRecordVideoPath;
121 |
122 | public ConfigBuilder() {
123 | }
124 |
125 | public ConfigBuilder withBitRate(int mBitRate) {
126 | this.mBitRate = mBitRate;
127 | return this;
128 | }
129 |
130 | public ConfigBuilder withFrameRate(int mFrameRate) {
131 | this.mFrameRate = mFrameRate;
132 | return this;
133 | }
134 |
135 | public ConfigBuilder withIFrameInterval(int mIFrameInterval) {
136 | this.mIFrameInterval = mIFrameInterval;
137 | return this;
138 | }
139 |
140 | public ConfigBuilder withVideoWidth(int mVideoWidth) {
141 | this.mVideoWidth = mVideoWidth;
142 | return this;
143 | }
144 |
145 | public ConfigBuilder withVideoHeight(int mVideoHeight) {
146 | this.mVideoHeight = mVideoHeight;
147 | return this;
148 | }
149 |
150 | public ConfigBuilder withPublishUrl(String mPublishUrl) {
151 | this.mPublishUrl = mPublishUrl;
152 | return this;
153 | }
154 | public ConfigBuilder withRecordVideo(boolean mRecordVideo) {
155 | this.mRecordVideo = mRecordVideo;
156 | return this;
157 | }
158 | public ConfigBuilder withRecordVideoPath(String mRecordVideoPath) {
159 | this.mRecordVideoPath = mRecordVideoPath;
160 | return this;
161 | }
162 |
163 | public Config build() {
164 | Config vRConfig = new Config();
165 | vRConfig.mIFrameInterval = this.mIFrameInterval;
166 | vRConfig.mFrameRate = this.mFrameRate;
167 | vRConfig.mVideoWidth = this.mVideoWidth;
168 | vRConfig.mVideoHeight = this.mVideoHeight;
169 | vRConfig.mPublishUrl = this.mPublishUrl;
170 | vRConfig.mBitRate = this.mBitRate;
171 | vRConfig.mRecordVideo = this.mRecordVideo;
172 | vRConfig.mRecordVideoPath = this.mRecordVideoPath;
173 |
174 | return vRConfig;
175 | }
176 | }
177 |
178 | @Override
179 | public String toString() {
180 | return "Config{" + "mBitRate=" + mBitRate + ", mFrameRate=" + mFrameRate + ", mIFrameInterval=" + mIFrameInterval + ", mVideoWidth=" + mVideoWidth + ", mVideoHeight=" + mVideoHeight + ", mPublishUrl='" + mPublishUrl + '\'' + ", mRecordVideo=" + mRecordVideo + ", mRecordVideoPath='" + mRecordVideoPath + '\'' + '}';
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/config/Const.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.config;
2 |
3 | public class Const {
4 |
5 | public static final int FRAME_TYPE_VIDEO = 0;
6 | public static final int FRAME_TYPE_AUDIO = 1;
7 |
8 | public static final int MAX_BUFFER_SIZE = 8192;
9 | public static final int AUDIO_SAMPLE_RATE = 44100;
10 | public static final int AUDIO_BITRATE = 96000;
11 |
12 | public static final int RTMP_DEFAULT_BITRATE = 2 * 1024 * 1000;//default 2m
13 | public static final int RTMP_DEFAULT_FRAME_RATE = 30;//default 30fps
14 | public static final int RTMP_I_FRAME_INTERVAL = 2;//default 10s
15 | public static final int RTMP_DEFAULT_VIDEO_WIDTH = 1920;
16 | public static final int RTMP_DEFAULT_VIDEO_HEIGHT = 1080;
17 | public static final String RTMP_TEST_PUSH_URL = "";
18 |
19 | public static final String CSD_0 = "csd-0";
20 | public static final String CSD_1 = "csd-1";
21 | }
22 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/encode/AudioEncoder.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.encode;
2 |
3 |
4 | import android.media.MediaCodec;
5 | import android.media.MediaFormat;
6 | import android.os.Handler;
7 | import android.os.HandlerThread;
8 | import android.os.Message;
9 | import android.os.SystemClock;
10 | import android.util.Log;
11 |
12 | import androidx.annotation.NonNull;
13 |
14 | import com.rtmpx.library.config.Config;
15 | import com.rtmpx.library.rtmp.RTMPFrame;
16 | import com.rtmpx.library.publish.RTMPPublisher;
17 |
18 | import java.nio.ByteBuffer;
19 | import java.util.Queue;
20 | import java.util.concurrent.ConcurrentLinkedDeque;
21 | import java.util.concurrent.atomic.AtomicBoolean;
22 |
23 | import static com.rtmpx.library.config.Const.AUDIO_BITRATE;
24 | import static com.rtmpx.library.config.Const.AUDIO_SAMPLE_RATE;
25 | import static com.rtmpx.library.config.Const.CSD_0;
26 | import static com.rtmpx.library.config.Const.FRAME_TYPE_AUDIO;
27 | import static com.rtmpx.library.config.Const.MAX_BUFFER_SIZE;
28 |
29 |
30 | public class AudioEncoder extends Encoder implements Handler.Callback {
31 | private static final String TAG = "AudioEncoder";
32 | private MediaCodec mAsyncAudioCodec;
33 | private AtomicBoolean mEncodeStarted = new AtomicBoolean(false);
34 | private Queue mIndexQueue = new ConcurrentLinkedDeque<>();
35 | private ByteBuffer mSps;
36 | private HandlerThread mWorkThread;
37 | private Handler mWorkHandler;
38 | private static final int MSG_START = 0;
39 |
40 | public AudioEncoder(Config mConfig) {
41 | super(mConfig);
42 | checkThread();
43 | }
44 |
45 | private void checkThread() {
46 | if (null == mWorkThread || !mWorkThread.isAlive() || mWorkThread.isInterrupted()) {
47 | mWorkThread = new HandlerThread("VRAudioEncoder") {
48 | @Override
49 | protected void onLooperPrepared() {
50 | super.onLooperPrepared();
51 | mWorkHandler = new Handler(getLooper(), AudioEncoder.this);
52 | mWorkHandler.obtainMessage(MSG_START).sendToTarget();
53 | }
54 | };
55 | mWorkThread.start();
56 | }
57 | }
58 |
59 | @Override
60 | public void config() throws Exception {
61 | try {
62 | mAsyncAudioCodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AAC);
63 | MediaFormat format = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, AUDIO_SAMPLE_RATE, 2);
64 | format.setInteger(MediaFormat.KEY_BIT_RATE, AUDIO_BITRATE);//比特率
65 | format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, MAX_BUFFER_SIZE);
66 | mAsyncAudioCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
67 | mAsyncAudioCodec.setCallback(this);
68 | } catch (Exception e) {
69 | e.printStackTrace();
70 | }
71 | }
72 |
73 | @Override
74 | public void start() {
75 | mEncodedFrameCount = 0;
76 | if (null == mAsyncAudioCodec) {
77 | try {
78 | config();
79 | startEncoder();
80 | } catch (Exception e) {
81 | e.printStackTrace();
82 | }
83 | } else {
84 | startEncoder();
85 | }
86 | }
87 |
88 | @Override
89 | public void encode(byte[] data) {
90 | if (null == mAsyncAudioCodec || !mEncodeStarted.get()) {
91 | Log.i(TAG, "====mAsyncAudioCodec not start====");
92 | return;
93 | }
94 | try {
95 | enCodeFrame(data);
96 | } catch (Exception e) {
97 | e.printStackTrace();
98 | }
99 | }
100 |
101 | private void enCodeFrame(byte[] encodeBuffer) throws Exception {
102 | Integer index = mIndexQueue.poll();
103 | if (index == null) return;
104 | ByteBuffer inputBuffer = mAsyncAudioCodec.getInputBuffer(index);
105 | inputBuffer.clear();
106 | int length = 0;
107 | if (null != encodeBuffer) {
108 | inputBuffer.put(encodeBuffer);
109 | length = encodeBuffer.length;
110 | mEncodedFrameCount++;
111 | mAsyncAudioCodec.queueInputBuffer(index, 0, length, SystemClock.uptimeMillis() * 1000 - mStartTime, 0);
112 | }
113 | }
114 |
115 | private void startEncoder() {
116 | if (null == mAsyncAudioCodec || mEncodeStarted.get()) return;
117 | mAsyncAudioCodec.start();
118 | mEncodeStarted.set(true);
119 | Log.i(TAG, "====mAsyncAudioCodec.start====");
120 | }
121 |
122 | @Override
123 | public void stop() {
124 | super.stop();
125 | mIndexQueue.clear();
126 | try {
127 | if (null != mAsyncAudioCodec) {
128 | mAsyncAudioCodec.stop();
129 | }
130 | } catch (Exception e) {
131 | e.printStackTrace();
132 | }
133 | mAsyncAudioCodec = null;
134 | mEncodeStarted.set(false);
135 | mStartTime = 0;
136 | }
137 |
138 | @Override
139 | public void release() {
140 | mAsyncAudioCodec = null;
141 | }
142 |
143 | @Override
144 | public ByteBuffer getSps() {
145 | return mSps;
146 | }
147 |
148 | @Override
149 | public ByteBuffer getPps() {
150 | return null;
151 | }
152 |
153 | @Override
154 | public void onInputBufferAvailable(MediaCodec codec, int index) {
155 | mIndexQueue.add(index);
156 | }
157 |
158 | @Override
159 | public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) {
160 | try {
161 | handleOutput(codec, index, info);
162 | } catch (Exception e) {
163 | e.printStackTrace();
164 | }
165 | }
166 |
167 | private void handleOutput(MediaCodec codec, int index, MediaCodec.BufferInfo info) throws Exception {
168 | ByteBuffer outputBuffer = codec.getOutputBuffer(index);
169 | if (null != outputBuffer && info.size > 0) {
170 | byte[] tmpBuffer = new byte[outputBuffer.remaining()];
171 | outputBuffer.get(tmpBuffer);
172 | RTMPFrame frame = new RTMPFrame();
173 | frame.setType(FRAME_TYPE_AUDIO);
174 | frame.setData(tmpBuffer);
175 | frame.setPresentationTimeUs(SystemClock.uptimeMillis() - mStartTime);
176 | frame.setBufferInfo(info);
177 | RTMPPublisher.getInstance().addFrame(frame);
178 | }
179 | codec.releaseOutputBuffer(index, true);
180 | }
181 |
182 | @Override
183 | public void onError(MediaCodec codec, MediaCodec.CodecException e) {
184 | Log.i(TAG, "=======onError=======" + e.toString());
185 | }
186 |
187 | @Override
188 | public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
189 | Log.i(TAG, "=======onOutputFormatChanged=======" + format.toString());
190 | mSps = format.getByteBuffer(CSD_0);
191 | }
192 |
193 | @Override
194 | public boolean handleMessage(@NonNull Message msg) {
195 | switch (msg.what) {
196 | case MSG_START:
197 | try {
198 | config();
199 | } catch (Exception e) {
200 | e.printStackTrace();
201 | }
202 | break;
203 | }
204 | return false;
205 | }
206 | }
207 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/encode/Encoder.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.encode;
2 |
3 | import android.media.MediaCodec;
4 | import android.media.MediaFormat;
5 |
6 | import com.rtmpx.library.config.Config;
7 |
8 | import java.nio.ByteBuffer;
9 | import java.util.Queue;
10 | import java.util.concurrent.ConcurrentLinkedQueue;
11 |
12 | public abstract class Encoder extends MediaCodec.Callback {
13 | protected Config mConfig;
14 | protected int mEncodedFrameCount = 0;
15 | protected long mStartTime;
16 |
17 | /**
18 | * Construction method
19 | * @param mConfig publish params config {@link Config}
20 | */
21 | public Encoder(Config mConfig) {
22 | this.mConfig = mConfig;
23 | }
24 |
25 | /**
26 | * encode video or audio
27 | * @param data the raw data
28 | */
29 | public abstract void encode(T data);
30 |
31 | /**
32 | * base time
33 | * @param startTime
34 | */
35 | public void setStartTime(long startTime){
36 | this.mStartTime = startTime;
37 | }
38 |
39 | /**
40 | * configuration codec
41 | * @throws Exception
42 | */
43 | public abstract void config() throws Exception;
44 |
45 | /**
46 | * start encode
47 | */
48 | public abstract void start();
49 |
50 | /**
51 | * stop encode
52 | */
53 | public void stop(){
54 | mEncodedFrameCount = 0;
55 | }
56 |
57 | /**
58 | * freed
59 | */
60 | public abstract void release();
61 |
62 | /**
63 | * get sps
64 | * @return {@link MediaCodec.Callback#onOutputFormatChanged(MediaCodec, MediaFormat)} {@link MediaFormat#getByteBuffer(String)} {@link com.rtmpx.library.config.Const#CSD_0}
65 | */
66 | public abstract ByteBuffer getSps();
67 |
68 | /**
69 | * get pps audio is null
70 | * @return @return {@link MediaCodec.Callback#onOutputFormatChanged(MediaCodec, MediaFormat)} {@link MediaFormat#getByteBuffer(String)} {@link com.rtmpx.library.config.Const#CSD_1}
71 | */
72 | public abstract ByteBuffer getPps();
73 | }
74 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/publish/IPublishListener.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.publish;
2 |
3 | public interface IPublishListener {
4 |
5 | /**
6 | * rtmp is connecting
7 | */
8 | void onConnecting();
9 |
10 | /**
11 | * rtmp connection is successful
12 | */
13 | void onConnected();
14 |
15 | /**
16 | * rtmp connection failed
17 | * @param code error code
18 | */
19 | void onConnectedFailed(int code);
20 |
21 | /**
22 | * Start publishing
23 | */
24 | void onStartPublish();
25 |
26 | /**
27 | * Stop publishing
28 | */
29 | void onStopPublish();
30 |
31 | /**
32 | * Start recording
33 | */
34 | void onStartRecord();
35 |
36 | /**
37 | * Stop recording
38 | */
39 | void onStopRecord();
40 |
41 | /**
42 | * fps statistics
43 | * @param fps avg fps
44 | */
45 | void onFpsStatistic(int fps);
46 |
47 | /**
48 | * rtmp disconnect
49 | */
50 | void onRtmpDisconnect();
51 | }
52 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/publish/PublisherX.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.publish;
2 |
3 | import android.util.Log;
4 |
5 | import androidx.camera.core.ImageProxy;
6 |
7 | import com.rtmpx.library.camera.ICamera;
8 | import com.rtmpx.library.camera.ICameraPreviewCallback;
9 | import com.rtmpx.library.config.Config;
10 | import com.rtmpx.library.record.audio.AudioRecorder;
11 | import com.rtmpx.library.utils.ConvertUtils;
12 |
13 | import java.util.concurrent.atomic.AtomicBoolean;
14 |
15 | public class PublisherX extends ICameraPreviewCallback implements AudioRecorder.OnAudioRecordListener {
16 | private static final String TAG = "PublisherX";
17 | private byte[] mBuff = new byte[2048];
18 | private Config mConfig;
19 | private ICamera mCamera;
20 | private AudioRecorder mAudioRecorder = new AudioRecorder(mBuff);
21 | private AtomicBoolean mPublishing = new AtomicBoolean(false);
22 |
23 | public PublisherX(Config mConfig, ICamera mCamera) {
24 | this.mConfig = mConfig;
25 | bindCamera(mCamera);
26 | }
27 |
28 | public PublisherX(Config mConfig) {
29 | this.mConfig = mConfig;
30 | }
31 |
32 | /**
33 | * bind a camera
34 | *
35 | * @param mCamera {@link ICamera}
36 | */
37 | public void bindCamera(ICamera mCamera) {
38 | this.mCamera = mCamera;
39 | this.mCamera.setPreviewCallback(this);
40 | mAudioRecorder.setAudioRecordListener(this);
41 | }
42 |
43 | /**
44 | * set a publishing listener
45 | *
46 | * @param mPublishListener
47 | */
48 | public void setPublishListener(IPublishListener mPublishListener) {
49 | RTMPPublisher.getInstance().setPublishListener(mPublishListener);
50 | }
51 |
52 | /**
53 | * start rtmp publish
54 | */
55 | public void startPublish() {
56 | if (mPublishing.get()) {
57 | Log.d(TAG, "is publishing no handle startPublish");
58 | return;
59 | }
60 | mAudioRecorder.startRecord();
61 | RTMPPublisher.getInstance().startPublish(mConfig);
62 | mPublishing.set(true);
63 | }
64 |
65 | /**
66 | * stop rtmp publish
67 | */
68 | public void stopPublish() {
69 | if (!mPublishing.get()) {
70 | Log.d(TAG, "not publishing no handle stopPublish");
71 | return;
72 | }
73 | RTMPPublisher.getInstance().stopPublish();
74 | if (null != mAudioRecorder) {
75 | mAudioRecorder.stopRecord();
76 | }
77 | mPublishing.set(false);
78 | }
79 |
80 | /**
81 | * freed
82 | */
83 | public void release() {
84 | if (null != mAudioRecorder) {
85 | mAudioRecorder.setAudioRecordListener(null);
86 | mAudioRecorder.release();
87 | }
88 | RTMPPublisher.getInstance().setPublishListener(null);
89 | }
90 |
91 | @Override
92 | public void onAudioRecord(byte[] pcm) {
93 | if (!RTMPPublisher.getInstance().isWorked()) {
94 | Log.d(TAG, "rtmp not worked no handle onAudioRecord");
95 | return;
96 | }
97 | RTMPPublisher.getInstance().encodeAudio(pcm);
98 | }
99 |
100 | @Override
101 | public void onAudioRecordError(String message) {
102 | Log.d(TAG, "onAudioRecordError message is " + message);
103 | }
104 |
105 | @Override
106 | public void handleImage(ImageProxy image, int rotation) {
107 | if (!RTMPPublisher.getInstance().isWorked()) {
108 | Log.d(TAG, "rtmp not worked no handle handleImage "+rotation + " image rotation "+image.getImageInfo().getRotationDegrees());
109 | return;
110 | }
111 | byte[] data = ConvertUtils.YUV_420_888toNV12(image, rotation);
112 | RTMPPublisher.getInstance().encodeVideo(data);
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/record/audio/AudioRecorder.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.record.audio;
2 |
3 | import android.media.AudioFormat;
4 | import android.media.AudioRecord;
5 | import android.media.MediaRecorder;
6 | import android.os.Handler;
7 | import android.os.HandlerThread;
8 | import android.os.Message;
9 |
10 | import com.rtmpx.library.publish.RTMPPublisher;
11 |
12 | import java.util.concurrent.atomic.AtomicBoolean;
13 |
14 | import static com.rtmpx.library.config.Const.AUDIO_SAMPLE_RATE;
15 |
16 | public class AudioRecorder implements Handler.Callback {
17 | private static final String TAG = "AudioRecorder";
18 |
19 | private static final int MSG_START_RECORD = 0XFF11;
20 | private OnAudioRecordListener mAudioRecordListener;
21 | private AudioRecord mAudioRecorder;
22 | private HandlerThread mAudioRecordThread;
23 | private Handler mAudioRecordHandler;
24 | private byte[] mBuffer ;
25 | private AtomicBoolean mRecordStarted = new AtomicBoolean(false);
26 |
27 |
28 | public AudioRecorder(byte[] mBuffer) {
29 | this.mBuffer = mBuffer;
30 | initAudioRecord();
31 | }
32 |
33 | /**
34 | * set audio record listener
35 | * @param mAudioRecordListener
36 | */
37 | public void setAudioRecordListener(OnAudioRecordListener mAudioRecordListener) {
38 | this.mAudioRecordListener = mAudioRecordListener;
39 | }
40 |
41 | /**
42 | * Initialize recording
43 | */
44 | private void initAudioRecord() {
45 | if (null == mAudioRecorder) {
46 | int audioSource = MediaRecorder.AudioSource.MIC;
47 | int sampleRate = AUDIO_SAMPLE_RATE;
48 | int channelConfig = AudioFormat.CHANNEL_IN_STEREO;
49 | int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
50 | int minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
51 | mAudioRecorder = new AudioRecord(audioSource, sampleRate, channelConfig, audioFormat, Math.max(minBufferSize, mBuffer.length));
52 | }
53 | }
54 |
55 | /**
56 | * Send a recorded message
57 | */
58 | private void sendStartRecordMessage() {
59 | if (null == mAudioRecordThread || !mAudioRecordThread.isAlive() || mAudioRecordThread.isInterrupted()) {
60 | mAudioRecordThread = new HandlerThread("AudioRecord") {
61 | @Override
62 | protected void onLooperPrepared() {
63 | super.onLooperPrepared();
64 | mAudioRecordHandler = new Handler(getLooper(), AudioRecorder.this);
65 | mAudioRecordHandler.obtainMessage(MSG_START_RECORD).sendToTarget();
66 | }
67 | };
68 | mAudioRecordThread.start();
69 | } else {
70 | mAudioRecordHandler.obtainMessage(MSG_START_RECORD).sendToTarget();
71 | }
72 | }
73 |
74 | /**
75 | * Start recording
76 | */
77 | private void startRecordPcm() {
78 | initAudioRecord();
79 | try {
80 | mAudioRecorder.startRecording();
81 | mRecordStarted.set(true);
82 | while (mRecordStarted.get()) {
83 | int read = mAudioRecorder.read(mBuffer, 0, mBuffer.length);
84 | if (read <= 0) {
85 | Thread.sleep(10);
86 | continue;
87 | }
88 | if (null != mAudioRecordListener && RTMPPublisher.getInstance().isWorked()) {
89 | mAudioRecordListener.onAudioRecord(mBuffer);
90 | }
91 | }
92 | } catch (Exception e) {
93 | e.printStackTrace();
94 | }
95 | }
96 |
97 | /**
98 | * Send stop recording message
99 | */
100 | private void sendStopRecordMessage() {
101 | stopRecordPcm();
102 | }
103 |
104 | /**
105 | * Stop recording
106 | */
107 | private void stopRecordPcm() {
108 | mRecordStarted.set(false);
109 | if (mAudioRecorder != null) {
110 | try {
111 | mAudioRecorder.stop();
112 | } catch (Exception e) {
113 | e.printStackTrace();
114 | }
115 | }
116 | if (null != mAudioRecordHandler) {
117 | mAudioRecordHandler.removeCallbacksAndMessages(null);
118 | mAudioRecordHandler = null;
119 | }
120 | if (null != mAudioRecordThread) {
121 | try {
122 | mAudioRecordThread.quit();
123 | mAudioRecordThread.interrupt();
124 | } catch (Exception e) {
125 | e.printStackTrace();
126 | } finally {
127 | mAudioRecordThread = null;
128 | }
129 | }
130 | }
131 |
132 | /**
133 | * Start recording
134 | */
135 | public void startRecord() {
136 | sendStartRecordMessage();
137 | }
138 |
139 | /**
140 | * Stop recording
141 | */
142 | public void stopRecord() {
143 | sendStopRecordMessage();
144 | }
145 |
146 | public void release() {
147 | if (null != mAudioRecorder) {
148 | mAudioRecorder.release();
149 | mAudioRecorder = null;
150 | }
151 | }
152 |
153 | @Override
154 | public boolean handleMessage(Message msg) {
155 | switch (msg.what) {
156 | case MSG_START_RECORD:
157 | startRecordPcm();
158 | break;
159 | }
160 | return false;
161 | }
162 |
163 | public interface OnAudioRecordListener {
164 | /**
165 | * get a pcm data
166 | * @param pcm
167 | */
168 | void onAudioRecord(byte[] pcm);
169 |
170 | /**
171 | * record get error
172 | * @param message
173 | */
174 | void onAudioRecordError(String message);
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/record/video/VideoRecorder.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.record.video;
2 |
3 | import android.media.MediaCodecInfo;
4 | import android.media.MediaFormat;
5 | import android.media.MediaMuxer;
6 | import android.text.TextUtils;
7 | import android.util.Log;
8 |
9 | import com.rtmpx.library.config.Config;
10 | import com.rtmpx.library.rtmp.RTMPFrame;
11 |
12 | import java.io.File;
13 | import java.nio.ByteBuffer;
14 | import java.util.concurrent.atomic.AtomicBoolean;
15 |
16 | import static com.rtmpx.library.config.Const.AUDIO_SAMPLE_RATE;
17 | import static com.rtmpx.library.config.Const.CSD_0;
18 | import static com.rtmpx.library.config.Const.CSD_1;
19 |
20 | public class VideoRecorder {
21 | private static final String TAG = "VideoRecorder";
22 | private MediaMuxer mediaMuxer;
23 | private Config mConfig;
24 | private ByteBuffer sps, pps, adts;
25 | private int mAudioTrackIndex;
26 | private int mVideoTrackIndex;
27 | private AtomicBoolean muxerStarted = new AtomicBoolean(false);
28 |
29 | public VideoRecorder(Config mVrConfig, ByteBuffer sps, ByteBuffer pps, ByteBuffer adts) {
30 | this.mConfig = mVrConfig;
31 | this.sps = sps;
32 | this.pps = pps;
33 | this.adts = adts;
34 | }
35 |
36 | /**
37 | * Start recording
38 | * @param targetPath Recording file save path
39 | * @throws Exception
40 | */
41 | public void startRecord(String targetPath) throws Exception {
42 | if (TextUtils.isEmpty(targetPath)) {
43 | Log.d(TAG, "record path is null");
44 | return;
45 | }
46 | startRecord(new File(targetPath));
47 | }
48 |
49 | /**
50 | * Start recording
51 | * @param targetFile Recording file
52 | * @throws Exception
53 | */
54 | public void startRecord(File targetFile) throws Exception {
55 | File dir = targetFile.getParentFile();
56 | if (!dir.exists()) {
57 | dir.mkdirs();
58 | }
59 | if (!targetFile.exists()) {
60 | targetFile.createNewFile();
61 | }
62 | if (null == mediaMuxer) {
63 | createMuxer(targetFile);
64 | }
65 | mediaMuxer.start();
66 | muxerStarted.set(true);
67 | }
68 |
69 | /**
70 | * Stop recording
71 | */
72 | public void stopRecord() {
73 | if (null != mediaMuxer) {
74 | mediaMuxer.stop();
75 | }
76 | }
77 |
78 | /**
79 | * freed
80 | */
81 | public void release() {
82 | if (null != mediaMuxer) {
83 | mediaMuxer.release();
84 | }
85 | muxerStarted.set(false);
86 | }
87 |
88 | /**
89 | * Has it started
90 | * @return true if started
91 | */
92 | public boolean isStart(){
93 | return muxerStarted.get();
94 | }
95 |
96 | /**
97 | * create a mp4 muxer
98 | * @param target
99 | * @throws Exception
100 | */
101 | private void createMuxer(File target) throws Exception {
102 | mediaMuxer = new MediaMuxer(target.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
103 | MediaFormat videoFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, mConfig.getVideoWidth(), mConfig.getVideoHeight());
104 | videoFormat.setByteBuffer(CSD_0, sps);
105 | videoFormat.setByteBuffer(CSD_1, pps);
106 | videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
107 | videoFormat.setInteger(MediaFormat.KEY_CAPTURE_RATE, mConfig.getFrameRate());
108 | MediaFormat audioFormat = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, AUDIO_SAMPLE_RATE, 1);
109 | audioFormat.setByteBuffer(CSD_0, adts);
110 | mAudioTrackIndex = mediaMuxer.addTrack(audioFormat);
111 | mVideoTrackIndex = mediaMuxer.addTrack(videoFormat);
112 | }
113 |
114 | /**
115 | * Write video data
116 | * @param rtmpFrame video frame
117 | */
118 | public void writeVideo(RTMPFrame rtmpFrame) {
119 | if (null == mediaMuxer || !muxerStarted.get()) return;
120 | mediaMuxer.writeSampleData(mVideoTrackIndex, ByteBuffer.wrap(rtmpFrame.getData()), rtmpFrame.getBufferInfo());
121 | }
122 |
123 | /**
124 | * Write audio data
125 | * @param rtmpFrame audio frame
126 | */
127 | public void writeAudio(RTMPFrame rtmpFrame) {
128 | if (null == mediaMuxer || !muxerStarted.get()) return;
129 | mediaMuxer.writeSampleData(mAudioTrackIndex, ByteBuffer.wrap(rtmpFrame.getData()), rtmpFrame.getBufferInfo());
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/rtmp/RTMPFrame.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.rtmp;
2 |
3 | import android.media.MediaCodec;
4 |
5 | import static android.media.MediaCodec.BUFFER_FLAG_KEY_FRAME;
6 |
7 | public class RTMPFrame {
8 | private byte [] data;
9 | private int type;
10 | private long presentationTimeUs;
11 | private MediaCodec.BufferInfo mBufferInfo;
12 |
13 | public byte[] getData() {
14 | return data;
15 | }
16 |
17 | public void setData(byte[] data) {
18 | this.data = data;
19 | }
20 |
21 | public int getType() {
22 | return type;
23 | }
24 |
25 | public void setType(int type) {
26 | this.type = type;
27 | }
28 |
29 | public long getPresentationTimeUs() {
30 | return presentationTimeUs;
31 | }
32 |
33 | public void setPresentationTimeUs(long presentationTimeUs) {
34 | this.presentationTimeUs = presentationTimeUs;
35 | }
36 |
37 | public boolean isKeyFrame(){
38 | return null != mBufferInfo && BUFFER_FLAG_KEY_FRAME == mBufferInfo.flags;
39 | }
40 |
41 | public MediaCodec.BufferInfo getBufferInfo() {
42 | return mBufferInfo;
43 | }
44 |
45 | public void setBufferInfo(MediaCodec.BufferInfo mBufferInfo) {
46 | this.mBufferInfo = mBufferInfo;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/rtmp/RTMPMuxer.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.rtmp;
2 |
3 | /**
4 | * Created by faraklit on 08.02.2016.
5 | */
6 | public class RTMPMuxer {
7 |
8 | static {
9 | System.loadLibrary("rtmpx");
10 | }
11 |
12 | public native int open(String url, int video_width, int video_height,int frame_rate);
13 |
14 | /**
15 | * write h264 nal units
16 | * @param data
17 | * @param offset
18 | * @param length
19 | * @param timestamp
20 | * @return 0 if it writes network successfully
21 | * -1 if it could not write
22 | */
23 | public native int writeVideo(byte[] data, int offset, int length, long timestamp);
24 |
25 | /**
26 | * Write raw aac data
27 | * @param data
28 | * @param offset
29 | * @param length
30 | * @param timestamp
31 | * @return 0 if it writes network successfully
32 | * -1 if it could not write
33 | */
34 | public native int writeAudio(byte[] data, int offset, int length, long timestamp);
35 |
36 |
37 | public native int read(byte[] data, int offset, int size);
38 |
39 | public native int close();
40 |
41 |
42 | public native void write_flv_header(boolean is_have_audio, boolean is_have_video);
43 |
44 | public native void file_open(String filename);
45 |
46 | public native void file_close();
47 |
48 | /**
49 | *
50 | * @return 1 if it is connected
51 | * 0 if it is not connected
52 | */
53 | public native boolean isConnected();
54 | }
55 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/utils/ConvertUtils.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.utils;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.util.Log;
5 |
6 | import androidx.camera.core.ImageProxy;
7 |
8 | import com.rtmpx.library.yuv.YuvFrame;
9 | import com.rtmpx.library.yuv.YuvHelper;
10 |
11 | import java.io.File;
12 | import java.io.FileNotFoundException;
13 | import java.io.FileOutputStream;
14 | import java.io.IOException;
15 | import java.nio.ByteBuffer;
16 |
17 | public class ConvertUtils {
18 | private static final String TAG = "ConvertUtils";
19 | private static byte[] mPortraitYUV;
20 | private static byte[] mLandscapeYUV;
21 |
22 | public static byte[] YUV_420_888toNV12(ImageProxy image, int rotation) {
23 | if (0 == rotation) {
24 | return YUV_420_888toPortraitNV12(image, rotation);
25 | } else {
26 | return YUV_420_888toLandscapeNV12(image, rotation);
27 | }
28 | }
29 |
30 | /**
31 | * YUV_420_888 to Landscape NV21
32 | *
33 | * @param image CameraX ImageProxy
34 | * @return nv12 byte array
35 | */
36 | @SuppressLint("UnsafeOptInUsageError")
37 | public static byte[] YUV_420_888toLandscapeNV12(ImageProxy image, int rotation) {
38 | byte [] bytes = YuvHelper.convertToI420(image.getImage()).asArray();
39 | if (null == mLandscapeYUV || mLandscapeYUV.length != bytes.length) {
40 | mLandscapeYUV = new byte[bytes.length];
41 | }
42 | YuvHelper.I420ToNV12(bytes, image.getWidth(), image.getHeight(), mLandscapeYUV);
43 | return mLandscapeYUV;
44 | }
45 |
46 | /**
47 | * YUV_420_888 to Portrait NV12
48 | * @param image CameraX ImageProxy
49 | * @param rotation display rotation
50 | * @return nv12 byte array
51 | */
52 | @SuppressLint("UnsafeOptInUsageError")
53 | public static byte[] YUV_420_888toPortraitNV12(ImageProxy image, int rotation) {
54 | YuvFrame yuvFrame = YuvHelper.convertToI420(image.getImage());
55 | //TODO optimization of vertical screen libyuv rotation
56 | byte[] bytes = YuvHelper.rotate(yuvFrame, image.getImageInfo().getRotationDegrees()).asArray();
57 | if (null == mPortraitYUV || mPortraitYUV.length != bytes.length) {
58 | mPortraitYUV = new byte[bytes.length];
59 | }
60 | YuvHelper.I420ToNV12(bytes, image.getWidth(), image.getHeight(), mPortraitYUV);
61 | return mPortraitYUV;
62 | }
63 |
64 | private static void writeFile(ImageProxy mImage, String path) {
65 | File file = new File(path);
66 | FileOutputStream output = null;
67 | ByteBuffer buffer;
68 | byte[] bytes;
69 | ByteBuffer prebuffer = ByteBuffer.allocate(16);
70 | prebuffer.putInt(mImage.getWidth())
71 | .putInt(mImage.getHeight())
72 | .putInt(mImage.getPlanes()[1].getPixelStride())
73 | .putInt(mImage.getPlanes()[1].getRowStride());
74 |
75 | try {
76 | output = new FileOutputStream(file);
77 | output.write(prebuffer.array()); // write meta information to file
78 | // Now write the actual planes.
79 | for (int i = 0; i < 3; i++) {
80 | buffer = mImage.getPlanes()[i].getBuffer();
81 | bytes = new byte[buffer.remaining()]; // makes byte array large enough to hold image
82 | buffer.get(bytes); // copies image from buffer to byte array
83 | output.write(bytes); // write the byte array to file
84 | }
85 | } catch (FileNotFoundException e) {
86 | e.printStackTrace();
87 | } catch (IOException e) {
88 | e.printStackTrace();
89 | } finally {
90 | // mImage.close(); // close this to free up buffer for other images
91 | if (null != output) {
92 | try {
93 | output.close();
94 | } catch (IOException e) {
95 | e.printStackTrace();
96 | }
97 | }
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/yuv/YuvFrame.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.yuv;
2 |
3 | import android.media.Image;
4 |
5 | import java.nio.ByteBuffer;
6 | public class YuvFrame {
7 |
8 | private ByteBuffer y;
9 | private ByteBuffer u;
10 | private ByteBuffer v;
11 |
12 | private int yStride;
13 | private int uStride;
14 | private int vStride;
15 |
16 | private int width;
17 | private int height;
18 |
19 | public YuvFrame() {
20 | super();
21 | }
22 |
23 | public void fill(ByteBuffer y, ByteBuffer u, ByteBuffer v, int yStride, int uStride, int vStride, int width, int height) {
24 | this.y = y;
25 | this.u = u;
26 | this.v = v;
27 | this.yStride = yStride;
28 | this.uStride = uStride;
29 | this.vStride = vStride;
30 | this.width = width;
31 | this.height = height;
32 | }
33 |
34 | public void fill(Image image) {
35 | Image.Plane[] planes = image.getPlanes();
36 | Image.Plane yPlane = planes[0];
37 | this.y = yPlane.getBuffer();
38 | this.yStride = yPlane.getRowStride();
39 |
40 | Image.Plane uPlane = planes[1];
41 | this.u = uPlane.getBuffer();
42 | this.uStride = uPlane.getRowStride();
43 |
44 | Image.Plane vPlane = planes[2];
45 | this.v = vPlane.getBuffer();
46 | this.vStride = vPlane.getRowStride();
47 |
48 | this.width = image.getWidth();
49 | this.height = image.getHeight();
50 | }
51 |
52 | public ByteBuffer getY() {
53 | return y;
54 | }
55 |
56 | public ByteBuffer getU() {
57 | return u;
58 | }
59 |
60 | public ByteBuffer getV() {
61 | return v;
62 | }
63 |
64 | public int getyStride() {
65 | return yStride;
66 | }
67 |
68 | public int getuStride() {
69 | return uStride;
70 | }
71 |
72 | public int getvStride() {
73 | return vStride;
74 | }
75 |
76 | public int getWidth() {
77 | return width;
78 | }
79 |
80 | public int getHeight() {
81 | return height;
82 | }
83 |
84 | public byte[] asArray() {
85 | byte[] array;
86 |
87 | int yPos = y.position();
88 | int uPos = u.position();
89 | int vPos = v.position();
90 |
91 | try {
92 | array = ByteBuffer.allocate(y.capacity() + u.capacity() + v.capacity()).put(y).put(u).put(v).array();
93 | y.position(yPos);
94 | u.position(uPos);
95 | v.position(vPos);
96 | } catch (Exception e) {
97 |
98 | array = new byte[size()];
99 |
100 | y.get(array, 0, y.remaining());
101 | y.position(yPos);
102 |
103 | u.get(array, y.remaining(), u.remaining());
104 | u.position(uPos);
105 |
106 | v.get(array, y.remaining() + u.remaining(), v.remaining());
107 | v.position(vPos);
108 | }
109 | return array;
110 | }
111 |
112 | public int size() {
113 | return y.remaining() + u.remaining() + v.remaining();
114 | }
115 |
116 | public void free() {
117 | y = ByteBuffer.allocate(1);
118 | u = ByteBuffer.allocate(1);
119 | v = ByteBuffer.allocate(1);
120 | yStride = 0;
121 | uStride = 0;
122 | vStride = 0;
123 | width = 0;
124 | height = 0;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/java/com/rtmpx/library/yuv/YuvHelper.java:
--------------------------------------------------------------------------------
1 | package com.rtmpx.library.yuv;
2 |
3 | import android.media.Image;
4 | import android.util.Log;
5 |
6 | import java.nio.ByteBuffer;
7 |
8 | public class YuvHelper {
9 | private static YuvFrame mYuvFrame;
10 | private static ByteBuffer y, u, v;
11 |
12 | static {
13 | System.loadLibrary("rtmpx");
14 | }
15 |
16 |
17 | public static YuvFrame createYuvFrame(int width, int height) {
18 | if (null == mYuvFrame || (mYuvFrame.getWidth() != width || mYuvFrame.getHeight() != height)) {
19 | mYuvFrame = new YuvFrame();
20 | y = u = v = null;
21 | }
22 | int ySize = width * height;
23 | int uvSize = width * height / 4;
24 | if (null == y) {
25 | y = ByteBuffer.allocateDirect(ySize);
26 | } else {
27 | y.clear();
28 | }
29 | if (null == u) {
30 | u = ByteBuffer.allocateDirect(uvSize);
31 | } else {
32 | u.clear();
33 | }
34 | if (null == v) {
35 | v = ByteBuffer.allocateDirect(uvSize);
36 | } else {
37 | v.clear();
38 | }
39 | int extra = (width % 2 == 0) ? 0 : 1;
40 | mYuvFrame.fill(y, u, v, width, width / 2 + extra, width / 2 + extra, width, height);
41 | return mYuvFrame;
42 | }
43 |
44 | public static YuvFrame createYuvFrame(int width, int height, int rotationMode) {
45 | int outWidth = (rotationMode == 90 || rotationMode == 270) ? height : width;
46 | int outHeight = (rotationMode == 90 || rotationMode == 270) ? width : height;
47 | return createYuvFrame(outWidth, outHeight);
48 | }
49 |
50 | public static YuvFrame rotate(Image image, int rotationMode) {
51 | assert (rotationMode == 0 || rotationMode == 90 || rotationMode == 180 || rotationMode == 270);
52 | YuvFrame outFrame = createYuvFrame(image.getWidth(), image.getHeight(), rotationMode);
53 | rotate(image.getPlanes()[0].getBuffer(), image.getPlanes()[1].getBuffer(), image.getPlanes()[2].getBuffer(), image.getPlanes()[0].getRowStride(), image.getPlanes()[1].getRowStride(), image.getPlanes()[2].getRowStride(), outFrame.getY(), outFrame.getU(), outFrame.getV(), outFrame.getyStride(), outFrame.getuStride(), outFrame.getvStride(), image.getWidth(), image.getHeight(), rotationMode);
54 | return outFrame;
55 | }
56 |
57 | public static YuvFrame rotate(YuvFrame yuvFrame, int rotationMode) {
58 | assert (rotationMode == 0 || rotationMode == 90 || rotationMode == 180 || rotationMode == 270);
59 | YuvFrame outFrame = createYuvFrame(yuvFrame.getWidth(), yuvFrame.getHeight(), rotationMode);
60 | rotate(yuvFrame.getY(), yuvFrame.getU(), yuvFrame.getV(), yuvFrame.getyStride(), yuvFrame.getuStride(), yuvFrame.getvStride(), outFrame.getY(), outFrame.getU(), outFrame.getV(), outFrame.getyStride(), outFrame.getuStride(), outFrame.getvStride(), yuvFrame.getWidth(), yuvFrame.getHeight(), rotationMode);
61 | return outFrame;
62 | }
63 |
64 | public static YuvFrame convertToI420(Image image) {
65 | YuvFrame outFrame = createYuvFrame(image.getWidth(), image.getHeight());
66 | convertToI420(image.getPlanes()[0].getBuffer(), image.getPlanes()[1].getBuffer(), image.getPlanes()[2].getBuffer(), image.getPlanes()[0].getRowStride(), image.getPlanes()[1].getRowStride(), image.getPlanes()[2].getRowStride(), image.getPlanes()[2].getPixelStride(), outFrame.getY(), outFrame.getU(), outFrame.getV(), outFrame.getyStride(), outFrame.getuStride(), outFrame.getvStride(), image.getWidth(), image.getHeight());
67 | return outFrame;
68 | }
69 |
70 | public static YuvFrame convertToI420(YuvFrame yuvFrame, int uvPixelStride) {
71 | YuvFrame outFrame = createYuvFrame(yuvFrame.getWidth(), yuvFrame.getHeight());
72 | convertToI420(yuvFrame.getY(), yuvFrame.getU(), yuvFrame.getV(), yuvFrame.getyStride(), yuvFrame.getuStride(), yuvFrame.getvStride(), uvPixelStride, outFrame.getY(), outFrame.getU(), outFrame.getV(), outFrame.getyStride(), outFrame.getuStride(), outFrame.getvStride(), yuvFrame.getWidth(), yuvFrame.getHeight());
73 | return outFrame;
74 | }
75 |
76 | public static native void rotate(ByteBuffer y, ByteBuffer u, ByteBuffer v, int yStride, int uStride, int vStride, ByteBuffer yOut, ByteBuffer uOut, ByteBuffer vOut, int yOutStride, int uOutStride, int vOutStride, int width, int height, int rotationMode);
77 |
78 | public static native void convertToI420(ByteBuffer y, ByteBuffer u, ByteBuffer v, int yStride, int uStride, int vStride, int srcPixelStrideUv, ByteBuffer yOut, ByteBuffer uOut, ByteBuffer vOut, int yOutStride, int uOutStride, int vOutStride, int width, int height);
79 |
80 | public static native void I420ToNV12(byte[] i420Src, int width, int height, byte[] nv12Dst);
81 | }
82 |
--------------------------------------------------------------------------------
/rtmpx_library/src/main/jniLibs/arm64-v8a/libyuv.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/rtmpx_library/src/main/jniLibs/arm64-v8a/libyuv.so
--------------------------------------------------------------------------------
/rtmpx_library/src/main/jniLibs/armeabi-v7a/libyuv.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luohaohaha/RTMPX/5efc17ef2a1f69d5c9efa967654b695ee5b6fb98/rtmpx_library/src/main/jniLibs/armeabi-v7a/libyuv.so
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = "RTMPX"
2 | include ':rtmpx_library'
3 | include ':app'
4 |
--------------------------------------------------------------------------------