├── .gitignore
├── ReadMe.md
├── app
├── .gitignore
├── build.gradle
├── libs
│ └── weplayer-release.aar
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── wtz
│ │ └── videomaker
│ │ ├── AudioRecordActivity.java
│ │ ├── CameraActivity.java
│ │ ├── ImageVideoActivity.java
│ │ ├── MainActivity.java
│ │ ├── MixAudioActivity.java
│ │ ├── MultiSurfaceActivity.java
│ │ ├── SingleSurfaceActivity.java
│ │ ├── VideoPushActivity.java
│ │ ├── VideoRecordActivity.java
│ │ ├── adapter
│ │ ├── BaseRecyclerViewAdapter.java
│ │ └── ImageChooserGridAdapter.java
│ │ ├── surfaceview
│ │ ├── FilterSurfaceView.java
│ │ ├── GraySurfaceView.java
│ │ ├── LuminanceSurfaceView.java
│ │ ├── MultiImgSurfaceView.java
│ │ ├── ReverseSurfaceView.java
│ │ └── SingleImgSurfaceView.java
│ │ ├── utils
│ │ ├── AudioUtils.java
│ │ ├── DateTimeUtil.java
│ │ ├── FileChooser.java
│ │ ├── ImageChooser.java
│ │ ├── PermissionChecker.java
│ │ ├── PermissionHandler.java
│ │ └── UriUtil.java
│ │ └── views
│ │ └── GridItemDecoration.java
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ ├── carry_up.jpg
│ ├── circle_ball_shape.xml
│ ├── grid_divider_line_shape.xml
│ ├── happy.jpg
│ ├── ic_launcher_background.xml
│ ├── icon_select.png
│ ├── image_default.png
│ ├── lotus.jpg
│ ├── purple_ball.png
│ ├── seekbar_style.xml
│ ├── seekbar_thumb.xml
│ ├── sunflower.jpg
│ └── tree.jpg
│ ├── layout
│ ├── activity_audio_record.xml
│ ├── activity_camera.xml
│ ├── activity_image_chooser.xml
│ ├── activity_image_video.xml
│ ├── activity_main.xml
│ ├── activity_mix_audio.xml
│ ├── activity_multi_surface.xml
│ ├── activity_single_surface.xml
│ ├── activity_video_push.xml
│ ├── activity_video_record.xml
│ ├── item_image_chooser.xml
│ └── item_spinner_time_unit.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-sw1024dp
│ └── dimens.xml
│ ├── values-sw1280dp
│ └── dimens.xml
│ ├── values-sw1365dp
│ └── dimens.xml
│ ├── values-sw384dp
│ └── dimens.xml
│ ├── values-sw392dp
│ └── dimens.xml
│ ├── values-sw400dp
│ └── dimens.xml
│ ├── values-sw410dp
│ └── dimens.xml
│ ├── values-sw411dp
│ └── dimens.xml
│ ├── values-sw432dp
│ └── dimens.xml
│ ├── values-sw480dp
│ └── dimens.xml
│ ├── values-sw533dp
│ └── dimens.xml
│ ├── values-sw592dp
│ └── dimens.xml
│ ├── values-sw600dp
│ └── dimens.xml
│ ├── values-sw640dp
│ └── dimens.xml
│ ├── values-sw662dp
│ └── dimens.xml
│ ├── values-sw720dp
│ └── dimens.xml
│ ├── values-sw768dp
│ └── dimens.xml
│ ├── values-sw800dp
│ └── dimens.xml
│ ├── values-sw811dp
│ └── dimens.xml
│ ├── values-sw820dp
│ └── dimens.xml
│ ├── values-sw960dp
│ └── dimens.xml
│ ├── values-sw961dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── images
├── VideoMaker-app-audio-mix.jpg
├── VideoMaker-app-audio-record.jpg
├── VideoMaker-app-camera-1.jpg
├── VideoMaker-app-camera-2.jpg
├── VideoMaker-app-camera-3.jpg
├── VideoMaker-app-image-video.jpg
├── VideoMaker-app-menu.jpg
├── VideoMaker-app-multi-texture-single-surface.jpg
├── VideoMaker-app-single-texture-multi-surface.jpg
├── VideoMaker-app-video-push.jpg
├── VideoMaker-app-video-record-1.jpg
└── VideoMaker-app-video-record-2.jpg
├── libmp3util
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── cpp
│ ├── CMakeLists.txt
│ ├── lamemp3
│ │ ├── VbrTag.c
│ │ ├── VbrTag.h
│ │ ├── bitstream.c
│ │ ├── bitstream.h
│ │ ├── encoder.c
│ │ ├── encoder.h
│ │ ├── fft.c
│ │ ├── fft.h
│ │ ├── gain_analysis.c
│ │ ├── gain_analysis.h
│ │ ├── id3tag.c
│ │ ├── id3tag.h
│ │ ├── include
│ │ │ └── lame.h
│ │ ├── l3side.h
│ │ ├── lame-analysis.h
│ │ ├── lame.c
│ │ ├── lame_global_flags.h
│ │ ├── lameerror.h
│ │ ├── machine.h
│ │ ├── mpglib_interface.c
│ │ ├── newmdct.c
│ │ ├── newmdct.h
│ │ ├── presets.c
│ │ ├── psymodel.c
│ │ ├── psymodel.h
│ │ ├── quantize.c
│ │ ├── quantize.h
│ │ ├── quantize_pvt.c
│ │ ├── quantize_pvt.h
│ │ ├── reservoir.c
│ │ ├── reservoir.h
│ │ ├── set_get.c
│ │ ├── set_get.h
│ │ ├── tables.c
│ │ ├── tables.h
│ │ ├── takehiro.c
│ │ ├── util.c
│ │ ├── util.h
│ │ ├── vbrquantize.c
│ │ ├── vbrquantize.h
│ │ ├── vector
│ │ │ ├── lame_intrin.h
│ │ │ └── xmm_quantize_sub.c
│ │ ├── version.c
│ │ └── version.h
│ └── wemp3
│ │ ├── JavaListener.cpp
│ │ ├── WeMp3Encoder.cpp
│ │ ├── WeMp3JNI.cpp
│ │ └── include
│ │ ├── AndroidLog.h
│ │ ├── JavaListener.h
│ │ ├── OnEncodeProgressListener.h
│ │ └── WeMp3Encoder.h
│ ├── java
│ └── com
│ │ └── wtz
│ │ └── libmp3util
│ │ ├── WeMp3Encoder.java
│ │ └── utlis
│ │ └── LogUtils.java
│ └── res
│ └── values
│ └── strings.xml
├── libnaudiorecord
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── cpp
│ ├── CMakeLists.txt
│ └── weaudiorecord
│ │ ├── DoubleBuffer.cpp
│ │ ├── JavaListener.cpp
│ │ ├── WeAudioRecordJNI.cpp
│ │ ├── WeAudioRecorder.cpp
│ │ └── include
│ │ ├── AndroidLog.h
│ │ ├── DoubleBuffer.h
│ │ ├── JavaListener.h
│ │ ├── OnPCMDataCall.h
│ │ └── WeAudioRecorder.h
│ ├── java
│ └── com
│ │ └── wtz
│ │ └── libnaudiorecord
│ │ ├── WeNAudioRecorder.java
│ │ └── utlis
│ │ └── LogUtils.java
│ └── res
│ └── values
│ └── strings.xml
├── libpushflow
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── cpp
│ ├── CMakeLists.txt
│ ├── librtmp
│ │ ├── amf.c
│ │ ├── amf.h
│ │ ├── bytes.h
│ │ ├── dh.h
│ │ ├── dhgroups.h
│ │ ├── handshake.h
│ │ ├── hashswf.c
│ │ ├── http.h
│ │ ├── log.c
│ │ ├── log.h
│ │ ├── parseurl.c
│ │ ├── rtmp.c
│ │ ├── rtmp.h
│ │ └── rtmp_sys.h
│ └── pushflow
│ │ ├── JavaListener.cpp
│ │ ├── RtmpPacketQueue.cpp
│ │ ├── WePushFlow.cpp
│ │ ├── WePushFlowJNI.cpp
│ │ └── include
│ │ ├── AndroidLog.h
│ │ ├── JavaListener.h
│ │ ├── OnPushDisconnectCall.h
│ │ ├── OnStartPushResultListener.h
│ │ ├── RtmpPacketQueue.h
│ │ └── WePushFlow.h
│ ├── java
│ └── com
│ │ └── wtz
│ │ └── libpushflow
│ │ ├── WePushFlow.java
│ │ └── utlis
│ │ └── LogUtils.java
│ └── res
│ └── values
│ └── strings.xml
├── libvideomaker
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── wtz
│ │ └── libvideomaker
│ │ ├── camera
│ │ ├── AcceleFocusListener.java
│ │ ├── WeCamera.java
│ │ └── WeCameraView.java
│ │ ├── egl
│ │ ├── WeEGLHelper.java
│ │ ├── WeGLRenderer.java
│ │ ├── WeGLSurfaceView.java
│ │ ├── WeGLThread.java
│ │ ├── WeGLVideoEncoder.java
│ │ └── WeGLVideoPushEncoder.java
│ │ ├── imagevideo
│ │ └── WeImageVideoView.java
│ │ ├── push
│ │ └── WeVideoPusher.java
│ │ ├── recorder
│ │ ├── WeJAudioRecorder.java
│ │ └── WeVideoRecorder.java
│ │ ├── renderer
│ │ ├── BaseRender.java
│ │ ├── OnScreenRenderer.java
│ │ ├── filters
│ │ │ ├── FilterRenderer.java
│ │ │ ├── GrayFilterRenderer.java
│ │ │ ├── LuminanceFilterRenderer.java
│ │ │ ├── ReverseFilterRenderer.java
│ │ │ └── WatermarkRenderer.java
│ │ └── origins
│ │ │ ├── CameraRenderer.java
│ │ │ ├── ImgRenderer.java
│ │ │ ├── MultiImgRenderer.java
│ │ │ └── SingleImgRenderer.java
│ │ └── utils
│ │ ├── ExponentialWaitStrategy.java
│ │ ├── GLBitmapUtils.java
│ │ ├── HexUtils.java
│ │ ├── LogUtils.java
│ │ ├── ScreenUtils.java
│ │ ├── ShaderUtil.java
│ │ ├── TextUtils.java
│ │ └── TextureUtils.java
│ └── res
│ ├── raw
│ ├── we_vidmk_fragment_camera_oes_shader.glsl
│ ├── we_vidmk_fragment_gray_texture2d_shader.glsl
│ ├── we_vidmk_fragment_luminance_texture2d_shader.glsl
│ ├── we_vidmk_fragment_normal_texture2d_shader.glsl
│ ├── we_vidmk_fragment_reverse_texture2d_shader.glsl
│ ├── we_vidmk_vertex_offscreen_shader.glsl
│ └── we_vidmk_vertex_onscreen_shader.glsl
│ └── values
│ ├── dimens.xml
│ └── strings.xml
├── screenMatch.properties
├── screenMatch_example_dimens.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 | out/
15 | build/
16 |
17 | # Gradle files
18 | .gradle/
19 | gradlew
20 | gradlew.bat
21 |
22 | # Proguard folder generated by Eclipse
23 | proguard/
24 |
25 | # Log Files
26 | *.log
27 |
28 | # Android Lint
29 | lint.xml
30 |
31 | # NDK
32 | obj/
33 |
34 | # Eclipse
35 | .settings/
36 |
37 | # Android Studio
38 | .idea/
39 | .navigation/
40 | .externalNativeBuild/
41 | captures/
42 | .cxx/
43 |
44 | # IntelliJ IDEA
45 | .idea/
46 | *.iml
47 | *.ipr
48 | *.iws
49 |
50 | # Local configuration file (sdk path, etc)
51 | local.properties
52 |
53 | # Mac system files
54 | .DS_Store
55 |
56 | # Keystore files
57 | *.jks
--------------------------------------------------------------------------------
/ReadMe.md:
--------------------------------------------------------------------------------
1 | # VideoMaker
2 |
3 | Video Making base on OpenGL ES + OpenSL ES + SurfaceTexture + SurfaceView + MediaCodec + MediaMuxer + AudioRecord + lame + rtmpdump + WePlayer.
4 |
5 | 此项目是在学习 CSDN 学院[杨万理](https://edu.csdn.net/lecturer/1846)的视频编码和直播推流课程基础上,加上自己的理解、查阅相关专业理论资料和一步步软件构思设计调试而成的,在此记录学习成果,也同时感谢杨老师的知识传播!
6 |
7 | ## libvideomaker 模块
8 |
9 | 实现视频制作的核心功能库,Java 层提供的主要最外层接口类有:
10 | WeCameraView、WeJAudioRecorder、WeImageVideoView、WeVideoRecorder、WeVideoPusher。
11 |
12 | ### WeCameraView
13 |
14 | 基于 OpenGL ES + SurfaceView + SurfaceTexture 实现的相机预览器。
15 |
16 | - 支持相机基本功能:画面预览、自动对焦、前后摄像头切换、拍照图片保存;
17 | - 支持水印:文字水印、图片水印、图文叠加水印、动态改变水印位置;
18 | - 支持简单滤镜:灰度滤镜、反色滤镜;
19 | - 支持预览画面自适应 SurfaceView 容器大小;
20 | - 支持纹理 TextureId 和 EGLContext 共享,可用于视频录制;
21 |
22 | ### WeJAudioRecorder
23 |
24 | 对 Java 层的 AudioRecord 的封装。
25 |
26 | - 支持基本的录音功能:回调 byte[] 数据;
27 | - 支持获取录音时间、声音分贝数等参数;
28 | - 使用单线程执行功能,避免并发调用导致的问题;
29 |
30 | ### WeImageVideoView
31 |
32 | 基于 OpenGL ES + SurfaceView 实现的图片渲染器。
33 |
34 | - 支持图片播放功能:可动态设置改变图片资源;
35 | - 支持水印:文字水印、图片水印、图文叠加水印、动态改变水印位置;
36 | - 支持纹理 TextureId 和 EGLContext 共享,可用于视频录制;
37 |
38 | ### WeVideoRecorder
39 |
40 | 基于 OpenGL ES + MediaCodec + MediaMuxer 实现的视频录制器。
41 |
42 | - 支持视频录制保存为 mp4,图像使用 h264 编码,音频使用 AAC 编码;
43 | - 图像来源可以是相机或图片渲染的纹理;
44 | - 声音来源可以是录音或本地音乐播放的字节数据;
45 |
46 | ### WeVideoPusher
47 |
48 | 基于 OpenGL ES + MediaCodec + rtmpdump 实现的视频直播推流器。
49 |
50 | - 图像使用 h264 编码,音频使用 AAC 编码,通过 RTMP 协议对音视频数据分别做相应的封装发送;
51 | - 图像来源可以是相机或图片渲染的纹理;
52 | - 声音来源可以是录音或本地音乐播放的字节数据;
53 | - 支持推流url、连接超时、音频相关参数等设置;
54 | - 推流连接失败自动重试,采用指数递增延时策略重试;
55 |
56 | ## libpushflow 模块
57 |
58 | 移植 C 库 rtmpdump 到 Android 平台 + 直播推流接口封装。
59 | Java 层提供的接口类为 WePushFlow。
60 |
61 | - 支持推流url、连接超时、音频相关参数等设置;
62 | - 分别提供 SPS/PPS、图像 H264 数据、音频 AAC 数据推送接口;
63 |
64 | ## libnaudiorecord 模块
65 |
66 | 使用 Native 层 OpenSL ES 实现的录音器。Java 层提供的接口类为 WeNAudioRecorder。
67 |
68 | - 支持基本的录音功能:回调 byte[] 数据;
69 | - 支持获取录音时间、声音分贝数等参数;
70 | - 使用单线程执行功能,避免并发调用导致的问题;
71 |
72 | ## libmp3util 模块
73 |
74 | 集成 C 库 lame 到 Android 平台 + mp3 编码接口封装。
75 | Java 层提供的接口类为 WeMp3Encoder。
76 |
77 | - 支持同一进程多实例操作。
78 | - 支持设置通道数、编码位数、输出质量等参数设置。
79 | - MP3 编码数据来源分两种:
80 | - 来源为 PCM 文件 / WAV 文件。每个文件独立编码,可以多任务、多线程、多文件操作。适用场景:批量文件异步编码。
81 | - 来源为 PCM buffer。从 PCM buffer 取数据编码的方法分成了多步操作,涉及状态切换,适合单任务执行。支持多线程操作。
82 |
83 | ## app 模块
84 |
85 | 主要是对以上各个库模块的使用验证测试,如下:
86 |
87 | 
88 |
89 | - EGL 环境测试:单纹理、多 Surface 渲染;
90 |
91 | 
92 |
93 | - EGL 环境测试:多纹理、单 Surface 渲染;
94 |
95 | 
96 |
97 | - 音频录制测试:使用 WeJAudioRecorder、WeNAudioRecorder 录音,使用 WeMp3Encoder 保存为 mp3文件,使用 WePlayer 播放录音文件;
98 |
99 | 
100 |
101 | - 音频混音测试:使用线性叠加平均混音算法对录音与背景音乐进行混音测试;
102 |
103 | 
104 |
105 | - 摄像头预览测试:使用 WeCameraView 实现画面预览、自动对焦、前后摄像头切换、拍照图片保存、水印、滤镜效果;
106 |
107 | 
108 | 
109 | 
110 |
111 | - 视频录制测试:使用 WeVideoRecorder 实现视频编码保存为 mp4,支持声音来源有:麦克风、音乐、麦克风与音乐混音,图像来自 WeCameraView;
112 |
113 | 
114 | 
115 |
116 | - 图像合成视频测试:使用 WeImageVideoView 手动或自动连续加载渲染多张图片,配合音乐播放,使用 WeVideoRecorder 合成为视频;
117 |
118 | 
119 |
120 | - 直播推流测试:与视频录制测试类似,区别在于使用 WeVideoPusher 而不是 WeVideoRecorder 来编码和封装数据并发送到直播服务器;
121 |
122 | 
123 |
124 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.2"
6 | defaultConfig {
7 | applicationId "com.wtz.videomaker"
8 | minSdkVersion 19
9 | targetSdkVersion 29
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | repositories {
14 | flatDir {
15 | dirs 'libs'
16 | }
17 | }
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
22 | ndk {
23 | abiFilters 'armeabi-v7a', 'arm64-v8a'
24 | }
25 | }
26 | debug {
27 | ndk {
28 | abiFilters 'armeabi-v7a', 'arm64-v8a'
29 | }
30 | }
31 | }
32 | }
33 |
34 | dependencies {
35 | implementation fileTree(dir: 'libs', include: ['*.jar'])
36 | implementation 'androidx.appcompat:appcompat:1.1.0'
37 | implementation project(path: ':libvideomaker')
38 | implementation project(path: ':libnaudiorecord')
39 | implementation(name:'weplayer-release', ext:'aar')
40 | implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
41 | implementation 'androidx.recyclerview:recyclerview:1.1.0'
42 | implementation 'com.squareup.picasso:picasso:2.71828'
43 | implementation 'com.github.zcweng:switch-button:0.0.3@aar'
44 | compile project(path: ':libmp3util')
45 | }
46 |
--------------------------------------------------------------------------------
/app/libs/weplayer-release.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/libs/weplayer-release.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
22 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
27 |
30 |
32 |
34 |
37 |
40 |
43 |
46 |
48 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wtz/videomaker/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.wtz.videomaker;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.View;
6 |
7 | import androidx.appcompat.app.AppCompatActivity;
8 |
9 | import com.wtz.libvideomaker.utils.LogUtils;
10 |
11 |
12 | public class MainActivity extends AppCompatActivity implements View.OnClickListener {
13 | private static final String TAG = "app.MainActivity";
14 |
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | LogUtils.d(TAG, "onCreate");
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_main);
21 |
22 | findViewById(R.id.btn_multi_surface).setOnClickListener(this);
23 | findViewById(R.id.btn_single_surface).setOnClickListener(this);
24 | findViewById(R.id.btn_audio_record).setOnClickListener(this);
25 | findViewById(R.id.btn_camera).setOnClickListener(this);
26 | findViewById(R.id.btn_video_record).setOnClickListener(this);
27 | findViewById(R.id.btn_image_video).setOnClickListener(this);
28 | findViewById(R.id.btn_mix_audio).setOnClickListener(this);
29 | findViewById(R.id.btn_push_video).setOnClickListener(this);
30 | }
31 |
32 | @Override
33 | public void onClick(View view) {
34 | switch (view.getId()) {
35 | case R.id.btn_multi_surface:
36 | startActivity(new Intent(MainActivity.this, MultiSurfaceActivity.class));
37 | break;
38 | case R.id.btn_single_surface:
39 | startActivity(new Intent(MainActivity.this, SingleSurfaceActivity.class));
40 | break;
41 | case R.id.btn_audio_record:
42 | startActivity(new Intent(MainActivity.this, AudioRecordActivity.class));
43 | break;
44 | case R.id.btn_mix_audio:
45 | startActivity(new Intent(MainActivity.this, MixAudioActivity.class));
46 | break;
47 | case R.id.btn_camera:
48 | startActivity(new Intent(MainActivity.this, CameraActivity.class));
49 | break;
50 | case R.id.btn_video_record:
51 | startActivity(new Intent(MainActivity.this, VideoRecordActivity.class));
52 | break;
53 | case R.id.btn_image_video:
54 | startActivity(new Intent(MainActivity.this, ImageVideoActivity.class));
55 | break;
56 | case R.id.btn_push_video:
57 | startActivity(new Intent(MainActivity.this, VideoPushActivity.class));
58 | break;
59 | }
60 | }
61 |
62 | @Override
63 | protected void onDestroy() {
64 | LogUtils.d(TAG, "onDestroy");
65 | super.onDestroy();
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wtz/videomaker/SingleSurfaceActivity.java:
--------------------------------------------------------------------------------
1 | package com.wtz.videomaker;
2 |
3 | import android.os.Bundle;
4 |
5 | import androidx.appcompat.app.AppCompatActivity;
6 |
7 | import com.wtz.libvideomaker.utils.LogUtils;
8 | import com.wtz.videomaker.surfaceview.MultiImgSurfaceView;
9 |
10 |
11 | public class SingleSurfaceActivity extends AppCompatActivity {
12 | private static final String TAG = "SingleSurfaceActivity";
13 |
14 | private MultiImgSurfaceView mMainSurfaceView;
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | LogUtils.d(TAG, "onCreate");
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_single_surface);
21 | mMainSurfaceView = findViewById(R.id.main_surface_view);
22 | }
23 |
24 | @Override
25 | protected void onDestroy() {
26 | LogUtils.d(TAG, "onDestroy");
27 | mMainSurfaceView.clearSourceImage();
28 | mMainSurfaceView = null;
29 | super.onDestroy();
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wtz/videomaker/adapter/BaseRecyclerViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.wtz.videomaker.adapter;
2 |
3 | import android.view.View;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.recyclerview.widget.RecyclerView;
7 |
8 | public abstract class BaseRecyclerViewAdapter extends RecyclerView.Adapter {
9 |
10 | public interface OnRecyclerViewItemClickListener {
11 |
12 | void onItemClick(View view, int position);
13 |
14 | boolean onItemLongClick(View view, int position);
15 |
16 | }
17 |
18 | protected OnRecyclerViewItemClickListener mOnItemClickListener;
19 |
20 | public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
21 | this.mOnItemClickListener = listener;
22 | }
23 |
24 | protected void bindItemClickListener(@NonNull final RecyclerView.ViewHolder holder) {
25 | holder.itemView.setOnClickListener(new View.OnClickListener() {
26 | @Override
27 | public void onClick(View v) {
28 | if (mOnItemClickListener != null) {
29 | int pos = holder.getLayoutPosition();
30 | mOnItemClickListener.onItemClick(holder.itemView, pos);
31 | }
32 | }
33 | });
34 | holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
35 | @Override
36 | public boolean onLongClick(View v) {
37 | if (mOnItemClickListener != null) {
38 | int pos = holder.getLayoutPosition();
39 | return mOnItemClickListener.onItemLongClick(holder.itemView, pos);
40 | }
41 | return false;
42 | }
43 | });
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wtz/videomaker/surfaceview/FilterSurfaceView.java:
--------------------------------------------------------------------------------
1 | package com.wtz.videomaker.surfaceview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.util.Log;
6 |
7 | import com.wtz.libvideomaker.egl.WeGLSurfaceView;
8 | import com.wtz.libvideomaker.egl.WeGLRenderer;
9 | import com.wtz.libvideomaker.renderer.OnScreenRenderer;
10 | import com.wtz.libvideomaker.renderer.filters.FilterRenderer;
11 |
12 | public abstract class FilterSurfaceView extends WeGLSurfaceView
13 | implements WeGLRenderer, FilterRenderer.OnFilterTextureChangedListener {
14 |
15 | private FilterRenderer mFilterRender;
16 | private OnScreenRenderer mOnScreenRenderer;
17 |
18 | public FilterSurfaceView(Context context) {
19 | this(context, null);
20 | }
21 |
22 | public FilterSurfaceView(Context context, AttributeSet attrs) {
23 | this(context, attrs, 0);
24 | }
25 |
26 | public FilterSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
27 | super(context, attrs, defStyleAttr);
28 | setRenderMode(RENDERMODE_WHEN_DIRTY);
29 |
30 | mFilterRender = createFilterRenderer(context);
31 | mFilterRender.setFilterTextureChangedListener(this);
32 |
33 | mOnScreenRenderer = new OnScreenRenderer(context, getExternalLogTag());
34 | mOnScreenRenderer.setExternalTextureId(mFilterRender.getFilterTextureId());
35 | }
36 |
37 | protected abstract FilterRenderer createFilterRenderer(Context context);
38 |
39 | public void setExternalTextureId(int id) {
40 | mFilterRender.setExternalTextureId(id);
41 | }
42 |
43 | @Override
44 | protected WeGLRenderer getRenderer() {
45 | return this;
46 | }
47 |
48 | @Override
49 | public void onEGLContextCreated() {
50 | Log.d(getExternalLogTag(), "onEGLContextCreated");
51 | mFilterRender.onEGLContextCreated();
52 | mOnScreenRenderer.onEGLContextCreated();
53 | }
54 |
55 | @Override
56 | public void onSurfaceChanged(int width, int height) {
57 | Log.d(getExternalLogTag(), "onSurfaceChanged " + width + "x" + height);
58 | mFilterRender.onSurfaceChanged(width, height);
59 | mOnScreenRenderer.onSurfaceChanged(width, height);
60 | }
61 |
62 | @Override
63 | public void onFilterTextureChanged(FilterRenderer renderer, int textureID) {
64 | mOnScreenRenderer.setExternalTextureId(textureID);
65 | }
66 |
67 | @Override
68 | public void onDrawFrame() {
69 | Log.d(getExternalLogTag(), "onDrawFrame");
70 | mFilterRender.onDrawFrame();
71 | mOnScreenRenderer.onDrawFrame();
72 | }
73 |
74 | @Override
75 | public void onEGLContextToDestroy() {
76 | Log.d(getExternalLogTag(), "onEGLContextToDestroy");
77 | mFilterRender.onEGLContextToDestroy();
78 | mOnScreenRenderer.onEGLContextToDestroy();
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wtz/videomaker/surfaceview/GraySurfaceView.java:
--------------------------------------------------------------------------------
1 | package com.wtz.videomaker.surfaceview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | import com.wtz.libvideomaker.renderer.filters.FilterRenderer;
7 | import com.wtz.libvideomaker.renderer.filters.GrayFilterRenderer;
8 |
9 | public class GraySurfaceView extends FilterSurfaceView{
10 | private static final String TAG = GraySurfaceView.class.getSimpleName();
11 |
12 | public GraySurfaceView(Context context) {
13 | super(context);
14 | }
15 |
16 | public GraySurfaceView(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | }
19 |
20 | public GraySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
21 | super(context, attrs, defStyleAttr);
22 | }
23 |
24 | @Override
25 | protected String getExternalLogTag() {
26 | return TAG;
27 | }
28 |
29 | @Override
30 | protected FilterRenderer createFilterRenderer(Context context) {
31 | return new GrayFilterRenderer(context);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wtz/videomaker/surfaceview/LuminanceSurfaceView.java:
--------------------------------------------------------------------------------
1 | package com.wtz.videomaker.surfaceview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | import com.wtz.libvideomaker.renderer.filters.FilterRenderer;
7 | import com.wtz.libvideomaker.renderer.filters.LuminanceFilterRenderer;
8 |
9 | public class LuminanceSurfaceView extends FilterSurfaceView{
10 | private static final String TAG = LuminanceSurfaceView.class.getSimpleName();
11 |
12 | public LuminanceSurfaceView(Context context) {
13 | super(context);
14 | }
15 |
16 | public LuminanceSurfaceView(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | }
19 |
20 | public LuminanceSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
21 | super(context, attrs, defStyleAttr);
22 | }
23 |
24 | @Override
25 | protected String getExternalLogTag() {
26 | return TAG;
27 | }
28 |
29 | @Override
30 | protected FilterRenderer createFilterRenderer(Context context) {
31 | return new LuminanceFilterRenderer(context);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wtz/videomaker/surfaceview/MultiImgSurfaceView.java:
--------------------------------------------------------------------------------
1 | package com.wtz.videomaker.surfaceview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.util.Log;
6 |
7 | import com.wtz.libvideomaker.egl.WeGLSurfaceView;
8 | import com.wtz.libvideomaker.egl.WeGLRenderer;
9 | import com.wtz.libvideomaker.renderer.OnScreenRenderer;
10 | import com.wtz.libvideomaker.renderer.origins.ImgRenderer;
11 | import com.wtz.libvideomaker.renderer.origins.MultiImgRenderer;
12 | import com.wtz.videomaker.R;
13 |
14 | public class MultiImgSurfaceView extends WeGLSurfaceView implements WeGLRenderer, ImgRenderer.OnSharedTextureChangedListener {
15 | private static final String TAG = MultiImgSurfaceView.class.getSimpleName();
16 |
17 | private MultiImgRenderer mImgOffScreenRenderer;
18 | private OnScreenRenderer mOnScreenRenderer;
19 |
20 | public MultiImgSurfaceView(Context context) {
21 | this(context, null);
22 | }
23 |
24 | public MultiImgSurfaceView(Context context, AttributeSet attrs) {
25 | this(context, attrs, 0);
26 | }
27 |
28 | public MultiImgSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
29 | super(context, attrs, defStyleAttr);
30 | setRenderMode(RENDERMODE_WHEN_DIRTY);
31 |
32 | mImgOffScreenRenderer = new MultiImgRenderer(context);
33 | mImgOffScreenRenderer.setImageList(new int[]{
34 | R.drawable.tree, R.drawable.sunflower, R.drawable.lotus,
35 | R.drawable.carry_up, R.drawable.happy
36 | });
37 | mImgOffScreenRenderer.setSharedTextureChangedListener(this);
38 |
39 | mOnScreenRenderer = new OnScreenRenderer(context, TAG);
40 | mOnScreenRenderer.setExternalTextureId(mImgOffScreenRenderer.getSharedTextureId());
41 | }
42 |
43 | @Override
44 | protected String getExternalLogTag() {
45 | return TAG;
46 | }
47 |
48 | @Override
49 | public void onSharedTextureChanged(int textureID) {
50 | mOnScreenRenderer.setExternalTextureId(textureID);
51 | }
52 |
53 | @Override
54 | protected WeGLRenderer getRenderer() {
55 | return this;
56 | }
57 |
58 | @Override
59 | public void onEGLContextCreated() {
60 | Log.d(TAG, "onEGLContextCreated");
61 | mImgOffScreenRenderer.onEGLContextCreated();
62 | mOnScreenRenderer.onEGLContextCreated();
63 | }
64 |
65 | @Override
66 | public void onSurfaceChanged(int width, int height) {
67 | Log.d(TAG, "onSurfaceChanged " + width + "x" + height);
68 | mImgOffScreenRenderer.onSurfaceChanged(width, height);
69 | mOnScreenRenderer.onSurfaceChanged(width, height);
70 | }
71 |
72 | @Override
73 | public void onDrawFrame() {
74 | Log.d(TAG, "onDrawFrame");
75 | mImgOffScreenRenderer.onDrawFrame();
76 | mOnScreenRenderer.onDrawFrame();
77 | }
78 |
79 | @Override
80 | public void onEGLContextToDestroy() {
81 | Log.d(TAG, "onEGLContextToDestroy");
82 | mImgOffScreenRenderer.onEGLContextToDestroy();
83 | mOnScreenRenderer.onEGLContextToDestroy();
84 | }
85 |
86 | public void clearSourceImage() {
87 | if (mImgOffScreenRenderer != null) {
88 | mImgOffScreenRenderer.clearSourceImage();
89 | }
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wtz/videomaker/surfaceview/ReverseSurfaceView.java:
--------------------------------------------------------------------------------
1 | package com.wtz.videomaker.surfaceview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | import com.wtz.libvideomaker.renderer.filters.FilterRenderer;
7 | import com.wtz.libvideomaker.renderer.filters.ReverseFilterRenderer;
8 |
9 | public class ReverseSurfaceView extends FilterSurfaceView{
10 | private static final String TAG = ReverseSurfaceView.class.getSimpleName();
11 |
12 | public ReverseSurfaceView(Context context) {
13 | super(context);
14 | }
15 |
16 | public ReverseSurfaceView(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | }
19 |
20 | public ReverseSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
21 | super(context, attrs, defStyleAttr);
22 | }
23 |
24 | @Override
25 | protected String getExternalLogTag() {
26 | return TAG;
27 | }
28 |
29 | @Override
30 | protected FilterRenderer createFilterRenderer(Context context) {
31 | return new ReverseFilterRenderer(context);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wtz/videomaker/utils/DateTimeUtil.java:
--------------------------------------------------------------------------------
1 | package com.wtz.videomaker.utils;
2 |
3 | import java.text.SimpleDateFormat;
4 | import java.util.Date;
5 |
6 | public class DateTimeUtil {
7 |
8 | /**
9 | * @param format e.g. "yy-MM-dd_HH-mm-ss"
10 | * @return DateTime
11 | */
12 | public static String getCurrentDateTime(String format) {
13 | Date date = new Date();
14 | SimpleDateFormat df = new SimpleDateFormat(format);
15 | String nowTime = df.format(date);
16 | return nowTime;
17 | }
18 |
19 | /**
20 | * 把剩余毫秒数转化成“时:分:秒”字符串
21 | *
22 | * @param timeMilli
23 | * @return
24 | */
25 | public static String changeRemainTimeToHms(long timeMilli) {
26 | if (timeMilli == 0) {
27 | return "00:00:00";
28 | }
29 | int totalSeconds = Math.round((float) timeMilli / 1000);// 毫秒数转秒数,毫秒部分四舍五入
30 | int second = totalSeconds % 60;// 秒数除60得分钟数再取余得秒数
31 | int minute = totalSeconds / 60 % 60;// 秒数除两个60得小时再取余得分钟数
32 | int hour = totalSeconds / 60 / 60;// 秒数除两个60得小时数
33 | String hourString = formatTime(String.valueOf(hour));
34 | String minuteString = formatTime(String.valueOf(minute));
35 | String secondString = formatTime(String.valueOf(second));
36 | return hourString + ":" + minuteString + ":" + secondString;
37 | }
38 | /**
39 | * 把剩余毫秒数转化成“分:秒”字符串
40 | *
41 | * @param timeMilli
42 | * @return
43 | */
44 | public static String changeRemainTimeToMs(long timeMilli) {
45 | if (timeMilli == 0) {
46 | return "00:00";
47 | }
48 | int totalSeconds = Math.round((float) timeMilli / 1000);// 毫秒数转秒数,毫秒部分四舍五入
49 | int second = totalSeconds % 60;// 秒数除60得分钟数再取余得秒数
50 | int minute = totalSeconds / 60;// 秒数除1个60得分钟数
51 | String minuteString = formatTime(String.valueOf(minute));
52 | String secondString = formatTime(String.valueOf(second));
53 | return minuteString + ":" + secondString;
54 | }
55 |
56 | private static String formatTime(String original) {
57 | if (original != null && original.length() < 2) {
58 | original = "0" + original;
59 | }
60 | return original;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wtz/videomaker/utils/UriUtil.java:
--------------------------------------------------------------------------------
1 | package com.wtz.videomaker.utils;
2 |
3 | import android.content.ContentUris;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.net.Uri;
7 | import android.os.Build;
8 | import android.os.Environment;
9 | import android.provider.DocumentsContract;
10 | import android.provider.MediaStore;
11 |
12 | public class UriUtil {
13 | public static String getUriPath(Context context, Uri uri) {
14 | if (uri == null) {
15 | return null;
16 | }
17 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
18 | if ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
19 | final String docId = DocumentsContract.getDocumentId(uri);
20 | final String[] split = docId.split(":");
21 | final String type = split[0];
22 | if ("primary".equalsIgnoreCase(type)) {
23 | return Environment.getExternalStorageDirectory() + "/" + split[1];
24 | }
25 | } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
26 | final String id = DocumentsContract.getDocumentId(uri);
27 | final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
28 | return getDataColumn(context, contentUri, null, null);
29 | } else if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
30 | final String docId = DocumentsContract.getDocumentId(uri);
31 | final String[] split = docId.split(":");
32 | final String type = split[0];
33 | Uri contentUri = null;
34 | if ("image".equals(type)) {
35 | contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
36 | } else if ("video".equals(type)) {
37 | contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
38 | } else if ("audio".equals(type)) {
39 | contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
40 | }
41 | final String selection = "_id=?";
42 | final String[] selectionArgs = new String[]{split[1]};
43 | return getDataColumn(context, contentUri, selection, selectionArgs);
44 | }
45 | } else if ("content".equalsIgnoreCase(uri.getScheme())) {
46 | if ("com.google.android.apps.photos.content".equals(uri.getAuthority())) {
47 | return uri.getLastPathSegment();
48 | }
49 | return getDataColumn(context, uri, null, null);
50 | } else if ("file".equalsIgnoreCase(uri.getScheme())) {
51 | return uri.getPath();
52 | }
53 | return null;
54 | }
55 |
56 | public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
57 | Cursor cursor = null;
58 | final String column = "_data";
59 | final String[] projection = {column};
60 | try {
61 | cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
62 | if (cursor != null && cursor.moveToFirst()) {
63 | final int column_index = cursor.getColumnIndexOrThrow(column);
64 | return cursor.getString(column_index);
65 | }
66 | } catch (Exception e) {
67 | e.printStackTrace();
68 | } finally {
69 | if (cursor != null) cursor.close();
70 | }
71 | return null;
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/carry_up.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/drawable/carry_up.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/circle_ball_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/grid_divider_line_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/happy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/drawable/happy.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/icon_select.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/drawable/icon_select.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/image_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/drawable/image_default.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/lotus.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/drawable/lotus.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/purple_ball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/drawable/purple_ball.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/seekbar_style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
24 | -
26 |
27 |
28 |
29 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/seekbar_thumb.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sunflower.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/drawable/sunflower.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tree.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/drawable/tree.jpg
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_camera.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
18 |
19 |
23 |
24 |
25 |
26 |
33 |
34 |
43 |
44 |
54 |
55 |
62 |
63 |
70 |
71 |
77 |
78 |
84 |
85 |
86 |
87 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_image_chooser.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
14 |
15 |
24 |
25 |
34 |
35 |
36 |
44 |
45 |
52 |
53 |
61 |
62 |
63 |
72 |
73 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
23 |
24 |
30 |
31 |
37 |
38 |
44 |
45 |
51 |
52 |
58 |
59 |
65 |
66 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_multi_surface.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_single_surface.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_image_chooser.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
30 |
31 |
37 |
38 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_spinner_time_unit.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/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/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | VideoMaker
3 |
4 | 权限请求
5 | 同意
6 | 拒绝
7 | 请授权以下权限以保证程序能正常运行:\n\n%1$s
8 | Calendar
9 | Camera
10 | Contacts
11 | Accounts
12 | Location
13 | Microphone
14 | Phone
15 | Body Sensors
16 | SMS
17 | Storage
18 | 系统设置
19 | 显示悬浮窗
20 | 安装应用
21 | 发送通知
22 | 访问系统通知
23 |
24 | 开始\n录制
25 | 停止\n录制
26 | 拍照
27 | 选择\n音乐
28 | 播放\n音乐
29 | 暂停\n音乐
30 | 切换\n摄像头
31 | 正常
32 | 灰度
33 | 反色
34 | 00:00
35 | 00:00:00
36 | 选择\n图片
37 | 开始\n合成
38 | 停止\n合成
39 | 上\n一张
40 | 下\n一张
41 | 自动换图
42 | 换图间隔
43 | 请选择图片
44 | 间隔太小,请设置大于%d毫秒
45 | 开始直播
46 | 停止直播
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 |
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.5.1'
11 |
12 | // NOTE: Do not place your application dependencies here; they belong
13 | // in the individual module build.gradle files
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | jcenter()
21 |
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/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=-Xmx1536m
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 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 |
21 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Mar 10 12:12:09 CST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/images/VideoMaker-app-audio-mix.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-audio-mix.jpg
--------------------------------------------------------------------------------
/images/VideoMaker-app-audio-record.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-audio-record.jpg
--------------------------------------------------------------------------------
/images/VideoMaker-app-camera-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-camera-1.jpg
--------------------------------------------------------------------------------
/images/VideoMaker-app-camera-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-camera-2.jpg
--------------------------------------------------------------------------------
/images/VideoMaker-app-camera-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-camera-3.jpg
--------------------------------------------------------------------------------
/images/VideoMaker-app-image-video.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-image-video.jpg
--------------------------------------------------------------------------------
/images/VideoMaker-app-menu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-menu.jpg
--------------------------------------------------------------------------------
/images/VideoMaker-app-multi-texture-single-surface.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-multi-texture-single-surface.jpg
--------------------------------------------------------------------------------
/images/VideoMaker-app-single-texture-multi-surface.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-single-texture-multi-surface.jpg
--------------------------------------------------------------------------------
/images/VideoMaker-app-video-push.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-video-push.jpg
--------------------------------------------------------------------------------
/images/VideoMaker-app-video-record-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-video-record-1.jpg
--------------------------------------------------------------------------------
/images/VideoMaker-app-video-record-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/images/VideoMaker-app-video-record-2.jpg
--------------------------------------------------------------------------------
/libmp3util/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/libmp3util/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 29
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
14 | consumerProguardFiles 'consumer-rules.pro'
15 |
16 | externalNativeBuild {
17 | cmake {
18 | cppFlags "-std=c++11 -frtti -fexceptions"
19 | arguments "-DANDROID_STL=c++_static" // 使用 stl map
20 | abiFilters 'armeabi-v7a','arm64-v8a'
21 | }
22 | }
23 | }
24 |
25 | buildTypes {
26 | release {
27 | minifyEnabled false
28 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
29 | }
30 | }
31 |
32 | externalNativeBuild {
33 | cmake {
34 | path "src/main/cpp/CMakeLists.txt"
35 | version "3.10.2"
36 | }
37 | }
38 | }
39 |
40 | dependencies {
41 | implementation fileTree(dir: 'libs', include: ['*.jar'])
42 | }
43 |
--------------------------------------------------------------------------------
/libmp3util/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/libmp3util/consumer-rules.pro
--------------------------------------------------------------------------------
/libmp3util/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/libmp3util/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.4.1)
2 |
3 | include_directories(wemp3/include/)
4 | include_directories(lamemp3/include/)
5 |
6 | aux_source_directory(lamemp3 LAME_SRC_LIST)# 查找在某个路径下的所有源文件
7 |
8 | # 因为很多类里用到的一些标准函数需要定义这个宏定义才会导入对应头文件
9 | add_compile_options("-DSTDC_HEADERS")
10 |
11 | # Creates and names a library, sets it as either STATIC or SHARED,
12 | # and provides the relative paths to its source code.
13 | add_library(
14 | wemp3
15 |
16 | # Sets the library as a shared library.
17 | SHARED
18 |
19 | # Provides a relative path to your source file(s).
20 | ${LAME_SRC_LIST}
21 | wemp3/WeMp3JNI.cpp
22 | wemp3/WeMp3Encoder.cpp
23 | wemp3/JavaListener.cpp )
24 |
25 | # Searches for a specified prebuilt library and stores the path as a variable.
26 | # Because CMake includes system libraries in the search path by default,
27 | # you only need to specify the name of the public NDK library you want to add.
28 | find_library(
29 | # Sets the name of the path variable.
30 | log-lib
31 | # Specifies the name of the NDK library that you want CMake to locate.
32 | log)
33 |
34 | # Specifies libraries CMake should link to your target library.
35 | target_link_libraries(
36 | wemp3
37 |
38 | # Links the target library to the log library included in the NDK.
39 | ${log-lib})
40 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/VbrTag.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Xing VBR tagging for LAME.
3 | *
4 | * Copyright (c) 1999 A.L. Faber
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_VRBTAG_H
23 | #define LAME_VRBTAG_H
24 |
25 |
26 | /* -----------------------------------------------------------
27 | * A Vbr header may be present in the ancillary
28 | * data field of the first frame of an mp3 bitstream
29 | * The Vbr header (optionally) contains
30 | * frames total number of audio frames in the bitstream
31 | * bytes total number of bytes in the bitstream
32 | * toc table of contents
33 |
34 | * toc (table of contents) gives seek points
35 | * for random access
36 | * the ith entry determines the seek point for
37 | * i-percent duration
38 | * seek point in bytes = (toc[i]/256.0) * total_bitstream_bytes
39 | * e.g. half duration seek point = (toc[50]/256.0) * total_bitstream_bytes
40 | */
41 |
42 |
43 | #define FRAMES_FLAG 0x0001
44 | #define BYTES_FLAG 0x0002
45 | #define TOC_FLAG 0x0004
46 | #define VBR_SCALE_FLAG 0x0008
47 |
48 | #define NUMTOCENTRIES 100
49 |
50 | #ifndef lame_internal_flags_defined
51 | #define lame_internal_flags_defined
52 | struct lame_internal_flags;
53 | typedef struct lame_internal_flags lame_internal_flags;
54 | #endif
55 |
56 |
57 | /*structure to receive extracted header */
58 | /* toc may be NULL*/
59 | typedef struct {
60 | int h_id; /* from MPEG header, 0=MPEG2, 1=MPEG1 */
61 | int samprate; /* determined from MPEG header */
62 | int flags; /* from Vbr header data */
63 | int frames; /* total bit stream frames from Vbr header data */
64 | int bytes; /* total bit stream bytes from Vbr header data */
65 | int vbr_scale; /* encoded vbr scale from Vbr header data */
66 | unsigned char toc[NUMTOCENTRIES]; /* may be NULL if toc not desired */
67 | int headersize; /* size of VBR header, in bytes */
68 | int enc_delay; /* encoder delay */
69 | int enc_padding; /* encoder paddign added at end of stream */
70 | } VBRTAGDATA;
71 |
72 | int GetVbrTag(VBRTAGDATA * pTagData, const unsigned char *buf);
73 |
74 | int InitVbrTag(lame_global_flags * gfp);
75 | int PutVbrTag(lame_global_flags const *gfp, FILE * fid);
76 | void AddVbrFrame(lame_internal_flags * gfc);
77 | void UpdateMusicCRC(uint16_t * crc, const unsigned char *buffer, int size);
78 |
79 | #endif
80 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/bitstream.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MP3 bitstream Output interface for LAME
3 | *
4 | * Copyright (c) 1999 Takehiro TOMINAGA
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_BITSTREAM_H
23 | #define LAME_BITSTREAM_H
24 |
25 | int getframebits(const lame_internal_flags * gfc);
26 |
27 | int format_bitstream(lame_internal_flags * gfc);
28 |
29 | void flush_bitstream(lame_internal_flags * gfc);
30 | void add_dummy_byte(lame_internal_flags * gfc, unsigned char val, unsigned int n);
31 |
32 | int copy_buffer(lame_internal_flags * gfc, unsigned char *buffer, int buffer_size,
33 | int update_crc);
34 | void init_bit_stream_w(lame_internal_flags * gfc);
35 | void CRC_writeheader(lame_internal_flags const *gfc, char *buffer);
36 | int compute_flushbits(const lame_internal_flags * gfp, int *nbytes);
37 |
38 | int get_max_frame_buffer_size_by_constraint(SessionConfig_t const * cfg, int constraint);
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/encoder.h:
--------------------------------------------------------------------------------
1 | /*
2 | * encoder.h include file
3 | *
4 | * Copyright (c) 2000 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 |
23 | #ifndef LAME_ENCODER_H
24 | #define LAME_ENCODER_H
25 |
26 | /***********************************************************************
27 | *
28 | * encoder and decoder delays
29 | *
30 | ***********************************************************************/
31 |
32 | /*
33 | * layer III enc->dec delay: 1056 (1057?) (observed)
34 | * layer II enc->dec delay: 480 (481?) (observed)
35 | *
36 | * polyphase 256-16 (dec or enc) = 240
37 | * mdct 256+32 (9*32) (dec or enc) = 288
38 | * total: 512+16
39 | *
40 | * My guess is that delay of polyphase filterbank is actualy 240.5
41 | * (there are technical reasons for this, see postings in mp3encoder).
42 | * So total Encode+Decode delay = ENCDELAY + 528 + 1
43 | */
44 |
45 | /*
46 | * ENCDELAY The encoder delay.
47 | *
48 | * Minimum allowed is MDCTDELAY (see below)
49 | *
50 | * The first 96 samples will be attenuated, so using a value less than 96
51 | * will result in corrupt data for the first 96-ENCDELAY samples.
52 | *
53 | * suggested: 576
54 | * set to 1160 to sync with FhG.
55 | */
56 |
57 | #define ENCDELAY 576
58 |
59 |
60 |
61 | /*
62 | * make sure there is at least one complete frame after the
63 | * last frame containing real data
64 | *
65 | * Using a value of 288 would be sufficient for a
66 | * a very sophisticated decoder that can decode granule-by-granule instead
67 | * of frame by frame. But lets not assume this, and assume the decoder
68 | * will not decode frame N unless it also has data for frame N+1
69 | *
70 | */
71 | /*#define POSTDELAY 288*/
72 | #define POSTDELAY 1152
73 |
74 |
75 |
76 | /*
77 | * delay of the MDCT used in mdct.c
78 | * original ISO routines had a delay of 528!
79 | * Takehiro's routines:
80 | */
81 |
82 | #define MDCTDELAY 48
83 | #define FFTOFFSET (224+MDCTDELAY)
84 |
85 | /*
86 | * Most decoders, including the one we use, have a delay of 528 samples.
87 | */
88 |
89 | #define DECDELAY 528
90 |
91 |
92 | /* number of subbands */
93 | #define SBLIMIT 32
94 |
95 | /* parition bands bands */
96 | #define CBANDS 64
97 |
98 | /* number of critical bands/scale factor bands where masking is computed*/
99 | #define SBPSY_l 21
100 | #define SBPSY_s 12
101 |
102 | /* total number of scalefactor bands encoded */
103 | #define SBMAX_l 22
104 | #define SBMAX_s 13
105 | #define PSFB21 6
106 | #define PSFB12 6
107 |
108 |
109 |
110 | /* FFT sizes */
111 | #define BLKSIZE 1024
112 | #define HBLKSIZE (BLKSIZE/2 + 1)
113 | #define BLKSIZE_s 256
114 | #define HBLKSIZE_s (BLKSIZE_s/2 + 1)
115 |
116 |
117 | /* #define switch_pe 1800 */
118 | #define NORM_TYPE 0
119 | #define START_TYPE 1
120 | #define SHORT_TYPE 2
121 | #define STOP_TYPE 3
122 |
123 | /*
124 | * Mode Extention:
125 | * When we are in stereo mode, there are 4 possible methods to store these
126 | * two channels. The stereo modes -m? are using a subset of them.
127 | *
128 | * -ms: MPG_MD_LR_LR
129 | * -mj: MPG_MD_LR_LR and MPG_MD_MS_LR
130 | * -mf: MPG_MD_MS_LR
131 | * -mi: all
132 | */
133 | #if 0
134 | #define MPG_MD_LR_LR 0
135 | #define MPG_MD_LR_I 1
136 | #define MPG_MD_MS_LR 2
137 | #define MPG_MD_MS_I 3
138 | #endif
139 | enum MPEGChannelMode
140 | { MPG_MD_LR_LR = 0
141 | , MPG_MD_LR_I = 1
142 | , MPG_MD_MS_LR = 2
143 | , MPG_MD_MS_I = 3
144 | };
145 |
146 | #ifndef lame_internal_flags_defined
147 | #define lame_internal_flags_defined
148 | struct lame_internal_flags;
149 | typedef struct lame_internal_flags lame_internal_flags;
150 | #endif
151 |
152 | int lame_encode_mp3_frame(lame_internal_flags * gfc,
153 | sample_t const *inbuf_l,
154 | sample_t const *inbuf_r, unsigned char *mp3buf, int mp3buf_size);
155 |
156 | #endif /* LAME_ENCODER_H */
157 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/fft.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Fast Fourier Transform include file
3 | *
4 | * Copyright (c) 2000 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_FFT_H
23 | #define LAME_FFT_H
24 |
25 | void fft_long(lame_internal_flags const *const gfc, FLOAT x_real[BLKSIZE],
26 | int chn, const sample_t *const data[2]);
27 |
28 | void fft_short(lame_internal_flags const *const gfc, FLOAT x_real[3][BLKSIZE_s],
29 | int chn, const sample_t *const data[2]);
30 |
31 | void init_fft(lame_internal_flags * const gfc);
32 |
33 | #endif
34 |
35 | /* End of fft.h */
36 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/gain_analysis.h:
--------------------------------------------------------------------------------
1 | /*
2 | * ReplayGainAnalysis - analyzes input samples and give the recommended dB change
3 | * Copyright (C) 2001 David Robinson and Glen Sawyer
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 2.1 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library; if not, write to the Free Software
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | *
19 | * concept and filter values by David Robinson (David@Robinson.org)
20 | * -- blame him if you think the idea is flawed
21 | * coding by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA
22 | * -- blame him if you think this runs too slowly, or the coding is otherwise flawed
23 | *
24 | * For an explanation of the concepts and the basic algorithms involved, go to:
25 | * http://www.replaygain.org/
26 | */
27 |
28 | #ifndef GAIN_ANALYSIS_H
29 | #define GAIN_ANALYSIS_H
30 |
31 | #ifdef HAVE_INTTYPES_H
32 | # include
33 | #else
34 | # ifdef HAVE_STDINT_H
35 | # include
36 | # endif
37 | #endif
38 |
39 | #ifdef __cplusplus
40 | extern "C" {
41 | #endif
42 |
43 |
44 | typedef sample_t Float_t; /* Type used for filtering */
45 |
46 |
47 | #define PINK_REF 64.82 /* 298640883795 */ /* calibration value for 89dB */
48 |
49 |
50 | #define YULE_ORDER 10
51 | #define BUTTER_ORDER 2
52 | #define YULE_FILTER filterYule
53 | #define BUTTER_FILTER filterButter
54 | #define RMS_PERCENTILE 0.95 /* percentile which is louder than the proposed level */
55 | #define MAX_SAMP_FREQ 48000L /* maximum allowed sample frequency [Hz] */
56 | #define RMS_WINDOW_TIME_NUMERATOR 1L
57 | #define RMS_WINDOW_TIME_DENOMINATOR 20L /* numerator / denominator = time slice size [s] */
58 | #define STEPS_per_dB 100 /* Table entries per dB */
59 | #define MAX_dB 120 /* Table entries for 0...MAX_dB (normal max. values are 70...80 dB) */
60 |
61 | enum { GAIN_NOT_ENOUGH_SAMPLES = -24601, GAIN_ANALYSIS_ERROR = 0, GAIN_ANALYSIS_OK =
62 | 1, INIT_GAIN_ANALYSIS_ERROR = 0, INIT_GAIN_ANALYSIS_OK = 1
63 | };
64 |
65 | enum { MAX_ORDER = (BUTTER_ORDER > YULE_ORDER ? BUTTER_ORDER : YULE_ORDER)
66 | , MAX_SAMPLES_PER_WINDOW = ((MAX_SAMP_FREQ * RMS_WINDOW_TIME_NUMERATOR) / RMS_WINDOW_TIME_DENOMINATOR + 1) /* max. Samples per Time slice */
67 | };
68 |
69 | struct replaygain_data {
70 | Float_t linprebuf[MAX_ORDER * 2];
71 | Float_t *linpre; /* left input samples, with pre-buffer */
72 | Float_t lstepbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
73 | Float_t *lstep; /* left "first step" (i.e. post first filter) samples */
74 | Float_t loutbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
75 | Float_t *lout; /* left "out" (i.e. post second filter) samples */
76 | Float_t rinprebuf[MAX_ORDER * 2];
77 | Float_t *rinpre; /* right input samples ... */
78 | Float_t rstepbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
79 | Float_t *rstep;
80 | Float_t routbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
81 | Float_t *rout;
82 | long sampleWindow; /* number of samples required to reach number of milliseconds required for RMS window */
83 | long totsamp;
84 | double lsum;
85 | double rsum;
86 | int freqindex;
87 | int first;
88 | uint32_t A[STEPS_per_dB * MAX_dB];
89 | uint32_t B[STEPS_per_dB * MAX_dB];
90 |
91 | };
92 | #ifndef replaygain_data_defined
93 | #define replaygain_data_defined
94 | typedef struct replaygain_data replaygain_t;
95 | #endif
96 |
97 |
98 |
99 |
100 | int InitGainAnalysis(replaygain_t * rgData, long samplefreq);
101 | int AnalyzeSamples(replaygain_t * rgData, const Float_t * left_samples,
102 | const Float_t * right_samples, size_t num_samples, int num_channels);
103 | Float_t GetTitleGain(replaygain_t * rgData);
104 |
105 |
106 | #ifdef __cplusplus
107 | }
108 | #endif
109 | #endif /* GAIN_ANALYSIS_H */
110 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/id3tag.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef LAME_ID3_H
3 | #define LAME_ID3_H
4 |
5 |
6 | #define CHANGED_FLAG (1U << 0)
7 | #define ADD_V2_FLAG (1U << 1)
8 | #define V1_ONLY_FLAG (1U << 2)
9 | #define V2_ONLY_FLAG (1U << 3)
10 | #define SPACE_V1_FLAG (1U << 4)
11 | #define PAD_V2_FLAG (1U << 5)
12 |
13 | enum {
14 | MIMETYPE_NONE = 0,
15 | MIMETYPE_JPEG,
16 | MIMETYPE_PNG,
17 | MIMETYPE_GIF
18 | };
19 |
20 | typedef struct FrameDataNode {
21 | struct FrameDataNode *nxt;
22 | uint32_t fid; /* Frame Identifier */
23 | char lng[4]; /* 3-character language descriptor */
24 | struct {
25 | union {
26 | char *l; /* ptr to Latin-1 chars */
27 | unsigned short *u; /* ptr to UCS-2 text */
28 | unsigned char *b; /* ptr to raw bytes */
29 | } ptr;
30 | size_t dim;
31 | int enc; /* 0:Latin-1, 1:UCS-2, 2:RAW */
32 | } dsc , txt;
33 | } FrameDataNode;
34 |
35 |
36 | typedef struct id3tag_spec {
37 | /* private data members */
38 | unsigned int flags;
39 | int year;
40 | char *title;
41 | char *artist;
42 | char *album;
43 | char *comment;
44 | int track_id3v1;
45 | int genre_id3v1;
46 | unsigned char *albumart;
47 | unsigned int albumart_size;
48 | unsigned int padding_size;
49 | int albumart_mimetype;
50 | char language[4]; /* the language of the frame's content, according to ISO-639-2 */
51 | FrameDataNode *v2_head, *v2_tail;
52 | } id3tag_spec;
53 |
54 |
55 | /* write tag into stream at current position */
56 | extern int id3tag_write_v2(lame_global_flags * gfp);
57 | extern int id3tag_write_v1(lame_global_flags * gfp);
58 | /*
59 | * NOTE: A version 2 tag will NOT be added unless one of the text fields won't
60 | * fit in a version 1 tag (e.g. the title string is longer than 30 characters),
61 | * or the "id3tag_add_v2" or "id3tag_v2_only" functions are used.
62 | */
63 |
64 | #endif
65 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/l3side.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Layer 3 side include file
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_L3SIDE_H
23 | #define LAME_L3SIDE_H
24 |
25 | /* max scalefactor band, max(SBMAX_l, SBMAX_s*3, (SBMAX_s-3)*3+8) */
26 | #define SFBMAX (SBMAX_s*3)
27 |
28 | /* Layer III side information. */
29 | typedef struct {
30 | int l[1 + SBMAX_l];
31 | int s[1 + SBMAX_s];
32 | int psfb21[1 + PSFB21];
33 | int psfb12[1 + PSFB12];
34 | } scalefac_struct;
35 |
36 |
37 | typedef struct {
38 | FLOAT l[SBMAX_l];
39 | FLOAT s[SBMAX_s][3];
40 | } III_psy_xmin;
41 |
42 | typedef struct {
43 | III_psy_xmin thm;
44 | III_psy_xmin en;
45 | } III_psy_ratio;
46 |
47 | typedef struct {
48 | FLOAT xr[576];
49 | int l3_enc[576];
50 | int scalefac[SFBMAX];
51 | FLOAT xrpow_max;
52 |
53 | int part2_3_length;
54 | int big_values;
55 | int count1;
56 | int global_gain;
57 | int scalefac_compress;
58 | int block_type;
59 | int mixed_block_flag;
60 | int table_select[3];
61 | int subblock_gain[3 + 1];
62 | int region0_count;
63 | int region1_count;
64 | int preflag;
65 | int scalefac_scale;
66 | int count1table_select;
67 |
68 | int part2_length;
69 | int sfb_lmax;
70 | int sfb_smin;
71 | int psy_lmax;
72 | int sfbmax;
73 | int psymax;
74 | int sfbdivide;
75 | int width[SFBMAX];
76 | int window[SFBMAX];
77 | int count1bits;
78 | /* added for LSF */
79 | const int *sfb_partition_table;
80 | int slen[4];
81 |
82 | int max_nonzero_coeff;
83 | char energy_above_cutoff[SFBMAX];
84 | } gr_info;
85 |
86 | typedef struct {
87 | gr_info tt[2][2];
88 | int main_data_begin;
89 | int private_bits;
90 | int resvDrain_pre;
91 | int resvDrain_post;
92 | int scfsi[2][4];
93 | } III_side_info_t;
94 |
95 | #endif
96 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/lame-analysis.h:
--------------------------------------------------------------------------------
1 | /*
2 | * GTK plotting routines source file
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_GTKANAL_H
23 | #define LAME_GTKANAL_H
24 |
25 |
26 | #define READ_AHEAD 40 /* number of frames to read ahead */
27 | #define MAXMPGLAG READ_AHEAD /* if the mpg123 lag becomes bigger than this
28 | we have to stop */
29 | #define NUMBACK 6 /* number of frames we can back up */
30 | #define NUMPINFO (NUMBACK+READ_AHEAD+1)
31 |
32 |
33 |
34 | struct plotting_data {
35 | int frameNum; /* current frame number */
36 | int frameNum123;
37 | int num_samples; /* number of pcm samples read for this frame */
38 | double frametime; /* starting time of frame, in seconds */
39 | double pcmdata[2][1600];
40 | double pcmdata2[2][1152 + 1152 - DECDELAY];
41 | double xr[2][2][576];
42 | double mpg123xr[2][2][576];
43 | double ms_ratio[2];
44 | double ms_ener_ratio[2];
45 |
46 | /* L,R, M and S values */
47 | double energy_save[4][BLKSIZE]; /* psymodel is one ahead */
48 | double energy[2][4][BLKSIZE];
49 | double pe[2][4];
50 | double thr[2][4][SBMAX_l];
51 | double en[2][4][SBMAX_l];
52 | double thr_s[2][4][3 * SBMAX_s];
53 | double en_s[2][4][3 * SBMAX_s];
54 | double ers_save[4]; /* psymodel is one ahead */
55 | double ers[2][4];
56 |
57 | double sfb[2][2][SBMAX_l];
58 | double sfb_s[2][2][3 * SBMAX_s];
59 | double LAMEsfb[2][2][SBMAX_l];
60 | double LAMEsfb_s[2][2][3 * SBMAX_s];
61 |
62 | int LAMEqss[2][2];
63 | int qss[2][2];
64 | int big_values[2][2];
65 | int sub_gain[2][2][3];
66 |
67 | double xfsf[2][2][SBMAX_l];
68 | double xfsf_s[2][2][3 * SBMAX_s];
69 |
70 | int over[2][2];
71 | double tot_noise[2][2];
72 | double max_noise[2][2];
73 | double over_noise[2][2];
74 | int over_SSD[2][2];
75 | int blocktype[2][2];
76 | int scalefac_scale[2][2];
77 | int preflag[2][2];
78 | int mpg123blocktype[2][2];
79 | int mixed[2][2];
80 | int mainbits[2][2];
81 | int sfbits[2][2];
82 | int LAMEmainbits[2][2];
83 | int LAMEsfbits[2][2];
84 | int framesize, stereo, js, ms_stereo, i_stereo, emph, bitrate, sampfreq, maindata;
85 | int crc, padding;
86 | int scfsi[2], mean_bits, resvsize;
87 | int totbits;
88 | };
89 | #ifndef plotting_data_defined
90 | #define plotting_data_defined
91 | typedef struct plotting_data plotting_data;
92 | #endif
93 | #if 0
94 | extern plotting_data *pinfo;
95 | #endif
96 | #endif
97 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/lameerror.h:
--------------------------------------------------------------------------------
1 | /*
2 | * A collection of LAME Error Codes
3 | *
4 | * Please use the constants defined here instead of some arbitrary
5 | * values. Currently the values starting at -10 to avoid intersection
6 | * with the -1, -2, -3 and -4 used in the current code.
7 | *
8 | * May be this should be a part of the include/lame.h.
9 | */
10 |
11 | typedef enum {
12 | LAME_OKAY = 0,
13 | LAME_NOERROR = 0,
14 | LAME_GENERICERROR = -1,
15 | LAME_NOMEM = -10,
16 | LAME_BADBITRATE = -11,
17 | LAME_BADSAMPFREQ = -12,
18 | LAME_INTERNALERROR = -13,
19 |
20 | FRONTEND_READERROR = -80,
21 | FRONTEND_WRITEERROR = -81,
22 | FRONTEND_FILETOOLARGE = -82,
23 |
24 | } lame_errorcodes_t;
25 |
26 | /* end of lameerror.h */
27 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/newmdct.h:
--------------------------------------------------------------------------------
1 | /*
2 | * New Modified DCT include file
3 | *
4 | * Copyright (c) 1999 Takehiro TOMINAGA
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_NEWMDCT_H
23 | #define LAME_NEWMDCT_H
24 |
25 | void mdct_sub48(lame_internal_flags * gfc, const sample_t * w0, const sample_t * w1);
26 |
27 | #endif /* LAME_NEWMDCT_H */
28 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/psymodel.h:
--------------------------------------------------------------------------------
1 | /*
2 | * psymodel.h
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_PSYMODEL_H
23 | #define LAME_PSYMODEL_H
24 |
25 |
26 | int L3psycho_anal_ns(lame_internal_flags * gfc,
27 | const sample_t *const buffer[2], int gr,
28 | III_psy_ratio ratio[2][2],
29 | III_psy_ratio MS_ratio[2][2],
30 | FLOAT pe[2], FLOAT pe_MS[2], FLOAT ener[2], int blocktype_d[2]);
31 |
32 | int L3psycho_anal_vbr(lame_internal_flags * gfc,
33 | const sample_t *const buffer[2], int gr,
34 | III_psy_ratio ratio[2][2],
35 | III_psy_ratio MS_ratio[2][2],
36 | FLOAT pe[2], FLOAT pe_MS[2], FLOAT ener[2], int blocktype_d[2]);
37 |
38 |
39 | int psymodel_init(lame_global_flags const* gfp);
40 |
41 |
42 | #define rpelev 2
43 | #define rpelev2 16
44 | #define rpelev_s 2
45 | #define rpelev2_s 16
46 |
47 | /* size of each partition band, in barks: */
48 | #define DELBARK .34
49 |
50 |
51 | /* tuned for output level (sensitive to energy scale) */
52 | #define VO_SCALE (1./( 14752*14752 )/(BLKSIZE/2))
53 |
54 | #define temporalmask_sustain_sec 0.01
55 |
56 | #define NS_PREECHO_ATT0 0.8
57 | #define NS_PREECHO_ATT1 0.6
58 | #define NS_PREECHO_ATT2 0.3
59 |
60 | #define NS_MSFIX 3.5
61 | #define NSATTACKTHRE 4.4
62 | #define NSATTACKTHRE_S 25
63 |
64 | #endif /* LAME_PSYMODEL_H */
65 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/quantize.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MP3 quantization
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_QUANTIZE_H
23 | #define LAME_QUANTIZE_H
24 |
25 | void CBR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2],
26 | const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]);
27 |
28 | void VBR_old_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2],
29 | const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]);
30 |
31 | void VBR_new_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2],
32 | const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]);
33 |
34 | void ABR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2],
35 | const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]);
36 |
37 |
38 | #endif /* LAME_QUANTIZE_H */
39 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/quantize_pvt.h:
--------------------------------------------------------------------------------
1 | /*
2 | * quantize_pvt include file
3 | *
4 | * Copyright (c) 1999 Takehiro TOMINAGA
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_QUANTIZE_PVT_H
23 | #define LAME_QUANTIZE_PVT_H
24 |
25 | #define IXMAX_VAL 8206 /* ix always <= 8191+15. see count_bits() */
26 |
27 | /* buggy Winamp decoder cannot handle values > 8191 */
28 | /* #define IXMAX_VAL 8191 */
29 |
30 | #define PRECALC_SIZE (IXMAX_VAL+2)
31 |
32 |
33 | extern const int nr_of_sfb_block[6][3][4];
34 | extern const int pretab[SBMAX_l];
35 | extern const int slen1_tab[16];
36 | extern const int slen2_tab[16];
37 |
38 | extern const scalefac_struct sfBandIndex[9];
39 |
40 | extern FLOAT pow43[PRECALC_SIZE];
41 | #ifdef TAKEHIRO_IEEE754_HACK
42 | extern FLOAT adj43asm[PRECALC_SIZE];
43 | #else
44 | extern FLOAT adj43[PRECALC_SIZE];
45 | #endif
46 |
47 | #define Q_MAX (256+1)
48 | #define Q_MAX2 116 /* minimum possible number of
49 | -cod_info->global_gain
50 | + ((scalefac[] + (cod_info->preflag ? pretab[sfb] : 0))
51 | << (cod_info->scalefac_scale + 1))
52 | + cod_info->subblock_gain[cod_info->window[sfb]] * 8;
53 |
54 | for long block, 0+((15+3)<<2) = 18*4 = 72
55 | for short block, 0+(15<<2)+7*8 = 15*4+56 = 116
56 | */
57 |
58 | extern FLOAT pow20[Q_MAX + Q_MAX2 + 1];
59 | extern FLOAT ipow20[Q_MAX];
60 |
61 | typedef struct calc_noise_result_t {
62 | FLOAT over_noise; /* sum of quantization noise > masking */
63 | FLOAT tot_noise; /* sum of all quantization noise */
64 | FLOAT max_noise; /* max quantization noise */
65 | int over_count; /* number of quantization noise > masking */
66 | int over_SSD; /* SSD-like cost of distorted bands */
67 | int bits;
68 | } calc_noise_result;
69 |
70 |
71 | /**
72 | * allows re-use of previously
73 | * computed noise values
74 | */
75 | typedef struct calc_noise_data_t {
76 | int global_gain;
77 | int sfb_count1;
78 | int step[39];
79 | FLOAT noise[39];
80 | FLOAT noise_log[39];
81 | } calc_noise_data;
82 |
83 |
84 | int on_pe(lame_internal_flags * gfc, const FLOAT pe[2][2],
85 | int targ_bits[2], int mean_bits, int gr, int cbr);
86 |
87 | void reduce_side(int targ_bits[2], FLOAT ms_ener_ratio, int mean_bits, int max_bits);
88 |
89 |
90 | void iteration_init(lame_internal_flags * gfc);
91 |
92 |
93 | int calc_xmin(lame_internal_flags const *gfc,
94 | III_psy_ratio const *const ratio, gr_info * const cod_info, FLOAT * l3_xmin);
95 |
96 | int calc_noise(const gr_info * const cod_info,
97 | const FLOAT * l3_xmin,
98 | FLOAT * distort, calc_noise_result * const res, calc_noise_data * prev_noise);
99 |
100 | void set_frame_pinfo(lame_internal_flags * gfc, const III_psy_ratio ratio[2][2]);
101 |
102 |
103 |
104 |
105 | /* takehiro.c */
106 |
107 | int count_bits(lame_internal_flags const *const gfc, const FLOAT * const xr,
108 | gr_info * const cod_info, calc_noise_data * prev_noise);
109 | int noquant_count_bits(lame_internal_flags const *const gfc,
110 | gr_info * const cod_info, calc_noise_data * prev_noise);
111 |
112 |
113 | void best_huffman_divide(const lame_internal_flags * const gfc, gr_info * const cod_info);
114 |
115 | void best_scalefac_store(const lame_internal_flags * gfc, const int gr, const int ch,
116 | III_side_info_t * const l3_side);
117 |
118 | int scale_bitcount(const lame_internal_flags * gfc, gr_info * cod_info);
119 |
120 | void huffman_init(lame_internal_flags * const gfc);
121 |
122 | void init_xrpow_core_init(lame_internal_flags * const gfc);
123 |
124 | FLOAT athAdjust(FLOAT a, FLOAT x, FLOAT athFloor, float ATHfixpoint);
125 |
126 | #define LARGE_BITS 100000
127 |
128 | #endif /* LAME_QUANTIZE_PVT_H */
129 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/reservoir.h:
--------------------------------------------------------------------------------
1 | /*
2 | * bit reservoir include file
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_RESERVOIR_H
23 | #define LAME_RESERVOIR_H
24 |
25 | int ResvFrameBegin(lame_internal_flags * gfc, int *mean_bits);
26 | void ResvMaxBits(lame_internal_flags * gfc, int mean_bits, int *targ_bits, int *max_bits,
27 | int cbr);
28 | void ResvAdjust(lame_internal_flags * gfc, gr_info const *gi);
29 | void ResvFrameEnd(lame_internal_flags * gfc, int mean_bits);
30 |
31 | #endif /* LAME_RESERVOIR_H */
32 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/set_get.h:
--------------------------------------------------------------------------------
1 | /*
2 | * set_get.h -- Internal set/get definitions
3 | *
4 | * Copyright (C) 2003 Gabriel Bouvigne / Lame project
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the Free Software
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifndef __SET_GET_H__
22 | #define __SET_GET_H__
23 |
24 | #include "lame.h"
25 |
26 | #if defined(__cplusplus)
27 | extern "C" {
28 | #endif
29 |
30 | /* select psychoacoustic model */
31 |
32 | /* manage short blocks */
33 | int CDECL lame_set_short_threshold(lame_global_flags *, float, float);
34 | int CDECL lame_set_short_threshold_lrm(lame_global_flags *, float);
35 | float CDECL lame_get_short_threshold_lrm(const lame_global_flags *);
36 | int CDECL lame_set_short_threshold_s(lame_global_flags *, float);
37 | float CDECL lame_get_short_threshold_s(const lame_global_flags *);
38 |
39 |
40 | int CDECL lame_set_maskingadjust(lame_global_flags *, float);
41 | float CDECL lame_get_maskingadjust(const lame_global_flags *);
42 |
43 | int CDECL lame_set_maskingadjust_short(lame_global_flags *, float);
44 | float CDECL lame_get_maskingadjust_short(const lame_global_flags *);
45 |
46 | /* select ATH formula 4 shape */
47 | int CDECL lame_set_ATHcurve(lame_global_flags *, float);
48 | float CDECL lame_get_ATHcurve(const lame_global_flags *);
49 |
50 | int CDECL lame_set_preset_notune(lame_global_flags *, int);
51 |
52 | /* substep shaping method */
53 | int CDECL lame_set_substep(lame_global_flags *, int);
54 | int CDECL lame_get_substep(const lame_global_flags *);
55 |
56 | /* scalefactors scale */
57 | int CDECL lame_set_sfscale(lame_global_flags *, int);
58 | int CDECL lame_get_sfscale(const lame_global_flags *);
59 |
60 | /* subblock gain */
61 | int CDECL lame_set_subblock_gain(lame_global_flags *, int);
62 | int CDECL lame_get_subblock_gain(const lame_global_flags *);
63 |
64 |
65 |
66 | /*presets*/
67 | int apply_preset(lame_global_flags *, int preset, int enforce);
68 |
69 | void CDECL lame_set_tune(lame_t, float); /* FOR INTERNAL USE ONLY */
70 | void CDECL lame_set_msfix(lame_t gfp, double msfix);
71 |
72 |
73 | #if defined(__cplusplus)
74 | }
75 | #endif
76 | #endif
77 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/tables.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MPEG layer 3 tables include file
3 | *
4 | * Copyright (c) 1999 Albert L Faber
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_TABLES_H
23 | #define LAME_TABLES_H
24 |
25 | #if 0
26 | typedef struct {
27 | unsigned char no;
28 | unsigned char width;
29 | unsigned char minval_2;
30 | float quiet_thr;
31 | float norm;
32 | float bark;
33 | } type1_t;
34 |
35 | typedef struct {
36 | unsigned char no;
37 | unsigned char width;
38 | float quiet_thr;
39 | float norm;
40 | float SNR;
41 | float bark;
42 | } type2_t;
43 |
44 | typedef struct {
45 | unsigned int no:5;
46 | unsigned int cbw:3;
47 | unsigned int bu:6;
48 | unsigned int bo:6;
49 | unsigned int w1_576:10;
50 | unsigned int w2_576:10;
51 | } type34_t;
52 |
53 | typedef struct {
54 | size_t len1;
55 | const type1_t *const tab1;
56 | size_t len2;
57 | const type2_t *const tab2;
58 | size_t len3;
59 | const type34_t *const tab3;
60 | size_t len4;
61 | const type34_t *const tab4;
62 | } type5_t;
63 |
64 | extern const type5_t table5[6];
65 |
66 | #endif
67 |
68 | #define HTN 34
69 |
70 | struct huffcodetab {
71 | const unsigned int xlen; /* max. x-index+ */
72 | const unsigned int linmax; /* max number to be stored in linbits */
73 | const uint16_t *table; /* pointer to array[xlen][ylen] */
74 | const uint8_t *hlen; /* pointer to array[xlen][ylen] */
75 | };
76 |
77 | extern const struct huffcodetab ht[HTN];
78 | /* global memory block */
79 | /* array of all huffcodtable headers */
80 | /* 0..31 Huffman code table 0..31 */
81 | /* 32,33 count1-tables */
82 |
83 | extern const uint8_t t32l[];
84 | extern const uint8_t t33l[];
85 |
86 | extern const uint32_t largetbl[16 * 16];
87 | extern const uint32_t table23[3 * 3];
88 | extern const uint32_t table56[4 * 4];
89 |
90 | extern const int scfsi_band[5];
91 |
92 | extern const int bitrate_table [3][16];
93 | extern const int samplerate_table [3][ 4];
94 |
95 | #endif /* LAME_TABLES_H */
96 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/vbrquantize.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MP3 VBR quantization
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_VBRQUANTIZE_H
23 | #define LAME_VBRQUANTIZE_H
24 |
25 | int VBR_encode_frame(lame_internal_flags * gfc, const FLOAT xr34orig[2][2][576],
26 | const FLOAT l3_xmin[2][2][SFBMAX], const int maxbits[2][2]);
27 |
28 | #endif /* LAME_VBRQUANTIZE_H */
29 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/vector/lame_intrin.h:
--------------------------------------------------------------------------------
1 | /*
2 | * lame_intrin.h include file
3 | *
4 | * Copyright (c) 2006 Gabriel Bouvigne
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 |
23 | #ifndef LAME_INTRIN_H
24 | #define LAME_INTRIN_H
25 |
26 |
27 | void
28 | init_xrpow_core_sse(gr_info * const cod_info, FLOAT xrpow[576], int upper, FLOAT * sum);
29 |
30 | void
31 | fht_SSE2(FLOAT* , int);
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/lamemp3/version.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Version numbering for LAME.
3 | *
4 | * Copyright (c) 1999 A.L. Faber
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_VERSION_H
23 | #define LAME_VERSION_H
24 |
25 |
26 | /*
27 | * To make a string from a token, use the # operator:
28 | */
29 | #ifndef STR
30 | # define __STR(x) #x
31 | # define STR(x) __STR(x)
32 | #endif
33 |
34 | # define LAME_URL "http://lame.sf.net"
35 |
36 |
37 | # define LAME_MAJOR_VERSION 3 /* Major version number */
38 | # define LAME_MINOR_VERSION 100 /* Minor version number */
39 | # define LAME_TYPE_VERSION 2 /* 0:alpha 1:beta 2:release */
40 | # define LAME_PATCH_VERSION 0 /* Patch level */
41 | # define LAME_ALPHA_VERSION (LAME_TYPE_VERSION==0)
42 | # define LAME_BETA_VERSION (LAME_TYPE_VERSION==1)
43 | # define LAME_RELEASE_VERSION (LAME_TYPE_VERSION==2)
44 |
45 | # define PSY_MAJOR_VERSION 1 /* Major version number */
46 | # define PSY_MINOR_VERSION 0 /* Minor version number */
47 | # define PSY_ALPHA_VERSION 0 /* Set number if this is an alpha version, otherwise zero */
48 | # define PSY_BETA_VERSION 0 /* Set number if this is a beta version, otherwise zero */
49 |
50 | #if LAME_ALPHA_VERSION
51 | #define LAME_PATCH_LEVEL_STRING " alpha " STR(LAME_PATCH_VERSION)
52 | #endif
53 | #if LAME_BETA_VERSION
54 | #define LAME_PATCH_LEVEL_STRING " beta " STR(LAME_PATCH_VERSION)
55 | #endif
56 | #if LAME_RELEASE_VERSION
57 | #if LAME_PATCH_VERSION
58 | #define LAME_PATCH_LEVEL_STRING " release " STR(LAME_PATCH_VERSION)
59 | #else
60 | #define LAME_PATCH_LEVEL_STRING ""
61 | #endif
62 | #endif
63 |
64 | # define LAME_VERSION_STRING STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) LAME_PATCH_LEVEL_STRING
65 |
66 | #endif /* LAME_VERSION_H */
67 |
68 | /* End of version.h */
69 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/wemp3/JavaListener.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WTZ on 2019/11/8.
3 | */
4 |
5 | #include "JavaListener.h"
6 | #include "AndroidLog.h"
7 |
8 |
9 | /**
10 | * 此构造方法需要在 C++ 主线程中调用,即直接从 java 层调用下来的线程
11 | *
12 | * @param jvm
13 | * @param mainEnv C++ 主线程 env
14 | * @param obj
15 | */
16 | JavaListener::JavaListener(JavaVM *jvm, JNIEnv *mainEnv, jobject obj) {
17 | _mainTid = gettid();
18 |
19 | _jvm = jvm;
20 | _mainEnv = mainEnv;
21 |
22 | // Fix: JNI ERROR (app bug): accessed stale local reference
23 | _globalObj = _mainEnv->NewGlobalRef(obj);
24 | }
25 |
26 | JavaListener::~JavaListener() {
27 | JNIEnv *env = initCallbackEnv();
28 | env->DeleteGlobalRef(_globalObj);// 回收 GlobalReference
29 | releaseCallbackEnv();
30 | }
31 |
32 | JNIEnv *JavaListener::initCallbackEnv() {
33 | needDetach = false;
34 | pid_t currentTid = gettid();
35 | if (currentTid == _mainTid) {
36 | // 在 C++ 主线程中直接使用主线程 env
37 | return _mainEnv;
38 | }
39 |
40 | JNIEnv *env1;
41 | if (_jvm->GetEnv(reinterpret_cast (&env1), JNI_VERSION_1_6) == JNI_OK) {
42 | // 虽然切换了线程,能 GetEnv 成功,说明这是直接从 Java 层切换的线程
43 | return env1;
44 | }
45 |
46 | // 到这里,说明是在 C++ 中开启的子线程,此时需要用 AttachCurrentThread 来获取 env,
47 | // 否则会报错 JNI ERROR: non-VM thread making JNI call
48 | JNIEnv *env2;
49 | if (_jvm->AttachCurrentThread(&env2, 0) != JNI_OK) {
50 | LOGE(LOG_TAG, "AttachCurrentThread exception! currentTid: %d", currentTid);
51 | return NULL;
52 | }
53 | needDetach = true;
54 | return env2;
55 | }
56 |
57 | void JavaListener::releaseCallbackEnv() {
58 | pid_t currentTid = gettid();
59 | if (currentTid == _mainTid || !needDetach) {
60 | return;
61 | }
62 |
63 | _jvm->DetachCurrentThread();
64 | needDetach = false;
65 | }
66 |
67 | void JavaListener::callback(int argCount, ...) {
68 | JNIEnv *env = initCallbackEnv();
69 | if (_methodID == NULL) {
70 | _methodID = env->GetMethodID(env->GetObjectClass(_globalObj), getMethodName(),
71 | getMethodSignature());
72 | if (env->ExceptionCheck()) {
73 | LOGE(LOG_TAG, "GetMethodID exception! method: %s %s", getMethodName(), getMethodSignature());
74 | env->Throw(env->ExceptionOccurred());
75 | return;
76 | }
77 | }
78 |
79 | va_list args;
80 | va_start(args, argCount);
81 |
82 | reallyCallback(env, _globalObj, _methodID, args);
83 |
84 | va_end(args);
85 | releaseCallbackEnv();
86 | }
87 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/wemp3/include/AndroidLog.h:
--------------------------------------------------------------------------------
1 | #ifndef VIDEOMAKER_ANDROIDLOG_H
2 | #define VIDEOMAKER_ANDROIDLOG_H
3 |
4 | #include
5 |
6 | #define LOG_DEBUG true // 表示一般步骤信息日志是否打开,比如初始化日志
7 | #define LOG_REPEAT_DEBUG false // 表示重复性的大量日志是否打开,例如入队出队数据日志
8 |
9 | #define LOGV(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, FORMAT, ##__VA_ARGS__);
10 | #define LOGD(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, FORMAT, ##__VA_ARGS__);
11 | #define LOGI(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, FORMAT, ##__VA_ARGS__);
12 | #define LOGW(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, FORMAT, ##__VA_ARGS__);
13 | #define LOGE(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, FORMAT, ##__VA_ARGS__);
14 |
15 | #endif //VIDEOMAKER_ANDROIDLOG_H
16 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/wemp3/include/JavaListener.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WTZ on 2019/11/8.
3 | */
4 |
5 | #ifndef FFMPEG_JAVALISTENER_H
6 | #define FFMPEG_JAVALISTENER_H
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | class JavaListener {
13 |
14 | private:
15 | const char *LOG_TAG = "JavaListener";
16 | pid_t _mainTid;
17 | JavaVM *_jvm;
18 | JNIEnv *_mainEnv;
19 | jobject _globalObj;
20 | jmethodID _methodID = NULL;// 若不初始化,则值为非空;置空用于后边判断一次性懒加载
21 | bool needDetach = false;
22 |
23 | public:
24 | /**
25 | * 此构造方法需要在 C++ 主线程中调用,即直接从 java 层调用下来的线程
26 | *
27 | * @param jvm
28 | * @param mainEnv C++ 主线程 env
29 | * @param obj
30 | */
31 | JavaListener(JavaVM *jvm, JNIEnv *mainEnv, jobject obj);
32 |
33 | virtual ~JavaListener();
34 |
35 | void callback(int argCount, ...);
36 |
37 | private:
38 | JNIEnv *initCallbackEnv();
39 |
40 | void releaseCallbackEnv();
41 |
42 | protected:
43 | virtual const char *getMethodName() = 0;
44 |
45 | virtual const char *getMethodSignature() = 0;
46 |
47 | virtual void reallyCallback(JNIEnv *env, jobject obj, jmethodID methodId, va_list args) = 0;
48 |
49 | };
50 |
51 | #endif //FFMPEG_JAVALISTENER_H
52 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/wemp3/include/OnEncodeProgressListener.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2020/4/18.
3 | //
4 |
5 | #ifndef VIDEOMAKER_ONENCODEPROGRESSLISTENER_H
6 | #define VIDEOMAKER_ONENCODEPROGRESSLISTENER_H
7 |
8 | #include "JavaListener.h"
9 | class OnEncodeProgressListener : public JavaListener {
10 |
11 | public:
12 | OnEncodeProgressListener(JavaVM *jvm, JNIEnv *mainEnv, jobject obj)
13 | : JavaListener(jvm, mainEnv, obj) {
14 | }
15 |
16 | ~OnEncodeProgressListener() {
17 | };
18 |
19 | const char *getMethodName() {
20 | return "onNativeEncodeProgressChanged";
21 | }
22 |
23 | const char *getMethodSignature() {
24 | return "(Ljava/lang/String;IZ)V";
25 | }
26 |
27 | void reallyCallback(JNIEnv *env, jobject obj, jmethodID methodId, va_list args) {
28 | const char *savePath = va_arg(args, const char *);
29 | int size = va_arg(args, int);
30 | bool complete = va_arg(args, bool);
31 |
32 | jstring jStrUtfPath = env->NewStringUTF(savePath);
33 | env->CallVoidMethod(obj, methodId, jStrUtfPath, size, complete);
34 | env->DeleteLocalRef(jStrUtfPath);
35 | }
36 |
37 | };
38 |
39 |
40 | #endif //VIDEOMAKER_ONENCODEPROGRESSLISTENER_H
41 |
--------------------------------------------------------------------------------
/libmp3util/src/main/cpp/wemp3/include/WeMp3Encoder.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2020/4/17.
3 | //
4 |
5 | #ifndef VIDEOMAKER_WEMP3ENCODER_H
6 | #define VIDEOMAKER_WEMP3ENCODER_H
7 |
8 | #include "lame.h"
9 | #include "OnEncodeProgressListener.h"
10 |
11 | /**
12 | * lame.h: lame_encode_buffer:
13 | *
14 | * The required mp3buf_size can be computed from num_samples,
15 | * samplerate and encoding rate, but here is a worst case estimate:
16 | *
17 | * mp3buf_size in bytes = 1.25*num_samples + 7200
18 | *
19 | * I think a tighter bound could be: (mt, March 2000)
20 | * MPEG1:
21 | * num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512
22 | * MPEG2:
23 | * num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256
24 | *
25 | * but test first if you use that!
26 | */
27 | #define MP3_BUFFER_SIZE 8192
28 |
29 | class WeMp3Encoder {
30 |
31 | private:
32 | const char *LOG_TAG = "_WeMp3Encoder";
33 |
34 | OnEncodeProgressListener *onEncodeProgressListener = NULL;
35 | bool stopEncodeFromPCMFile = false;
36 |
37 | // 公共输出参数
38 | MPEG_mode outChannelMode = STEREO;// 默认使用立体声
39 | vbr_mode_e brMode = vbr_mtrh;// 默认使用 VBR
40 | int outBitrate = 128;// 默认使用 128Kbps
41 | int outQuality = 5;// 默认使用中等质量
42 |
43 | // For PCM buffer Operate
44 | // 从 PCM buffer 取数据编码的方法分成了多步操作,涉及状态切换,只能单任务执行
45 | int inChannelNumForPCMBuf = 0;
46 | int bytesPerSampleForPCMBuf = 0;
47 | lame_t lameForPCMBuf = NULL;
48 | unsigned char *mp3BufForPCMBuf = NULL;
49 | FILE *outFileForPCMBuf = NULL;
50 |
51 | public:
52 | WeMp3Encoder(OnEncodeProgressListener *listener);
53 |
54 | ~WeMp3Encoder();
55 |
56 | /**
57 | * @param mode 0:STEREO 1:MONO
58 | */
59 | void setOutChannelMode(int mode);
60 |
61 | /**
62 | * @param mode 0:CBR 1:ABR 2:VBR
63 | * @param bitrate
64 | */
65 | void setOutBitrateMode(int mode, int bitrate);
66 |
67 | /**
68 | * @param quality quality=0..9. 0=best (very slow). 9=worst.
69 | * recommended:
70 | * 2 near-best quality, not too slow
71 | * 5 good quality, fast
72 | * 7 ok quality, really fast
73 | */
74 | void setOutQuality(int quality);
75 |
76 | /**
77 | * 开启或停止所有从 PCM 文件读取数据编码 MP3 的工作
78 | */
79 | void enableEncodeFromPCMFile(bool enable);
80 |
81 | /**
82 | * 每个 PCM 文件独立编码,可以多任务多文件操作
83 | */
84 | void encodeFromPCMFile(const char *pcmFilePath, int inSampleRate, int inChannelNum,
85 | int bitsPerSample, bool hasWavHead, const char *savePath);
86 |
87 | /**
88 | * !!!注意:从 PCMBuffer 取数据编码的方法分成了多步操作,涉及状态切换,适合单任务执行
89 | */
90 | bool startEncodePCMBuffer(int inSampleRate, int inChannelNum, int bitsPerSample,
91 | const char *savePath);
92 |
93 | /**
94 | * !!!注意:从 PCMBuffer 取数据编码的方法分成了多步操作,涉及状态切换,适合单任务执行
95 | * @param pcmBuffer
96 | * @param bufferSize pcmBuffer 的 short 元素个数
97 | */
98 | void encodeFromPCMBuffer(short *pcmBuffer, int bufferSize);
99 |
100 | /**
101 | * !!!注意:从 PCMBuffer 取数据编码的方法分成了多步操作,涉及状态切换,适合单任务执行
102 | */
103 | void stopEncodePCMBuffer();
104 |
105 | private:
106 | lame_t initLame(int inSampleRate, int inChannelNum);
107 |
108 | };
109 |
110 |
111 | #endif //VIDEOMAKER_WEMP3ENCODER_H
112 |
--------------------------------------------------------------------------------
/libmp3util/src/main/java/com/wtz/libmp3util/utlis/LogUtils.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libmp3util.utlis;
2 |
3 | import android.util.Log;
4 |
5 | public class LogUtils {
6 |
7 | public static boolean canPrintLog = true;
8 |
9 | public static void v(String tag, String msg) {
10 | if (canPrintLog) {
11 | Log.v(tag, msg);
12 | }
13 | }
14 |
15 | public static void d(String tag, String msg) {
16 | if (canPrintLog) {
17 | Log.d(tag, msg);
18 | }
19 | }
20 |
21 | public static void i(String tag, String msg) {
22 | if (canPrintLog) {
23 | Log.i(tag, msg);
24 | }
25 | }
26 |
27 | public static void w(String tag, String msg) {
28 | if (canPrintLog) {
29 | Log.w(tag, msg);
30 | }
31 | }
32 |
33 | public static void e(String tag, String msg) {
34 | if (canPrintLog) {
35 | Log.e(tag, msg);
36 | }
37 | }
38 |
39 | public static void printStackTrace(Throwable e) {
40 | if (canPrintLog && e != null) {
41 | e.printStackTrace();
42 | }
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/libmp3util/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | libmp3util
3 |
4 |
--------------------------------------------------------------------------------
/libnaudiorecord/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/libnaudiorecord/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.2"
6 |
7 |
8 | defaultConfig {
9 | minSdkVersion 14
10 | targetSdkVersion 29
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
15 | consumerProguardFiles 'consumer-rules.pro'
16 |
17 | externalNativeBuild {
18 | cmake {
19 | cppFlags ""
20 | abiFilters 'armeabi-v7a','arm64-v8a'
21 | }
22 | }
23 | }
24 |
25 | buildTypes {
26 | release {
27 | minifyEnabled false
28 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
29 | }
30 | }
31 |
32 | externalNativeBuild {
33 | cmake {
34 | path "src/main/cpp/CMakeLists.txt"
35 | version "3.10.2"
36 | }
37 | }
38 | }
39 |
40 | dependencies {
41 | implementation fileTree(dir: 'libs', include: ['*.jar'])
42 |
43 | implementation 'androidx.appcompat:appcompat:1.1.0'
44 | testImplementation 'junit:junit:4.12'
45 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
46 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
47 | }
48 |
--------------------------------------------------------------------------------
/libnaudiorecord/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/libnaudiorecord/consumer-rules.pro
--------------------------------------------------------------------------------
/libnaudiorecord/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.4.1)
2 |
3 | include_directories(weaudiorecord/include/)
4 |
5 | # Creates and names a library, sets it as either STATIC or SHARED,
6 | # and provides the relative paths to its source code.
7 | add_library(
8 | we_audio_record
9 |
10 | # Sets the library as a shared library.
11 | SHARED
12 |
13 | # Provides a relative path to your source file(s).
14 | weaudiorecord/WeAudioRecordJNI.cpp
15 | weaudiorecord/WeAudioRecorder.cpp
16 | weaudiorecord/JavaListener.cpp
17 | weaudiorecord/DoubleBuffer.cpp )
18 |
19 | # Searches for a specified prebuilt library and stores the path as a variable.
20 | # Because CMake includes system libraries in the search path by default,
21 | # you only need to specify the name of the public NDK library you want to add.
22 | find_library(
23 | # Sets the name of the path variable.
24 | log-lib
25 | # Specifies the name of the NDK library that you want CMake to locate.
26 | log)
27 |
28 | # Specifies libraries CMake should link to your target library.
29 | target_link_libraries(
30 | we_audio_record
31 |
32 | OpenSLES
33 |
34 | # Links the target library to the log library included in the NDK.
35 | ${log-lib})
36 |
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/cpp/weaudiorecord/DoubleBuffer.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2020/4/15.
3 | //
4 |
5 | #include "DoubleBuffer.h"
6 |
7 | DoubleBuffer::DoubleBuffer(int elemCountPerBuffer) {
8 | this->bytesSizePerBuffer = elemCountPerBuffer * sizeof(short);
9 | buffers = new short *[VIDMK_DOUBLE_BUFFER_COUNT];
10 | for (int i = 0; i < VIDMK_DOUBLE_BUFFER_COUNT; i++) {
11 | buffers[i] = new short[elemCountPerBuffer];
12 | }
13 | }
14 |
15 | DoubleBuffer::~DoubleBuffer() {
16 | for (int i = 0; i < VIDMK_DOUBLE_BUFFER_COUNT; i++) {
17 | delete buffers[i];
18 | buffers[i] = NULL;
19 | }
20 | delete buffers;
21 | buffers = NULL;
22 | }
23 |
24 | short *DoubleBuffer::getFreeBuffer() {
25 | index++;
26 | if (index >= VIDMK_DOUBLE_BUFFER_COUNT) {
27 | index = 0;
28 | }
29 | return buffers[index];
30 | }
31 |
32 | short *DoubleBuffer::getDataBuffer() {
33 | return buffers[index];
34 | }
35 |
36 | int DoubleBuffer::getBytesSizePerBuffer() {
37 | return bytesSizePerBuffer;
38 | }
39 |
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/cpp/weaudiorecord/JavaListener.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WTZ on 2019/11/8.
3 | */
4 |
5 | #include "JavaListener.h"
6 | #include "AndroidLog.h"
7 |
8 |
9 | /**
10 | * 此构造方法需要在 C++ 主线程中调用,即直接从 java 层调用下来的线程
11 | *
12 | * @param jvm
13 | * @param mainEnv C++ 主线程 env
14 | * @param obj
15 | */
16 | JavaListener::JavaListener(JavaVM *jvm, JNIEnv *mainEnv, jobject obj) {
17 | _mainTid = gettid();
18 |
19 | _jvm = jvm;
20 | _mainEnv = mainEnv;
21 |
22 | // Fix: JNI ERROR (app bug): accessed stale local reference
23 | _globalObj = _mainEnv->NewGlobalRef(obj);
24 | }
25 |
26 | JavaListener::~JavaListener() {
27 | JNIEnv *env = initCallbackEnv();
28 | env->DeleteGlobalRef(_globalObj);// 回收 GlobalReference
29 | releaseCallbackEnv();
30 | }
31 |
32 | JNIEnv *JavaListener::initCallbackEnv() {
33 | needDetach = false;
34 | pid_t currentTid = gettid();
35 | if (currentTid == _mainTid) {
36 | // 在 C++ 主线程中直接使用主线程 env
37 | return _mainEnv;
38 | }
39 |
40 | JNIEnv *env1;
41 | if (_jvm->GetEnv(reinterpret_cast (&env1), JNI_VERSION_1_6) == JNI_OK) {
42 | // 虽然切换了线程,能 GetEnv 成功,说明这是直接从 Java 层切换的线程
43 | return env1;
44 | }
45 |
46 | // 到这里,说明是在 C++ 中开启的子线程,此时需要用 AttachCurrentThread 来获取 env,
47 | // 否则会报错 JNI ERROR: non-VM thread making JNI call
48 | JNIEnv *env2;
49 | if (_jvm->AttachCurrentThread(&env2, 0) != JNI_OK) {
50 | LOGE(LOG_TAG, "AttachCurrentThread exception! currentTid: %d", currentTid);
51 | return NULL;
52 | }
53 | needDetach = true;
54 | return env2;
55 | }
56 |
57 | void JavaListener::releaseCallbackEnv() {
58 | pid_t currentTid = gettid();
59 | if (currentTid == _mainTid || !needDetach) {
60 | return;
61 | }
62 |
63 | _jvm->DetachCurrentThread();
64 | needDetach = false;
65 | }
66 |
67 | void JavaListener::callback(int argCount, ...) {
68 | JNIEnv *env = initCallbackEnv();
69 | if (_methodID == NULL) {
70 | _methodID = env->GetMethodID(env->GetObjectClass(_globalObj), getMethodName(),
71 | getMethodSignature());
72 | if (env->ExceptionCheck()) {
73 | LOGE(LOG_TAG, "GetMethodID exception! method: %s %s", getMethodName(), getMethodSignature());
74 | env->Throw(env->ExceptionOccurred());
75 | return;
76 | }
77 | }
78 |
79 | va_list args;
80 | va_start(args, argCount);
81 |
82 | reallyCallback(env, _globalObj, _methodID, args);
83 |
84 | va_end(args);
85 | releaseCallbackEnv();
86 | }
87 |
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/cpp/weaudiorecord/WeAudioRecordJNI.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2020/4/15.
3 | //
4 |
5 | #include
6 | #include "WeAudioRecorder.h"
7 | #include "AndroidLog.h"
8 |
9 |
10 | #define LOG_TAG "WeAudioRecordJNI"
11 |
12 | JavaVM *jvm;
13 | WeAudioRecorder *pWeAudioRecorder;
14 |
15 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
16 | JNIEnv *env;
17 | jvm = vm;
18 | if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
19 | LOGE(LOG_TAG, "JNI_OnLoad vm->GetEnv exception!");
20 | return -1;
21 | }
22 | return JNI_VERSION_1_6;
23 | }
24 |
25 | extern "C"
26 | JNIEXPORT jboolean JNICALL
27 | Java_com_wtz_libnaudiorecord_WeNAudioRecorder_nativeInitRecorder(JNIEnv *env, jobject thiz) {
28 | OnPCMDataCall *onPcmDataCall = new OnPCMDataCall(jvm, env, thiz);
29 | pWeAudioRecorder = new WeAudioRecorder(onPcmDataCall);
30 | return pWeAudioRecorder->init();
31 | }
32 |
33 | extern "C"
34 | JNIEXPORT jboolean JNICALL
35 | Java_com_wtz_libnaudiorecord_WeNAudioRecorder_nativeInitRecorder2(JNIEnv *env, jobject thiz,
36 | jint sampleRate,
37 | jint channelLayout,
38 | jint encodingBits) {
39 | OnPCMDataCall *onPcmDataCall = new OnPCMDataCall(jvm, env, thiz);
40 | pWeAudioRecorder = new WeAudioRecorder(onPcmDataCall);
41 | return pWeAudioRecorder->init2(sampleRate, channelLayout, encodingBits);
42 | }
43 |
44 | extern "C"
45 | JNIEXPORT jint JNICALL
46 | Java_com_wtz_libnaudiorecord_WeNAudioRecorder_nativeGetSampleRate(JNIEnv *env, jobject thiz) {
47 | if (pWeAudioRecorder == NULL) {
48 | LOGE(LOG_TAG, "Invoke nativeGetSampleRate but pWeAudioRecorder is NULL!");
49 | return 0;
50 | }
51 |
52 | return pWeAudioRecorder->getSampleRate();
53 | }
54 |
55 | extern "C"
56 | JNIEXPORT jint JNICALL
57 | Java_com_wtz_libnaudiorecord_WeNAudioRecorder_nativeGetChannelNums(JNIEnv *env, jobject thiz) {
58 | if (pWeAudioRecorder == NULL) {
59 | LOGE(LOG_TAG, "Invoke nativeGetChannelNums but pWeAudioRecorder is NULL!");
60 | return 0;
61 | }
62 |
63 | return pWeAudioRecorder->getChannelNums();
64 | }
65 |
66 | extern "C"
67 | JNIEXPORT jint JNICALL
68 | Java_com_wtz_libnaudiorecord_WeNAudioRecorder_nativeGetBitsPerSample(JNIEnv *env, jobject thiz) {
69 | if (pWeAudioRecorder == NULL) {
70 | LOGE(LOG_TAG, "Invoke nativeGetBitsPerSample but pWeAudioRecorder is NULL!");
71 | return 0;
72 | }
73 |
74 | return pWeAudioRecorder->getBitsPerSample();
75 | }
76 |
77 | extern "C"
78 | JNIEXPORT jboolean JNICALL
79 | Java_com_wtz_libnaudiorecord_WeNAudioRecorder_nativeStartRecord(JNIEnv *env, jobject thiz) {
80 | if (pWeAudioRecorder == NULL) {
81 | LOGE(LOG_TAG, "Invoke nativeStartRecord but pWeAudioRecorder is NULL!");
82 | return false;
83 | }
84 |
85 | return pWeAudioRecorder->start();
86 | }
87 |
88 | extern "C"
89 | JNIEXPORT jboolean JNICALL
90 | Java_com_wtz_libnaudiorecord_WeNAudioRecorder_nativeResumeRecord(JNIEnv *env, jobject thiz) {
91 | if (pWeAudioRecorder == NULL) {
92 | LOGE(LOG_TAG, "Invoke nativeResumeRecord but pWeAudioRecorder is NULL!");
93 | return false;
94 | }
95 |
96 | return pWeAudioRecorder->resume();
97 | }
98 |
99 | extern "C"
100 | JNIEXPORT void JNICALL
101 | Java_com_wtz_libnaudiorecord_WeNAudioRecorder_nativePauseRecord(JNIEnv *env, jobject thiz) {
102 | if (pWeAudioRecorder == NULL) {
103 | LOGE(LOG_TAG, "Invoke nativePauseRecord but pWeAudioRecorder is NULL!");
104 | return;
105 | }
106 |
107 | pWeAudioRecorder->pause();
108 | }
109 |
110 | extern "C"
111 | JNIEXPORT void JNICALL
112 | Java_com_wtz_libnaudiorecord_WeNAudioRecorder_nativeStopRecord(JNIEnv *env, jobject thiz) {
113 | if (pWeAudioRecorder == NULL) {
114 | LOGE(LOG_TAG, "Invoke nativeStopRecord but pWeAudioRecorder is NULL!");
115 | return;
116 | }
117 |
118 | pWeAudioRecorder->stop();
119 | }
120 |
121 | extern "C"
122 | JNIEXPORT void JNICALL
123 | Java_com_wtz_libnaudiorecord_WeNAudioRecorder_nativeReleaseRecorder(JNIEnv *env, jobject thiz) {
124 | if (pWeAudioRecorder == NULL) {
125 | LOGE(LOG_TAG, "Invoke nativeReleaseRecorder but pWeAudioRecorder is NULL!");
126 | return;
127 | }
128 |
129 | pWeAudioRecorder->release();
130 | delete pWeAudioRecorder;
131 | pWeAudioRecorder = NULL;
132 | }
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/cpp/weaudiorecord/include/AndroidLog.h:
--------------------------------------------------------------------------------
1 | #ifndef VIDEOMAKER_ANDROIDLOG_H
2 | #define VIDEOMAKER_ANDROIDLOG_H
3 |
4 | #include
5 |
6 | #define LOG_DEBUG true // 表示一般步骤信息日志是否打开,比如初始化日志
7 | #define LOG_REPEAT_DEBUG false // 表示重复性的大量日志是否打开,例如入队出队数据日志
8 |
9 | #define LOGV(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, FORMAT, ##__VA_ARGS__);
10 | #define LOGD(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, FORMAT, ##__VA_ARGS__);
11 | #define LOGI(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, FORMAT, ##__VA_ARGS__);
12 | #define LOGW(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, FORMAT, ##__VA_ARGS__);
13 | #define LOGE(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, FORMAT, ##__VA_ARGS__);
14 |
15 | #endif //VIDEOMAKER_ANDROIDLOG_H
16 |
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/cpp/weaudiorecord/include/DoubleBuffer.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2020/4/15.
3 | //
4 |
5 | #ifndef VIDEOMAKER_DOUBLEBUFFER_H
6 | #define VIDEOMAKER_DOUBLEBUFFER_H
7 |
8 | #include
9 |
10 | #define VIDMK_DOUBLE_BUFFER_COUNT 2
11 |
12 | class DoubleBuffer {
13 |
14 | private:
15 | short **buffers = NULL;
16 | int index = 0;
17 | int bytesSizePerBuffer = 0;
18 |
19 | public:
20 | DoubleBuffer(int elemCountPerBuffer);
21 |
22 | ~DoubleBuffer();
23 |
24 | short *getFreeBuffer();
25 |
26 | short *getDataBuffer();
27 |
28 | int getBytesSizePerBuffer();
29 |
30 | };
31 |
32 |
33 | #endif //VIDEOMAKER_DOUBLEBUFFER_H
34 |
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/cpp/weaudiorecord/include/JavaListener.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WTZ on 2019/11/8.
3 | */
4 |
5 | #ifndef FFMPEG_JAVALISTENER_H
6 | #define FFMPEG_JAVALISTENER_H
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | class JavaListener {
13 |
14 | private:
15 | const char *LOG_TAG = "JavaListener";
16 | pid_t _mainTid;
17 | JavaVM *_jvm;
18 | JNIEnv *_mainEnv;
19 | jobject _globalObj;
20 | jmethodID _methodID = NULL;// 若不初始化,则值为非空;置空用于后边判断一次性懒加载
21 | bool needDetach = false;
22 |
23 | public:
24 | /**
25 | * 此构造方法需要在 C++ 主线程中调用,即直接从 java 层调用下来的线程
26 | *
27 | * @param jvm
28 | * @param mainEnv C++ 主线程 env
29 | * @param obj
30 | */
31 | JavaListener(JavaVM *jvm, JNIEnv *mainEnv, jobject obj);
32 |
33 | virtual ~JavaListener();
34 |
35 | void callback(int argCount, ...);
36 |
37 | private:
38 | JNIEnv *initCallbackEnv();
39 |
40 | void releaseCallbackEnv();
41 |
42 | protected:
43 | virtual const char *getMethodName() = 0;
44 |
45 | virtual const char *getMethodSignature() = 0;
46 |
47 | virtual void reallyCallback(JNIEnv *env, jobject obj, jmethodID methodId, va_list args) = 0;
48 |
49 | };
50 |
51 | #endif //FFMPEG_JAVALISTENER_H
52 |
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/cpp/weaudiorecord/include/OnPCMDataCall.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2019/12/16.
3 | //
4 |
5 | #ifndef FFMPEG_ONPCMDATACALL_H
6 | #define FFMPEG_ONPCMDATACALL_H
7 |
8 |
9 | #include "JavaListener.h"
10 |
11 | class OnPCMDataCall : public JavaListener {
12 |
13 | private:
14 | const char *LOG_TAG = "_OnPCMDataCall";
15 |
16 | public:
17 | OnPCMDataCall(JavaVM *jvm, JNIEnv *mainEnv, jobject obj)
18 | : JavaListener(jvm, mainEnv, obj) {
19 | }
20 |
21 | ~OnPCMDataCall() {
22 | };
23 |
24 | const char *getMethodName() {
25 | return "onNativePCMDataCall";
26 | }
27 |
28 | const char *getMethodSignature() {
29 | return "([BI)V";
30 | }
31 |
32 | void reallyCallback(JNIEnv *env, jobject obj, jmethodID methodId, va_list args) {
33 | void *data = va_arg(args, void *);
34 | int size = va_arg(args, int);
35 |
36 | jbyteArray jbyteBuffer = env->NewByteArray(size);
37 |
38 | env->SetByteArrayRegion(jbyteBuffer, 0, size, static_cast(data));
39 | env->CallVoidMethod(obj, methodId, jbyteBuffer, size);
40 |
41 | env->DeleteLocalRef(jbyteBuffer);
42 | }
43 |
44 | };
45 |
46 |
47 | #endif //FFMPEG_ONPCMDATACALL_H
48 |
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/cpp/weaudiorecord/include/WeAudioRecorder.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2020/4/15.
3 | //
4 |
5 | #ifndef VIDEOMAKER_WEAUDIORECORDER_H
6 | #define VIDEOMAKER_WEAUDIORECORDER_H
7 |
8 |
9 | #include
10 | #include "OnPCMDataCall.h"
11 | #include "DoubleBuffer.h"
12 |
13 | extern "C"
14 | {
15 | #include
16 | #include
17 | }
18 |
19 | #define VIDMK_DOUBLE_BUFFER_ELEM_COUNT 4096
20 |
21 | class WeAudioRecorder {
22 |
23 | private:
24 | OnPCMDataCall *onPCMDataCall = NULL;
25 |
26 | SLuint32 slSampleRate = 0;
27 | SLuint32 slChannelLayout = 0;
28 | SLuint16 slEncodingBits = 0;
29 |
30 | int sampleRateInHz = 0;
31 | int channelNum = 0;
32 | int bitsPerSample = 0;
33 |
34 | bool initOpenSLSuccess = false;
35 | bool enqueueFailed = false;
36 |
37 | // 引擎
38 | SLObjectItf engineObject = NULL;
39 | SLEngineItf engineItf = NULL;
40 |
41 | // 录音机
42 | SLObjectItf recordObject = NULL;
43 | SLRecordItf recordItf = NULL;
44 |
45 | // 用于注册接收数据回调和传入接收数据 buffer 的队列接口
46 | SLAndroidSimpleBufferQueueItf bufferQueueItf = NULL;
47 | // 用于接收数据的 buffer
48 | DoubleBuffer *recordBuffer = NULL;
49 |
50 | public:
51 | const char *LOG_TAG = "_WeAudioRecorder";
52 | bool isRecording = false;
53 | bool workFinished = true;
54 |
55 | public:
56 | WeAudioRecorder(OnPCMDataCall *onPcmDataCall);
57 |
58 | ~WeAudioRecorder();
59 |
60 | bool init();
61 |
62 | bool init2(int sampleRateInHz, int channelConfig, int encodingBits);
63 |
64 | int getSampleRate();
65 |
66 | int getChannelNums();
67 |
68 | int getBitsPerSample();
69 |
70 | bool start();
71 |
72 | bool resume();
73 |
74 | bool enqueueReceiveBuffer();
75 |
76 | void callbackData();
77 |
78 | void pause();
79 |
80 | void stop();
81 |
82 | void release();
83 |
84 | private:
85 | SLuint32 transformSampleRate(int sampleRateInHz);
86 |
87 | SLuint32 transformChannelLayout(int channelLayout);
88 |
89 | SLuint32 getChannelNum(int channelLayout);
90 |
91 | SLuint16 transformEncodingBits(int encodingFormat);
92 |
93 | bool _initOpenSL();
94 |
95 | bool _initEngine();
96 |
97 | bool _initRecorder();
98 |
99 | bool _setRecordState(SLuint32 state);
100 |
101 | /**
102 | * 确保在退出应用时销毁所有对象。
103 | * 对象应按照与创建时相反的顺序销毁,因为销毁具有依赖对象的对象并不安全。
104 | * 例如,请按照以下顺序销毁:音频播放器和录制器、输出混合,最后是引擎。
105 | */
106 | void _destroyOpenSL();
107 |
108 | /**
109 | * destroy audio recorder object, and invalidate all associated interfaces
110 | */
111 | void _destroyRecorder();
112 |
113 | /**
114 | * destroy engine object, and invalidate all associated interfaces
115 | */
116 | void _destroyEngine();
117 |
118 | };
119 |
120 |
121 | #endif //VIDEOMAKER_WEAUDIORECORDER_H
122 |
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/java/com/wtz/libnaudiorecord/utlis/LogUtils.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libnaudiorecord.utlis;
2 |
3 | import android.util.Log;
4 |
5 | public class LogUtils {
6 |
7 | public static boolean canPrintLog = true;
8 |
9 | public static void v(String tag, String msg) {
10 | if (canPrintLog) {
11 | Log.v(tag, msg);
12 | }
13 | }
14 |
15 | public static void d(String tag, String msg) {
16 | if (canPrintLog) {
17 | Log.d(tag, msg);
18 | }
19 | }
20 |
21 | public static void i(String tag, String msg) {
22 | if (canPrintLog) {
23 | Log.i(tag, msg);
24 | }
25 | }
26 |
27 | public static void w(String tag, String msg) {
28 | if (canPrintLog) {
29 | Log.w(tag, msg);
30 | }
31 | }
32 |
33 | public static void e(String tag, String msg) {
34 | if (canPrintLog) {
35 | Log.e(tag, msg);
36 | }
37 | }
38 |
39 | public static void printStackTrace(Throwable e) {
40 | if (canPrintLog && e != null) {
41 | e.printStackTrace();
42 | }
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/libnaudiorecord/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | libnative_audiorecord
3 |
4 |
--------------------------------------------------------------------------------
/libpushflow/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/libpushflow/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.2"
6 |
7 |
8 | defaultConfig {
9 | minSdkVersion 14
10 | targetSdkVersion 29
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
15 | consumerProguardFiles 'consumer-rules.pro'
16 |
17 | externalNativeBuild {
18 | cmake {
19 | cppFlags "-std=c++11 -frtti -fexceptions"
20 | abiFilters 'armeabi-v7a','arm64-v8a'
21 | }
22 | }
23 | }
24 |
25 | buildTypes {
26 | release {
27 | minifyEnabled false
28 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
29 | }
30 | }
31 |
32 | externalNativeBuild {
33 | cmake {
34 | path "src/main/cpp/CMakeLists.txt"
35 | version "3.10.2"
36 | }
37 | }
38 |
39 | }
40 |
41 | dependencies {
42 | implementation fileTree(dir: 'libs', include: ['*.jar'])
43 | }
44 |
--------------------------------------------------------------------------------
/libpushflow/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/libpushflow/consumer-rules.pro
--------------------------------------------------------------------------------
/libpushflow/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/libpushflow/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/libpushflow/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.4.1)
2 |
3 | include_directories(pushflow/include/)
4 | include_directories(librtmp/)
5 |
6 | aux_source_directory(librtmp RTMP_SRC_LIST)# 查找在某个路径下的所有源文件
7 |
8 | # 大多数不使用 OpenSSL 功能
9 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_CRYPTO")
10 |
11 | # Creates and names a library, sets it as either STATIC or SHARED,
12 | # and provides the relative paths to its source code.
13 | add_library(
14 | wepushflow
15 |
16 | # Sets the library as a shared library.
17 | SHARED
18 |
19 | # Provides a relative path to your source file(s).
20 | ${RTMP_SRC_LIST}
21 | pushflow/WePushFlowJNI.cpp
22 | pushflow/WePushFlow.cpp
23 | pushflow/RtmpPacketQueue.cpp
24 | pushflow/JavaListener.cpp)
25 |
26 | # Searches for a specified prebuilt library and stores the path as a variable.
27 | # Because CMake includes system libraries in the search path by default,
28 | # you only need to specify the name of the public NDK library you want to add.
29 | find_library(
30 | # Sets the name of the path variable.
31 | log-lib
32 | # Specifies the name of the NDK library that you want CMake to locate.
33 | log)
34 |
35 | # Specifies libraries CMake should link to your target library.
36 | target_link_libraries(
37 | wepushflow
38 |
39 | # Links the target library to the log library included in the NDK.
40 | ${log-lib})
41 |
--------------------------------------------------------------------------------
/libpushflow/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 |
--------------------------------------------------------------------------------
/libpushflow/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 |
--------------------------------------------------------------------------------
/libpushflow/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 |
--------------------------------------------------------------------------------
/libpushflow/src/main/cpp/pushflow/JavaListener.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WTZ on 2019/11/8.
3 | */
4 |
5 | #include "JavaListener.h"
6 | #include "AndroidLog.h"
7 |
8 |
9 | /**
10 | * 此构造方法需要在 C++ 主线程中调用,即直接从 java 层调用下来的线程
11 | *
12 | * @param jvm
13 | * @param mainEnv C++ 主线程 env
14 | * @param obj
15 | */
16 | JavaListener::JavaListener(JavaVM *jvm, JNIEnv *mainEnv, jobject obj) {
17 | _mainTid = gettid();
18 |
19 | _jvm = jvm;
20 | _mainEnv = mainEnv;
21 |
22 | // Fix: JNI ERROR (app bug): accessed stale local reference
23 | _globalObj = _mainEnv->NewGlobalRef(obj);
24 | }
25 |
26 | JavaListener::~JavaListener() {
27 | JNIEnv *env = initCallbackEnv();
28 | env->DeleteGlobalRef(_globalObj);// 回收 GlobalReference
29 | releaseCallbackEnv();
30 | }
31 |
32 | JNIEnv *JavaListener::initCallbackEnv() {
33 | needDetach = false;
34 | pid_t currentTid = gettid();
35 | if (currentTid == _mainTid) {
36 | // 在 C++ 主线程中直接使用主线程 env
37 | return _mainEnv;
38 | }
39 |
40 | JNIEnv *env1;
41 | if (_jvm->GetEnv(reinterpret_cast (&env1), JNI_VERSION_1_6) == JNI_OK) {
42 | // 虽然切换了线程,能 GetEnv 成功,说明这是直接从 Java 层切换的线程
43 | return env1;
44 | }
45 |
46 | // 到这里,说明是在 C++ 中开启的子线程,此时需要用 AttachCurrentThread 来获取 env,
47 | // 否则会报错 JNI ERROR: non-VM thread making JNI call
48 | JNIEnv *env2;
49 | if (_jvm->AttachCurrentThread(&env2, 0) != JNI_OK) {
50 | LOGE(LOG_TAG, "AttachCurrentThread exception! currentTid: %d", currentTid);
51 | return NULL;
52 | }
53 | needDetach = true;
54 | return env2;
55 | }
56 |
57 | void JavaListener::releaseCallbackEnv() {
58 | pid_t currentTid = gettid();
59 | if (currentTid == _mainTid || !needDetach) {
60 | return;
61 | }
62 |
63 | _jvm->DetachCurrentThread();
64 | needDetach = false;
65 | }
66 |
67 | void JavaListener::callback(int argCount, ...) {
68 | JNIEnv *env = initCallbackEnv();
69 | if (_methodID == NULL) {
70 | _methodID = env->GetMethodID(env->GetObjectClass(_globalObj), getMethodName(),
71 | getMethodSignature());
72 | if (env->ExceptionCheck()) {
73 | LOGE(LOG_TAG, "GetMethodID exception! method: %s %s", getMethodName(), getMethodSignature());
74 | env->Throw(env->ExceptionOccurred());
75 | return;
76 | }
77 | }
78 |
79 | va_list args;
80 | va_start(args, argCount);
81 |
82 | reallyCallback(env, _globalObj, _methodID, args);
83 |
84 | va_end(args);
85 | releaseCallbackEnv();
86 | }
87 |
--------------------------------------------------------------------------------
/libpushflow/src/main/cpp/pushflow/RtmpPacketQueue.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2020/4/20.
3 | //
4 |
5 | #include "RtmpPacketQueue.h"
6 |
7 | RtmpPacketQueue::RtmpPacketQueue() {
8 | allowOperation = true;
9 | pthread_mutex_init(&mutex, NULL);
10 | pthread_cond_init(&condition, NULL);
11 | }
12 |
13 | RtmpPacketQueue::~RtmpPacketQueue() {
14 | allowOperation = false;
15 | releaseQueue();
16 | pthread_cond_destroy(&condition);
17 | pthread_mutex_destroy(&mutex);
18 | }
19 |
20 | void RtmpPacketQueue::setAllowOperation(bool allow) {
21 | this->allowOperation = allow;
22 | }
23 |
24 | void RtmpPacketQueue::setProductDataComplete(bool complete) {
25 | pthread_mutex_lock(&mutex);
26 |
27 | if (LOG_DEBUG) {
28 | LOGD(LOG_TAG, "setProductDataComplete: %d", complete);
29 | }
30 | productDataComplete = complete;// 作用:当完成标志位设置早于消费者读数据时,消费者不会再 wait
31 | if (complete) {// 作用:当完成标志位设置晚于消费者 wait 时,可以通知消费者退出
32 | pthread_cond_signal(&condition);
33 | }
34 |
35 | pthread_mutex_unlock(&mutex);
36 | }
37 |
38 | bool RtmpPacketQueue::isProductDataComplete() {
39 | bool ret;
40 | pthread_mutex_lock(&mutex);
41 | ret = productDataComplete;
42 | pthread_mutex_unlock(&mutex);
43 | return ret;
44 | }
45 |
46 | void RtmpPacketQueue::putPacket(RTMPPacket *packet) {
47 | pthread_mutex_lock(&mutex);
48 |
49 | queue.push(packet);
50 | if (LOG_REPEAT_DEBUG) {
51 | LOGD(LOG_TAG, "putAVpacket current size:%d", queue.size());
52 | }
53 | pthread_cond_signal(&condition);
54 |
55 | pthread_mutex_unlock(&mutex);
56 | }
57 |
58 | RTMPPacket *RtmpPacketQueue::getPacket() {
59 | pthread_mutex_lock(&mutex);
60 |
61 | RTMPPacket *packet = NULL;
62 | // 循环是为了在队列为空导致阻塞等待后被唤醒时继续取下一个
63 | while (allowOperation) {
64 | if (!queue.empty()) {
65 | packet = queue.front();
66 | queue.pop();
67 | break;
68 | } else if (!productDataComplete) {
69 | pthread_cond_wait(&condition, &mutex);
70 | } else {
71 | // 队列为空,也不再生产数据,那就退出
72 | break;
73 | }
74 | }
75 |
76 | pthread_mutex_unlock(&mutex);
77 | return packet;
78 | }
79 |
80 | int RtmpPacketQueue::getQueueSize() {
81 | int size = 0;
82 | pthread_mutex_lock(&mutex);
83 | size = queue.size();
84 | pthread_mutex_unlock(&mutex);
85 | return size;
86 | }
87 |
88 | void RtmpPacketQueue::clearQueue() {
89 | if (LOG_DEBUG) {
90 | LOGD(LOG_TAG, "clearQueue...");
91 | }
92 | pthread_cond_signal(&condition);
93 | pthread_mutex_lock(&mutex);
94 |
95 | RTMPPacket *packet = NULL;
96 | while (!queue.empty()) {
97 | packet = queue.front();
98 | queue.pop();
99 | RTMPPacket_Free(packet);
100 | }
101 | packet = NULL;
102 |
103 | pthread_mutex_unlock(&mutex);
104 | if (LOG_DEBUG) {
105 | LOGD(LOG_TAG, "clearQueue finished");
106 | }
107 | }
108 |
109 | void RtmpPacketQueue::releaseQueue() {
110 | clearQueue();
111 | std::queue empty;
112 | swap(empty, queue);
113 | }
114 |
--------------------------------------------------------------------------------
/libpushflow/src/main/cpp/pushflow/include/AndroidLog.h:
--------------------------------------------------------------------------------
1 | #ifndef FFMPEG_ANDROIDLOG_H
2 | #define FFMPEG_ANDROIDLOG_H
3 |
4 | #include
5 |
6 | #define LOG_DEBUG true // 表示一般步骤信息日志是否打开,比如初始化日志
7 | #define LOG_REPEAT_DEBUG false // 表示重复性的大量日志是否打开,例如入队出队数据日志
8 |
9 | #define LOGV(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, FORMAT, ##__VA_ARGS__);
10 | #define LOGD(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, FORMAT, ##__VA_ARGS__);
11 | #define LOGI(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, FORMAT, ##__VA_ARGS__);
12 | #define LOGW(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, FORMAT, ##__VA_ARGS__);
13 | #define LOGE(LOG_TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, FORMAT, ##__VA_ARGS__);
14 |
15 | #endif //FFMPEG_ANDROIDLOG_H
16 |
--------------------------------------------------------------------------------
/libpushflow/src/main/cpp/pushflow/include/JavaListener.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WTZ on 2019/11/8.
3 | */
4 |
5 | #ifndef FFMPEG_JAVALISTENER_H
6 | #define FFMPEG_JAVALISTENER_H
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | class JavaListener {
13 |
14 | private:
15 | const char *LOG_TAG = "JavaListener";
16 | pid_t _mainTid;
17 | JavaVM *_jvm;
18 | JNIEnv *_mainEnv;
19 | jobject _globalObj;
20 | jmethodID _methodID = NULL;// 若不初始化,则值为非空;置空用于后边判断一次性懒加载
21 | bool needDetach = false;
22 |
23 | public:
24 | /**
25 | * 此构造方法需要在 C++ 主线程中调用,即直接从 java 层调用下来的线程
26 | *
27 | * @param jvm
28 | * @param mainEnv C++ 主线程 env
29 | * @param obj
30 | */
31 | JavaListener(JavaVM *jvm, JNIEnv *mainEnv, jobject obj);
32 |
33 | virtual ~JavaListener();
34 |
35 | void callback(int argCount, ...);
36 |
37 | private:
38 | JNIEnv *initCallbackEnv();
39 |
40 | void releaseCallbackEnv();
41 |
42 | protected:
43 | virtual const char *getMethodName() = 0;
44 |
45 | virtual const char *getMethodSignature() = 0;
46 |
47 | virtual void reallyCallback(JNIEnv *env, jobject obj, jmethodID methodId, va_list args) = 0;
48 |
49 | };
50 |
51 | #endif //FFMPEG_JAVALISTENER_H
52 |
--------------------------------------------------------------------------------
/libpushflow/src/main/cpp/pushflow/include/OnPushDisconnectCall.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2020/4/24.
3 | //
4 |
5 | #ifndef VIDEOMAKER_ONPUSHDISCONNECTCALL_H
6 | #define VIDEOMAKER_ONPUSHDISCONNECTCALL_H
7 |
8 | #include "JavaListener.h"
9 |
10 | class OnPushDisconnectCall : public JavaListener {
11 |
12 | public:
13 | OnPushDisconnectCall(JavaVM *jvm, JNIEnv *mainEnv, jobject obj)
14 | : JavaListener(jvm, mainEnv, obj) {
15 | }
16 |
17 | ~OnPushDisconnectCall() {
18 | };
19 |
20 | const char *getMethodName() {
21 | return "onNativePushDisconnect";
22 | }
23 |
24 | const char *getMethodSignature() {
25 | return "()V";
26 | }
27 |
28 | void reallyCallback(JNIEnv *env, jobject obj, jmethodID methodId, va_list args) {
29 | env->CallVoidMethod(obj, methodId);
30 | }
31 |
32 | };
33 |
34 |
35 | #endif //VIDEOMAKER_ONPUSHDISCONNECTCALL_H
36 |
--------------------------------------------------------------------------------
/libpushflow/src/main/cpp/pushflow/include/OnStartPushResultListener.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2020/4/24.
3 | //
4 |
5 | #ifndef VIDEOMAKER_ONSTARTPUSHRESULTLISTENER_H
6 | #define VIDEOMAKER_ONSTARTPUSHRESULTLISTENER_H
7 |
8 | #include "JavaListener.h"
9 |
10 | class OnStartPushResultListener : public JavaListener {
11 |
12 | public:
13 | OnStartPushResultListener(JavaVM *jvm, JNIEnv *mainEnv, jobject obj)
14 | : JavaListener(jvm, mainEnv, obj) {
15 | }
16 |
17 | ~OnStartPushResultListener() {
18 | };
19 |
20 | const char *getMethodName() {
21 | return "onNativeStartPushResult";
22 | }
23 |
24 | const char *getMethodSignature() {
25 | return "(ZLjava/lang/String;)V";
26 | }
27 |
28 | void reallyCallback(JNIEnv *env, jobject obj, jmethodID methodId, va_list args) {
29 | bool success = va_arg(args, bool);
30 | const char *info = va_arg(args, const char *);
31 |
32 | jstring jStr = env->NewStringUTF(info);
33 | env->CallVoidMethod(obj, methodId, success, jStr);
34 | env->DeleteLocalRef(jStr);
35 | }
36 |
37 | };
38 |
39 |
40 | #endif //VIDEOMAKER_ONSTARTPUSHRESULTLISTENER_H
41 |
--------------------------------------------------------------------------------
/libpushflow/src/main/cpp/pushflow/include/RtmpPacketQueue.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2020/4/20.
3 | //
4 |
5 | #ifndef VIDEOMAKER_RTMPPACKETQUEUE_H
6 | #define VIDEOMAKER_RTMPPACKETQUEUE_H
7 |
8 | #include "queue"
9 | #include
10 | #include "AndroidLog.h"
11 |
12 | extern "C"
13 | {
14 | #include "rtmp.h"
15 | };
16 |
17 | class RtmpPacketQueue {
18 |
19 | private:
20 | const char *LOG_TAG = "RtmpPacketQueue";
21 |
22 | bool allowOperation = true;
23 | bool productDataComplete = false;
24 |
25 | std::queue queue;
26 | pthread_mutex_t mutex;
27 | pthread_cond_t condition;
28 |
29 | public:
30 | static const int MAX_CACHE_NUM = 40;//TODO TEST
31 |
32 | public:
33 | RtmpPacketQueue();
34 |
35 | ~RtmpPacketQueue();
36 |
37 | /**
38 | * 是否允许操作队列
39 | *
40 | * @param allow
41 | */
42 | void setAllowOperation(bool allow);
43 |
44 | /**
45 | * 生产者线程通知是否还有数据可以入队,防止最后消费者线程一直阻塞等待
46 | */
47 | void setProductDataComplete(bool complete);
48 |
49 | bool isProductDataComplete();
50 |
51 | void putPacket(RTMPPacket *packet);
52 |
53 | RTMPPacket *getPacket();
54 |
55 | int getQueueSize();
56 |
57 | void clearQueue();
58 |
59 | private:
60 | void releaseQueue();
61 |
62 | };
63 |
64 |
65 | #endif //VIDEOMAKER_RTMPPACKETQUEUE_H
66 |
--------------------------------------------------------------------------------
/libpushflow/src/main/cpp/pushflow/include/WePushFlow.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by WTZ on 2020/4/20.
3 | //
4 |
5 | #ifndef VIDEOMAKER_WEPUSHFLOW_H
6 | #define VIDEOMAKER_WEPUSHFLOW_H
7 |
8 | extern "C" {
9 | #include "rtmp.h"
10 | };
11 |
12 | #include
13 | #include "RtmpPacketQueue.h"
14 | #include "OnStartPushResultListener.h"
15 | #include "OnPushDisconnectCall.h"
16 |
17 | #define RTMP_SPS_PPS_EXTRA_BYTES_SIZE 16
18 | #define RTMP_VIDEO_EXTRA_BYTES_SIZE 9
19 | #define RTMP_AAC_EXTRA_BYTES_SIZE 2
20 |
21 | #define RTMP_STREAM_CHANNEL_METADATA 0x03
22 | #define RTMP_STREAM_CHANNEL_VIDEO 0x04
23 | #define RTMP_STREAM_CHANNEL_AUDIO 0x05
24 |
25 | class WePushFlow {
26 |
27 | private:
28 | const char *LOG_TAG = "_WePushFlow";
29 |
30 | OnStartPushResultListener *onStartPushResultListener = NULL;
31 | OnPushDisconnectCall *onPushDisconnectCall = NULL;
32 |
33 | RTMP *rtmp = NULL;
34 | char *pushUrl = NULL;
35 | int connectTimeout = 5;// seconds
36 |
37 | int audioEncodeBitsFlag = 0x2;// 第2位标志 default 16bits
38 | int audioChannelFlag = 0x1;// 第1位标志 default stereo
39 |
40 | RtmpPacketQueue *queue = NULL;
41 | RTMPPacket *packet = NULL;
42 |
43 | bool isStarting = false;
44 | bool isStartSuccess = false;
45 | long startPushTime = 0;
46 | bool isShouldCallDisconnect = false;
47 | bool isShouldExit = false;
48 |
49 | public:
50 | pthread_t pushThread;
51 | bool isPushThreadStarted = false;
52 |
53 | public:
54 | WePushFlow(OnStartPushResultListener *startListener, OnPushDisconnectCall *disconnectCall);
55 |
56 | ~WePushFlow();
57 |
58 | void setPushUrl(char *url);
59 |
60 | void setConnectTimeout(int seconds);
61 |
62 | void setAudioEncodeBits(int audioEncodeBits);
63 |
64 | void setAudioChannels(int audioChannels);
65 |
66 | void startPush();
67 |
68 | void _loopPush();
69 |
70 | void pushSpsPps(char *sps, int spsLength, char *pps, int ppsLength);
71 |
72 | void pushVideoData(char *data, int dataLength, bool isKeyframe);
73 |
74 | void pushAudioData(char *data, int dataLength);
75 |
76 | void setStopFlag();
77 |
78 | void stopPush();
79 |
80 | private:
81 | void handleOnStartPushFailed(char *error);
82 |
83 | void freeRTMP();
84 |
85 | };
86 |
87 |
88 | #endif //VIDEOMAKER_WEPUSHFLOW_H
89 |
--------------------------------------------------------------------------------
/libpushflow/src/main/java/com/wtz/libpushflow/utlis/LogUtils.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libpushflow.utlis;
2 |
3 | import android.util.Log;
4 |
5 | public class LogUtils {
6 |
7 | public static boolean canPrintLog = true;
8 |
9 | public static void v(String tag, String msg) {
10 | if (canPrintLog) {
11 | Log.v(tag, msg);
12 | }
13 | }
14 |
15 | public static void d(String tag, String msg) {
16 | if (canPrintLog) {
17 | Log.d(tag, msg);
18 | }
19 | }
20 |
21 | public static void i(String tag, String msg) {
22 | if (canPrintLog) {
23 | Log.i(tag, msg);
24 | }
25 | }
26 |
27 | public static void w(String tag, String msg) {
28 | if (canPrintLog) {
29 | Log.w(tag, msg);
30 | }
31 | }
32 |
33 | public static void e(String tag, String msg) {
34 | if (canPrintLog) {
35 | Log.e(tag, msg);
36 | }
37 | }
38 |
39 | public static void printStackTrace(Throwable e) {
40 | if (canPrintLog && e != null) {
41 | e.printStackTrace();
42 | }
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/libpushflow/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | libpushflow
3 |
4 |
--------------------------------------------------------------------------------
/libvideomaker/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/libvideomaker/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.2"
6 |
7 |
8 | defaultConfig {
9 | minSdkVersion 19
10 | targetSdkVersion 29
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | consumerProguardFiles 'consumer-rules.pro'
15 | }
16 |
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 |
24 | }
25 |
26 | dependencies {
27 | implementation fileTree(dir: 'libs', include: ['*.jar'])
28 | compile project(path: ':libpushflow')
29 | }
30 |
--------------------------------------------------------------------------------
/libvideomaker/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/libvideomaker/consumer-rules.pro
--------------------------------------------------------------------------------
/libvideomaker/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/egl/WeGLRenderer.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.egl;
2 |
3 | /**
4 | * 接口方法在 WeGLThread 中回调
5 | */
6 | public interface WeGLRenderer {
7 |
8 | /**
9 | * The renderer only renders
10 | * when the surface is created, or when requestRender() is called.
11 | */
12 | int RENDERMODE_WHEN_DIRTY = 0;
13 |
14 | /**
15 | * The renderer is called
16 | * continuously to re-render the scene.
17 | */
18 | int RENDERMODE_CONTINUOUSLY = 1;
19 |
20 | void onEGLContextCreated();
21 |
22 | void onSurfaceChanged(int width, int height);
23 |
24 | void onDrawFrame();
25 |
26 | void onEGLContextToDestroy();
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/recorder/WeVideoRecorder.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.recorder;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.media.MediaFormat;
6 | import android.net.Uri;
7 |
8 | import com.wtz.libvideomaker.egl.WeGLRenderer;
9 | import com.wtz.libvideomaker.egl.WeGLVideoEncoder;
10 | import com.wtz.libvideomaker.renderer.OnScreenRenderer;
11 | import com.wtz.libvideomaker.utils.LogUtils;
12 |
13 | import java.io.File;
14 | import java.text.SimpleDateFormat;
15 | import java.util.Date;
16 |
17 | import javax.microedition.khronos.egl.EGLContext;
18 |
19 | public class WeVideoRecorder extends WeGLVideoEncoder implements WeGLRenderer {
20 | private static final String TAG = WeVideoRecorder.class.getSimpleName();
21 |
22 | private Context mContext;
23 | private boolean isReleased;
24 |
25 | private OnScreenRenderer mOnScreenRenderer;
26 | private static final int RENDER_FPS = 30;//大部分摄像头最高30fps,FPS过高会导致部分低端机型渲染闪屏
27 |
28 | private String mSaveVideoDir;
29 | private String mVideoPathName;
30 | private static final String VIDEO_PREFIX = "We_VID_";
31 | private static final String VIDEO_SUFFIX = ".mp4";
32 | private final SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
33 |
34 | public WeVideoRecorder(Context context) {
35 | super();
36 | this.mContext = context;
37 | setRenderMode(RENDERMODE_CONTINUOUSLY);
38 | setRenderFps(RENDER_FPS);
39 |
40 | mOnScreenRenderer = new OnScreenRenderer(context, TAG);
41 | mOnScreenRenderer.setClearScreenOnDraw(false);// 缓解某些低端机型录制视频时闪屏问题
42 | }
43 |
44 | public void setExternalTextureId(int id) {
45 | mOnScreenRenderer.setExternalTextureId(id);
46 | }
47 |
48 | public void setSaveVideoDir(String dir) {
49 | LogUtils.d(TAG, "setSaveVideoDir: " + dir);
50 | this.mSaveVideoDir = dir;
51 | }
52 |
53 | @Override
54 | protected WeGLRenderer getRenderer() {
55 | return this;
56 | }
57 |
58 | @Override
59 | protected String getExternalLogTag() {
60 | return TAG;
61 | }
62 |
63 | public void startEncode(EGLContext context, int videoWidth, int videoHeight) {
64 | mVideoPathName = getVideoPathName();
65 | super.startEncode(context, mVideoPathName, MediaFormat.MIMETYPE_VIDEO_AVC, videoWidth, videoHeight);
66 | }
67 |
68 | private String getVideoPathName() {
69 | String time = mSimpleDateFormat.format(new Date());
70 | return new File(mSaveVideoDir, VIDEO_PREFIX + time + VIDEO_SUFFIX).getAbsolutePath();
71 | }
72 |
73 | @Override
74 | public void onEGLContextCreated() {
75 | mOnScreenRenderer.onEGLContextCreated();
76 | }
77 |
78 | @Override
79 | public void onSurfaceChanged(int width, int height) {
80 | mOnScreenRenderer.onSurfaceChanged(width, height);
81 | }
82 |
83 | @Override
84 | public void onDrawFrame() {
85 | mOnScreenRenderer.onDrawFrame();
86 | }
87 |
88 | @Override
89 | public void stopEncode() {
90 | super.stopEncode();
91 |
92 | if (mContext != null && mVideoPathName != null) {
93 | // 注意:以 Environment.getExternalStorageDirectory() 为开头的路径才会通知图库扫描有效
94 | Uri contentUri = Uri.fromFile(new File(mVideoPathName));
95 | Intent i = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, contentUri);
96 | mContext.sendBroadcast(i);
97 | }
98 | }
99 |
100 | public void release() {
101 | isReleased = true;
102 | super.release();
103 | mContext = null;
104 | }
105 |
106 | @Override
107 | public void onEGLContextToDestroy() {
108 | mOnScreenRenderer.onEGLContextToDestroy();
109 | if (isReleased) {
110 | mOnScreenRenderer = null;
111 | }
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/renderer/BaseRender.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.renderer;
2 |
3 | import android.opengl.GLES20;
4 |
5 | import com.wtz.libvideomaker.egl.WeGLRenderer;
6 |
7 | public abstract class BaseRender implements WeGLRenderer {
8 |
9 | protected boolean canClearScreenOnDraw = true;
10 | protected boolean forceClearScreenOnce = false;
11 |
12 | public void setClearScreenOnDraw(boolean clearScreen) {
13 | canClearScreenOnDraw = clearScreen;
14 | }
15 |
16 | protected float[] getDefaultVertexCoordData() {
17 | return new float[]{
18 | // 整个视口区域
19 | -1f, -1f,
20 | 1f, -1f,
21 | -1f, 1f,
22 | 1f, 1f
23 | };
24 | }
25 |
26 | protected float[] getDefaultTextureCoordData() {
27 | return new float[]{
28 | // 默认选取纹理全部区域
29 | 0f, 1f,
30 | 1f, 1f,
31 | 0f, 0f,
32 | 1f, 0f
33 | };
34 | }
35 |
36 | @Override
37 | public void onSurfaceChanged(int width, int height) {
38 | GLES20.glViewport(0, 0, width, height);
39 | forceClearScreenOnce = true;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/renderer/filters/GrayFilterRenderer.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.renderer.filters;
2 |
3 | import android.content.Context;
4 |
5 | import com.wtz.libvideomaker.R;
6 |
7 | public class GrayFilterRenderer extends FilterRenderer {
8 |
9 | private static final String TAG = GrayFilterRenderer.class.getSimpleName();
10 |
11 | private float[] mPositionMatrix;// 用来保存位置变换矩阵数值的数组
12 |
13 | public GrayFilterRenderer(Context mContext) {
14 | super(mContext, TAG);
15 | }
16 |
17 | @Override
18 | public void onEGLContextCreated() {
19 | // 创建位置转换矩阵(4x4)返回值存储的数组
20 | mPositionMatrix = new float[16];
21 |
22 | super.onEGLContextCreated();
23 | }
24 |
25 | @Override
26 | protected int getVertexShaderResId() {
27 | return R.raw.we_vidmk_vertex_offscreen_shader;
28 | }
29 |
30 | @Override
31 | protected int getFragmentShaderResId() {
32 | return R.raw.we_vidmk_fragment_gray_texture2d_shader;
33 | }
34 |
35 | @Override
36 | protected float[] getVertexCoordData() {
37 | return getDefaultVertexCoordData();
38 | }
39 |
40 | @Override
41 | protected float[] getTextureCoordData() {
42 | return getDefaultTextureCoordData();
43 | }
44 |
45 | @Override
46 | protected int getVertexDrawCount() {
47 | return 4;
48 | }
49 |
50 | @Override
51 | protected void changePositionMatrix(int width, int height) {
52 | defaultPositionMatrixChange(mPositionMatrix);
53 | }
54 |
55 | @Override
56 | protected float[] getPositionMatrix() {
57 | return mPositionMatrix;
58 | }
59 |
60 | @Override
61 | public void onEGLContextToDestroy() {
62 | super.onEGLContextToDestroy();
63 | mPositionMatrix = null;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/renderer/filters/LuminanceFilterRenderer.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.renderer.filters;
2 |
3 | import android.content.Context;
4 |
5 | import com.wtz.libvideomaker.R;
6 |
7 | public class LuminanceFilterRenderer extends FilterRenderer {
8 |
9 | private static final String TAG = LuminanceFilterRenderer.class.getSimpleName();
10 |
11 | private float[] mPositionMatrix;// 用来保存位置变换矩阵数值的数组
12 |
13 | public LuminanceFilterRenderer(Context mContext) {
14 | super(mContext, TAG);
15 | }
16 |
17 | @Override
18 | public void onEGLContextCreated() {
19 | // 创建位置转换矩阵(4x4)返回值存储的数组
20 | mPositionMatrix = new float[16];
21 |
22 | super.onEGLContextCreated();
23 | }
24 |
25 | @Override
26 | protected int getVertexShaderResId() {
27 | return R.raw.we_vidmk_vertex_offscreen_shader;
28 | }
29 |
30 | @Override
31 | protected int getFragmentShaderResId() {
32 | return R.raw.we_vidmk_fragment_luminance_texture2d_shader;
33 | }
34 |
35 | @Override
36 | protected float[] getVertexCoordData() {
37 | return getDefaultVertexCoordData();
38 | }
39 |
40 | @Override
41 | protected float[] getTextureCoordData() {
42 | return getDefaultTextureCoordData();
43 | }
44 |
45 | @Override
46 | protected int getVertexDrawCount() {
47 | return 4;
48 | }
49 |
50 | @Override
51 | protected void changePositionMatrix(int width, int height) {
52 | defaultPositionMatrixChange(mPositionMatrix);
53 | }
54 |
55 | @Override
56 | protected float[] getPositionMatrix() {
57 | return mPositionMatrix;
58 | }
59 |
60 | @Override
61 | public void onEGLContextToDestroy() {
62 | super.onEGLContextToDestroy();
63 | mPositionMatrix = null;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/renderer/filters/ReverseFilterRenderer.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.renderer.filters;
2 |
3 | import android.content.Context;
4 |
5 | import com.wtz.libvideomaker.R;
6 |
7 | public class ReverseFilterRenderer extends FilterRenderer {
8 |
9 | private static final String TAG = ReverseFilterRenderer.class.getSimpleName();
10 |
11 | private float[] mPositionMatrix;// 用来保存位置变换矩阵数值的数组
12 |
13 | public ReverseFilterRenderer(Context mContext) {
14 | super(mContext, TAG);
15 | }
16 |
17 | @Override
18 | public void onEGLContextCreated() {
19 | // 创建位置转换矩阵(4x4)返回值存储的数组
20 | mPositionMatrix = new float[16];
21 |
22 | super.onEGLContextCreated();
23 | }
24 |
25 | @Override
26 | protected int getVertexShaderResId() {
27 | return R.raw.we_vidmk_vertex_offscreen_shader;
28 | }
29 |
30 | @Override
31 | protected int getFragmentShaderResId() {
32 | return R.raw.we_vidmk_fragment_reverse_texture2d_shader;
33 | }
34 |
35 | @Override
36 | protected float[] getVertexCoordData() {
37 | return getDefaultVertexCoordData();
38 | }
39 |
40 | @Override
41 | protected float[] getTextureCoordData() {
42 | return getDefaultTextureCoordData();
43 | }
44 |
45 | @Override
46 | protected int getVertexDrawCount() {
47 | return 4;
48 | }
49 |
50 | @Override
51 | protected void changePositionMatrix(int width, int height) {
52 | defaultPositionMatrixChange(mPositionMatrix);
53 | }
54 |
55 | @Override
56 | protected float[] getPositionMatrix() {
57 | return mPositionMatrix;
58 | }
59 |
60 | @Override
61 | public void onEGLContextToDestroy() {
62 | super.onEGLContextToDestroy();
63 | mPositionMatrix = null;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/renderer/origins/MultiImgRenderer.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.renderer.origins;
2 |
3 | import android.content.Context;
4 | import android.opengl.Matrix;
5 |
6 | public class MultiImgRenderer extends ImgRenderer {
7 |
8 | private static final String TAG = MultiImgRenderer.class.getSimpleName();
9 |
10 | private float[] mPositionMatrix;// 用来保存位置变换矩阵数值的数组
11 |
12 | public MultiImgRenderer(Context mContext) {
13 | super(mContext, TAG);
14 | }
15 |
16 | @Override
17 | public void onEGLContextCreated() {
18 | // 创建位置转换矩阵(4x4)返回值存储的数组
19 | mPositionMatrix = new float[16];
20 |
21 | super.onEGLContextCreated();
22 | }
23 |
24 | @Override
25 | protected float[] getVertexCoordData() {
26 | /*
27 | * 归一化顶点坐标系 窗口纹理坐标系 FBO 纹理坐标系
28 | * y y
29 | * ↑ ┆ ↑
30 | * (-1,1)------(0,1)------(1,1) ---(0,0)------(1,0)-->x ---(0,1)------(1,1)
31 | * ┆ ┆ ┆ ┆ ┆ ┆ ┆
32 | * ┆ ┆ ┆ ┆ ┆ ┆ ┆
33 | * (-1,0)------(0,0)------(1,0)-->x ┆ ┆ ┆ ┆
34 | * ┆ ┆ ┆ ┆ ┆ ┆ ┆
35 | * ┆ ┆ ┆ ┆ ┆ ┆ ┆
36 | * (-1,-1)-----(0,-1)-----(1,-1) (0,1)------(1,1) ---(0,0)------(1,0)-->x
37 | * ↓ ┆
38 | * y
39 | */
40 | return new float[]{
41 | // 视口左上角 1/4 区域
42 | -1f, 0f,
43 | 0f, 0f,
44 | -1f, 1f,
45 | 0f, 1f,
46 |
47 | // 视口右上角 1/4 区域
48 | 0f, 0f,
49 | 1f, 0f,
50 | 0f, 1f,
51 | 1f, 1f,
52 |
53 | // 视口左下角 1/4 区域
54 | -1f, -1f,
55 | 0f, -1f,
56 | -1f, 0f,
57 | 0f, 0f,
58 |
59 | // 视口右下角 1/4 区域
60 | 0f, -1f,
61 | 1f, -1f,
62 | 0f, 0f,
63 | 1f, 0f,
64 |
65 | // 整个视口中心 1/16 区域
66 | -0.25f, -0.25f,
67 | 0.25f, -0.25f,
68 | -0.25f, 0.25f,
69 | 0.25f, 0.25f,
70 | };
71 | }
72 |
73 | @Override
74 | protected int getVertexDrawOffsetBytes(int sourceImgIndex) {
75 | // 最多支持5个索引,此后循环
76 | int index = sourceImgIndex % 5;
77 | // 每一组为一个矩形,4个点,8个浮点数值,每个浮点数值4字节
78 | return index * 8 * 4;
79 | }
80 |
81 | @Override
82 | protected int getVertexDrawCount(int sourceImgIndex) {
83 | // 每组4个点一共2个三角形,组成一个矩形
84 | return 4;
85 | }
86 |
87 | public void setImageList(int[] resIds) {
88 | if (resIds == null || resIds.length == 0) return;
89 | setImageResources(resIds);
90 | }
91 |
92 | public void setImageList(String[] paths) {
93 | if (paths == null || paths.length == 0) return;
94 | setImagePaths(paths);
95 | }
96 |
97 | @Override
98 | protected void onSourceImageLoaded(int[][] mSourceBitmapInfos) {
99 | }
100 |
101 | @Override
102 | protected void changePositionMatrix(int width, int height) {
103 | // 初始化单位矩阵
104 | Matrix.setIdentityM(mPositionMatrix, 0);
105 |
106 | // 沿 x 轴旋转 180 度
107 | // rotateM(float[] m, int mOffset, float a, float x, float y, float z)
108 | // * @param a angle to rotate in degrees
109 | // * @param x、y、z: 是否需要沿着 X、Y、Z 轴旋转, 0 不旋转,1f 需要旋转
110 | Matrix.rotateM(mPositionMatrix, 0, 180f, 1f, 0, 0);
111 | }
112 |
113 | @Override
114 | protected float[] getPositionMatrix(int sourceImgIndex) {
115 | return mPositionMatrix;
116 | }
117 |
118 | @Override
119 | public void onEGLContextToDestroy() {
120 | super.onEGLContextToDestroy();
121 | mPositionMatrix = null;
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/renderer/origins/SingleImgRenderer.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.renderer.origins;
2 |
3 | import android.content.Context;
4 | import android.opengl.Matrix;
5 | import android.text.TextUtils;
6 |
7 | public class SingleImgRenderer extends ImgRenderer {
8 |
9 | private static final String TAG = SingleImgRenderer.class.getSimpleName();
10 |
11 | private int mSurfaceWidth;
12 | private int mSurfaceHeight;
13 | private int mSourceImageWidth;
14 | private int mSourceImageHeight;
15 |
16 | private int[] mResIds;
17 | private String[] mPaths;
18 |
19 | private float[] mPositionMatrix;// 用来保存位置变换矩阵数值的数组
20 |
21 | public SingleImgRenderer(Context mContext) {
22 | super(mContext, TAG);
23 | }
24 |
25 | @Override
26 | public void onEGLContextCreated() {
27 | // 创建位置转换矩阵(4x4)返回值存储的数组
28 | mPositionMatrix = new float[16];
29 |
30 | super.onEGLContextCreated();
31 | }
32 |
33 | @Override
34 | protected float[] getVertexCoordData() {
35 | return getDefaultVertexCoordData();
36 | }
37 |
38 | @Override
39 | protected int getVertexDrawOffsetBytes(int sourceImgIndex) {
40 | return 0;
41 | }
42 |
43 | @Override
44 | protected int getVertexDrawCount(int sourceImgIndex) {
45 | // 4个点一共 2 个三角形,组成一个矩形
46 | return 4;
47 | }
48 |
49 | @Override
50 | public void onSurfaceChanged(int width, int height) {
51 | super.onSurfaceChanged(width, height);
52 | this.mSurfaceWidth = width;
53 | this.mSurfaceHeight = height;
54 | }
55 |
56 | public void setImageResource(int resId) {
57 | if (mResIds == null) {
58 | mResIds = new int[]{resId};
59 | } else {
60 | mResIds[0] = resId;
61 | }
62 | setImageResources(mResIds);
63 | }
64 |
65 | public void setImagePath(String path) {
66 | if (TextUtils.isEmpty(path)) return;
67 |
68 | if (mPaths == null) {
69 | mPaths = new String[]{path};
70 | } else {
71 | mPaths[0] = path;
72 | }
73 | setImagePaths(mPaths);
74 | }
75 |
76 | @Override
77 | protected void onSourceImageLoaded(int[][] mSourceBitmapInfos) {
78 | mSourceImageWidth = mSourceBitmapInfos[0][0];
79 | mSourceImageHeight = mSourceBitmapInfos[0][1];
80 | changePositionMatrix(mSurfaceWidth, mSurfaceHeight);
81 | }
82 |
83 | @Override
84 | protected void changePositionMatrix(int width, int height) {
85 | // 初始化单位矩阵
86 | Matrix.setIdentityM(mPositionMatrix, 0);
87 |
88 | if (mSourceImageWidth > 0 && mSourceImageHeight > 0) {
89 | // 设置正交投影
90 | float imageRatio = mSourceImageWidth * 1.0f / mSourceImageHeight;
91 | float containerRatio = width * 1.0f / height;
92 | if (containerRatio >= imageRatio) {
93 | // 容器比图像更宽一些,横向居中展示
94 | float imageNormalWidth = 1 - (-1);
95 | float containerNormalWidth = width / (height * imageRatio) * imageNormalWidth;
96 | Matrix.orthoM(mPositionMatrix, 0,
97 | -containerNormalWidth / 2, containerNormalWidth / 2,
98 | -1f, 1f,
99 | -1f, 1f);
100 | } else {
101 | // 容器比图像更高一些,纵向居中展示
102 | float imageNormalHeight = 1 - (-1);
103 | float containerNormalHeight = height / (width / imageRatio) * imageNormalHeight;
104 | Matrix.orthoM(mPositionMatrix, 0,
105 | -1, 1,
106 | -containerNormalHeight / 2, containerNormalHeight / 2,
107 | -1f, 1f);
108 | }
109 | }
110 |
111 | // 沿 x 轴旋转 180 度
112 | // rotateM(float[] m, int mOffset, float a, float x, float y, float z)
113 | // * @param a angle to rotate in degrees
114 | // * @param x、y、z: 是否需要沿着 X、Y、Z 轴旋转, 0 不旋转,1f 需要旋转
115 | Matrix.rotateM(mPositionMatrix, 0, 180f, 1f, 0, 0);
116 | }
117 |
118 | @Override
119 | protected float[] getPositionMatrix(int sourceImgIndex) {
120 | return mPositionMatrix;
121 | }
122 |
123 | @Override
124 | public void onEGLContextToDestroy() {
125 | super.onEGLContextToDestroy();
126 | mPositionMatrix = null;
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/utils/ExponentialWaitStrategy.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.utils;
2 |
3 | import java.util.Random;
4 | import java.util.concurrent.TimeUnit;
5 |
6 | public final class ExponentialWaitStrategy {
7 |
8 | private final long multiplier;
9 | private final long maximumWait;
10 |
11 | public ExponentialWaitStrategy(long multiplier, long maximumWait, TimeUnit maximumTimeUnit) {
12 | this.multiplier = multiplier;
13 | this.maximumWait = maximumTimeUnit.toMillis(maximumWait);
14 | }
15 |
16 | public long computeSleepTime(long retryNumber) {
17 | double exp = Math.pow(2, retryNumber);
18 | long result = Math.round(multiplier * exp);
19 | if (result > maximumWait) {
20 | result = maximumWait;
21 | }
22 | return result >= 0L ? result : 0L;
23 | }
24 |
25 | public static long getRandomDelayMillis(int boundSeconds) {
26 | long seed = System.nanoTime() + android.os.Process.myPid() + android.os.Process.myTid();
27 | Random random = new Random(seed);
28 | int seconds = random.nextInt(boundSeconds);
29 | return seconds * 1000;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/utils/HexUtils.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.utils;
2 |
3 | public class HexUtils {
4 |
5 | public static String byteToHex(byte[] bytes, int max) {
6 | StringBuffer stringBuffer = new StringBuffer();
7 | for (int i = 0; i < bytes.length; i++) {
8 | String hex = Integer.toHexString(bytes[i]);
9 | if (hex.length() == 1) {
10 | stringBuffer.append("0" + hex);
11 | } else {
12 | stringBuffer.append(hex);
13 | }
14 | if (i > max) {
15 | break;
16 | }
17 | }
18 | return stringBuffer.toString();
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/utils/LogUtils.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.utils;
2 |
3 | import android.util.Log;
4 |
5 | public class LogUtils {
6 |
7 | public static boolean canPrintLog = true;
8 |
9 | public static void v(String tag, String msg) {
10 | if (canPrintLog) {
11 | Log.v(tag, msg);
12 | }
13 | }
14 |
15 | public static void d(String tag, String msg) {
16 | if (canPrintLog) {
17 | Log.d(tag, msg);
18 | }
19 | }
20 |
21 | public static void i(String tag, String msg) {
22 | if (canPrintLog) {
23 | Log.i(tag, msg);
24 | }
25 | }
26 |
27 | public static void w(String tag, String msg) {
28 | if (canPrintLog) {
29 | Log.w(tag, msg);
30 | }
31 | }
32 |
33 | public static void e(String tag, String msg) {
34 | if (canPrintLog) {
35 | Log.e(tag, msg);
36 | }
37 | }
38 |
39 | public static void printStackTrace(Throwable e) {
40 | if (canPrintLog && e != null) {
41 | e.printStackTrace();
42 | }
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/utils/ScreenUtils.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.res.Configuration;
6 | import android.content.res.Resources;
7 | import android.os.Build;
8 | import android.util.DisplayMetrics;
9 | import android.view.Display;
10 | import android.view.View;
11 | import android.view.WindowManager;
12 |
13 | import java.lang.reflect.Method;
14 |
15 | import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
16 | import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE;
17 |
18 | public class ScreenUtils {
19 |
20 | public static boolean isPortrait(Context context) {
21 | return context.getResources().getConfiguration().orientation
22 | == Configuration.ORIENTATION_PORTRAIT;
23 | }
24 |
25 | /**
26 | * 获取手机屏幕分辨率
27 | *
28 | * @return 手机屏幕分辨率
29 | */
30 | public static int[] getScreenPixels(Context context) {
31 | if (context == null) {
32 | return new int[]{0, 0};
33 | }
34 |
35 | int widthPixels;
36 | int heightPixels;
37 |
38 | WindowManager wm = (WindowManager) (context.getSystemService(Context.WINDOW_SERVICE));
39 | Display display = wm.getDefaultDisplay();
40 | DisplayMetrics dm = new DisplayMetrics();
41 | display.getMetrics(dm);
42 | widthPixels = dm.widthPixels;
43 | heightPixels = dm.heightPixels;
44 |
45 | if (Build.VERSION.SDK_INT >= 17) {
46 | try {
47 | Method method = display.getClass().getMethod("getRealMetrics", DisplayMetrics.class);
48 | method.invoke(display, dm);
49 | } catch (Exception e) {
50 | e.printStackTrace();
51 | }
52 | heightPixels = dm.heightPixels;
53 | } else {
54 | try {
55 | Method method = display.getClass().getMethod("getRawHeight");
56 | heightPixels = (Integer) method.invoke(display);
57 | } catch (Exception e) {
58 | e.printStackTrace();
59 | }
60 | }
61 |
62 | return new int[]{widthPixels, heightPixels};
63 | }
64 |
65 | public static DisplayMetrics getDisplayMetrics(Context context) {
66 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
67 | DisplayMetrics dm = new DisplayMetrics();
68 | wm.getDefaultDisplay().getMetrics(dm);
69 | return dm;
70 | }
71 |
72 | /**
73 | * 获取设计像素对应的dip值
74 | *
75 | * @param designPx 以 1080p,320dpi,density2.0 为基础 UI 设计的像素大小
76 | * @return
77 | */
78 | public static float getDipByDesignPx(int designPx) {
79 | // float scale = 3.0f;//1080p,480dpi,density3.0
80 | float scale = 2.0f;//1080p,320dpi,density2.0
81 | return designPx / scale;
82 | }
83 |
84 | public static int dip2px(Context context, float dip) {
85 | float scale = context.getResources().getDisplayMetrics().density;
86 | return (int) (dip * scale + 0.5f);
87 | }
88 |
89 | /**
90 | * 获取状态栏高度
91 | *
92 | * @param context
93 | * @return
94 | */
95 | public static int getStatusBarHeight(Context context) {
96 | int result = 0;
97 | if (context == null) return result;
98 |
99 | Resources resources = context.getResources();
100 | if (resources == null) return result;
101 |
102 | int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
103 | if (resourceId > 0) {
104 | result = resources.getDimensionPixelSize(resourceId);
105 | }
106 | return result;
107 | }
108 |
109 | public static void hideNavigationBar(Activity activity) {
110 | View decorView = activity.getWindow().getDecorView();
111 | int option = SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE;
112 | decorView.setSystemUiVisibility(option);
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/utils/ShaderUtil.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.utils;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES20;
5 | import android.util.Log;
6 |
7 | import java.io.BufferedReader;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.io.InputStreamReader;
11 |
12 | public class ShaderUtil {
13 | private static final String TAG = "ShaderUtil";
14 |
15 | public static String readRawText(Context context, int rawId) {
16 | BufferedReader reader = null;
17 | StringBuffer sb = new StringBuffer();
18 | try {
19 | InputStream inputStream = context.getResources().openRawResource(rawId);
20 | reader = new BufferedReader(new InputStreamReader(inputStream));
21 | String line;
22 | while ((line = reader.readLine()) != null) {
23 | sb.append(line).append("\n");
24 | }
25 | reader.close();
26 | } catch (Exception e) {
27 | e.printStackTrace();
28 | } finally {
29 | if (reader != null) {
30 | try {
31 | reader.close();
32 | } catch (IOException e) {
33 | e.printStackTrace();
34 | }
35 | }
36 | }
37 | return sb.toString();
38 | }
39 |
40 | public static int[] createAndLinkProgram(String vertexSource, String fragmentSource) {
41 | int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
42 | if (vertexShader == 0) {
43 | return new int[]{0, 0, 0};
44 | }
45 | int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
46 | if (fragmentShader == 0) {
47 | return new int[]{0, 0, 0};
48 | }
49 | int program = GLES20.glCreateProgram();
50 | if (program != 0) {
51 | GLES20.glAttachShader(program, vertexShader);
52 | GLES20.glAttachShader(program, fragmentShader);
53 | GLES20.glLinkProgram(program);
54 | LogUtils.d(TAG, "Shader Program " + program + " info:\n" + GLES20.glGetProgramInfoLog(program));
55 |
56 | int[] linsStatus = new int[1];
57 | GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linsStatus, 0);
58 | if (linsStatus[0] != GLES20.GL_TRUE) {
59 | Log.d(TAG, "link program error");
60 | GLES20.glDeleteProgram(program);
61 | program = 0;
62 | }
63 | }
64 | return new int[]{vertexShader, fragmentShader, program};
65 | }
66 |
67 | private static int loadShader(int shaderType, String source) {
68 | int shader = GLES20.glCreateShader(shaderType);
69 | if (shader != 0) {
70 | GLES20.glShaderSource(shader, source);
71 | GLES20.glCompileShader(shader);
72 | LogUtils.d(TAG, "Shader " + shader + " info:\n" + GLES20.glGetShaderInfoLog(shader));
73 | int[] compile = new int[1];
74 | GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compile, 0);
75 | if (compile[0] != GLES20.GL_TRUE) {
76 | LogUtils.e(TAG, "shader compile failed, type is " + shaderType);
77 | GLES20.glDeleteShader(shader);
78 | shader = 0;
79 | }
80 | } else {
81 | LogUtils.e(TAG, "shader create failed, type is " + shaderType);
82 | }
83 | return shader;
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/utils/TextUtils.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.utils;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 |
8 | public class TextUtils {
9 |
10 | public static Bitmap drawText(String text, float textSizePixels, int paddingLeft, int paddingRight,
11 | int paddingTop, int paddingBottom, int textColor, int bgColor) {
12 | Paint paint = new Paint();
13 | paint.setColor(textColor);
14 | paint.setTextSize(textSizePixels);
15 | paint.setStyle(Paint.Style.FILL);
16 | paint.setAntiAlias(true);
17 |
18 | float fontWidth = paint.measureText(text, 0, text.length());
19 | float fontTop = paint.getFontMetrics().top;
20 | float fontBottom = paint.getFontMetrics().bottom;
21 |
22 | int bmpWidth = (int) (fontWidth + paddingLeft + paddingRight);
23 | int bmpHeight = (int) ((fontBottom - fontTop) + paddingTop + paddingBottom);
24 | Bitmap bitmap = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
25 | bitmap.setHasAlpha(true);
26 | bitmap.eraseColor(Color.argb(0,0,0,0));
27 |
28 | Canvas canvas = new Canvas(bitmap);
29 | canvas.drawColor(bgColor);
30 |
31 | // 绘制文字
32 | // ----------top
33 | // ----------ascent
34 | // xxxxxxxxxx
35 | // ----------baseline
36 | // xxxxxxxxxx
37 | // ----------descent
38 | // ----------bottom
39 | // 因为 fontTop = fontTopY - baseline,绘制矩形的左上角顶点为(0, 0)
40 | // 所以 baseline = fontTopY - fontTop 也就是 baseline = 0 - fontTop
41 | canvas.drawText(text, paddingLeft, 0 - fontTop + paddingTop, paint);
42 |
43 | return bitmap;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/java/com/wtz/libvideomaker/utils/TextureUtils.java:
--------------------------------------------------------------------------------
1 | package com.wtz.libvideomaker.utils;
2 |
3 | import android.opengl.GLES11Ext;
4 | import android.opengl.GLES20;
5 |
6 | public class TextureUtils {
7 |
8 | public static int[] genTexture2D(int num) {
9 | return genTexture(GLES20.GL_TEXTURE_2D, num);
10 | }
11 |
12 | public static int[] genTextureOES(int num) {
13 | return genTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, num);
14 | }
15 |
16 | private static int[] genTexture(int type, int num) {
17 | // 创建 Texture 对象并初始化配置
18 | int[] ids = new int[num];
19 | GLES20.glGenTextures(num, ids, 0);
20 |
21 | for (int i = 0; i < num; i++) {
22 | if (ids[i] == 0) {
23 | throw new RuntimeException("genTexture texture " + i + " failed!");
24 | }
25 | GLES20.glBindTexture(type, ids[i]);
26 | GLES20.glTexParameteri(type, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
27 | GLES20.glTexParameteri(type, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
28 | GLES20.glTexParameteri(type, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
29 | GLES20.glTexParameteri(type, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
30 | }
31 |
32 | // 解绑 Texture
33 | GLES20.glBindTexture(type, 0);
34 | return ids;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/res/raw/we_vidmk_fragment_camera_oes_shader.glsl:
--------------------------------------------------------------------------------
1 | #extension GL_OES_EGL_image_external : require
2 | precision mediump float;
3 | varying vec2 v_TexCoordinate; // 从顶点着色器插入的纹理坐标
4 | uniform samplerExternalOES u_Texture; // 用来传入 Camera 预览内容的句柄
5 | void main(){
6 | // OpenGL 会使用 gl_FragColor 的值作为当前片段的最终颜色
7 | gl_FragColor = texture2D(u_Texture, v_TexCoordinate);
8 | }
9 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/res/raw/we_vidmk_fragment_gray_texture2d_shader.glsl:
--------------------------------------------------------------------------------
1 | // 精度 precision 可以选择 lowp、mediump和 highp
2 | // 顶点着色器由于位置的精确度,一般默认为高精度,所以不需要再去怎么修改;
3 | // 而片段着色器则采用中等精度,主要是考虑到性能和兼容性。
4 | precision mediump float;
5 | varying vec2 v_TexCoordinate;// 从顶点着色器插入的纹理坐标
6 | uniform sampler2D u_Texture;// 用来传入纹理内容的句柄
7 | void main(){
8 | // 使用 texture2D 得到在当前纹理坐标的纹理值
9 | lowp vec4 textureColor = texture2D(u_Texture, v_TexCoordinate);
10 | // 计算灰度值
11 | float gray = textureColor.r * 0.2125 + textureColor.g * 0.7154 + textureColor.b * 0.0721;
12 |
13 | // OpenGL 会使用 gl_FragColor 的值作为当前片段的最终颜色
14 | gl_FragColor = vec4(gray, gray, gray, textureColor.w);
15 | }
16 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/res/raw/we_vidmk_fragment_luminance_texture2d_shader.glsl:
--------------------------------------------------------------------------------
1 | // 精度 precision 可以选择 lowp、mediump和 highp
2 | // 顶点着色器由于位置的精确度,一般默认为高精度,所以不需要再去怎么修改;
3 | // 而片段着色器则采用中等精度,主要是考虑到性能和兼容性。
4 | precision mediump float;
5 | varying vec2 v_TexCoordinate; // 从顶点着色器插入的纹理坐标
6 | uniform sampler2D u_Texture; // 用来传入纹理内容的句柄
7 | void main(){
8 | // 使用 texture2D 得到在当前纹理坐标的纹理值
9 | lowp vec4 textureColor = texture2D(u_Texture, v_TexCoordinate);
10 |
11 | // OpenGL 会使用 gl_FragColor 的值作为当前片段的最终颜色
12 | // 把 RGB 三个分量都降低 0.5
13 | gl_FragColor = vec4((textureColor.rgb + vec3(-0.5)), textureColor.w);
14 | }
15 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/res/raw/we_vidmk_fragment_normal_texture2d_shader.glsl:
--------------------------------------------------------------------------------
1 | // 精度 precision 可以选择 lowp、mediump和 highp
2 | // 顶点着色器由于位置的精确度,一般默认为高精度,所以不需要再去怎么修改;
3 | // 而片段着色器则采用中等精度,主要是考虑到性能和兼容性。
4 | precision mediump float;
5 | varying vec2 v_TexCoordinate; // 从顶点着色器插入的纹理坐标
6 | uniform sampler2D u_Texture; // 用来传入纹理内容的句柄
7 | void main(){
8 | // OpenGL 会使用 gl_FragColor 的值作为当前片段的最终颜色
9 | gl_FragColor = texture2D(u_Texture, v_TexCoordinate);// 使用 texture2D 得到在当前纹理坐标的纹理值
10 | }
11 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/res/raw/we_vidmk_fragment_reverse_texture2d_shader.glsl:
--------------------------------------------------------------------------------
1 | // 精度 precision 可以选择 lowp、mediump和 highp
2 | // 顶点着色器由于位置的精确度,一般默认为高精度,所以不需要再去怎么修改;
3 | // 而片段着色器则采用中等精度,主要是考虑到性能和兼容性。
4 | precision mediump float;
5 | varying vec2 v_TexCoordinate; // 从顶点着色器插入的纹理坐标
6 | uniform sampler2D u_Texture; // 用来传入纹理内容的句柄
7 | void main(){
8 | // OpenGL 会使用 gl_FragColor 的值作为当前片段的最终颜色
9 | // 使用 texture2D 得到在当前纹理坐标的纹理值
10 | // 再用 1.0 减去当前颜色值就得到反色
11 | gl_FragColor = vec4(vec3(1.0 - texture2D(u_Texture, v_TexCoordinate)), 1.0);
12 | }
13 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/res/raw/we_vidmk_vertex_offscreen_shader.glsl:
--------------------------------------------------------------------------------
1 | attribute vec4 a_Position;// 我们将要传入的每个顶点的位置信息
2 | attribute vec2 a_TexCoordinate;// 我们将要传入的每个顶点的纹理坐标信息,vec2是一个包含两个元素的数组
3 | varying vec2 v_TexCoordinate;// 用来传入到片段着色器
4 | uniform mat4 u_PositionMatrix;// 位置矩阵
5 | void main(){
6 | // 传入纹理坐标到片段着色器
7 | v_TexCoordinate = a_TexCoordinate;
8 | // OpenGL 会把 gl_Position 中存储的值作为当前顶点的最终位置
9 | gl_Position = a_Position * u_PositionMatrix;
10 | }
11 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/res/raw/we_vidmk_vertex_onscreen_shader.glsl:
--------------------------------------------------------------------------------
1 | attribute vec4 a_Position;// 我们将要传入的每个顶点的位置信息
2 | attribute vec2 a_TexCoordinate;// 我们将要传入的每个顶点的纹理坐标信息,vec2是一个包含两个元素的数组
3 | varying vec2 v_TexCoordinate;// 用来传入到片段着色器
4 | void main(){
5 | // 传入纹理坐标到片段着色器
6 | v_TexCoordinate = a_TexCoordinate;
7 | // OpenGL 会把 gl_Position 中存储的值作为当前顶点的最终位置
8 | gl_Position = a_Position;
9 | }
10 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 2dp
4 |
5 |
--------------------------------------------------------------------------------
/libvideomaker/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LibVideoMaker
3 |
4 |
--------------------------------------------------------------------------------
/screenMatch.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wtz2017/VideoMaker/49fb888984122f757b11b8a182addff141926b01/screenMatch.properties
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':libvideomaker', ':libnaudiorecord', ':libmp3util', ':libpushflow'
2 | rootProject.name='VideoMaker'
3 |
--------------------------------------------------------------------------------