├── Douyin ├── .gitignore ├── .idea │ ├── caches │ │ └── build_file_checksums.ser │ ├── codeStyles │ │ └── Project.xml │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ └── runConfigurations.xml ├── app │ ├── .gitignore │ ├── build.gradle │ ├── libs │ │ └── armeabi │ │ │ ├── libavcodec.so │ │ │ ├── libavdevice.so │ │ │ ├── libavfilter.so │ │ │ ├── libavformat.so │ │ │ ├── libavutil.so │ │ │ ├── libffmpeg.so │ │ │ ├── libpostproc.so │ │ │ ├── libsoundtouch.so │ │ │ ├── libswresample.so │ │ │ └── libswscale.so │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── xue │ │ │ └── douyin │ │ │ └── douyin │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ ├── Jni │ │ │ │ └── FFmpegCmd.java │ │ │ └── com │ │ │ │ ├── netease │ │ │ │ └── soundtouch │ │ │ │ │ └── SoundTouch.java │ │ │ │ └── xue │ │ │ │ └── douyin │ │ │ │ ├── application │ │ │ │ ├── AppProfile.java │ │ │ │ └── DYApplication.java │ │ │ │ ├── base │ │ │ │ ├── activity │ │ │ │ │ ├── BaseActionBarActivity.java │ │ │ │ │ ├── BaseActivity.java │ │ │ │ │ └── BaseBlankActivity.java │ │ │ │ └── presenter │ │ │ │ │ ├── BaseActivityPresenter.java │ │ │ │ │ └── BasePresenter.java │ │ │ │ ├── common │ │ │ │ ├── C.java │ │ │ │ ├── camera │ │ │ │ │ ├── CameraCompat.java │ │ │ │ │ ├── CameraCompatV19.java │ │ │ │ │ ├── CameraCompatV21.java │ │ │ │ │ └── CameraUtil.java │ │ │ │ ├── player │ │ │ │ │ └── VideoPlayer.java │ │ │ │ ├── preview │ │ │ │ │ ├── GLUtils.java │ │ │ │ │ ├── ParamHolder.java │ │ │ │ │ ├── RenderBuffer.java │ │ │ │ │ ├── RendererInfo.java │ │ │ │ │ ├── TextureProgram.java │ │ │ │ │ └── filters │ │ │ │ │ │ ├── GlitchFilter.java │ │ │ │ │ │ ├── ImageFilter.java │ │ │ │ │ │ ├── ScaleFilter.java │ │ │ │ │ │ ├── ShakeEffectFilter.java │ │ │ │ │ │ ├── ShineWhiteFilter.java │ │ │ │ │ │ ├── SoulOutFilter.java │ │ │ │ │ │ └── VertigoFilter.java │ │ │ │ ├── recorder │ │ │ │ │ ├── AudioRecorder.java │ │ │ │ │ ├── ClipInfo.java │ │ │ │ │ ├── MediaConfig.java │ │ │ │ │ ├── MediaRecorder.java │ │ │ │ │ ├── OnRecordFinishListener.java │ │ │ │ │ ├── OnRecordProgressListener.java │ │ │ │ │ ├── Recorder.java │ │ │ │ │ ├── VideoRecorder.java │ │ │ │ │ ├── audio │ │ │ │ │ │ └── AudioConfig.java │ │ │ │ │ └── video │ │ │ │ │ │ ├── BaseGLSurface.java │ │ │ │ │ │ ├── GLCore.java │ │ │ │ │ │ ├── OffScreenWrapper.java │ │ │ │ │ │ ├── VideoConfig.java │ │ │ │ │ │ ├── VideoFrameData.java │ │ │ │ │ │ └── WindowSurface.java │ │ │ │ ├── util │ │ │ │ │ ├── FileUtils.java │ │ │ │ │ ├── LogUtil.java │ │ │ │ │ ├── ScreenUtil.java │ │ │ │ │ ├── StorageUtil.java │ │ │ │ │ ├── ThreadUtil.java │ │ │ │ │ └── VideoUtil.java │ │ │ │ └── view │ │ │ │ │ ├── ProgressBar.java │ │ │ │ │ ├── ProgressView.java │ │ │ │ │ ├── RecordButton.java │ │ │ │ │ ├── RoundImageView.java │ │ │ │ │ ├── record │ │ │ │ │ ├── OnFrameAvailableListener.java │ │ │ │ │ ├── OnSurfaceCreatedCallback.java │ │ │ │ │ ├── RecordRenderer.java │ │ │ │ │ └── RecordSurfaceView.java │ │ │ │ │ └── roundrect │ │ │ │ │ └── RoundRectLayout.java │ │ │ │ ├── ffmpeg │ │ │ │ ├── VideoCmdCallback.java │ │ │ │ ├── VideoCommand.java │ │ │ │ └── VideoQueue.java │ │ │ │ ├── module │ │ │ │ ├── effect │ │ │ │ │ ├── activity │ │ │ │ │ │ └── AfterEffectActivity.java │ │ │ │ │ └── presenter │ │ │ │ │ │ ├── AfterEffectPresenter.java │ │ │ │ │ │ └── PlayRenderer.java │ │ │ │ └── record │ │ │ │ │ ├── activity │ │ │ │ │ └── RecordActivity.java │ │ │ │ │ └── presenter │ │ │ │ │ └── RecordPresenter.java │ │ │ │ ├── permission │ │ │ │ ├── PermissionFragment.java │ │ │ │ ├── PermissionLifeCycleImpl.java │ │ │ │ ├── PermissionManager.java │ │ │ │ └── SimplePermissionCallback.java │ │ │ │ └── utils │ │ │ │ └── ResourcesUtil.java │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ ├── bg_record_next_button.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── selector_beautify.xml │ │ │ ├── selector_camera.xml │ │ │ ├── selector_flashlight.xml │ │ │ ├── selector_speed_button.xml │ │ │ ├── selector_speed_text.xml │ │ │ ├── shape_play_progress.xml │ │ │ ├── shape_play_progress_thumb.xml │ │ │ └── shape_speed_control.xml │ │ │ ├── layout │ │ │ ├── activity_after_effect.xml │ │ │ ├── activity_blank.xml │ │ │ ├── activity_main.xml │ │ │ ├── activity_record.xml │ │ │ ├── activity_with_actionbar.xml │ │ │ └── test.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 │ │ │ ├── filter_age.jpg │ │ │ ├── filter_extraordinary.jpg │ │ │ ├── filter_japan.jpg │ │ │ ├── filter_normal.jpg │ │ │ ├── filter_pure.jpg │ │ │ ├── ic_effect.png │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── ic_play.png │ │ │ └── ic_white_back.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_beautify_off.png │ │ │ ├── ic_beautify_on.png │ │ │ ├── ic_camera_back.png │ │ │ ├── ic_camera_front.png │ │ │ ├── ic_countdown.png │ │ │ ├── ic_cut_music.png │ │ │ ├── ic_delete.png │ │ │ ├── ic_flash_off.png │ │ │ ├── ic_flash_on.png │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── raw │ │ │ ├── fragment_3d.glsl │ │ │ ├── fragment_common.glsl │ │ │ ├── fragment_current_frame.glsl │ │ │ ├── fragment_sobel_edge_detect.glsl │ │ │ ├── glitch.glsl │ │ │ ├── lookup_glitch.png │ │ │ ├── lookup_vertigo.png │ │ │ ├── test.glsl │ │ │ ├── vertex_3d.glsl │ │ │ ├── vertex_common.glsl │ │ │ ├── vertex_sobel_edge_detect.glsl │ │ │ └── vertigo_fragment.glsl │ │ │ └── values │ │ │ ├── attr.xml │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── xue │ │ └── douyin │ │ └── douyin │ │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── README.md └── soundtouch ├── Android.mk ├── Application.mk ├── SoundStretch ├── Makefile.am ├── RunParameters.cpp ├── RunParameters.h ├── WavFile.cpp ├── WavFile.h ├── main.cpp ├── soundstretch.dsp ├── soundstretch.dsw ├── soundstretch.sln └── soundstretch.vcproj ├── SoundTouch ├── AAFilter.cpp ├── AAFilter.h ├── BPMDetect.cpp ├── FIFOSampleBuffer.cpp ├── FIRFilter.cpp ├── FIRFilter.h ├── InterpolateCubic.cpp ├── InterpolateCubic.h ├── InterpolateLinear.cpp ├── InterpolateLinear.h ├── InterpolateShannon.cpp ├── InterpolateShannon.h ├── Makefile.am ├── PeakFinder.cpp ├── PeakFinder.h ├── RateTransposer.cpp ├── RateTransposer.h ├── SoundTouch.cpp ├── SoundTouch.dsp ├── SoundTouch.dsw ├── SoundTouch.sln ├── SoundTouch.vcproj ├── TDStretch.cpp ├── TDStretch.h ├── cpu_detect.h ├── cpu_detect_x86.cpp ├── mmx_optimized.cpp └── sse_optimized.cpp ├── com_netease_soundtouch_SoundTouch.cpp ├── com_netease_soundtouch_SoundTouch.h └── include ├── BPMDetect.h ├── FIFOSampleBuffer.h ├── FIFOSamplePipe.h ├── Makefile.am ├── STTypes.h ├── SoundTouch.h └── soundtouch_config.h.in /Douyin/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /Douyin/.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /Douyin/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Douyin/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /Douyin/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /Douyin/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Douyin/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /Douyin/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Douyin/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | defaultConfig { 6 | applicationId "com.xue.douyin.douyin" 7 | minSdkVersion 19 8 | targetSdkVersion 26 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | sourceSets { 20 | main { 21 | jniLibs.srcDirs = ['libs'] 22 | } 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(include: ['*.jar'], dir: 'libs') 28 | implementation 'com.android.support:appcompat-v7:26.1.0' 29 | implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta4' 30 | compile 'com.googlecode.mp4parser:isoparser:1.1.21' 31 | testImplementation 'junit:junit:4.12' 32 | compile fileTree(include: ['*.jar'], dir: 'libs') 33 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 34 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 35 | } 36 | -------------------------------------------------------------------------------- /Douyin/app/libs/armeabi/libavcodec.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/libs/armeabi/libavcodec.so -------------------------------------------------------------------------------- /Douyin/app/libs/armeabi/libavdevice.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/libs/armeabi/libavdevice.so -------------------------------------------------------------------------------- /Douyin/app/libs/armeabi/libavfilter.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/libs/armeabi/libavfilter.so -------------------------------------------------------------------------------- /Douyin/app/libs/armeabi/libavformat.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/libs/armeabi/libavformat.so -------------------------------------------------------------------------------- /Douyin/app/libs/armeabi/libavutil.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/libs/armeabi/libavutil.so -------------------------------------------------------------------------------- /Douyin/app/libs/armeabi/libffmpeg.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/libs/armeabi/libffmpeg.so -------------------------------------------------------------------------------- /Douyin/app/libs/armeabi/libpostproc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/libs/armeabi/libpostproc.so -------------------------------------------------------------------------------- /Douyin/app/libs/armeabi/libsoundtouch.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/libs/armeabi/libsoundtouch.so -------------------------------------------------------------------------------- /Douyin/app/libs/armeabi/libswresample.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/libs/armeabi/libswresample.so -------------------------------------------------------------------------------- /Douyin/app/libs/armeabi/libswscale.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/libs/armeabi/libswscale.so -------------------------------------------------------------------------------- /Douyin/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 | -------------------------------------------------------------------------------- /Douyin/app/src/androidTest/java/com/xue/douyin/douyin/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.douyin; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.xue.douyin.douyin", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Douyin/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/Jni/FFmpegCmd.java: -------------------------------------------------------------------------------- 1 | package Jni; 2 | 3 | import android.support.annotation.Keep; 4 | 5 | import com.xue.douyin.ffmpeg.VideoCmdCallback; 6 | import com.xue.douyin.common.util.LogUtil; 7 | 8 | @Keep 9 | public class FFmpegCmd { 10 | 11 | public static Object sLock = new Object(); 12 | 13 | /** 14 | * 加载所有相关链接库 15 | */ 16 | static { 17 | System.loadLibrary("avutil"); 18 | System.loadLibrary("avcodec"); 19 | System.loadLibrary("swresample"); 20 | System.loadLibrary("avformat"); 21 | System.loadLibrary("swscale"); 22 | System.loadLibrary("avfilter"); 23 | System.loadLibrary("avdevice"); 24 | System.loadLibrary("ffmpeg"); 25 | } 26 | 27 | 28 | /** 29 | * 调用底层执行 30 | * 31 | * @param argc 32 | * @param argv 33 | * @return 34 | */ 35 | @Keep 36 | public static native int exec(int argc, String[] argv); 37 | 38 | @Keep 39 | public static native void exit(); 40 | 41 | @Keep 42 | public static void onExecuted(int ret) { 43 | synchronized (sLock) { 44 | sLock.notify(); 45 | } 46 | } 47 | 48 | @Keep 49 | public static void onProgress(float progress) { 50 | LogUtil.d("progress is " + progress); 51 | } 52 | 53 | 54 | /** 55 | * 执行ffmoeg命令 56 | * 57 | * @param cmds 58 | */ 59 | @Keep 60 | public static void exec(String[] cmds, VideoCmdCallback callback) { 61 | long t1 = System.currentTimeMillis(); 62 | int ret = exec(cmds.length, cmds); 63 | synchronized (sLock) { 64 | try { 65 | sLock.wait(); 66 | } catch (InterruptedException e) { 67 | e.printStackTrace(); 68 | } 69 | } 70 | if (callback != null) { 71 | callback.onCommandFinish(ret == 0); 72 | } 73 | long t2 = System.currentTimeMillis(); 74 | LogUtil.d("耗时 " + (t2 - t1) + "ms"); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/netease/soundtouch/SoundTouch.java: -------------------------------------------------------------------------------- 1 | package com.netease.soundtouch; 2 | 3 | /** 4 | * Created by 薛贤俊 on 2018/4/8. 5 | */ 6 | 7 | public class SoundTouch { 8 | private native final void setTempo(long handle, float tempo); 9 | 10 | private native final void setPitchSemiTones(long handle, float pitch); 11 | 12 | private native final void putBytes(long handle, byte[] input, int offset, int length); 13 | 14 | private native final int getBytes(long handle, byte[] output, int length); 15 | 16 | private native final static long newInstance(); 17 | 18 | private native final void deleteInstance(long handle); 19 | 20 | private native final void flush(long handle); 21 | 22 | private long handle = 0; 23 | 24 | public SoundTouch() { 25 | handle = newInstance(); 26 | } 27 | 28 | public void putBytes(byte[] input) { 29 | this.putBytes(handle, input, 0, input.length); 30 | } 31 | 32 | public int getBytes(byte[] output) { 33 | return this.getBytes(handle, output, output.length); 34 | } 35 | 36 | 37 | public void close() { 38 | deleteInstance(handle); 39 | handle = 0; 40 | } 41 | 42 | public void flush() { 43 | this.flush(handle); 44 | } 45 | 46 | public void setTempo(float tempo) { 47 | setTempo(handle, tempo); 48 | } 49 | 50 | 51 | public void setPitchSemiTones(float pitch) { 52 | setPitchSemiTones(handle, pitch); 53 | } 54 | 55 | static { 56 | System.loadLibrary("soundtouch"); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/application/AppProfile.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.application; 2 | 3 | import android.app.Application; 4 | 5 | /** 6 | * Created by 薛贤俊 on 2018/2/25. 7 | */ 8 | 9 | public class AppProfile { 10 | public static Application sContext; 11 | 12 | public static void setContext(Application context) { 13 | sContext = context; 14 | } 15 | 16 | public static Application getContext() { 17 | return sContext; 18 | } 19 | 20 | public static void registerActivityLifeCycle(Application.ActivityLifecycleCallbacks cb) { 21 | sContext.registerActivityLifecycleCallbacks(cb); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/application/DYApplication.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.application; 2 | 3 | import android.app.Application; 4 | 5 | import com.xue.douyin.permission.PermissionManager; 6 | 7 | /** 8 | * Created by 薛贤俊 on 2018/2/25. 9 | */ 10 | 11 | public class DYApplication extends Application { 12 | @Override 13 | public void onCreate() { 14 | super.onCreate(); 15 | AppProfile.setContext(this); 16 | PermissionManager.instance(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/base/activity/BaseActionBarActivity.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.base.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | 8 | import com.xue.douyin.R; 9 | import com.xue.douyin.base.presenter.BaseActivityPresenter; 10 | 11 | /** 12 | * Created by 薛贤俊 on 2018/3/1. 13 | */ 14 | 15 | public abstract class BaseActionBarActivity extends BaseActivity { 16 | 17 | private ViewGroup mContentView; 18 | 19 | @Override 20 | protected void onCreate(@Nullable Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | super.setContentView(R.layout.activity_with_actionbar); 23 | mContentView = findViewById(R.id.ll_content); 24 | } 25 | 26 | @Override 27 | public void setContentView(int layoutResID) { 28 | if (mContentView == null) { 29 | throw new RuntimeException("should call super.onCreate first"); 30 | } 31 | mContentView.removeAllViews(); 32 | View view = getLayoutInflater().inflate(layoutResID, null); 33 | mContentView.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 34 | ViewGroup.LayoutParams.MATCH_PARENT)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/base/activity/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.base.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | 8 | import com.xue.douyin.base.presenter.BaseActivityPresenter; 9 | 10 | /** 11 | * Created by 薛贤俊 on 2018/3/1. 12 | */ 13 | 14 | public abstract class BaseActivity extends AppCompatActivity { 15 | 16 | protected T mPresenter; 17 | 18 | public T getPresenter() { 19 | return mPresenter; 20 | } 21 | 22 | protected abstract void initPresenter(); 23 | 24 | @Override 25 | protected void onCreate(@Nullable Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | initPresenter(); 28 | if(mPresenter==null) { 29 | return; 30 | } 31 | mPresenter.onCreate(); 32 | } 33 | 34 | @Override 35 | protected void onStart() { 36 | super.onStart(); 37 | if(mPresenter==null) { 38 | return; 39 | } 40 | mPresenter.onStart(); 41 | } 42 | 43 | @Override 44 | protected void onResume() { 45 | super.onResume(); 46 | if(mPresenter==null) { 47 | return; 48 | } 49 | mPresenter.onResume(); 50 | } 51 | 52 | @Override 53 | protected void onPause() { 54 | super.onPause(); 55 | if(mPresenter==null) { 56 | return; 57 | } 58 | mPresenter.onPause(); 59 | } 60 | 61 | @Override 62 | protected void onStop() { 63 | super.onStop(); 64 | if(mPresenter==null) { 65 | return; 66 | } 67 | mPresenter.onStop(); 68 | } 69 | 70 | @Override 71 | protected void onDestroy() { 72 | super.onDestroy(); 73 | if(mPresenter==null) { 74 | return; 75 | } 76 | mPresenter.onDestroy(); 77 | } 78 | 79 | 80 | protected void hideSystemNavigationBar() { 81 | View decorView = getWindow().getDecorView(); 82 | int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 83 | | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN; 84 | decorView.setSystemUiVisibility(uiOptions); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/base/activity/BaseBlankActivity.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.base.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.view.ViewGroup; 6 | 7 | import com.xue.douyin.R; 8 | import com.xue.douyin.base.presenter.BaseActivityPresenter; 9 | 10 | /** 11 | * Created by 薛贤俊 on 2018/3/1. 12 | */ 13 | 14 | public abstract class BaseBlankActivity extends BaseActivity { 15 | 16 | private ViewGroup mContentView; 17 | 18 | @Override 19 | protected void onCreate(@Nullable Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | super.setContentView(R.layout.activity_blank); 22 | mContentView = findViewById(R.id.fl_content); 23 | } 24 | 25 | @Override 26 | public void setContentView(int layoutResID) { 27 | if (mContentView == null) { 28 | throw new RuntimeException("should call super.onCreate first"); 29 | } 30 | mContentView.removeAllViews(); 31 | getLayoutInflater().inflate(layoutResID, mContentView, true); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/base/presenter/BaseActivityPresenter.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.base.presenter; 2 | 3 | import com.xue.douyin.base.activity.BaseActivity; 4 | 5 | /** 6 | * Created by 薛贤俊 on 2018/3/1. 7 | */ 8 | 9 | public class BaseActivityPresenter extends BasePresenter { 10 | 11 | public BaseActivityPresenter(T target) { 12 | super(target); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/base/presenter/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.base.presenter; 2 | 3 | /** 4 | * Created by 薛贤俊 on 2018/3/1. 5 | */ 6 | 7 | public class BasePresenter { 8 | private T mTarget; 9 | 10 | public BasePresenter(T target) { 11 | this.mTarget = target; 12 | } 13 | 14 | public T getTarget() { 15 | return mTarget; 16 | } 17 | 18 | public void onCreate() { 19 | 20 | } 21 | 22 | public void onStart() { 23 | 24 | } 25 | 26 | public void onResume() { 27 | 28 | } 29 | 30 | public void onPause() { 31 | 32 | } 33 | 34 | public void onStop() { 35 | 36 | } 37 | 38 | public void onDestroy() { 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/C.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common; 2 | 3 | import android.media.AudioFormat; 4 | import android.support.annotation.IntDef; 5 | 6 | import com.xue.douyin.common.util.StorageUtil; 7 | 8 | import java.io.File; 9 | import java.lang.annotation.Retention; 10 | import java.lang.annotation.RetentionPolicy; 11 | 12 | /** 13 | * Created by 薛贤俊 on 2018/4/7. 14 | */ 15 | 16 | public class C { 17 | 18 | private C() { 19 | 20 | } 21 | 22 | public static final int SECOND_IN_US = 1000000; 23 | 24 | public static final int BUFFER_TIME_OUT = 10000; 25 | 26 | public static final class AudioParams { 27 | public static final int SAMPLE_PER_FRAME = 1024; 28 | public static final int CHANNEL = AudioFormat.CHANNEL_IN_MONO; 29 | 30 | public static final int CHANNEL_COUNT = 1; 31 | 32 | public static final int BITS_PER_SAMPLE = AudioFormat.ENCODING_PCM_16BIT; 33 | 34 | public static final int BIT_RATE = 64000; 35 | 36 | 37 | public static final int SAMPLE_RATE = 44100; 38 | 39 | public static final String MIME_TYPE = "audio/mp4a-latm"; 40 | } 41 | 42 | 43 | public static final class VideoParams { 44 | 45 | public static final String MIME_TYPE = "video/avc"; 46 | 47 | public static final int SAMPLE_RATE = 30; 48 | 49 | public static final int I_FRAME_INTERVAL = 0; 50 | /** 51 | * 16*1000 bps:可视电话质量 52 | * 128-384 * 1000 bps:视频会议系统质量 53 | * 1.25 * 1000000 bps:VCD质量(使用MPEG1压缩) 54 | * 5 * 1000000 bps:DVD质量(使用MPEG2压缩) 55 | * 8-15 * 1000000 bps:高清晰度电视(HDTV) 质量(使用H.264压缩) 56 | * 29.4 * 1000000 bps:HD DVD质量 57 | * 40 * 1000000 bps:蓝光光碟质量(使用MPEG2、H.264或VC-1压缩) 58 | */ 59 | public static final int BIT_RATE = 15 * 1000000; 60 | } 61 | 62 | 63 | public static final String AUDIO_TEMP_FILE_NAME = StorageUtil.getExternalStoragePath() + 64 | File.separator + "tmp" + ".aac"; 65 | 66 | public static final String VIDEO_TEMP_FILE_NAME = StorageUtil.getExternalStoragePath() + 67 | File.separator + "tmp" + ".mp4"; 68 | 69 | public static final int MODE_EXTRA_SLOW = 1; 70 | 71 | public static final int MODE_SLOW = 2; 72 | 73 | public static final int MODE_NORMAL = 3; 74 | 75 | public static final int MODE_FAST = 4; 76 | 77 | public static final int MODE_EXTRA_FAST = 5; 78 | 79 | @IntDef({MODE_EXTRA_SLOW, MODE_SLOW, MODE_NORMAL, MODE_FAST, MODE_EXTRA_FAST}) 80 | @Retention(RetentionPolicy.SOURCE) 81 | public @interface SpeedMode { 82 | 83 | } 84 | public static final int VIDEO = 1; 85 | 86 | public static final int AUDIO = 2; 87 | 88 | @IntDef({VIDEO, AUDIO}) 89 | @Retention(RetentionPolicy.SOURCE) 90 | public @interface DataType { 91 | 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/camera/CameraCompatV19.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.camera; 2 | 3 | import android.Manifest; 4 | import android.content.Context; 5 | import android.graphics.Rect; 6 | import android.hardware.Camera; 7 | import android.os.Handler; 8 | import android.os.Looper; 9 | 10 | import com.xue.douyin.common.util.LogUtil; 11 | import com.xue.douyin.common.util.ScreenUtil; 12 | import com.xue.douyin.permission.PermissionManager; 13 | import com.xue.douyin.permission.SimplePermissionCallback; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | import static android.hardware.Camera.Parameters.FOCUS_MODE_AUTO; 19 | import static android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO; 20 | import static android.hardware.Camera.Parameters.FOCUS_MODE_FIXED; 21 | 22 | /** 23 | * Created by 薛贤俊 on 2018/3/7. 24 | */ 25 | 26 | public class CameraCompatV19 extends CameraCompat { 27 | 28 | private static final String TAG = "CameraCompatV19"; 29 | 30 | private Camera mCamera; 31 | 32 | private boolean mIsLightOn; 33 | 34 | public CameraCompatV19(Context context) { 35 | super(context); 36 | } 37 | 38 | @Override 39 | protected void initCameraInfo() { 40 | int numberOfCameras = Camera.getNumberOfCameras(); 41 | Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); 42 | for (int i = 0; i < numberOfCameras; i++) { 43 | Camera.getCameraInfo(i, cameraInfo); 44 | if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 45 | setFrontCameraId(i); 46 | } else { 47 | setBackCameraId(i); 48 | } 49 | } 50 | } 51 | 52 | @Override 53 | protected void onStartPreview() { 54 | try { 55 | mCamera.setPreviewTexture(mSurfaceTexture); 56 | mCamera.startPreview(); 57 | } catch (Throwable e) { 58 | LogUtil.e(TAG, e); 59 | } 60 | } 61 | 62 | @Override 63 | public void onStopPreview() { 64 | mCamera.stopPreview(); 65 | mCamera.release(); 66 | mCamera = null; 67 | mCameraReady = false; 68 | } 69 | 70 | @Override 71 | protected void onOpenCamera(final int cameraType) { 72 | PermissionManager.instance().checkPermission(new String[]{Manifest.permission.CAMERA}, 73 | new SimplePermissionCallback() { 74 | @Override 75 | public void onPermissionGranted(String permission) { 76 | try { 77 | mCamera = Camera.open(cameraType == FRONT_CAMERA ? getFrontCameraIdV19() : 78 | getBackCameraIdV19()); 79 | initialize(); 80 | } catch (Throwable e) { 81 | LogUtil.e(TAG, e); 82 | } 83 | } 84 | }); 85 | } 86 | 87 | @Override 88 | protected void onTurnLight(boolean on) { 89 | if (mIsLightOn == on) { 90 | return; 91 | } 92 | mIsLightOn = on; 93 | Camera.Parameters parameters = mCamera.getParameters(); 94 | parameters.setFlashMode(on ? Camera.Parameters.FLASH_MODE_TORCH : 95 | Camera.Parameters.FLASH_MODE_OFF); 96 | mCamera.setParameters(parameters); 97 | } 98 | 99 | private void initialize() { 100 | if (mCamera == null) { 101 | return; 102 | } 103 | try { 104 | mCamera.setDisplayOrientation(90); 105 | Camera.Parameters parameters = mCamera.getParameters(); 106 | parameters.setFocusMode(FOCUS_MODE_CONTINUOUS_VIDEO); 107 | List previewSizeList = parameters.getSupportedPreviewSizes(); 108 | setOutputSize(CameraUtil.findBestSize(DESIRED_HEIGHT, previewSizeList)); 109 | parameters.setPreviewSize(getOutputSize().width, getOutputSize().height); 110 | mCamera.setParameters(parameters); 111 | if (mSurfaceTexture != null) { 112 | onStartPreview(); 113 | } 114 | mCameraReady = true; 115 | } catch (Throwable e) { 116 | LogUtil.e(TAG, "", e); 117 | mCameraReady = false; 118 | } 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/camera/CameraUtil.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.camera; 2 | 3 | import android.annotation.TargetApi; 4 | import android.hardware.Camera; 5 | import android.util.Size; 6 | 7 | import java.util.Arrays; 8 | import java.util.Collections; 9 | import java.util.Comparator; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by 薛贤俊 on 2018/3/7. 14 | */ 15 | 16 | public class CameraUtil { 17 | 18 | public static CameraCompat.CameraSize findBestSize(int height, List supportList) { 19 | Collections.sort(supportList, new Comparator() { 20 | @Override 21 | public int compare(Camera.Size o1, Camera.Size o2) { 22 | if (o1.width > o2.width) { 23 | return -1; 24 | } else if (o1.width < o2.width) { 25 | return 1; 26 | } 27 | return 0; 28 | } 29 | }); 30 | 31 | for (Camera.Size size : supportList) { 32 | if (size.height <= height) { 33 | //找到第一个相等或者小于width的尺寸 34 | return new CameraCompat.CameraSize(size); 35 | } 36 | } 37 | //如果不存在比width还小的,那就返回最小的那个 38 | return new CameraCompat.CameraSize(supportList.get(supportList.size() - 1)); 39 | 40 | } 41 | 42 | @TargetApi(21) 43 | public static CameraCompat.CameraSize findBestSize(int height, Size[] sizes) { 44 | Arrays.sort(sizes, new Comparator() { 45 | @Override 46 | public int compare(android.util.Size o1, android.util.Size o2) { 47 | if (o1.getHeight() < o2.getHeight()) { 48 | return -1; 49 | } else if (o1.getHeight() > o2.getHeight()) { 50 | return 1; 51 | } 52 | return 0; 53 | } 54 | }); 55 | for (android.util.Size size : sizes) { 56 | if (size.getHeight() >= height) { 57 | //找到第一个相等或者小于width的尺寸 58 | return new CameraCompat.CameraSize(size); 59 | } 60 | } 61 | //如果不存在比width还小的,那就返回最小的那个 62 | return new CameraCompat.CameraSize(sizes[sizes.length-1]); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/preview/ParamHolder.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.preview; 2 | 3 | /** 4 | * Created by 薛贤俊 on 2018/3/13. 5 | */ 6 | 7 | public abstract class ParamHolder { 8 | 9 | private int mProgramId; 10 | 11 | public ParamHolder(int programId) { 12 | this.mProgramId = programId; 13 | } 14 | 15 | public abstract void enableAttrs(); 16 | 17 | public abstract void disableAttrs(); 18 | } 19 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/preview/RenderBuffer.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.preview; 2 | 3 | import android.opengl.GLES20; 4 | 5 | import java.nio.ByteBuffer; 6 | import java.nio.ByteOrder; 7 | import java.nio.IntBuffer; 8 | 9 | import javax.microedition.khronos.opengles.GL10; 10 | 11 | import static com.xue.douyin.common.preview.filters.ImageFilter.checkGlError; 12 | 13 | /** 14 | * Created by 薛贤俊 on 2018/9/7. 15 | */ 16 | public class RenderBuffer { 17 | private int mTextureId; 18 | 19 | private int mActiveTextureUnit; 20 | 21 | private int mRenderBufferId; 22 | 23 | private int mFrameBufferId; 24 | 25 | private int mWidth, mHeight; 26 | 27 | public RenderBuffer(int activeTextureUnit, int width, int height) { 28 | this.mActiveTextureUnit = activeTextureUnit; 29 | this.mWidth = width; 30 | this.mHeight = height; 31 | int[] buffer = new int[1]; 32 | GLES20.glActiveTexture(activeTextureUnit); 33 | mTextureId = GLUtils.genTexture(); 34 | IntBuffer texBuffer = 35 | ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.nativeOrder()).asIntBuffer(); 36 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, texBuffer); 37 | 38 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); 39 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 40 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); 41 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); 42 | 43 | // Generate frame buffer 44 | GLES20.glGenFramebuffers(1, buffer, 0); 45 | mFrameBufferId = buffer[0]; 46 | // Bind frame buffer 47 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBufferId); 48 | // Generate render buffer 49 | GLES20.glGenRenderbuffers(1, buffer, 0); 50 | mRenderBufferId = buffer[0]; 51 | // Bind render buffer 52 | GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, mRenderBufferId); 53 | GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, width, height); 54 | } 55 | 56 | public void bind() { 57 | GLES20.glViewport(0, 0, mWidth, mHeight); 58 | checkGlError("glViewport"); 59 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBufferId); 60 | checkGlError("glBindFramebuffer"); 61 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, 62 | GLES20.GL_TEXTURE_2D, mTextureId, 0); 63 | checkGlError("glFramebufferTexture2D"); 64 | GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, 65 | GLES20.GL_RENDERBUFFER, mRenderBufferId); 66 | checkGlError("glFramebufferRenderbuffer"); 67 | } 68 | 69 | 70 | public void unbind() { 71 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 72 | } 73 | 74 | public int getTextureId(){ 75 | return mTextureId; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/preview/RendererInfo.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.preview; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.nio.ByteOrder; 5 | import java.nio.FloatBuffer; 6 | 7 | /** 8 | * Created by 薛贤俊 on 2018/3/7. 9 | */ 10 | 11 | public class RendererInfo { 12 | 13 | private static final float FULL_RECTANGLE_COORDS[] = { 14 | -1.0f, -1.0f, // 0 bottom left 15 | 1.0f, -1.0f, // 1 bottom right 16 | -1.0f, 1.0f, // 2 top left 17 | 1.0f, 1.0f, // 3 top right 18 | }; 19 | private static final float FULL_RECTANGLE_TEX_COORDS[] = { 20 | 0.0f, 0.0f, // 0 bottom left 21 | 1.0f, 0.0f, // 1 bottom right 22 | 0.0f, 1.0f, // 2 top left 23 | 1.0f, 1.0f // 3 top right 24 | }; 25 | 26 | private FloatBuffer mVertexBuffer; 27 | 28 | private FloatBuffer mTexBuffer; 29 | 30 | public RendererInfo() { 31 | mVertexBuffer = ByteBuffer.allocateDirect(FULL_RECTANGLE_COORDS.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer(); 32 | mVertexBuffer.position(0); 33 | mVertexBuffer.put(FULL_RECTANGLE_COORDS); 34 | 35 | mTexBuffer = ByteBuffer.allocateDirect(FULL_RECTANGLE_TEX_COORDS.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer(); 36 | mTexBuffer.position(0); 37 | mTexBuffer.put(FULL_RECTANGLE_TEX_COORDS); 38 | } 39 | 40 | public FloatBuffer getVertexBuffer() { 41 | return mVertexBuffer; 42 | } 43 | 44 | public FloatBuffer getTextureBuffer() { 45 | return mTexBuffer; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/preview/TextureProgram.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.preview; 2 | 3 | import static android.opengl.GLES20.glUseProgram; 4 | 5 | /** 6 | * Created by 薛贤俊 on 2018/3/7. 7 | */ 8 | 9 | public class TextureProgram { 10 | 11 | private int mProgramId; 12 | 13 | public TextureProgram(String vertexCode, String fragmentCode) { 14 | mProgramId = GLUtils.buildProgram(vertexCode, fragmentCode); 15 | } 16 | 17 | public void useProgram() { 18 | glUseProgram(mProgramId); 19 | } 20 | 21 | public int getProgramId() { 22 | return mProgramId; 23 | } 24 | 25 | public void enableAttrs() { 26 | 27 | } 28 | 29 | public void disableAttrs() { 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/preview/filters/GlitchFilter.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.preview.filters; 2 | 3 | import static android.opengl.GLES20.glGetUniformLocation; 4 | import static android.opengl.GLES20.glUniform1f; 5 | import static android.opengl.GLES20.glUniform2fv; 6 | 7 | /** 8 | * Created by 薛贤俊 on 2018/8/29. 9 | * 毛刺 10 | */ 11 | public class GlitchFilter extends ImageFilter { 12 | 13 | private static final String FRAGMENT1 = "#extension GL_OES_EGL_image_external : require\n" + 14 | " precision highp float;\n" + 15 | " varying vec2 vTextureCoord;\n" + 16 | " uniform samplerExternalOES uTexture;\n" + 17 | " uniform vec2 uScanLineJitter;//displacement threshold\n" + 18 | " uniform float uColorDrift;\n" + 19 | " uniform float uGlobalTime;\n" + 20 | "float nrand(in float x, in float y)\n" + 21 | "{\n" + 22 | " return fract(sin(dot(vec2(x, y), vec2(12.9898, 78.233))) * 43758.5453);\n" + 23 | "}\n" + 24 | "void main(){\n" + 25 | " float u = vTextureCoord.x;\n" + 26 | " float v = vTextureCoord.y;\n" + 27 | " float jitter = nrand(v,0.0) * 2.0 - 1.0;\n" + 28 | " float drift = uColorDrift;\n" + 29 | " float offsetParam = step(uScanLineJitter.y,abs(jitter));\n" + 30 | " jitter = jitter * offsetParam * uScanLineJitter.x;\n" + 31 | " vec4 color1 = texture2D(uTexture,fract(vec2( u + jitter,v)));\n" + 32 | " vec4 color2 = texture2D(uTexture,fract(vec2(u + jitter + v*drift ,v)));\n" + 33 | " gl_FragColor = vec4(color1.r,color2.g,color1.b,1.0);\n" + 34 | "}"; 35 | 36 | private int mScanLineJitterLocation; 37 | private int mColorDriftLocation; 38 | private int mGlobalTimeLocation; 39 | 40 | private long mStartTime; 41 | 42 | private int mFrames = 0; 43 | 44 | /** 45 | * 动画总共8帧 46 | */ 47 | private int mMaxFrames = 8; 48 | 49 | private float[] mDriftSequence = new float[]{0f, 0.03f, 0.032f, 0.035f, 0.03f, 0.032f, 0.031f, 0.029f, 0.025f}; 50 | 51 | private float[] mJitterSequence = new float[]{0f, 0.03f, 0.01f, 0.02f, 0.05f, 0.055f, 0.03f, 0.02f, 0.025f}; 52 | 53 | private float[] mThreshHoldSequence = new float[]{1.0f, 0.965f, 0.9f, 0.9f, 0.9f, 0.6f, 0.8f, 0.5f, 0.5f}; 54 | 55 | @Override 56 | protected String getFragmentCode() { 57 | return FRAGMENT1; 58 | } 59 | 60 | @Override 61 | protected void initFragmentArguments() { 62 | super.initFragmentArguments(); 63 | mScanLineJitterLocation = glGetUniformLocation(getProgramId(), "uScanLineJitter"); 64 | mColorDriftLocation = glGetUniformLocation(getProgramId(), "uColorDrift"); 65 | mGlobalTimeLocation = glGetUniformLocation(getProgramId(), "uGlobalTime"); 66 | } 67 | 68 | @Override 69 | protected void setFragmentAttrs() { 70 | super.setFragmentAttrs(); 71 | long time = System.currentTimeMillis(); 72 | if (mStartTime == 0) { 73 | mStartTime = time; 74 | } 75 | glUniform1f(mGlobalTimeLocation, mFrames); 76 | mStartTime = time; 77 | 78 | float slDisplacement = mJitterSequence[mFrames]; 79 | float slThreshold = mThreshHoldSequence[mFrames]; 80 | float drift = mDriftSequence[mFrames]; 81 | mFrames++; 82 | if (mFrames > mMaxFrames) { 83 | mFrames = 0; 84 | } 85 | glUniform2fv(mScanLineJitterLocation, 1, new float[]{slDisplacement, slThreshold}, 0); 86 | glUniform1f(mColorDriftLocation, drift); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/preview/filters/ScaleFilter.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.preview.filters; 2 | 3 | import android.opengl.Matrix; 4 | 5 | import static android.opengl.GLES20.glGetUniformLocation; 6 | import static android.opengl.GLES20.glUniformMatrix4fv; 7 | 8 | /** 9 | * Created by 薛贤俊 on 2018/8/30. 10 | * 缩放 11 | */ 12 | public class ScaleFilter extends ImageFilter { 13 | 14 | private static final String VERTEX = "uniform mat4 uTexMatrix;\n" + 15 | "attribute vec2 aPosition;\n" + 16 | "attribute vec4 aTextureCoord;\n" + 17 | "varying vec2 vTextureCoord;\n" + 18 | "uniform mat4 uMvpMatrix;\n" + 19 | "void main(){\n" + 20 | " gl_Position = uMvpMatrix * vec4(aPosition,0.1,1.0);\n" + 21 | " vTextureCoord = (uTexMatrix * aTextureCoord).xy;\n" + 22 | "}\n" + 23 | "\n"; 24 | 25 | private int mScaleMatrixLocation; 26 | 27 | private static final float mScale = 0.3f; 28 | 29 | private int mFrames; 30 | 31 | private int mMaxFrames = 14; 32 | 33 | private int mMiddleFrames = mMaxFrames / 2; 34 | 35 | private float[] mScaleMatrix = new float[16]; 36 | 37 | @Override 38 | protected String getVertexCode() { 39 | return VERTEX; 40 | } 41 | 42 | @Override 43 | protected void initVertexArguments() { 44 | super.initVertexArguments(); 45 | mScaleMatrixLocation = glGetUniformLocation(getProgramId(), "uMvpMatrix"); 46 | } 47 | 48 | @Override 49 | protected void setVertexAttrs() { 50 | super.setVertexAttrs(); 51 | Matrix.setIdentityM(mScaleMatrix, 0); 52 | float progress; 53 | if (mFrames <= mMiddleFrames) { 54 | progress = mFrames * 1.0f / mMiddleFrames; 55 | } else { 56 | progress = 2f - mFrames * 1.0f / mMiddleFrames; 57 | } 58 | float scale = 1f + mScale * progress; 59 | Matrix.scaleM(mScaleMatrix, 0, scale, scale, scale); 60 | glUniformMatrix4fv(mScaleMatrixLocation, 1, false, mScaleMatrix, 0); 61 | mFrames++; 62 | if (mFrames > mMaxFrames) { 63 | mFrames = 0; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/preview/filters/ShakeEffectFilter.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.preview.filters; 2 | 3 | import android.opengl.Matrix; 4 | 5 | import static android.opengl.GLES20.glGetUniformLocation; 6 | import static android.opengl.GLES20.glUniform1f; 7 | import static android.opengl.GLES20.glUniformMatrix4fv; 8 | 9 | /** 10 | * Created by 薛贤俊 on 2018/3/26. 11 | * 抖音-抖动滤镜 12 | */ 13 | public class ShakeEffectFilter extends ImageFilter { 14 | 15 | private static final String VERTEX = "uniform mat4 uTexMatrix;\n" + 16 | "attribute vec2 aPosition;\n" + 17 | "attribute vec4 aTextureCoord;\n" + 18 | "varying vec2 vTextureCoord;\n" + 19 | "uniform mat4 uMvpMatrix;\n" + 20 | "void main(){\n" + 21 | " gl_Position = uMvpMatrix * vec4(aPosition,0.1,1.0);\n" + 22 | " vTextureCoord = (uTexMatrix * aTextureCoord).xy;\n" + 23 | "}"; 24 | private static final String FRAGMENT = "#extension GL_OES_EGL_image_external : require\n" + 25 | " precision mediump float;\n" + 26 | " varying vec2 vTextureCoord;\n" + 27 | " uniform samplerExternalOES uTexture;\n" + 28 | " uniform float uTextureCoordOffset;\n" + 29 | " void main(){\n" + 30 | " vec4 blue = texture2D(uTexture,vTextureCoord);\n" + 31 | " vec4 green = texture2D(uTexture,vec2(vTextureCoord.x + uTextureCoordOffset,vTextureCoord.y + uTextureCoordOffset));\n" + 32 | " vec4 red = texture2D(uTexture,vec2(vTextureCoord.x - uTextureCoordOffset,vTextureCoord.y - uTextureCoordOffset));\n" + 33 | " gl_FragColor = vec4(red.x,green.y,blue.z,blue.w);\n" + 34 | "}"; 35 | 36 | private float[] mMvpMatrix = new float[16]; 37 | 38 | private int mMvpMatrixLocation; 39 | 40 | private int mTextureCoordOffsetLocation; 41 | 42 | private float mProgress = 0.0f; 43 | 44 | private int mFrames = 0; 45 | 46 | private static final int mMaxFrames = 8; 47 | 48 | private static final int mSkipFrames = 4; 49 | 50 | public ShakeEffectFilter() { 51 | } 52 | 53 | 54 | @Override 55 | protected String getVertexCode() { 56 | return VERTEX; 57 | } 58 | 59 | @Override 60 | protected String getFragmentCode() { 61 | return FRAGMENT; 62 | } 63 | 64 | @Override 65 | protected void initFragmentArguments() { 66 | super.initFragmentArguments(); 67 | mTextureCoordOffsetLocation = glGetUniformLocation(getProgramId(), "uTextureCoordOffset"); 68 | } 69 | 70 | @Override 71 | protected void setFragmentAttrs() { 72 | float textureCoordOffset = 0.01f * mProgress; 73 | glUniform1f(mTextureCoordOffsetLocation, textureCoordOffset); 74 | } 75 | 76 | @Override 77 | protected void initVertexArguments() { 78 | super.initVertexArguments(); 79 | mMvpMatrixLocation = glGetUniformLocation(getProgramId(), "uMvpMatrix"); 80 | } 81 | 82 | 83 | @Override 84 | protected void onDraw(int textureId, float[] texMatrix) { 85 | mProgress = (float) mFrames / mMaxFrames; 86 | if (mProgress > 1f) { 87 | mProgress = 0f; 88 | } 89 | mFrames++; 90 | if (mFrames > mMaxFrames + mSkipFrames) { 91 | mFrames = 0; 92 | } 93 | super.onDraw(textureId, texMatrix); 94 | } 95 | 96 | @Override 97 | protected void setVertexAttrs() { 98 | super.setVertexAttrs(); 99 | float scale = 1.0f + 0.2f * mProgress; 100 | Matrix.setIdentityM(mMvpMatrix, 0); 101 | Matrix.scaleM(mMvpMatrix, 0, scale, scale, 1.0f); 102 | glUniformMatrix4fv(mMvpMatrixLocation, 1, false, mMvpMatrix, 0); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/preview/filters/ShineWhiteFilter.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.preview.filters; 2 | 3 | import static android.opengl.GLES20.glGetUniformLocation; 4 | import static android.opengl.GLES20.glUniform1f; 5 | 6 | /** 7 | * Created by 薛贤俊 on 2018/8/30. 8 | * 闪白 9 | */ 10 | public class ShineWhiteFilter extends ImageFilter { 11 | private static final String FRAGMENT = "#extension GL_OES_EGL_image_external : require\n" + 12 | "precision mediump float;\n" + 13 | "varying vec2 vTextureCoord;\n" + 14 | "uniform samplerExternalOES uTexture;\n" + 15 | "uniform float uAdditionalColor;\n" + 16 | "void main(){\n" + 17 | " vec4 color = texture2D(uTexture,vTextureCoord);\n" + 18 | " gl_FragColor = vec4(color.r + uAdditionalColor,color.g + uAdditionalColor,color.b + uAdditionalColor,color.a);\n" + 19 | "}"; 20 | 21 | private int mAdditionColorLocation; 22 | 23 | private int mFrames; 24 | 25 | private int mMaxFrames = 8; 26 | 27 | private int mHalfFrames = mMaxFrames / 2; 28 | 29 | @Override 30 | protected String getFragmentCode() { 31 | return FRAGMENT; 32 | } 33 | 34 | @Override 35 | protected void initFragmentArguments() { 36 | super.initFragmentArguments(); 37 | mAdditionColorLocation = glGetUniformLocation(getProgramId(), "uAdditionalColor"); 38 | } 39 | 40 | @Override 41 | protected void setFragmentAttrs() { 42 | super.setFragmentAttrs(); 43 | float progress; 44 | if (mFrames <= mHalfFrames) { 45 | progress = mFrames * 1.0f / mHalfFrames; 46 | } else { 47 | progress = 2.0f - mFrames * 1.0f / mHalfFrames; 48 | } 49 | mFrames++; 50 | if (mFrames > mMaxFrames) { 51 | mFrames = 0; 52 | } 53 | glUniform1f(mAdditionColorLocation, progress); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/preview/filters/SoulOutFilter.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.preview.filters; 2 | 3 | import android.opengl.GLES11Ext; 4 | import android.opengl.GLES20; 5 | import android.opengl.Matrix; 6 | 7 | import static android.opengl.GLES20.GL_BLEND; 8 | import static android.opengl.GLES20.GL_DST_ALPHA; 9 | import static android.opengl.GLES20.GL_FLOAT; 10 | import static android.opengl.GLES20.GL_ONE; 11 | import static android.opengl.GLES20.GL_SRC_ALPHA; 12 | import static android.opengl.GLES20.glBlendFunc; 13 | import static android.opengl.GLES20.glDisable; 14 | import static android.opengl.GLES20.glEnable; 15 | import static android.opengl.GLES20.glGetUniformLocation; 16 | import static android.opengl.GLES20.glUniform1f; 17 | import static android.opengl.GLES20.glUniformMatrix4fv; 18 | import static android.opengl.GLES20.glVertexAttribPointer; 19 | 20 | /** 21 | * Created by 薛贤俊 on 2018/8/27. 22 | * 灵魂出窍 23 | */ 24 | public class SoulOutFilter extends ImageFilter { 25 | private static final String VERTEX = "uniform mat4 uTexMatrix;\n" + 26 | "attribute vec2 aPosition;\n" + 27 | "attribute vec4 aTextureCoord;\n" + 28 | "varying vec2 vTextureCoord;\n" + 29 | "uniform mat4 uMvpMatrix;\n" + 30 | "void main(){\n" + 31 | " gl_Position = uMvpMatrix * vec4(aPosition,0.1,1.0);\n" + 32 | " vTextureCoord = (uTexMatrix * aTextureCoord).xy;\n" + 33 | "}\n"; 34 | 35 | 36 | private static final String FRAGMENT = "#extension GL_OES_EGL_image_external : require\n" + 37 | " precision mediump float;\n" + 38 | " varying vec2 vTextureCoord;\n" + 39 | " uniform samplerExternalOES uTexture;\n" + 40 | " uniform float uAlpha;\n" + 41 | " void main(){\n" + 42 | " gl_FragColor = vec4(texture2D(uTexture,vTextureCoord).rgb,uAlpha);\n" + 43 | " }"; 44 | 45 | 46 | private float mProgress = 0.0f; 47 | 48 | private int mFrames = 0; 49 | 50 | private static final int mMaxFrames = 15; 51 | 52 | private static final int mSkipFrames = 8; 53 | 54 | private float[] mMvpMatrix = new float[16]; 55 | 56 | private int mMvpMatrixLocation; 57 | 58 | private int mAlphaLocation; 59 | 60 | public SoulOutFilter() { 61 | } 62 | 63 | @Override 64 | protected String getVertexCode() { 65 | return VERTEX; 66 | } 67 | 68 | @Override 69 | protected String getFragmentCode() { 70 | return FRAGMENT; 71 | } 72 | 73 | @Override 74 | protected void initVertexArguments() { 75 | super.initVertexArguments(); 76 | mMvpMatrixLocation = glGetUniformLocation(getProgramId(), "uMvpMatrix"); 77 | } 78 | 79 | @Override 80 | protected void initFragmentArguments() { 81 | super.initFragmentArguments(); 82 | mAlphaLocation = glGetUniformLocation(getProgramId(), "uAlpha"); 83 | } 84 | 85 | @Override 86 | protected void onDraw(int textureId, float[] texMatrix) { 87 | glEnable(GL_BLEND); 88 | glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA); 89 | mProgress = (float) mFrames / mMaxFrames; 90 | if (mProgress > 1f) { 91 | mProgress = 0f; 92 | } 93 | mFrames++; 94 | if (mFrames > mMaxFrames + mSkipFrames) { 95 | mFrames = 0; 96 | } 97 | setVertexAttrs(); 98 | setFragmentAttrs(); 99 | Matrix.setIdentityM(mMvpMatrix, 0); 100 | glUniformMatrix4fv(mMvpMatrixLocation, 1, false, mMvpMatrix, 0); 101 | float backAlpha = 1f; 102 | float alpha = 0f; 103 | if (mProgress > 0f) { 104 | alpha = 0.2f - mProgress * 0.2f; 105 | backAlpha = 1 - alpha; 106 | } 107 | glUniform1f(mAlphaLocation, backAlpha); 108 | glUniformMatrix4fv(mUniformTexMatrixLocation, 1, false, texMatrix, 0); 109 | mRendererInfo.getVertexBuffer().position(0); 110 | glVertexAttribPointer(mAttrPositionLocation, 2, 111 | GL_FLOAT, false, 0, mRendererInfo.getVertexBuffer()); 112 | mRendererInfo.getTextureBuffer().position(0); 113 | glVertexAttribPointer(mAttrTexCoordLocation, 2, 114 | GL_FLOAT, false, 0, mRendererInfo.getTextureBuffer()); 115 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 116 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId); 117 | 118 | GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 119 | if (mProgress > 0f) { 120 | glUniform1f(mAlphaLocation, alpha); 121 | float scale = 1.0f + 1f * mProgress; 122 | Matrix.scaleM(mMvpMatrix, 0, scale, scale, scale); 123 | glUniformMatrix4fv(mMvpMatrixLocation, 1, false, mMvpMatrix, 0); 124 | GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 125 | } 126 | 127 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); 128 | GLES20.glUseProgram(0); 129 | glDisable(GL_BLEND); 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/preview/filters/VertigoFilter.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.preview.filters; 2 | 3 | 4 | import android.graphics.BitmapFactory; 5 | import android.opengl.GLES20; 6 | 7 | import com.xue.douyin.R; 8 | 9 | import com.xue.douyin.application.AppProfile; 10 | import com.xue.douyin.common.preview.GLUtils; 11 | import com.xue.douyin.common.preview.RenderBuffer; 12 | import com.xue.douyin.common.util.FileUtils; 13 | 14 | import static android.opengl.GLES20.GL_FLOAT; 15 | import static android.opengl.GLES20.GL_TEXTURE0; 16 | import static android.opengl.GLES20.GL_TEXTURE10; 17 | import static android.opengl.GLES20.GL_TEXTURE8; 18 | import static android.opengl.GLES20.GL_TEXTURE9; 19 | import static android.opengl.GLES20.GL_TEXTURE_2D; 20 | import static android.opengl.GLES20.glActiveTexture; 21 | import static android.opengl.GLES20.glBindTexture; 22 | import static android.opengl.GLES20.glEnableVertexAttribArray; 23 | import static android.opengl.GLES20.glGetAttribLocation; 24 | import static android.opengl.GLES20.glGetUniformLocation; 25 | import static android.opengl.GLES20.glUniform1i; 26 | import static android.opengl.GLES20.glUseProgram; 27 | import static android.opengl.GLES20.glVertexAttribPointer; 28 | 29 | /** 30 | * Created by 薛贤俊 on 2018/9/7. 31 | * 幻觉 32 | */ 33 | public class VertigoFilter extends ImageFilter { 34 | 35 | private RenderBuffer mRenderBuffer; 36 | 37 | private RenderBuffer mRenderBuffer2; 38 | 39 | private RenderBuffer mRenderBuffer3; 40 | 41 | private int mLutTexture; 42 | //当前帧 43 | private int mCurrentFrameProgram; 44 | //上一帧 45 | private int mLastFrameProgram; 46 | 47 | private boolean mFirst = true; 48 | 49 | @Override 50 | public void draw(int textureId, float[] texMatrix, int canvasWidth, int canvasHeight) { 51 | if (mRenderBuffer == null) { 52 | mRenderBuffer = new RenderBuffer(GL_TEXTURE8, canvasWidth, canvasHeight); 53 | mRenderBuffer2 = new RenderBuffer(GL_TEXTURE9, canvasWidth, canvasHeight); 54 | mRenderBuffer3 = new RenderBuffer(GL_TEXTURE10, canvasWidth, canvasHeight); 55 | mLastFrameProgram = GLUtils.buildProgram(FileUtils.readFromRaw(R.raw.vertex_common), FileUtils.readFromRaw(R.raw.fragment_common)); 56 | mCurrentFrameProgram = GLUtils.buildProgram(FileUtils.readFromRaw(R.raw.vertex_common), FileUtils.readFromRaw(R.raw.fragment_current_frame)); 57 | mLutTexture = GLUtils.genLutTexture(); 58 | android.opengl.GLUtils.texImage2D(GL_TEXTURE_2D, 0, BitmapFactory.decodeResource(AppProfile.getContext().getResources(), R.raw.lookup_vertigo), 0); 59 | } 60 | mRenderBuffer.bind(); 61 | super.draw(textureId, texMatrix, canvasWidth, canvasHeight); 62 | mRenderBuffer.unbind(); 63 | //绘制当前帧 64 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 65 | drawCurrentFrame(); 66 | mRenderBuffer3.bind(); 67 | drawCurrentFrame(); 68 | mRenderBuffer3.unbind(); 69 | //只用两个buffer的话,屏幕中会有黑格子 70 | //把3中的内容画到2中 71 | mRenderBuffer2.bind(); 72 | drawToBuffer(); 73 | mRenderBuffer2.unbind(); 74 | mFirst = false; 75 | } 76 | 77 | private void drawToBuffer() { 78 | glUseProgram(mLastFrameProgram); 79 | setup(mLastFrameProgram, new int[]{mRenderBuffer3.getTextureId()}); 80 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 81 | GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 82 | 83 | } 84 | 85 | private void drawCurrentFrame() { 86 | glUseProgram(mCurrentFrameProgram); 87 | int textureId = mRenderBuffer.getTextureId(); 88 | setup(mCurrentFrameProgram, new int[]{textureId, mFirst ? textureId : mRenderBuffer2.getTextureId(), mLutTexture}); 89 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 90 | GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 91 | } 92 | 93 | private void setup(int programId, int[] textureId) { 94 | glUseProgram(programId); 95 | int aPositionLocation = glGetAttribLocation(programId, "aPosition"); 96 | int aTexCoordLocation = glGetAttribLocation(programId, "aTextureCoord"); 97 | mRendererInfo.getVertexBuffer().position(0); 98 | glEnableVertexAttribArray(aPositionLocation); 99 | glVertexAttribPointer(aPositionLocation, 2, 100 | GL_FLOAT, false, 0, mRendererInfo.getVertexBuffer()); 101 | mRendererInfo.getTextureBuffer().position(0); 102 | glEnableVertexAttribArray(aTexCoordLocation); 103 | glVertexAttribPointer(aTexCoordLocation, 2, 104 | GL_FLOAT, false, 0, mRendererInfo.getTextureBuffer()); 105 | for (int i = 0; i < textureId.length; i++) { 106 | int textureLocation = glGetUniformLocation(programId, "uTexture" + i); 107 | glActiveTexture(GL_TEXTURE0 + i); 108 | glBindTexture(GLES20.GL_TEXTURE_2D, textureId[i]); 109 | glUniform1i(textureLocation, i); 110 | } 111 | } 112 | 113 | 114 | } 115 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/ClipInfo.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder; 2 | 3 | import com.xue.douyin.common.C; 4 | 5 | /** 6 | * Created by 薛贤俊 on 2018/4/11. 7 | */ 8 | 9 | public class ClipInfo { 10 | 11 | private String fileName; 12 | 13 | private long duration; 14 | 15 | private int type; 16 | 17 | public ClipInfo(String fileName, long duration,@C.DataType int type) { 18 | this.fileName = fileName; 19 | this.duration = duration; 20 | this.type = type; 21 | } 22 | 23 | public String getFileName() { 24 | return fileName; 25 | } 26 | 27 | public long getDuration() { 28 | return duration; 29 | } 30 | 31 | public @C.DataType 32 | int getType() { 33 | return type; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/MediaConfig.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder; 2 | 3 | 4 | import com.xue.douyin.common.C; 5 | import com.xue.douyin.common.recorder.audio.AudioConfig; 6 | import com.xue.douyin.common.recorder.video.VideoConfig; 7 | 8 | import static com.xue.douyin.common.C.MODE_EXTRA_FAST; 9 | import static com.xue.douyin.common.C.MODE_EXTRA_SLOW; 10 | import static com.xue.douyin.common.C.MODE_FAST; 11 | import static com.xue.douyin.common.C.MODE_NORMAL; 12 | import static com.xue.douyin.common.C.MODE_SLOW; 13 | 14 | 15 | /** 16 | * Created by 薛贤俊 on 2018/3/21. 17 | */ 18 | 19 | public class MediaConfig { 20 | 21 | 22 | 23 | private String filePath; 24 | 25 | private VideoConfig videoConfig; 26 | 27 | private AudioConfig audioConfig; 28 | 29 | private long maxDuration; 30 | 31 | private boolean supportAudio; 32 | 33 | private @C.SpeedMode 34 | int mSpeedMode; 35 | 36 | public MediaConfig(String filePath) { 37 | this.filePath = filePath; 38 | } 39 | 40 | public void setSpeedMode(@C.SpeedMode int speedMode) { 41 | this.mSpeedMode = speedMode; 42 | } 43 | 44 | public void setSupportAudio(boolean supportAudio) { 45 | this.supportAudio = supportAudio; 46 | } 47 | 48 | public void configure(AudioConfig audio, VideoConfig video) { 49 | this.audioConfig = audio; 50 | this.videoConfig = video; 51 | } 52 | 53 | public void setMaxDuration(long maxDuration) { 54 | this.maxDuration = maxDuration; 55 | } 56 | 57 | public long getMaxDuration() { 58 | return maxDuration; 59 | } 60 | 61 | public String getFilePath() { 62 | return filePath; 63 | } 64 | 65 | public int getSpeedMode() { 66 | return mSpeedMode; 67 | } 68 | 69 | public VideoConfig getVideoConfig() { 70 | return videoConfig; 71 | } 72 | 73 | public AudioConfig getAudioConfig() { 74 | return audioConfig; 75 | } 76 | 77 | public boolean supportAudio() { 78 | return supportAudio; 79 | } 80 | 81 | public float getSpeedFactor() { 82 | return getSpeedFactor(mSpeedMode); 83 | } 84 | 85 | public static float getSpeedFactor(@C.SpeedMode int speedMode) { 86 | switch (speedMode) { 87 | case MODE_EXTRA_SLOW: 88 | return 1f / 3; 89 | case MODE_SLOW: 90 | return 0.5f; 91 | case MODE_NORMAL: 92 | return 1f; 93 | case MODE_FAST: 94 | return 2f; 95 | case MODE_EXTRA_FAST: 96 | return 3f; 97 | } 98 | return 1; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/MediaRecorder.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder; 2 | 3 | import android.opengl.EGLContext; 4 | import android.support.annotation.Nullable; 5 | import com.xue.douyin.common.C; 6 | import com.xue.douyin.common.recorder.audio.AudioConfig; 7 | import com.xue.douyin.common.recorder.video.VideoConfig; 8 | import com.xue.douyin.common.recorder.video.VideoFrameData; 9 | import com.xue.douyin.common.util.FileUtils; 10 | import com.xue.douyin.common.view.record.OnFrameAvailableListener; 11 | 12 | import static com.xue.douyin.common.C.VIDEO; 13 | 14 | 15 | /** 16 | * Created by 薛贤俊 on 2018/3/15. 17 | */ 18 | 19 | public class MediaRecorder implements OnFrameAvailableListener, OnRecordFinishListener { 20 | 21 | private long maxDuration; 22 | /** 23 | * 视频还可以拍摄的帧数 24 | */ 25 | private int remainDuration; 26 | 27 | private OnRecordFinishListener mFinishListener; 28 | 29 | private AudioRecorder audioRecorder; 30 | 31 | private VideoRecorder videoRecorder; 32 | 33 | private boolean supportAudio = true; 34 | 35 | public MediaRecorder(int seconds, @Nullable OnRecordFinishListener listener) { 36 | mFinishListener = listener; 37 | audioRecorder = new AudioRecorder(); 38 | videoRecorder = new VideoRecorder(); 39 | remainDuration = seconds * C.SECOND_IN_US; 40 | maxDuration = remainDuration; 41 | audioRecorder.setOnRecordFinishListener(this); 42 | videoRecorder.setOnRecordFinishListener(this); 43 | } 44 | 45 | 46 | public boolean start(EGLContext context, int width, int height, @C.SpeedMode int mode) { 47 | if (remainDuration <= 0) { 48 | return false; 49 | } 50 | FileUtils.createFile(C.VIDEO_TEMP_FILE_NAME); 51 | FileUtils.createFile(C.AUDIO_TEMP_FILE_NAME); 52 | AudioConfig audio = new AudioConfig(C.AUDIO_TEMP_FILE_NAME, C.AudioParams.SAMPLE_RATE, C.AudioParams.SAMPLE_PER_FRAME); 53 | audio.setSpeedMode(mode); 54 | audio.setMaxDuration(remainDuration); 55 | VideoConfig video = new VideoConfig(C.VIDEO_TEMP_FILE_NAME, context, width, height, C.VideoParams.BIT_RATE); 56 | video.setFactor(MediaConfig.getSpeedFactor(mode)); 57 | video.setMaxDuration(remainDuration); 58 | audioRecorder.configure(audio); 59 | videoRecorder.configure(video); 60 | try { 61 | audioRecorder.prepareCodec(); 62 | videoRecorder.prepareCodec(); 63 | } catch (Throwable e) { 64 | audioRecorder.shutdown(); 65 | videoRecorder.shutdown(); 66 | return false; 67 | } 68 | 69 | 70 | if (supportAudio) { 71 | audioRecorder.start(); 72 | } 73 | videoRecorder.start(); 74 | return true; 75 | } 76 | 77 | public void stop() { 78 | if (supportAudio) 79 | audioRecorder.stop(); 80 | videoRecorder.stop(); 81 | } 82 | 83 | private void quit() { 84 | 85 | } 86 | 87 | 88 | @Override 89 | public void onFrameAvailable(VideoFrameData frameData) { 90 | videoRecorder.frameAvailable(frameData); 91 | } 92 | 93 | public void setOnProgressListener(OnRecordProgressListener listener) { 94 | videoRecorder.setOnProgressListener(listener); 95 | } 96 | 97 | @Override 98 | public void onRecordFinish(ClipInfo info) { 99 | if (info.getType() == VIDEO) { 100 | remainDuration -= info.getDuration(); 101 | } 102 | if (mFinishListener != null) { 103 | mFinishListener.onRecordFinish(info); 104 | } 105 | } 106 | 107 | 108 | public float getMaxDuration() { 109 | return maxDuration; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/OnRecordFinishListener.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder; 2 | 3 | /** 4 | * Created by 薛贤俊 on 2018/3/15. 5 | */ 6 | 7 | public interface OnRecordFinishListener { 8 | void onRecordFinish(ClipInfo info); 9 | } 10 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/OnRecordProgressListener.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder; 2 | 3 | /** 4 | * Created by 薛贤俊 on 2018/3/15. 5 | */ 6 | 7 | public interface OnRecordProgressListener { 8 | void onRecordProgress(long duration); 9 | } 10 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/Recorder.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder; 2 | 3 | import com.xue.douyin.common.C; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * Created by 薛贤俊 on 2018/4/10. 9 | */ 10 | 11 | public interface Recorder { 12 | 13 | 14 | 15 | @C.DataType 16 | int getDataType(); 17 | 18 | void setOnRecordFinishListener(OnRecordFinishListener listener); 19 | 20 | void configure(T configuration); 21 | 22 | void start(); 23 | 24 | void stop(); 25 | 26 | void prepareCodec() throws IOException; 27 | 28 | void shutdown(); 29 | 30 | boolean isStarted(); 31 | } 32 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/audio/AudioConfig.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder.audio; 2 | 3 | import com.xue.douyin.common.C; 4 | import com.xue.douyin.common.recorder.MediaConfig; 5 | 6 | /** 7 | * Created by 薛贤俊 on 2018/3/9. 8 | */ 9 | 10 | public class AudioConfig { 11 | 12 | private int sampleRate; 13 | 14 | private int samplePerFrame; 15 | 16 | private @C.SpeedMode 17 | int speedMode; 18 | 19 | private String fileName; 20 | 21 | private long maxDuration; 22 | 23 | public AudioConfig(String fileName, int sampleRate, int samplePerFrame) { 24 | this.sampleRate = sampleRate; 25 | this.samplePerFrame = samplePerFrame; 26 | this.fileName = fileName; 27 | } 28 | 29 | public int getSampleRate() { 30 | return sampleRate; 31 | } 32 | 33 | public int getSamplePerFrame() { 34 | return samplePerFrame; 35 | } 36 | 37 | public int getSpeedMode() { 38 | return speedMode; 39 | } 40 | 41 | public void setSpeedMode(int speedMode) { 42 | this.speedMode = speedMode; 43 | } 44 | 45 | public String getFileName(){ 46 | return fileName; 47 | } 48 | 49 | public long getMaxDuration() { 50 | return maxDuration; 51 | } 52 | 53 | public void setMaxDuration(long maxDuration) { 54 | this.maxDuration = maxDuration; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/video/BaseGLSurface.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder.video; 2 | 3 | import android.opengl.EGL14; 4 | import android.opengl.EGLSurface; 5 | 6 | import com.xue.douyin.common.util.LogUtil; 7 | 8 | /** 9 | * Created by 薛贤俊 on 2018/3/8. 10 | */ 11 | 12 | public class BaseGLSurface { 13 | protected static final String TAG = "BaseGLSurface"; 14 | 15 | protected GLCore mGlCore; 16 | 17 | private EGLSurface mGlSurface = EGL14.EGL_NO_SURFACE; 18 | 19 | protected BaseGLSurface(GLCore core) { 20 | mGlCore = core; 21 | } 22 | 23 | public void createWindowSurface(Object surface) { 24 | if (mGlSurface != EGL14.EGL_NO_SURFACE) { 25 | LogUtil.d(TAG, "try to create window surface redundantly"); 26 | return; 27 | } 28 | mGlSurface = mGlCore.createWindowSurface(surface); 29 | } 30 | 31 | /** 32 | * Release the EGL surface. 33 | */ 34 | public void releaseEglSurface() { 35 | mGlCore.releaseSurface(mGlSurface); 36 | mGlSurface = EGL14.EGL_NO_SURFACE; 37 | } 38 | 39 | /** 40 | * Makes our EGL context and surface current. 41 | */ 42 | public void makeCurrent() { 43 | mGlCore.makeCurrent(mGlSurface); 44 | } 45 | 46 | /** 47 | * Calls eglSwapBuffers. Use this to "publish" the current frame. 48 | * 49 | * @return false on failure 50 | */ 51 | public boolean swapBuffers() { 52 | boolean result = mGlCore.swapBuffers(mGlSurface); 53 | if (!result) { 54 | LogUtil.d(TAG, "WARNING: swapBuffers() failed"); 55 | } 56 | return result; 57 | } 58 | 59 | /** 60 | * Sends the presentation time stamp to EGL. 61 | */ 62 | public void setPresentationTime(long nanoSeconds) { 63 | mGlCore.setPresentationTime(mGlSurface, nanoSeconds); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/video/OffScreenWrapper.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder.video; 2 | 3 | import android.opengl.EGLContext; 4 | import android.view.Surface; 5 | 6 | import com.xue.douyin.common.preview.filters.ImageFilter; 7 | 8 | /** 9 | * Created by 薛贤俊 on 2018/3/9. 10 | */ 11 | 12 | public class OffScreenWrapper { 13 | private GLCore mGLCore; 14 | 15 | private WindowSurface mEncoderSurface; 16 | 17 | private ImageFilter mFilter; 18 | 19 | public OffScreenWrapper(EGLContext context, Surface surface) { 20 | mGLCore = new GLCore(context, GLCore.FLAG_RECORDABLE); 21 | mEncoderSurface = new WindowSurface(mGLCore, surface, true); 22 | mEncoderSurface.makeCurrent(); 23 | } 24 | 25 | public void release() { 26 | if (mEncoderSurface == null) { 27 | return; 28 | } 29 | 30 | mEncoderSurface.release(); 31 | mGLCore.release(); 32 | mEncoderSurface = null; 33 | mGLCore = null; 34 | } 35 | 36 | public void draw(ImageFilter filter, float[] matrix, int textureId, long time) { 37 | mEncoderSurface.makeCurrent(); 38 | if (mFilter != filter && mFilter != null) { 39 | mFilter.release(); 40 | } 41 | mFilter = filter; 42 | filter.init(); 43 | filter.draw(textureId, matrix,0,0); 44 | mEncoderSurface.setPresentationTime(time); 45 | mEncoderSurface.swapBuffers(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/video/VideoConfig.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder.video; 2 | 3 | import android.opengl.EGLContext; 4 | 5 | /** 6 | * Created by 薛贤俊 on 2018/3/9. 7 | */ 8 | 9 | public class VideoConfig { 10 | 11 | private EGLContext mGLContext; 12 | 13 | private int mVideoWidth; 14 | 15 | private int mVideoHeight; 16 | 17 | private int mBitRate; 18 | 19 | private String fileName; 20 | 21 | private float factor; 22 | 23 | private long maxDuration; 24 | 25 | public VideoConfig(String fileName, EGLContext context, int width, int height, int bitRate) { 26 | this.mGLContext = context; 27 | this.mVideoWidth = width; 28 | this.mVideoHeight = height; 29 | this.mBitRate = bitRate; 30 | this.fileName = fileName; 31 | } 32 | 33 | public String getFileName() { 34 | return this.fileName; 35 | } 36 | 37 | public float getFactor() { 38 | return factor; 39 | } 40 | 41 | public void setFactor(float factor) { 42 | this.factor = factor; 43 | } 44 | 45 | public EGLContext getGLContext() { 46 | return mGLContext; 47 | } 48 | 49 | public int getVideoWidth() { 50 | return mVideoWidth; 51 | } 52 | 53 | public int getVideoHeight() { 54 | return mVideoHeight; 55 | } 56 | 57 | public int getBitRate() { 58 | return mBitRate; 59 | } 60 | 61 | public long getMaxDuration() { 62 | return maxDuration; 63 | } 64 | 65 | public void setMaxDuration(long maxDuration) { 66 | this.maxDuration = maxDuration; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/video/VideoFrameData.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder.video; 2 | 3 | import com.xue.douyin.common.preview.filters.ImageFilter; 4 | 5 | /** 6 | * Created by 薛贤俊 on 2018/3/9. 7 | */ 8 | 9 | public class VideoFrameData { 10 | private ImageFilter mFilter; 11 | private float[] mMatrix; 12 | private long mTimeStamp; 13 | private int mTextureId; 14 | 15 | public VideoFrameData(ImageFilter filter, float[] matrix, long timestamp, int textureId) { 16 | this.mFilter = filter; 17 | this.mMatrix = matrix; 18 | this.mTimeStamp = timestamp; 19 | this.mTextureId = textureId; 20 | } 21 | 22 | public ImageFilter getFilter() { 23 | return mFilter; 24 | } 25 | 26 | public float[] getMatrix() { 27 | return mMatrix; 28 | } 29 | 30 | public long getTimestamp() { 31 | return mTimeStamp; 32 | } 33 | 34 | public int getTextureId() { 35 | return mTextureId; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/recorder/video/WindowSurface.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.recorder.video; 2 | 3 | import android.graphics.SurfaceTexture; 4 | import android.view.Surface; 5 | 6 | /** 7 | * Created by 薛贤俊 on 2018/3/8. 8 | */ 9 | 10 | public class WindowSurface extends BaseGLSurface { 11 | 12 | private Surface mSurface; 13 | 14 | private boolean mReleaseSurface; 15 | 16 | public WindowSurface(GLCore core, Surface surface, boolean releaseSurface) { 17 | super(core); 18 | createWindowSurface(surface); 19 | mSurface = surface; 20 | mReleaseSurface = releaseSurface; 21 | } 22 | 23 | /** 24 | * Associates an EGL surface with the SurfaceTexture. 25 | */ 26 | public WindowSurface(GLCore eglCore, SurfaceTexture surfaceTexture) { 27 | super(eglCore); 28 | createWindowSurface(surfaceTexture); 29 | } 30 | 31 | /** 32 | * Releases any resources associated with the EGL surface (and, if configured to do so, 33 | * with the Surface as well). 34 | *

35 | * Does not require that the surface's EGL context be current. 36 | */ 37 | public void release() { 38 | releaseEglSurface(); 39 | if (mSurface != null) { 40 | if (mReleaseSurface) { 41 | mSurface.release(); 42 | } 43 | mSurface = null; 44 | } 45 | } 46 | 47 | /** 48 | * Recreate the EGLSurface, using the new EglBase. The caller should have already 49 | * freed the old EGLSurface with releaseEglSurface(). 50 | *

51 | * This is useful when we want to update the EGLSurface associated with a Surface. 52 | * For example, if we want to share with a different EGLContext, which can only 53 | * be done by tearing down and recreating the context. (That's handled by the caller; 54 | * this just creates a new EGLSurface for the Surface we were handed earlier.) 55 | *

56 | * If the previous EGLSurface isn't fully destroyed, e.g. it's still current on a 57 | * context somewhere, the create call will fail with complaints from the Surface 58 | * about already being connected. 59 | */ 60 | public void recreate(GLCore newEglCore) { 61 | if (mSurface == null) { 62 | throw new RuntimeException("not yet implemented for SurfaceTexture"); 63 | } 64 | mGlCore = newEglCore; // switch to new context 65 | createWindowSurface(mSurface); // create new surface 66 | } 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/util/FileUtils.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.util; 2 | 3 | import android.content.res.AssetManager; 4 | import android.util.Log; 5 | 6 | import com.xue.douyin.R; 7 | import com.xue.douyin.application.AppProfile; 8 | 9 | import java.io.BufferedInputStream; 10 | import java.io.BufferedReader; 11 | import java.io.File; 12 | import java.io.FileOutputStream; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.io.InputStreamReader; 16 | import java.io.OutputStream; 17 | import java.io.RandomAccessFile; 18 | import java.util.List; 19 | 20 | /** 21 | * Created by 薛贤俊 on 2018/3/15. 22 | */ 23 | 24 | public class FileUtils { 25 | /** 26 | * 此类用于生成合并视频所需要的文档 27 | * 28 | * @param strcontent 视频路径集合 29 | * @param filePath 生成的地址 30 | * @param fileName 生成的文件名 31 | */ 32 | public static void writeTxtToFile(List strcontent, String filePath, String fileName) { 33 | //生成文件夹之后,再生成文件,不然会出错 34 | String strFilePath = filePath + fileName; 35 | // 每次写入时,都换行写 36 | String strContent = ""; 37 | for (int i = 0; i < strcontent.size(); i++) { 38 | strContent += "file " + strcontent.get(i) + "\r\n"; 39 | } 40 | try { 41 | File file = new File(strFilePath); 42 | //检查文件是否存在,存在则删除 43 | if (file.isFile() && file.exists()) { 44 | file.delete(); 45 | } 46 | file.getParentFile().mkdirs(); 47 | file.createNewFile(); 48 | RandomAccessFile raf = new RandomAccessFile(file, "rwd"); 49 | raf.seek(file.length()); 50 | raf.write(strContent.getBytes()); 51 | raf.close(); 52 | Log.e("TestFile", "写入成功:" + strFilePath); 53 | } catch (Exception e) { 54 | Log.e("TestFile", "Error on write File:" + e); 55 | } 56 | } 57 | 58 | public static void deleteFile(String fileName) { 59 | File file = new File(fileName); 60 | if (file.exists()) { 61 | file.delete(); 62 | } 63 | } 64 | 65 | public static void renameFile(String original, String dest) { 66 | File file = new File(original); 67 | file.renameTo(new File(dest)); 68 | } 69 | 70 | public static void createFile(String path) { 71 | File file = new File(path); 72 | if (file.exists()) { 73 | file.delete(); 74 | } 75 | try { 76 | file.createNewFile(); 77 | } catch (IOException e) { 78 | LogUtil.e(e); 79 | } 80 | } 81 | 82 | public static void closeSafely(OutputStream fos) { 83 | try { 84 | fos.flush(); 85 | fos.close(); 86 | } catch (IOException e) { 87 | LogUtil.e(e); 88 | } 89 | 90 | } 91 | 92 | public static String readFromRaw(int rawId) { 93 | InputStream inputStream = AppProfile.getContext().getResources().openRawResource(rawId); 94 | BufferedInputStream bis = new BufferedInputStream(inputStream); 95 | BufferedReader br = new BufferedReader(new InputStreamReader(bis)); 96 | StringBuilder builder = new StringBuilder(); 97 | String line; 98 | try { 99 | while ((line = br.readLine()) != null) { 100 | builder.append(line); 101 | builder.append("\n"); 102 | } 103 | } catch (Throwable e) { 104 | LogUtil.e(e); 105 | } finally { 106 | try { 107 | br.close(); 108 | bis.close(); 109 | inputStream.close(); 110 | } catch (Throwable e) { 111 | 112 | } 113 | } 114 | return builder.toString(); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/util/LogUtil.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.util; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * Created by 薛贤俊 on 2018/3/1. 7 | */ 8 | 9 | public class LogUtil { 10 | 11 | private static final String TAG = "DouyinDemo"; 12 | 13 | public static void e(String tag, String msg, Throwable e) { 14 | Log.e(tag, msg, e); 15 | } 16 | 17 | public static void e(String tag, Throwable e) { 18 | Log.e(tag, "", e); 19 | } 20 | 21 | public static void e(String msg) { 22 | e(TAG, msg); 23 | } 24 | 25 | public static void e(Throwable e) { 26 | e(TAG, e); 27 | } 28 | 29 | public static void d(String tag, String msg) { 30 | Log.d(tag, msg); 31 | } 32 | 33 | public static void d(String msg) { 34 | d(TAG, msg); 35 | } 36 | 37 | public static void e(String tag, String msg) { 38 | Log.e(tag, msg); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/util/ScreenUtil.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.util; 2 | 3 | import android.util.DisplayMetrics; 4 | 5 | import com.xue.douyin.application.AppProfile; 6 | 7 | /** 8 | * Created by 薛贤俊 on 2018/4/19. 9 | */ 10 | 11 | public class ScreenUtil { 12 | 13 | private static int sScreenWidth; 14 | 15 | private static int sScreenHeight; 16 | 17 | private static void init() { 18 | DisplayMetrics dm = AppProfile.getContext().getApplicationContext().getResources().getDisplayMetrics(); 19 | sScreenWidth = dm.widthPixels; 20 | sScreenHeight = dm.heightPixels; 21 | } 22 | 23 | public static int getScreenWidth() { 24 | if (sScreenWidth == 0) { 25 | init(); 26 | } 27 | return sScreenWidth; 28 | } 29 | 30 | public static int getScreenHeight() { 31 | if (sScreenHeight == 0) { 32 | init(); 33 | } 34 | return sScreenHeight; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/util/StorageUtil.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.util; 2 | 3 | import android.os.Environment; 4 | 5 | import java.io.File; 6 | 7 | /** 8 | * Created by 薛贤俊 on 2018/2/25. 9 | */ 10 | 11 | public class StorageUtil { 12 | private static final String APP_DIRECTORY_NAME = "DYDemo"; 13 | 14 | private static boolean sMounted = false; 15 | 16 | private static String APP_DIRECTORY = null; 17 | 18 | public static String getExternalStoragePath() { 19 | if (APP_DIRECTORY != null) { 20 | return APP_DIRECTORY; 21 | } 22 | sMounted = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED); 23 | if (sMounted) { 24 | APP_DIRECTORY = Environment.getExternalStorageDirectory().getPath() + File.separator + APP_DIRECTORY_NAME; 25 | File file = new File(APP_DIRECTORY); 26 | if (file.exists() && !file.isDirectory()) { 27 | file.delete(); 28 | } 29 | if(!file.exists()){ 30 | file.mkdirs(); 31 | } 32 | } 33 | return APP_DIRECTORY; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/util/ThreadUtil.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.util; 2 | 3 | import android.os.Handler; 4 | import android.os.HandlerThread; 5 | 6 | /** 7 | * Created by 薛贤俊 on 2018/4/11. 8 | */ 9 | 10 | public class ThreadUtil { 11 | public static Handler newHandlerThread(String tag) { 12 | HandlerThread thread = new HandlerThread(tag); 13 | thread.start(); 14 | return new Handler(thread.getLooper()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/util/VideoUtil.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.util; 2 | 3 | import android.media.MediaExtractor; 4 | import android.media.MediaFormat; 5 | 6 | import com.xue.douyin.common.C; 7 | 8 | /** 9 | * Created by 薛贤俊 on 2018/3/14. 10 | */ 11 | 12 | public class VideoUtil { 13 | 14 | /** 15 | * 获取视频信息 16 | * 17 | * @param url 18 | * @return 视频时长(单位微秒) 19 | */ 20 | public static long getDuration(String url) { 21 | try { 22 | MediaExtractor mediaExtractor = new MediaExtractor(); 23 | mediaExtractor.setDataSource(url); 24 | int videoExt = selectVideoTrack(mediaExtractor); 25 | if (videoExt == -1) { 26 | videoExt = selectAudioTrack(mediaExtractor); 27 | if (videoExt == -1) { 28 | return 0; 29 | } 30 | } 31 | MediaFormat mediaFormat = mediaExtractor.getTrackFormat(videoExt); 32 | long res = mediaFormat.containsKey(MediaFormat.KEY_DURATION) ? mediaFormat.getLong(MediaFormat.KEY_DURATION) : 0;//时长 33 | mediaExtractor.release(); 34 | return res; 35 | } catch (Exception e) { 36 | return 0; 37 | } 38 | } 39 | 40 | /** 41 | * 查找视频轨道 42 | * 43 | * @param extractor 44 | * @return 45 | */ 46 | public static int selectVideoTrack(MediaExtractor extractor) { 47 | int numTracks = extractor.getTrackCount(); 48 | for (int i = 0; i < numTracks; i++) { 49 | MediaFormat format = extractor.getTrackFormat(i); 50 | String mime = format.getString(MediaFormat.KEY_MIME); 51 | if (mime.startsWith("video/")) { 52 | LogUtil.d("Extractor selected track " + i + " (" + mime + "): " + format); 53 | return i; 54 | } 55 | } 56 | return -1; 57 | } 58 | 59 | /** 60 | * 查找音频轨道 61 | * 62 | * @param extractor 63 | * @return 64 | */ 65 | public static int selectAudioTrack(MediaExtractor extractor) { 66 | int numTracks = extractor.getTrackCount(); 67 | for (int i = 0; i < numTracks; i++) { 68 | MediaFormat format = extractor.getTrackFormat(i); 69 | String mime = format.getString(MediaFormat.KEY_MIME); 70 | if (mime.startsWith("audio/")) { 71 | LogUtil.d("Extractor selected track " + i + " (" + mime + "): " + format); 72 | return i; 73 | } 74 | } 75 | return -1; 76 | } 77 | 78 | public static int calculateAudioSamples(int seconds, int sampleRate, int samplePerFrame) { 79 | return (int) (Math.ceil(seconds * 1.0 * sampleRate / samplePerFrame)) * 2; 80 | } 81 | 82 | public static int calculateVideoSamples(int seconds, int fps) { 83 | return seconds * fps; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/view/ProgressView.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.view; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.RectF; 9 | import android.support.annotation.Nullable; 10 | import android.util.AttributeSet; 11 | import android.view.View; 12 | 13 | 14 | import com.xue.douyin.R; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | /** 20 | * Created by 薛贤俊 on 2018/2/25. 21 | */ 22 | 23 | public class ProgressView extends View { 24 | 25 | private static final int RADIUS = 4; 26 | 27 | private static final int DIVIDER_WIDTH = 2; 28 | 29 | private static final int BACKGROUND_COLOR = Color.parseColor("#22000000"); 30 | 31 | private static final int CONTENT_COLOR = Color.parseColor("#face15"); 32 | 33 | private static final int DIVIDER_COLOR = Color.WHITE; 34 | 35 | private Paint mPaint; 36 | 37 | private float mRadius = RADIUS; 38 | 39 | private int mBackgroundColor = BACKGROUND_COLOR; 40 | 41 | private int mContentColor = CONTENT_COLOR; 42 | 43 | private int mDividerColor = DIVIDER_COLOR; 44 | 45 | private int mDividerWidth = DIVIDER_WIDTH; 46 | 47 | private float mLoadingProgress; 48 | 49 | private List mProgressList = new ArrayList<>(); 50 | 51 | public ProgressView(Context context) { 52 | super(context); 53 | init(); 54 | } 55 | 56 | public ProgressView(Context context, @Nullable AttributeSet attrs) { 57 | super(context, attrs); 58 | init(); 59 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ProgressView); 60 | try { 61 | mRadius = ta.getDimensionPixelSize(R.styleable.ProgressView_pv_radius, RADIUS); 62 | mBackgroundColor = ta.getColor(R.styleable.ProgressView_pv_bg_color, BACKGROUND_COLOR); 63 | mContentColor = ta.getColor(R.styleable.ProgressView_pv_content_color, CONTENT_COLOR); 64 | mDividerColor = ta.getColor(R.styleable.ProgressView_pv_divider_color, DIVIDER_COLOR); 65 | mDividerWidth = ta.getDimensionPixelSize(R.styleable.ProgressView_pv_divider_width, DIVIDER_WIDTH); 66 | } finally { 67 | ta.recycle(); 68 | } 69 | } 70 | 71 | 72 | private void init() { 73 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 74 | } 75 | 76 | @Override 77 | protected void onDraw(Canvas canvas) { 78 | drawBackground(canvas); 79 | drawContent(canvas); 80 | drawDivider(canvas); 81 | } 82 | 83 | private void drawBackground(Canvas canvas) { 84 | mPaint.setColor(mBackgroundColor); 85 | canvas.drawRoundRect(new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()), 86 | mRadius, mRadius, mPaint); 87 | } 88 | 89 | private void drawContent(Canvas canvas) { 90 | float total = 0; 91 | for (float progress : mProgressList) { 92 | total += progress; 93 | } 94 | total += mLoadingProgress; 95 | int width = (int) (total * getMeasuredWidth()); 96 | mPaint.setColor(mContentColor); 97 | canvas.drawRoundRect(new RectF(0, 0, width, getMeasuredHeight()), 98 | mRadius, mRadius, mPaint); 99 | if (width < mRadius) { 100 | return; 101 | } 102 | canvas.drawRect(new RectF(mRadius, 0, width, getMeasuredHeight()), mPaint); 103 | } 104 | 105 | private void drawDivider(Canvas canvas) { 106 | mPaint.setColor(mDividerColor); 107 | int left = 0; 108 | for (float progress : mProgressList) { 109 | left += progress * getMeasuredWidth(); 110 | canvas.drawRect(left - mDividerWidth, 0, left, getMeasuredHeight(), mPaint); 111 | } 112 | } 113 | 114 | public void setLoadingProgress(float loadingProgress) { 115 | mLoadingProgress = loadingProgress; 116 | invalidate(); 117 | } 118 | 119 | public void addProgress(float progress) { 120 | mLoadingProgress = 0; 121 | mProgressList.add(progress); 122 | invalidate(); 123 | } 124 | 125 | public void deleteProgress() { 126 | mProgressList.remove(mProgressList.size() - 1); 127 | invalidate(); 128 | } 129 | 130 | public void clear() { 131 | mProgressList.clear(); 132 | invalidate(); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/view/RecordButton.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.support.annotation.Nullable; 8 | import android.util.AttributeSet; 9 | import android.view.MotionEvent; 10 | import android.widget.TextView; 11 | 12 | /** 13 | * Created by 薛贤俊 on 2018/2/25. 14 | */ 15 | 16 | public class RecordButton extends TextView { 17 | 18 | private static final int BACKGROUND_COLOR = Color.parseColor("#fe2c55"); 19 | 20 | private int mBackgroundColor = BACKGROUND_COLOR; 21 | 22 | private Paint mPaint; 23 | 24 | private OnRecordListener mListener; 25 | 26 | public RecordButton(Context context) { 27 | super(context); 28 | init(); 29 | } 30 | 31 | public RecordButton(Context context, @Nullable AttributeSet attrs) { 32 | super(context, attrs); 33 | init(); 34 | } 35 | 36 | private void init() { 37 | setBackground(null); 38 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 39 | mPaint.setColor(mBackgroundColor); 40 | } 41 | 42 | @Override 43 | protected void onDraw(Canvas canvas) { 44 | canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, 45 | getMeasuredWidth() / 2, mPaint); 46 | super.onDraw(canvas); 47 | } 48 | 49 | @Override 50 | public boolean onTouchEvent(MotionEvent event) { 51 | if (mListener == null) { 52 | return false; 53 | } 54 | switch (event.getAction()) { 55 | case MotionEvent.ACTION_DOWN: 56 | mListener.onRecordStart(); 57 | startAnimation(); 58 | break; 59 | case MotionEvent.ACTION_UP: 60 | case MotionEvent.ACTION_CANCEL: 61 | mListener.onRecordStop(); 62 | stopAnimation(); 63 | break; 64 | } 65 | return true; 66 | } 67 | 68 | private void startAnimation() { 69 | 70 | } 71 | 72 | private void stopAnimation() { 73 | 74 | } 75 | 76 | public void setOnRecordListener(OnRecordListener listener) { 77 | mListener = listener; 78 | } 79 | 80 | public interface OnRecordListener { 81 | void onRecordStart(); 82 | 83 | void onRecordStop(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/view/RoundImageView.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.view; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.Canvas; 6 | import android.graphics.Path; 7 | import android.support.annotation.Nullable; 8 | import android.util.AttributeSet; 9 | import android.widget.ImageView; 10 | 11 | /** 12 | * Created by 薛贤俊 on 2018/3/6. 13 | */ 14 | 15 | @SuppressLint("AppCompatCustomView") 16 | public class RoundImageView extends ImageView { 17 | 18 | private Path mCirclePath; 19 | 20 | public RoundImageView(Context context) { 21 | super(context); 22 | } 23 | 24 | public RoundImageView(Context context, @Nullable AttributeSet attrs) { 25 | super(context, attrs); 26 | } 27 | 28 | @Override 29 | protected void onDraw(Canvas canvas) { 30 | ensurePath(); 31 | canvas.save(); 32 | canvas.clipPath(mCirclePath); 33 | super.onDraw(canvas); 34 | canvas.restore(); 35 | } 36 | 37 | private void ensurePath() { 38 | if (mCirclePath != null) { 39 | return; 40 | } 41 | mCirclePath = new Path(); 42 | mCirclePath.addCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, 43 | Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2, Path.Direction.CW); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/view/record/OnFrameAvailableListener.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.view.record; 2 | 3 | import com.xue.douyin.common.recorder.video.VideoFrameData; 4 | 5 | /** 6 | * Created by 薛贤俊 on 2018/3/9. 7 | */ 8 | 9 | public interface OnFrameAvailableListener { 10 | void onFrameAvailable(VideoFrameData frameData); 11 | } 12 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/view/record/OnSurfaceCreatedCallback.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.view.record; 2 | 3 | import android.graphics.SurfaceTexture; 4 | import android.opengl.EGLContext; 5 | 6 | /** 7 | * Created by 薛贤俊 on 2018/3/9. 8 | */ 9 | 10 | public interface OnSurfaceCreatedCallback { 11 | void onSurfaceCreated(SurfaceTexture texture, EGLContext context); 12 | } 13 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/view/record/RecordRenderer.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.view.record; 2 | 3 | import android.graphics.SurfaceTexture; 4 | import android.opengl.EGL14; 5 | import android.opengl.GLES11Ext; 6 | import android.opengl.GLSurfaceView; 7 | 8 | import com.xue.douyin.common.recorder.video.VideoFrameData; 9 | import com.xue.douyin.common.preview.filters.ImageFilter; 10 | import com.xue.douyin.common.preview.GLUtils; 11 | 12 | import java.util.List; 13 | 14 | import javax.microedition.khronos.egl.EGLConfig; 15 | import javax.microedition.khronos.opengles.GL10; 16 | 17 | import static android.opengl.GLES20.glViewport; 18 | 19 | /** 20 | * Created by 薛贤俊 on 2018/3/9. 21 | */ 22 | 23 | public class RecordRenderer implements GLSurfaceView.Renderer { 24 | 25 | private RecordSurfaceView mTarget; 26 | 27 | private ImageFilter mOldFilter; 28 | 29 | private List mFilterList; 30 | 31 | private ImageFilter mFilter; 32 | 33 | private int mTextureId; 34 | 35 | private SurfaceTexture mSurfaceTexture; 36 | 37 | private OnFrameAvailableListener mFrameListener; 38 | 39 | private int mPreviewWidth; 40 | 41 | private int mPreviewHeight; 42 | 43 | private float[] mMatrix = new float[16]; 44 | 45 | private int mCanvasWidth; 46 | 47 | private int mCanvasHeight; 48 | 49 | public RecordRenderer(RecordSurfaceView target) { 50 | this.mTarget = target; 51 | } 52 | 53 | @Override 54 | public void onSurfaceCreated(GL10 gl, EGLConfig config) { 55 | mTextureId = GLUtils.createTextureObject(GLES11Ext.GL_TEXTURE_EXTERNAL_OES); 56 | mSurfaceTexture = new SurfaceTexture(mTextureId); 57 | mTarget.onSurfaceCreated(mSurfaceTexture, EGL14.eglGetCurrentContext()); 58 | if (mFilter == null) { 59 | mFilter = new ImageFilter(); 60 | } else { 61 | mFilter.release(); 62 | } 63 | 64 | // mFilter = new ImageFilter(); 65 | } 66 | 67 | public void setPreviewSize(int width, int height) { 68 | mPreviewHeight = height; 69 | mPreviewWidth = width; 70 | } 71 | 72 | @Override 73 | public void onSurfaceChanged(GL10 gl, int width, int height) { 74 | mCanvasWidth = width; 75 | mCanvasHeight = height; 76 | glViewport(0, 0, width, height); 77 | } 78 | 79 | public void setFilter(ImageFilter filter) { 80 | mOldFilter = mFilter; 81 | mFilter = filter; 82 | } 83 | 84 | public void setFilterList(List filterList) { 85 | mFilterList = filterList; 86 | } 87 | 88 | 89 | @Override 90 | public void onDrawFrame(GL10 gl) { 91 | if (mFilter == null) { 92 | return; 93 | } 94 | float matrix[] = new float[16]; 95 | if (mSurfaceTexture != null) { 96 | mSurfaceTexture.updateTexImage(); 97 | } 98 | mSurfaceTexture.getTransformMatrix(matrix); 99 | 100 | if (mFrameListener != null) { 101 | mFrameListener.onFrameAvailable(new VideoFrameData(mFilter, 102 | matrix, mSurfaceTexture.getTimestamp(), mTextureId)); 103 | } 104 | 105 | mFilter.init(); 106 | if (mOldFilter != null) { 107 | mOldFilter.release(); 108 | mOldFilter = null; 109 | } 110 | mSurfaceTexture.getTransformMatrix(mMatrix); 111 | if (mFilterList != null && !mFilterList.isEmpty()) { 112 | for (ImageFilter filter : mFilterList) { 113 | filter.draw(mTextureId, mMatrix, mCanvasWidth, mCanvasHeight); 114 | } 115 | } else { 116 | mFilter.draw(mTextureId, mMatrix, mCanvasWidth, mCanvasHeight); 117 | } 118 | } 119 | 120 | public void setFrameListener(OnFrameAvailableListener listener) { 121 | this.mFrameListener = listener; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/view/record/RecordSurfaceView.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.view.record; 2 | 3 | import android.content.Context; 4 | import android.graphics.SurfaceTexture; 5 | import android.opengl.EGLContext; 6 | import android.opengl.GLSurfaceView; 7 | import android.util.AttributeSet; 8 | 9 | import com.xue.douyin.common.preview.filters.ImageFilter; 10 | 11 | /** 12 | * Created by 薛贤俊 on 2018/3/9. 13 | */ 14 | 15 | public class RecordSurfaceView extends GLSurfaceView implements SurfaceTexture.OnFrameAvailableListener { 16 | 17 | private OnSurfaceCreatedCallback mCreatedCallback; 18 | 19 | private RecordRenderer mRenderer; 20 | 21 | public RecordSurfaceView(Context context) { 22 | super(context); 23 | setup(); 24 | } 25 | 26 | public RecordSurfaceView(Context context, AttributeSet attrs) { 27 | super(context, attrs); 28 | setup(); 29 | } 30 | 31 | private void setup() { 32 | mRenderer = new RecordRenderer(this); 33 | setEGLContextClientVersion(2); 34 | setRenderer(mRenderer); 35 | setRenderMode(RENDERMODE_WHEN_DIRTY); 36 | } 37 | 38 | public void setOnSurfaceCreatedCallback(OnSurfaceCreatedCallback callback) { 39 | this.mCreatedCallback = callback; 40 | } 41 | 42 | void onSurfaceCreated(SurfaceTexture texture, EGLContext context) { 43 | if (mCreatedCallback != null) { 44 | mCreatedCallback.onSurfaceCreated(texture, context); 45 | } 46 | texture.setOnFrameAvailableListener(this); 47 | } 48 | 49 | @Override 50 | public void onFrameAvailable(SurfaceTexture surfaceTexture) { 51 | requestRender(); 52 | } 53 | 54 | public void setFrameListener(OnFrameAvailableListener listener) { 55 | mRenderer.setFrameListener(listener); 56 | } 57 | 58 | public void setPreviewSize(int width,int height){ 59 | mRenderer.setPreviewSize(width,height); 60 | } 61 | 62 | public void setFilter(ImageFilter filter){ 63 | mRenderer.setFilter(filter); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/common/view/roundrect/RoundRectLayout.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.common.view.roundrect; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Path; 7 | import android.graphics.RectF; 8 | import android.support.constraint.ConstraintLayout; 9 | import android.util.AttributeSet; 10 | 11 | import com.xue.douyin.R; 12 | 13 | /** 14 | * Created by 薛贤俊 on 2018/2/25. 15 | */ 16 | 17 | public class RoundRectLayout extends ConstraintLayout { 18 | 19 | private Path mPath; 20 | 21 | private float mRadius; 22 | 23 | public RoundRectLayout(Context context) { 24 | super(context); 25 | } 26 | 27 | public RoundRectLayout(Context context, AttributeSet attrs) { 28 | super(context, attrs); 29 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundRectLayout); 30 | try { 31 | mRadius = ta.getDimensionPixelSize(R.styleable.RoundRectLayout_radius, 0); 32 | } finally { 33 | ta.recycle(); 34 | } 35 | } 36 | 37 | @Override 38 | public void dispatchDraw(Canvas canvas) { 39 | ensurePath(); 40 | canvas.save(); 41 | canvas.clipPath(mPath); 42 | super.dispatchDraw(canvas); 43 | canvas.restore(); 44 | } 45 | 46 | private void ensurePath() { 47 | if (mPath != null) { 48 | return; 49 | } 50 | mPath = new Path(); 51 | mPath.addRoundRect(new RectF(0,0,getMeasuredWidth(),getMeasuredHeight()),mRadius,mRadius, Path.Direction.CW); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/ffmpeg/VideoCmdCallback.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.ffmpeg; 2 | 3 | /** 4 | * Created by 薛贤俊 on 2018/3/14. 5 | */ 6 | 7 | public interface VideoCmdCallback { 8 | void onCommandFinish(boolean success); 9 | } 10 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/ffmpeg/VideoQueue.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.ffmpeg; 2 | 3 | import android.os.Handler; 4 | import android.os.HandlerThread; 5 | 6 | import Jni.FFmpegCmd; 7 | 8 | /** 9 | * Created by 薛贤俊 on 2018/3/14. 10 | */ 11 | 12 | public class VideoQueue { 13 | private Handler mHandler = new Handler(); 14 | 15 | public VideoQueue() { 16 | HandlerThread thread = new HandlerThread("ffmpeg"); 17 | thread.start(); 18 | mHandler = new Handler(thread.getLooper()); 19 | } 20 | 21 | public void release() { 22 | if (mHandler == null) { 23 | return; 24 | } 25 | mHandler.getLooper().quitSafely(); 26 | mHandler = null; 27 | } 28 | 29 | public void execCommand(final String[] cmd, final VideoCmdCallback callback) { 30 | mHandler.post(new Runnable() { 31 | @Override 32 | public void run() { 33 | FFmpegCmd.exec(cmd, callback); 34 | } 35 | }); 36 | } 37 | 38 | public void execCommand(final String[] cmd) { 39 | execCommand(cmd, null); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/module/effect/presenter/AfterEffectPresenter.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.module.effect.presenter; 2 | 3 | 4 | import android.content.Intent; 5 | import android.graphics.SurfaceTexture; 6 | import android.support.annotation.IntDef; 7 | import android.view.Surface; 8 | import android.view.View; 9 | import android.widget.SeekBar; 10 | 11 | import com.xue.douyin.R; 12 | import com.xue.douyin.base.presenter.BaseActivityPresenter; 13 | import com.xue.douyin.common.player.VideoPlayer; 14 | import com.xue.douyin.module.effect.activity.AfterEffectActivity; 15 | 16 | import java.lang.annotation.Retention; 17 | import java.lang.annotation.RetentionPolicy; 18 | 19 | 20 | /** 21 | * Created by 薛贤俊 on 2018/3/24. 22 | */ 23 | 24 | public class AfterEffectPresenter extends BaseActivityPresenter implements 25 | View.OnClickListener, VideoPlayer.OnPlayerProgressListener, SeekBar.OnSeekBarChangeListener { 26 | /** 27 | * 正在播放 28 | */ 29 | private static final int STATE_PLAYING = 1; 30 | /** 31 | * 正在编辑 32 | */ 33 | private static final int STATE_EDITING = 2; 34 | 35 | @IntDef({STATE_PLAYING, STATE_EDITING}) 36 | @Retention(RetentionPolicy.SOURCE) 37 | public @interface State { 38 | } 39 | 40 | private @State 41 | int state = STATE_PLAYING; 42 | 43 | 44 | private String filePath; 45 | 46 | private VideoPlayer player; 47 | 48 | private boolean seekBarTouching = false; 49 | 50 | private boolean playing = true; 51 | 52 | public AfterEffectPresenter(AfterEffectActivity target) { 53 | super(target); 54 | } 55 | 56 | public void init() { 57 | Intent intent = getTarget().getIntent(); 58 | filePath = intent.getStringExtra(AfterEffectActivity.KEY_FINAL_PATH); 59 | player = new VideoPlayer(filePath); 60 | player.setOnPlayerProgressListener(this); 61 | } 62 | 63 | 64 | public void start(SurfaceTexture surface) { 65 | player.configure(surface); 66 | getTarget().setMaxSeconds(player.getDuration()); 67 | getTarget().setCurrentSeconds(0); 68 | getTarget().setSeekBarMax(player.getDuration()); 69 | getTarget().setSeekBarProgress(0); 70 | player.start(); 71 | } 72 | 73 | 74 | public void pause() { 75 | player.pause(); 76 | getTarget().showPlayButton(); 77 | playing = false; 78 | } 79 | 80 | public void resume() { 81 | player.resume(); 82 | getTarget().hidePlayButton(); 83 | playing = true; 84 | } 85 | 86 | public void stop() { 87 | player.stop(); 88 | } 89 | 90 | @Override 91 | public void onClick(View v) { 92 | switch (v.getId()) { 93 | case R.id.btn_back: 94 | onBackClick(); 95 | break; 96 | case R.id.btn_effect: 97 | onEffectClick(); 98 | break; 99 | case R.id.btn_play: 100 | onPlayClick(); 101 | break; 102 | } 103 | } 104 | 105 | private void onPlayClick() { 106 | if (state != STATE_EDITING) { 107 | return; 108 | } 109 | if (playing) { 110 | pause(); 111 | } else { 112 | resume(); 113 | } 114 | 115 | } 116 | 117 | private void onBackClick() { 118 | if (state == STATE_PLAYING) { 119 | //如果是播放状态,那么直接返回上一个页面 120 | getTarget().finish(); 121 | } else { 122 | //编辑状态,则返回播放状态 123 | getTarget().hideEffectPanel(); 124 | getTarget().enlargeSurfaceView(); 125 | getTarget().hidePlayButton(); 126 | state = STATE_PLAYING; 127 | if (!playing) { 128 | resume(); 129 | } 130 | } 131 | } 132 | 133 | private void onEffectClick() { 134 | if (state == STATE_EDITING) { 135 | return; 136 | } 137 | pause(); 138 | player.seekTo(0); 139 | getTarget().setSeekBarProgress(0); 140 | getTarget().showEffectPanel(); 141 | getTarget().shrinkSurfaceView(); 142 | getTarget().showPlayButton(); 143 | state = STATE_EDITING; 144 | } 145 | 146 | 147 | @Override 148 | public void onPlayerProgress(final long currentTimeUs) { 149 | getTarget().runOnUiThread(new Runnable() { 150 | @Override 151 | public void run() { 152 | getTarget().setCurrentSeconds(currentTimeUs); 153 | getTarget().setSeekBarProgress(currentTimeUs); 154 | } 155 | }); 156 | } 157 | 158 | @Override 159 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 160 | if (seekBarTouching && fromUser) { 161 | if (playing) { 162 | pause(); 163 | } 164 | player.seekTo(progress); 165 | } 166 | } 167 | 168 | @Override 169 | public void onStartTrackingTouch(SeekBar seekBar) { 170 | seekBarTouching = true; 171 | } 172 | 173 | @Override 174 | public void onStopTrackingTouch(SeekBar seekBar) { 175 | seekBarTouching = false; 176 | } 177 | } 178 | 179 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/module/effect/presenter/PlayRenderer.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.module.effect.presenter; 2 | 3 | import android.graphics.SurfaceTexture; 4 | import android.opengl.GLES11Ext; 5 | import android.opengl.GLSurfaceView; 6 | 7 | import com.xue.douyin.common.preview.GLUtils; 8 | import com.xue.douyin.common.preview.filters.ImageFilter; 9 | 10 | import javax.microedition.khronos.egl.EGLConfig; 11 | import javax.microedition.khronos.opengles.GL10; 12 | 13 | import static android.opengl.GLES20.glViewport; 14 | 15 | /** 16 | * Created by 薛贤俊 on 2018/4/18. 17 | */ 18 | 19 | public class PlayRenderer implements GLSurfaceView.Renderer { 20 | 21 | private ImageFilter filter; 22 | 23 | private int textureId; 24 | 25 | private SurfaceTexture surfaceTexture; 26 | 27 | @Override 28 | public void onSurfaceCreated(GL10 gl, EGLConfig config) { 29 | textureId = GLUtils.createTextureObject(GLES11Ext.GL_TEXTURE_EXTERNAL_OES); 30 | surfaceTexture = new SurfaceTexture(textureId); 31 | } 32 | 33 | @Override 34 | public void onSurfaceChanged(GL10 gl, int width, int height) { 35 | glViewport(0, 0, width, height); 36 | } 37 | 38 | @Override 39 | public void onDrawFrame(GL10 gl) { 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/module/record/activity/RecordActivity.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.module.record.activity; 2 | 3 | import android.graphics.SurfaceTexture; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.view.WindowManager; 9 | import android.widget.CheckBox; 10 | import android.widget.RadioGroup; 11 | 12 | import com.xue.douyin.common.view.ProgressView; 13 | import com.xue.douyin.common.view.record.OnFrameAvailableListener; 14 | import com.xue.douyin.R; 15 | import com.xue.douyin.base.activity.BaseBlankActivity; 16 | import com.xue.douyin.common.camera.CameraCompat; 17 | import com.xue.douyin.common.view.RecordButton; 18 | import com.xue.douyin.common.view.record.RecordSurfaceView; 19 | import com.xue.douyin.module.record.presenter.RecordPresenter; 20 | 21 | /** 22 | * Created by 薛贤俊 on 2018/3/9. 23 | */ 24 | 25 | public class RecordActivity extends BaseBlankActivity { 26 | 27 | 28 | private RecordSurfaceView mSurfaceView; 29 | 30 | private CameraCompat mCamera; 31 | 32 | private CheckBox mCbFlashLight; 33 | 34 | private RecordButton mButton; 35 | 36 | private RadioGroup mSpeedButtons; 37 | 38 | private ProgressView mProgressView; 39 | 40 | private CameraCompat.CameraSize mPreviewSize; 41 | 42 | @Override 43 | protected void initPresenter() { 44 | mPresenter = new RecordPresenter(this); 45 | } 46 | 47 | @Override 48 | protected void onCreate(@Nullable Bundle savedInstanceState) { 49 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 50 | WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏 51 | super.onCreate(savedInstanceState); 52 | setContentView(R.layout.activity_record); 53 | mPresenter.init(); 54 | mCamera = CameraCompat.newInstance(this); 55 | 56 | mSurfaceView = findViewById(R.id.sv_record); 57 | mSurfaceView.setOnSurfaceCreatedCallback(mPresenter); 58 | CheckBox cb = findViewById(R.id.cb_flashlight); 59 | cb.setOnCheckedChangeListener(mPresenter); 60 | mCbFlashLight = cb; 61 | cb = findViewById(R.id.cb_camera); 62 | cb.setOnCheckedChangeListener(mPresenter); 63 | mButton = findViewById(R.id.btn_record); 64 | mButton.setOnRecordListener(mPresenter); 65 | findViewById(R.id.btn_next).setOnClickListener(mPresenter); 66 | mSpeedButtons = findViewById(R.id.rg_speed); 67 | mSpeedButtons.setOnCheckedChangeListener(mPresenter); 68 | findViewById(R.id.btn_delete).setOnClickListener(mPresenter); 69 | mProgressView = findViewById(R.id.record_progress); 70 | } 71 | 72 | @Override 73 | protected void onResume() { 74 | super.onResume(); 75 | mSurfaceView.onResume(); 76 | mCamera.startPreview(); 77 | mPreviewSize = mCamera.getOutputSize(); 78 | mSurfaceView.setPreviewSize(mPreviewSize.height,mPreviewSize.width); 79 | hideSystemNavigationBar(); 80 | } 81 | 82 | public CameraCompat.CameraSize getCameraSize(){ 83 | return mCamera.getOutputSize(); 84 | } 85 | 86 | 87 | @Override 88 | protected void onPause() { 89 | mPresenter.stopRecord(); 90 | mCamera.stopPreview(true); 91 | mSurfaceView.onPause(); 92 | super.onPause(); 93 | } 94 | 95 | @Override 96 | protected void onDestroy() { 97 | super.onDestroy(); 98 | } 99 | 100 | 101 | public void setFrameListener(OnFrameAvailableListener listener) { 102 | mSurfaceView.setFrameListener(listener); 103 | } 104 | 105 | public void startPreview(final SurfaceTexture texture) { 106 | runOnUiThread(new Runnable() { 107 | @Override 108 | public void run() { 109 | mCamera.setSurfaceTexture(texture); 110 | mCamera.startPreview(); 111 | } 112 | }); 113 | } 114 | 115 | public void switchCamera(boolean checked) { 116 | mCbFlashLight.setEnabled(!checked); 117 | mCamera.switchCamera(); 118 | mCbFlashLight.setChecked(false); 119 | } 120 | 121 | public void switchFlashLight(boolean checked) { 122 | if (checked) { 123 | mCamera.turnLight(true); 124 | } else { 125 | mCamera.turnLight(false); 126 | } 127 | } 128 | 129 | public void hideViews() { 130 | findViewById(R.id.record_group).setVisibility(View.GONE); 131 | } 132 | 133 | public void showViews() { 134 | findViewById(R.id.record_group).setVisibility(View.VISIBLE); 135 | } 136 | 137 | public void setProgress(float progress){ 138 | mProgressView.setLoadingProgress(progress); 139 | } 140 | 141 | public void addProgress(float progress){ 142 | mProgressView.addProgress(progress); 143 | } 144 | 145 | public void deleteProgress(){ 146 | mProgressView.deleteProgress(); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/permission/PermissionFragment.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.permission; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | /** 12 | * Created by 薛贤俊 on 2018/2/25. 13 | */ 14 | 15 | public class PermissionFragment extends Fragment { 16 | 17 | private OnRequestPermissionsResultCallback mCallback; 18 | 19 | @Nullable 20 | @Override 21 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 22 | @Nullable Bundle savedInstanceState) { 23 | View view = new View(getActivity()); 24 | view.setLayoutParams(new ViewGroup.LayoutParams(0, 0)); 25 | view.setVisibility(View.INVISIBLE); 26 | return view; 27 | } 28 | 29 | public void setCallback(OnRequestPermissionsResultCallback callback) { 30 | this.mCallback = callback; 31 | } 32 | 33 | @Override 34 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 35 | @NonNull int[] grantResults) { 36 | if (mCallback != null) { 37 | mCallback.onRequestPermissionsResult(requestCode, permissions, grantResults); 38 | } 39 | } 40 | 41 | public interface OnRequestPermissionsResultCallback { 42 | void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/permission/PermissionLifeCycleImpl.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.permission; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.os.Bundle; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v4.app.FragmentActivity; 8 | import android.support.v4.app.FragmentTransaction; 9 | 10 | /** 11 | * Created by 薛贤俊 on 2018/2/25. 12 | */ 13 | 14 | public class PermissionLifeCycleImpl implements Application.ActivityLifecycleCallbacks { 15 | 16 | private static final String FRAGMENT_TAG = "permission:fragment"; 17 | 18 | private PermissionFragment mFragment; 19 | 20 | @Override 21 | public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 22 | FragmentActivity fActivity = (FragmentActivity) activity; 23 | Fragment fragment = fActivity.getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG); 24 | if (fragment == null) { 25 | addFragment(fActivity); 26 | } else { 27 | mFragment = (PermissionFragment) fragment; 28 | } 29 | } 30 | 31 | @Override 32 | public void onActivityStarted(Activity activity) { 33 | 34 | } 35 | 36 | @Override 37 | public void onActivityResumed(Activity activity) { 38 | FragmentActivity fActivity = (FragmentActivity) activity; 39 | Fragment fragment = fActivity.getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG); 40 | if (fragment == null) { 41 | addFragment(fActivity); 42 | } else { 43 | mFragment = (PermissionFragment) fragment; 44 | } 45 | } 46 | 47 | @Override 48 | public void onActivityPaused(Activity activity) { 49 | 50 | } 51 | 52 | @Override 53 | public void onActivityStopped(Activity activity) { 54 | 55 | } 56 | 57 | @Override 58 | public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 59 | 60 | } 61 | 62 | @Override 63 | public void onActivityDestroyed(Activity activity) { 64 | 65 | } 66 | 67 | private void addFragment(FragmentActivity activity) { 68 | mFragment = new PermissionFragment(); 69 | FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction(); 70 | ft.add(mFragment,FRAGMENT_TAG); 71 | ft.commitAllowingStateLoss(); 72 | } 73 | 74 | public PermissionFragment getFragment(){ 75 | return mFragment; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/permission/PermissionManager.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.permission; 2 | 3 | import android.content.pm.PackageManager; 4 | import android.support.annotation.NonNull; 5 | import android.support.v4.app.ActivityCompat; 6 | 7 | import com.xue.douyin.application.AppProfile; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by 薛贤俊 on 2018/2/25. 14 | */ 15 | 16 | public class PermissionManager implements PermissionFragment.OnRequestPermissionsResultCallback { 17 | 18 | private static final int PERMISSION_REQUEST_CODE = 888; 19 | 20 | private static PermissionManager sInstance; 21 | 22 | private PermissionLifeCycleImpl mCycleImpl; 23 | 24 | private OnPermissionGrantedListener mPermissionCallback; 25 | 26 | public static PermissionManager instance() { 27 | if (sInstance == null) { 28 | synchronized (PermissionManager.class) { 29 | if (sInstance == null) { 30 | sInstance = new PermissionManager(); 31 | } 32 | } 33 | } 34 | return sInstance; 35 | } 36 | 37 | private PermissionManager() { 38 | mCycleImpl = new PermissionLifeCycleImpl(); 39 | AppProfile.registerActivityLifeCycle(mCycleImpl); 40 | } 41 | 42 | public void checkPermission(String[] permissions, OnPermissionGrantedListener listener) { 43 | if (permissions == null || listener == null) { 44 | return; 45 | } 46 | mPermissionCallback = listener; 47 | List shouldRequest = new ArrayList<>(); 48 | for (String permission : permissions) { 49 | if (ActivityCompat.checkSelfPermission(AppProfile.getContext(), permission) 50 | != PackageManager.PERMISSION_GRANTED) { 51 | shouldRequest.add(permission); 52 | } else { 53 | listener.onPermissionGranted(permission); 54 | } 55 | } 56 | if (shouldRequest.isEmpty()) { 57 | return; 58 | } 59 | String[] requests = new String[shouldRequest.size()]; 60 | mCycleImpl.getFragment().setCallback(this); 61 | mCycleImpl.getFragment().requestPermissions(shouldRequest.toArray(requests), 62 | PERMISSION_REQUEST_CODE); 63 | 64 | } 65 | 66 | public void checkPermission(String permission, OnPermissionGrantedListener listener) { 67 | if (permission == null) { 68 | return; 69 | } 70 | checkPermission(new String[]{permission}, listener); 71 | } 72 | 73 | 74 | @Override 75 | public void onRequestPermissionsResult(int requestCode, 76 | @NonNull String permissions[], @NonNull int[] grantResults) { 77 | if (mPermissionCallback == null) { 78 | return; 79 | } 80 | if (permissions.length != grantResults.length) { 81 | return; 82 | } 83 | switch (requestCode) { 84 | case PERMISSION_REQUEST_CODE: 85 | for (int i = 0; i < grantResults.length; i++) { 86 | if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { 87 | mPermissionCallback.onPermissionGranted(permissions[i]); 88 | } else { 89 | mPermissionCallback.onPermissionDenied(permissions[i]); 90 | } 91 | } 92 | } 93 | } 94 | 95 | public interface OnPermissionGrantedListener { 96 | void onPermissionGranted(String permission); 97 | 98 | void onPermissionDenied(String permission); 99 | } 100 | 101 | 102 | } 103 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/permission/SimplePermissionCallback.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.permission; 2 | 3 | /** 4 | * Created by 薛贤俊 on 2018/3/1. 5 | */ 6 | 7 | public class SimplePermissionCallback implements PermissionManager.OnPermissionGrantedListener { 8 | @Override 9 | public void onPermissionGranted(String permission) { 10 | 11 | } 12 | 13 | @Override 14 | public void onPermissionDenied(String permission) { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Douyin/app/src/main/java/com/xue/douyin/utils/ResourcesUtil.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.utils; 2 | 3 | import android.support.annotation.DimenRes; 4 | 5 | import com.xue.douyin.application.AppProfile; 6 | 7 | /** 8 | * Created by 薛贤俊 on 2018/4/23. 9 | */ 10 | 11 | public class ResourcesUtil { 12 | 13 | public static int getDimensionPixel(@DimenRes int id) { 14 | return AppProfile.getContext().getResources().getDimensionPixelSize(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/drawable/bg_record_next_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/drawable/selector_beautify.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/drawable/selector_camera.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/drawable/selector_flashlight.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/drawable/selector_speed_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/drawable/selector_speed_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/drawable/shape_play_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/drawable/shape_play_progress_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/drawable/shape_speed_control.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/layout/activity_after_effect.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 31 | 32 | 41 | 42 | 52 | 53 | 64 | 65 | 74 | 75 | 81 | 82 | 87 | 88 | 99 | 100 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/layout/activity_blank.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 29 | 30 | 41 | 42 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/layout/activity_with_actionbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/layout/test.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xhdpi/filter_age.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xhdpi/filter_age.jpg -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xhdpi/filter_extraordinary.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xhdpi/filter_extraordinary.jpg -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xhdpi/filter_japan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xhdpi/filter_japan.jpg -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xhdpi/filter_normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xhdpi/filter_normal.jpg -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xhdpi/filter_pure.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xhdpi/filter_pure.jpg -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xhdpi/ic_effect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xhdpi/ic_effect.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xhdpi/ic_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xhdpi/ic_play.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xhdpi/ic_white_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xhdpi/ic_white_back.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxhdpi/ic_beautify_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxhdpi/ic_beautify_off.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxhdpi/ic_beautify_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxhdpi/ic_beautify_on.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxhdpi/ic_camera_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxhdpi/ic_camera_back.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxhdpi/ic_camera_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxhdpi/ic_camera_front.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxhdpi/ic_countdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxhdpi/ic_countdown.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxhdpi/ic_cut_music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxhdpi/ic_cut_music.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxhdpi/ic_delete.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxhdpi/ic_flash_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxhdpi/ic_flash_off.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxhdpi/ic_flash_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxhdpi/ic_flash_on.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/fragment_3d.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | varying vec2 vTextureCoord; 3 | uniform sampler2D uTexture; 4 | uniform sampler2D uTexture1; 5 | uniform sampler2D uTexture2; 6 | const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721); 7 | void main(){ 8 | float strength = 0.5; 9 | vec4 textureColor = texture2D(uTexture,vTextureCoord); 10 | mediump float blueColor = textureColor.b * 63.0; 11 | mediump vec2 quad1; 12 | quad1.y = floor(blueColor/8.0); 13 | quad1.x = floor(blueColor) - quad1.y*8.0; 14 | mediump vec2 quad2; 15 | quad2.y = floor(ceil(blueColor)/7.999); 16 | quad2.x = ceil(blueColor) - quad2.y * 8.0; 17 | highp vec2 texPos1; 18 | texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); 19 | texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); 20 | highp vec2 texPos2; 21 | texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); 22 | texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); 23 | lowp vec4 newColor1 = texture2D(uTexture1, texPos1); 24 | lowp vec4 newColor2 = texture2D(uTexture1, texPos2); 25 | lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor)); 26 | vec4 origin = mix(textureColor, vec4(newColor.rgb, textureColor.w), strength); 27 | lowp float luminance = dot(origin.rgb, luminanceWeighting); 28 | lowp vec3 greyScaleColor = vec3(luminance); 29 | gl_FragColor = vec4(mix(greyScaleColor, origin.rgb, 3.0), origin.w); 30 | } -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/fragment_common.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | varying vec2 vTextureCoord; 3 | uniform sampler2D uTexture0; 4 | void main(){ 5 | gl_FragColor = texture2D(uTexture0,vTextureCoord); 6 | } -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/fragment_current_frame.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | varying vec2 vTextureCoord; 3 | uniform sampler2D uTexture0; 4 | uniform sampler2D uTexture1; 5 | uniform sampler2D uTexture2; 6 | 7 | vec4 lookup(in vec4 textureColor){ 8 | mediump float blueColor = textureColor.b * 63.0; 9 | mediump vec2 quad1; 10 | quad1.y = floor(floor(blueColor) / 8.0); 11 | quad1.x = floor(blueColor) - (quad1.y * 8.0); 12 | mediump vec2 quad2; 13 | quad2.y = floor(ceil(blueColor) / 8.0); 14 | quad2.x = ceil(blueColor) - (quad2.y * 8.0); 15 | highp vec2 texPos1; 16 | texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); 17 | texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); 18 | texPos1.y = 1.0-texPos1.y; 19 | highp vec2 texPos2; 20 | texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); 21 | texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); 22 | texPos2.y = 1.0-texPos2.y; 23 | lowp vec4 newColor1 = texture2D(uTexture2, texPos1); 24 | lowp vec4 newColor2 = texture2D(uTexture2, texPos2); 25 | lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor)); 26 | return newColor; 27 | } 28 | void main(){ 29 | vec4 lastFrame = texture2D(uTexture1,vTextureCoord); 30 | vec4 currentFrame = lookup(texture2D(uTexture0,vTextureCoord)); 31 | 32 | gl_FragColor = vec4(0.95 * lastFrame.r + 0.05* currentFrame.r,currentFrame.g * 0.2 + lastFrame.g * 0.8, currentFrame.b,1.0); 33 | } -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/fragment_sobel_edge_detect.glsl: -------------------------------------------------------------------------------- 1 | #extension GL_OES_EGL_image_external : require 2 | precision mediump float; 3 | uniform samplerExternalOES uTexture; 4 | varying vec2 vTextureCoordinate; 5 | varying vec2 vLeftTextureCoordinate; 6 | varying vec2 vRightTextureCoordinate; 7 | varying vec2 vTopTextureCoordinate; 8 | varying vec2 vTopLeftTextureCoordinate; 9 | varying vec2 vTopRightTextureCoordinate; 10 | varying vec2 vBottomTextureCoordinate; 11 | varying vec2 vBottomLeftTextureCoordinate; 12 | varying vec2 vBottomRightTextureCoordinate; 13 | 14 | void main(){ 15 | float bottomLeftIntensity = texture2D(uTexture, vBottomLeftTextureCoordinate).r; 16 | float topRightIntensity = texture2D(uTexture, vTopRightTextureCoordinate).r; 17 | float topLeftIntensity = texture2D(uTexture, vTopLeftTextureCoordinate).r; 18 | float bottomRightIntensity = texture2D(uTexture, vBottomRightTextureCoordinate).r; 19 | float leftIntensity = texture2D(uTexture, vLeftTextureCoordinate).r; 20 | float rightIntensity = texture2D(uTexture, vRightTextureCoordinate).r; 21 | float bottomIntensity = texture2D(uTexture, vBottomTextureCoordinate).r; 22 | float topIntensity = texture2D(uTexture, vTopTextureCoordinate).r; 23 | float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; 24 | float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; 25 | float mag = length(vec2(h, v)); 26 | gl_FragColor = vec4(vec3(mag), 1.0); 27 | } 28 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/glitch.glsl: -------------------------------------------------------------------------------- 1 | #extension GL_OES_EGL_image_external : require 2 | precision highp float; 3 | varying vec2 vTextureCoord; 4 | uniform samplerExternalOES uTexture; 5 | uniform vec2 uScanLineJitter;//displacement threshold 6 | uniform float uColorDrift; 7 | uniform float uGlobalTime; 8 | float nrand(in float x, in float y) 9 | { 10 | return fract(sin(dot(vec2(x, y), vec2(12.9898, 78.233))) * 43758.5453); 11 | } 12 | void main(){ 13 | float u = vTextureCoord.x; 14 | float v = vTextureCoord.y; 15 | float jitter = nrand(u,0.0) * 2.0 - 1.0; 16 | float drift = uColorDrift; 17 | float offsetParam = step(uScanLineJitter.y,abs(jitter)); 18 | jitter = jitter * offsetParam * uScanLineJitter.x; 19 | vec4 color1 = texture2D(uTexture,fract(vec2( u,v + jitter))); 20 | vec4 color2 = texture2D(uTexture,fract(vec2(u,v+jitter-u*drift))); 21 | gl_FragColor = vec4(color1.r,color2.g,color1.b,1.0); 22 | } -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/lookup_glitch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/raw/lookup_glitch.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/lookup_vertigo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/app/src/main/res/raw/lookup_vertigo.png -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/test.glsl: -------------------------------------------------------------------------------- 1 | #extension GL_OES_EGL_image_external : require 2 | precision mediump float; 3 | varying vec2 vTextureCoord; 4 | uniform samplerExternalOES uTexture; 5 | uniform float uAdditionalColor; 6 | void main(){ 7 | vec4 color = texture2D(uTexture,vTextureCoord); 8 | gl_FragColor = vec4(color.r + uAdditionalColor,color.g + uAdditionalColor,color.b + uAdditionalColor,color.a); 9 | } -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/vertex_3d.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 aPosition; 2 | attribute vec4 aTextureCoord; 3 | varying vec2 vTextureCoord; 4 | void main(){ 5 | gl_Position = vec4(aPosition,0.0,1.0); 6 | vTextureCoord = (uTexMatrix * aTextureCoord).xy; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/vertex_common.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 aPosition; 2 | attribute vec4 aTextureCoord; 3 | varying vec2 vTextureCoord; 4 | void main(){ 5 | gl_Position = vec4(aPosition,0.0,1.0); 6 | vTextureCoord = aTextureCoord.xy; 7 | } -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/vertex_sobel_edge_detect.glsl: -------------------------------------------------------------------------------- 1 | uniform mat4 uTexMatrix; 2 | attribute vec2 aPosition; 3 | attribute vec4 aTextureCoordinate; 4 | uniform highp float texelWidth; 5 | uniform highp float texelHeight; 6 | varying vec2 vTextureCoordinate; 7 | varying vec2 vLeftTextureCoordinate; 8 | varying vec2 vRightTextureCoordinate; 9 | varying vec2 vTopTextureCoordinate; 10 | varying vec2 vTopLeftTextureCoordinate; 11 | varying vec2 vTopRightTextureCoordinate; 12 | varying vec2 vBottomTextureCoordinate; 13 | varying vec2 vBottomLeftTextureCoordinate; 14 | varying vec2 vBottomRightTextureCoordinate; 15 | 16 | void main(){ 17 | gl_Position = vec4(aPosition,0.0,1.0); 18 | vTextureCoordinate = (uTexMatrix * aTextureCoordinate).xy; 19 | vec2 widthStep = vec2(texelWidth, 0.0); 20 | vec2 heightStep = vec2(0.0, texelHeight); 21 | vec2 widthHeightStep = vec2(texelWidth, texelHeight); 22 | vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight); 23 | vLeftTextureCoordinate = vTextureCoordinate - widthStep; 24 | vRightTextureCoordinate = vTextureCoordinate + widthStep; 25 | vTopTextureCoordinate = vTextureCoordinate - heightStep; 26 | vTopLeftTextureCoordinate = vTextureCoordinate - widthHeightStep; 27 | vTopRightTextureCoordinate = vTextureCoordinate + widthNegativeHeightStep; 28 | vBottomTextureCoordinate = vTextureCoordinate + heightStep; 29 | vBottomLeftTextureCoordinate = vTextureCoordinate - widthNegativeHeightStep; 30 | vBottomRightTextureCoordinate = vTextureCoordinate + widthHeightStep; 31 | } -------------------------------------------------------------------------------- /Douyin/app/src/main/res/raw/vertigo_fragment.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | varying vec2 vTextureCoord; 3 | uniform sampler2D uTexture; 4 | uniform sampler2D uTexture1; 5 | uniform sampler2D uLookTexture; 6 | 7 | void lookup(out vec4 fragColor,in vec4 textureColor){ 8 | float strength = 0.5; 9 | mediump float blueColor = textureColor.b * 63.0; 10 | mediump vec2 quad1; 11 | quad1.y = floor(blueColor/8.0); 12 | quad1.x = floor(blueColor) - quad1.y*8.0; 13 | mediump vec2 quad2; 14 | quad2.y = floor(ceil(blueColor)/7.999); 15 | quad2.x = ceil(blueColor) - quad2.y * 8.0; 16 | highp vec2 texPos1; 17 | texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); 18 | texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); 19 | highp vec2 texPos2; 20 | texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); 21 | texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); 22 | lowp vec4 newColor1 = texture2D(uLookTexture, texPos1); 23 | lowp vec4 newColor2 = texture2D(uLookTexture, texPos2); 24 | lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor)); 25 | fragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), strength); 26 | } 27 | 28 | void main(){ 29 | vec4 origin = texture2D(uTexture,vTextureCoord); 30 | vec4 last = texture2D(uTexture1,vTextureCoord); 31 | gl_FragColor = vec4(origin.r * 0.7 + last.r * 0.3,origin.g * 0.7 + last.g * 0.3,origin.b * 0.8 + last.b * 0.2,1.0); 32 | } -------------------------------------------------------------------------------- /Douyin/app/src/main/res/values/attr.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #000000 4 | #fe2c55 5 | #ffffff 6 | #face15 7 | #161823 8 | #ffffff 9 | 10 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15dp 5 | 6 | 43dp 7 | 8 | 7dp 9 | 6dp 10 | 6dp 11 | 4dp 12 | 1dp 13 | 40dp 14 | 80dp 15 | 20dp 16 | 20dp 17 | 10dp 18 | 40dp 19 | 30dp 20 | 70dp 21 | 35dp 22 | 7dp 23 | 9dp 24 | 12dp 25 | 10dp 26 | 14dp 27 | 16dp 28 | 29 | 250dp 30 | 50dp 31 | 25dp 32 | 275dp 33 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 抖音Demo 3 | 按住拍 4 | 下一步 5 | 6 | -------------------------------------------------------------------------------- /Douyin/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Douyin/app/src/test/java/com/xue/douyin/douyin/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.xue.douyin.douyin; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /Douyin/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.0.1' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /Douyin/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /Douyin/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/Douyin/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Douyin/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Feb 24 13:52:49 CST 2018 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-4.1-all.zip 7 | -------------------------------------------------------------------------------- /Douyin/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /Douyin/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VideoAudioDemo 2 | Video Audio practice demo 3 | 4 | ### 毛刺 - GlitchFilter 5 | ### 缩放 - ScaleFilter 6 | ### 抖动 - ShakeEffectFilter 7 | ### 闪白 - ShineWhiteFilter 8 | ### 灵魂出窍 - SoulOutFilter 9 | ### 幻觉 - VertigoFilter 10 | -------------------------------------------------------------------------------- /soundtouch/Android.mk: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2010 The Android Open Source Project 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # $Id: Android.mk 216 2015-05-18 15:28:41Z oparviai $ 16 | 17 | LOCAL_PATH := $(call my-dir) 18 | 19 | include $(CLEAR_VARS) 20 | 21 | # *** Remember: Change -O0 into -O2 in add-applications.mk *** 22 | 23 | LOCAL_MODULE := soundtouch 24 | LOCAL_SRC_FILES := com_netease_soundtouch_SoundTouch.cpp SoundTouch/AAFilter.cpp SoundTouch/FIFOSampleBuffer.cpp \ 25 | SoundTouch/FIRFilter.cpp SoundTouch/cpu_detect_x86.cpp \ 26 | SoundTouch/sse_optimized.cpp SoundStretch/WavFile.cpp \ 27 | SoundTouch/RateTransposer.cpp SoundTouch/SoundTouch.cpp \ 28 | SoundTouch/InterpolateCubic.cpp SoundTouch/InterpolateLinear.cpp \ 29 | SoundTouch/InterpolateShannon.cpp SoundTouch/TDStretch.cpp \ 30 | SoundTouch/BPMDetect.cpp SoundTouch/PeakFinder.cpp 31 | 32 | # for native audio 33 | LOCAL_SHARED_LIBRARIES += -lgcc 34 | # --whole-archive -lgcc 35 | # for logging 36 | LOCAL_LDLIBS += -llog 37 | # for native asset manager 38 | #LOCAL_LDLIBS += -landroid 39 | 40 | # Custom Flags: 41 | # -fvisibility=hidden : don't export all symbols 42 | LOCAL_CFLAGS += -fvisibility=hidden -I include -fdata-sections -ffunction-sections 43 | 44 | # OpenMP mode : enable these flags to enable using OpenMP for parallel computation 45 | #LOCAL_CFLAGS += -fopenmp 46 | #LOCAL_LDFLAGS += -fopenmp 47 | 48 | 49 | # Use ARM instruction set instead of Thumb for improved calculation performance in ARM CPUs 50 | LOCAL_ARM_MODE := arm 51 | 52 | include $(BUILD_SHARED_LIBRARY) 53 | -------------------------------------------------------------------------------- /soundtouch/Application.mk: -------------------------------------------------------------------------------- 1 | # $Id: Application.mk 212 2015-05-15 10:22:36Z oparviai $ 2 | # 3 | # Build library bilaries for all supported architectures 4 | # 5 | 6 | APP_ABI := armeabi 7 | APP_OPTIM := release 8 | APP_STL := stlport_static 9 | APP_CPPFLAGS := -fexceptions # -D SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS 10 | 11 | -------------------------------------------------------------------------------- /soundtouch/SoundStretch/Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to create Makefile.in 2 | ## 3 | ## $Id: Makefile.am 209 2015-05-01 07:55:47Z oparviai $ 4 | ## 5 | ## Copyright (C) 2003 - David W. Durham 6 | ## 7 | ## This file is part of SoundTouch, an audio processing library for pitch/time adjustments 8 | ## 9 | ## SoundTouch is free software; you can redistribute it and/or modify it under the 10 | ## terms of the GNU General Public License as published by the Free Software 11 | ## Foundation; either version 2 of the License, or (at your option) any later 12 | ## version. 13 | ## 14 | ## SoundTouch is distributed in the hope that it will be useful, but WITHOUT ANY 15 | ## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | ## A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | ## 18 | ## You should have received a copy of the GNU General Public License along with 19 | ## this program; if not, write to the Free Software Foundation, Inc., 59 Temple 20 | ## Place - Suite 330, Boston, MA 02111-1307, USA 21 | 22 | include $(top_srcdir)/config/am_include.mk 23 | 24 | 25 | ## bin_PROGRAMS is the macro that tells automake the name of the programs to 26 | ## install in the bin directory (/usr/local/bin) by default. By setting 27 | ## --prefix= at configure time the user can change this (eg: ./configure 28 | ## --prefix=/usr will install soundstretch under /usr/bin/soundstretch ) 29 | bin_PROGRAMS=soundstretch 30 | 31 | noinst_HEADERS=RunParameters.h WavFile.h 32 | 33 | # extra files to include in distrubution tarball 34 | EXTRA_DIST=soundstretch.dsp soundstretch.dsw soundstretch.sln soundstretch.vcproj 35 | 36 | ## for every name listed under bin_PROGRAMS, you have a _SOURCES. This lists 37 | ## all the sources in the current directory that are used to build soundstretch. 38 | soundstretch_SOURCES=main.cpp RunParameters.cpp WavFile.cpp 39 | 40 | ## soundstretch_LDADD is a list of extras to pass at link time. All the objects 41 | ## created by the above soundstretch_SOURCES are automatically linked in, so here I 42 | ## list object files from other directories as well as flags passed to the 43 | ## linker. 44 | soundstretch_LDADD=../SoundTouch/libSoundTouch.la -lm 45 | 46 | ## linker flags. 47 | # OP 2011-7-17 Linker flag -s disabled to prevent stripping symbols by default 48 | #soundstretch_LDFLAGS=-s 49 | 50 | ## additional compiler flags 51 | soundstretch_CXXFLAGS=-O3 $(AM_CXXFLAGS) 52 | 53 | #clean-local: 54 | # -rm -f additional-files-to-remove-on-make-clean 55 | -------------------------------------------------------------------------------- /soundtouch/SoundStretch/RunParameters.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// 3 | /// A class for parsing the 'soundstretch' application command line parameters 4 | /// 5 | /// Author : Copyright (c) Olli Parviainen 6 | /// Author e-mail : oparviai 'at' iki.fi 7 | /// SoundTouch WWW: http://www.surina.net/soundtouch 8 | /// 9 | //////////////////////////////////////////////////////////////////////////////// 10 | // 11 | // Last changed : $Date: 2014-04-06 18:57:21 +0300 (su, 06 huhti 2014) $ 12 | // File revision : $Revision: 4 $ 13 | // 14 | // $Id: RunParameters.h 195 2014-04-06 15:57:21Z oparviai $ 15 | // 16 | //////////////////////////////////////////////////////////////////////////////// 17 | // 18 | // License : 19 | // 20 | // SoundTouch audio processing library 21 | // Copyright (c) Olli Parviainen 22 | // 23 | // This library is free software; you can redistribute it and/or 24 | // modify it under the terms of the GNU Lesser General Public 25 | // License as published by the Free Software Foundation; either 26 | // version 2.1 of the License, or (at your option) any later version. 27 | // 28 | // This library is distributed in the hope that it will be useful, 29 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 31 | // Lesser General Public License for more details. 32 | // 33 | // You should have received a copy of the GNU Lesser General Public 34 | // License along with this library; if not, write to the Free Software 35 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 36 | // 37 | //////////////////////////////////////////////////////////////////////////////// 38 | 39 | #ifndef RUNPARAMETERS_H 40 | #define RUNPARAMETERS_H 41 | 42 | #include "STTypes.h" 43 | #include 44 | 45 | using namespace std; 46 | 47 | /// Parses command line parameters into program parameters 48 | class RunParameters 49 | { 50 | private: 51 | void throwIllegalParamExp(const string &str) const; 52 | void throwLicense() const; 53 | void parseSwitchParam(const string &str); 54 | void checkLimits(); 55 | float parseSwitchValue(const string &str) const; 56 | 57 | public: 58 | char *inFileName; 59 | char *outFileName; 60 | float tempoDelta; 61 | float pitchDelta; 62 | float rateDelta; 63 | int quick; 64 | int noAntiAlias; 65 | float goalBPM; 66 | bool detectBPM; 67 | bool speech; 68 | 69 | RunParameters(const int nParams, const char * const paramStr[]); 70 | }; 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /soundtouch/SoundStretch/soundstretch.dsw: -------------------------------------------------------------------------------- 1 | Microsoft Developer Studio Workspace File, Format Version 6.00 2 | # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! 3 | 4 | ############################################################################### 5 | 6 | Project: "SoundTouch"=..\SoundTouch\SoundTouch.dsp - Package Owner=<4> 7 | 8 | Package=<5> 9 | {{{ 10 | }}} 11 | 12 | Package=<4> 13 | {{{ 14 | }}} 15 | 16 | ############################################################################### 17 | 18 | Project: "soundstretch"=.\soundstretch.dsp - Package Owner=<4> 19 | 20 | Package=<5> 21 | {{{ 22 | }}} 23 | 24 | Package=<4> 25 | {{{ 26 | Begin Project Dependency 27 | Project_Dep_Name SoundTouch 28 | End Project Dependency 29 | }}} 30 | 31 | ############################################################################### 32 | 33 | Global: 34 | 35 | Package=<5> 36 | {{{ 37 | }}} 38 | 39 | Package=<3> 40 | {{{ 41 | }}} 42 | 43 | ############################################################################### 44 | 45 | -------------------------------------------------------------------------------- /soundtouch/SoundStretch/soundstretch.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 10.00 2 | # Visual Studio 2008 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soundstretch", "soundstretch.vcproj", "{5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}" 4 | ProjectSection(ProjectDependencies) = postProject 5 | {68A5DD20-7057-448B-8FE0-B6AC8D205509} = {68A5DD20-7057-448B-8FE0-B6AC8D205509} 6 | EndProjectSection 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SoundTouch", "..\SoundTouch\SoundTouch.vcproj", "{68A5DD20-7057-448B-8FE0-B6AC8D205509}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Win32 = Debug|Win32 13 | Release|Win32 = Release|Win32 14 | ReleaseX64|Win32 = ReleaseX64|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}.Debug|Win32.Build.0 = Debug|Win32 19 | {5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}.Release|Win32.ActiveCfg = Release|Win32 20 | {5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}.Release|Win32.Build.0 = Release|Win32 21 | {5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}.ReleaseX64|Win32.ActiveCfg = ReleaseX64|x64 22 | {5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}.ReleaseX64|Win32.Build.0 = ReleaseX64|x64 23 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Debug|Win32.ActiveCfg = Debug|Win32 24 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Debug|Win32.Build.0 = Debug|Win32 25 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Release|Win32.ActiveCfg = Release|Win32 26 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Release|Win32.Build.0 = Release|Win32 27 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.ReleaseX64|Win32.ActiveCfg = ReleaseX64|x64 28 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.ReleaseX64|Win32.Build.0 = ReleaseX64|x64 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | EndGlobal 34 | -------------------------------------------------------------------------------- /soundtouch/SoundTouch/AAFilter.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// 3 | /// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo 4 | /// while maintaining the original pitch by using a time domain WSOLA-like method 5 | /// with several performance-increasing tweaks. 6 | /// 7 | /// Anti-alias filter is used to prevent folding of high frequencies when 8 | /// transposing the sample rate with interpolation. 9 | /// 10 | /// Author : Copyright (c) Olli Parviainen 11 | /// Author e-mail : oparviai 'at' iki.fi 12 | /// SoundTouch WWW: http://www.surina.net/soundtouch 13 | /// 14 | //////////////////////////////////////////////////////////////////////////////// 15 | // 16 | // Last changed : $Date: 2014-01-07 21:41:23 +0200 (ti, 07 tammi 2014) $ 17 | // File revision : $Revision: 4 $ 18 | // 19 | // $Id: AAFilter.h 187 2014-01-07 19:41:23Z oparviai $ 20 | // 21 | //////////////////////////////////////////////////////////////////////////////// 22 | // 23 | // License : 24 | // 25 | // SoundTouch audio processing library 26 | // Copyright (c) Olli Parviainen 27 | // 28 | // This library is free software; you can redistribute it and/or 29 | // modify it under the terms of the GNU Lesser General Public 30 | // License as published by the Free Software Foundation; either 31 | // version 2.1 of the License, or (at your option) any later version. 32 | // 33 | // This library is distributed in the hope that it will be useful, 34 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 35 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 36 | // Lesser General Public License for more details. 37 | // 38 | // You should have received a copy of the GNU Lesser General Public 39 | // License along with this library; if not, write to the Free Software 40 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 41 | // 42 | //////////////////////////////////////////////////////////////////////////////// 43 | 44 | #ifndef AAFilter_H 45 | #define AAFilter_H 46 | 47 | #include "STTypes.h" 48 | #include "FIFOSampleBuffer.h" 49 | 50 | namespace soundtouch 51 | { 52 | 53 | class AAFilter 54 | { 55 | protected: 56 | class FIRFilter *pFIR; 57 | 58 | /// Low-pass filter cut-off frequency, negative = invalid 59 | double cutoffFreq; 60 | 61 | /// num of filter taps 62 | uint length; 63 | 64 | /// Calculate the FIR coefficients realizing the given cutoff-frequency 65 | void calculateCoeffs(); 66 | public: 67 | AAFilter(uint length); 68 | 69 | ~AAFilter(); 70 | 71 | /// Sets new anti-alias filter cut-off edge frequency, scaled to sampling 72 | /// frequency (nyquist frequency = 0.5). The filter will cut off the 73 | /// frequencies than that. 74 | void setCutoffFreq(double newCutoffFreq); 75 | 76 | /// Sets number of FIR filter taps, i.e. ~filter complexity 77 | void setLength(uint newLength); 78 | 79 | uint getLength() const; 80 | 81 | /// Applies the filter to the given sequence of samples. 82 | /// Note : The amount of outputted samples is by value of 'filter length' 83 | /// smaller than the amount of input samples. 84 | uint evaluate(SAMPLETYPE *dest, 85 | const SAMPLETYPE *src, 86 | uint numSamples, 87 | uint numChannels) const; 88 | 89 | /// Applies the filter to the given src & dest pipes, so that processed amount of 90 | /// samples get removed from src, and produced amount added to dest 91 | /// Note : The amount of outputted samples is by value of 'filter length' 92 | /// smaller than the amount of input samples. 93 | uint evaluate(FIFOSampleBuffer &dest, 94 | FIFOSampleBuffer &src) const; 95 | 96 | }; 97 | 98 | } 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /soundtouch/SoundTouch/InterpolateCubic.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// 3 | /// Cubic interpolation routine. 4 | /// 5 | /// Author : Copyright (c) Olli Parviainen 6 | /// Author e-mail : oparviai 'at' iki.fi 7 | /// SoundTouch WWW: http://www.surina.net/soundtouch 8 | /// 9 | //////////////////////////////////////////////////////////////////////////////// 10 | // 11 | // $Id: InterpolateCubic.h 225 2015-07-26 14:45:48Z oparviai $ 12 | // 13 | //////////////////////////////////////////////////////////////////////////////// 14 | // 15 | // License : 16 | // 17 | // SoundTouch audio processing library 18 | // Copyright (c) Olli Parviainen 19 | // 20 | // This library is free software; you can redistribute it and/or 21 | // modify it under the terms of the GNU Lesser General Public 22 | // License as published by the Free Software Foundation; either 23 | // version 2.1 of the License, or (at your option) any later version. 24 | // 25 | // This library is distributed in the hope that it will be useful, 26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28 | // Lesser General Public License for more details. 29 | // 30 | // You should have received a copy of the GNU Lesser General Public 31 | // License along with this library; if not, write to the Free Software 32 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 33 | // 34 | //////////////////////////////////////////////////////////////////////////////// 35 | 36 | #ifndef _InterpolateCubic_H_ 37 | #define _InterpolateCubic_H_ 38 | 39 | #include "RateTransposer.h" 40 | #include "STTypes.h" 41 | 42 | namespace soundtouch 43 | { 44 | 45 | class InterpolateCubic : public TransposerBase 46 | { 47 | protected: 48 | virtual void resetRegisters(); 49 | virtual int transposeMono(SAMPLETYPE *dest, 50 | const SAMPLETYPE *src, 51 | int &srcSamples); 52 | virtual int transposeStereo(SAMPLETYPE *dest, 53 | const SAMPLETYPE *src, 54 | int &srcSamples); 55 | virtual int transposeMulti(SAMPLETYPE *dest, 56 | const SAMPLETYPE *src, 57 | int &srcSamples); 58 | 59 | double fract; 60 | 61 | public: 62 | InterpolateCubic(); 63 | }; 64 | 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /soundtouch/SoundTouch/InterpolateLinear.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// 3 | /// Linear interpolation routine. 4 | /// 5 | /// Author : Copyright (c) Olli Parviainen 6 | /// Author e-mail : oparviai 'at' iki.fi 7 | /// SoundTouch WWW: http://www.surina.net/soundtouch 8 | /// 9 | //////////////////////////////////////////////////////////////////////////////// 10 | // 11 | // $Id: InterpolateLinear.h 225 2015-07-26 14:45:48Z oparviai $ 12 | // 13 | //////////////////////////////////////////////////////////////////////////////// 14 | // 15 | // License : 16 | // 17 | // SoundTouch audio processing library 18 | // Copyright (c) Olli Parviainen 19 | // 20 | // This library is free software; you can redistribute it and/or 21 | // modify it under the terms of the GNU Lesser General Public 22 | // License as published by the Free Software Foundation; either 23 | // version 2.1 of the License, or (at your option) any later version. 24 | // 25 | // This library is distributed in the hope that it will be useful, 26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28 | // Lesser General Public License for more details. 29 | // 30 | // You should have received a copy of the GNU Lesser General Public 31 | // License along with this library; if not, write to the Free Software 32 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 33 | // 34 | //////////////////////////////////////////////////////////////////////////////// 35 | 36 | #ifndef _InterpolateLinear_H_ 37 | #define _InterpolateLinear_H_ 38 | 39 | #include "RateTransposer.h" 40 | #include "STTypes.h" 41 | 42 | namespace soundtouch 43 | { 44 | 45 | /// Linear transposer class that uses integer arithmetics 46 | class InterpolateLinearInteger : public TransposerBase 47 | { 48 | protected: 49 | int iFract; 50 | int iRate; 51 | 52 | virtual void resetRegisters(); 53 | 54 | virtual int transposeMono(SAMPLETYPE *dest, 55 | const SAMPLETYPE *src, 56 | int &srcSamples); 57 | virtual int transposeStereo(SAMPLETYPE *dest, 58 | const SAMPLETYPE *src, 59 | int &srcSamples); 60 | virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples); 61 | public: 62 | InterpolateLinearInteger(); 63 | 64 | /// Sets new target rate. Normal rate = 1.0, smaller values represent slower 65 | /// rate, larger faster rates. 66 | virtual void setRate(double newRate); 67 | }; 68 | 69 | 70 | /// Linear transposer class that uses floating point arithmetics 71 | class InterpolateLinearFloat : public TransposerBase 72 | { 73 | protected: 74 | double fract; 75 | 76 | virtual void resetRegisters(); 77 | 78 | virtual int transposeMono(SAMPLETYPE *dest, 79 | const SAMPLETYPE *src, 80 | int &srcSamples); 81 | virtual int transposeStereo(SAMPLETYPE *dest, 82 | const SAMPLETYPE *src, 83 | int &srcSamples); 84 | virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples); 85 | 86 | public: 87 | InterpolateLinearFloat(); 88 | }; 89 | 90 | } 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /soundtouch/SoundTouch/InterpolateShannon.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// 3 | /// Sample interpolation routine using 8-tap band-limited Shannon interpolation 4 | /// with kaiser window. 5 | /// 6 | /// Notice. This algorithm is remarkably much heavier than linear or cubic 7 | /// interpolation, and not remarkably better than cubic algorithm. Thus mostly 8 | /// for experimental purposes 9 | /// 10 | /// Author : Copyright (c) Olli Parviainen 11 | /// Author e-mail : oparviai 'at' iki.fi 12 | /// SoundTouch WWW: http://www.surina.net/soundtouch 13 | /// 14 | //////////////////////////////////////////////////////////////////////////////// 15 | // 16 | // $Id: InterpolateShannon.h 225 2015-07-26 14:45:48Z oparviai $ 17 | // 18 | //////////////////////////////////////////////////////////////////////////////// 19 | // 20 | // License : 21 | // 22 | // SoundTouch audio processing library 23 | // Copyright (c) Olli Parviainen 24 | // 25 | // This library is free software; you can redistribute it and/or 26 | // modify it under the terms of the GNU Lesser General Public 27 | // License as published by the Free Software Foundation; either 28 | // version 2.1 of the License, or (at your option) any later version. 29 | // 30 | // This library is distributed in the hope that it will be useful, 31 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 32 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 33 | // Lesser General Public License for more details. 34 | // 35 | // You should have received a copy of the GNU Lesser General Public 36 | // License along with this library; if not, write to the Free Software 37 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 38 | // 39 | //////////////////////////////////////////////////////////////////////////////// 40 | 41 | #ifndef _InterpolateShannon_H_ 42 | #define _InterpolateShannon_H_ 43 | 44 | #include "RateTransposer.h" 45 | #include "STTypes.h" 46 | 47 | namespace soundtouch 48 | { 49 | 50 | class InterpolateShannon : public TransposerBase 51 | { 52 | protected: 53 | void resetRegisters(); 54 | int transposeMono(SAMPLETYPE *dest, 55 | const SAMPLETYPE *src, 56 | int &srcSamples); 57 | int transposeStereo(SAMPLETYPE *dest, 58 | const SAMPLETYPE *src, 59 | int &srcSamples); 60 | int transposeMulti(SAMPLETYPE *dest, 61 | const SAMPLETYPE *src, 62 | int &srcSamples); 63 | 64 | double fract; 65 | 66 | public: 67 | InterpolateShannon(); 68 | }; 69 | 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /soundtouch/SoundTouch/Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to create Makefile.in 2 | ## 3 | ## $Id: Makefile.am 230 2015-09-20 07:38:32Z oparviai $ 4 | ## 5 | ## This file is part of SoundTouch, an audio processing library for pitch/time adjustments 6 | ## 7 | ## SoundTouch is free software; you can redistribute it and/or modify it under the 8 | ## terms of the GNU General Public License as published by the Free Software 9 | ## Foundation; either version 2 of the License, or (at your option) any later 10 | ## version. 11 | ## 12 | ## SoundTouch is distributed in the hope that it will be useful, but WITHOUT ANY 13 | ## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | ## A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | ## 16 | ## You should have received a copy of the GNU General Public License along with 17 | ## this program; if not, write to the Free Software Foundation, Inc., 59 Temple 18 | ## Place - Suite 330, Boston, MA 02111-1307, USA 19 | 20 | 21 | include $(top_srcdir)/config/am_include.mk 22 | 23 | 24 | # set to something if you want other stuff to be included in the distribution tarball 25 | EXTRA_DIST=SoundTouch.dsp SoundTouch.dsw SoundTouch.sln SoundTouch.vcproj 26 | 27 | noinst_HEADERS=AAFilter.h cpu_detect.h cpu_detect_x86.cpp FIRFilter.h RateTransposer.h TDStretch.h PeakFinder.h 28 | 29 | lib_LTLIBRARIES=libSoundTouch.la 30 | # 31 | libSoundTouch_la_SOURCES=AAFilter.cpp FIRFilter.cpp FIFOSampleBuffer.cpp \ 32 | RateTransposer.cpp SoundTouch.cpp TDStretch.cpp cpu_detect_x86.cpp \ 33 | BPMDetect.cpp PeakFinder.cpp InterpolateLinear.cpp InterpolateCubic.cpp \ 34 | InterpolateShannon.cpp 35 | 36 | # Compiler flags 37 | AM_CXXFLAGS+=-O3 38 | 39 | # Compile the files that need MMX and SSE individually. 40 | libSoundTouch_la_LIBADD=libSoundTouchMMX.la libSoundTouchSSE.la 41 | noinst_LTLIBRARIES=libSoundTouchMMX.la libSoundTouchSSE.la 42 | libSoundTouchMMX_la_SOURCES=mmx_optimized.cpp 43 | libSoundTouchSSE_la_SOURCES=sse_optimized.cpp 44 | 45 | # We enable optimizations by default. 46 | # If MMX is supported compile with -mmmx. 47 | # Do not assume -msse is also supported. 48 | if HAVE_MMX 49 | libSoundTouchMMX_la_CXXFLAGS = -mmmx $(AM_CXXFLAGS) 50 | else 51 | libSoundTouchMMX_la_CXXFLAGS = $(AM_CXXFLAGS) 52 | endif 53 | 54 | # We enable optimizations by default. 55 | # If SSE is supported compile with -msse. 56 | if HAVE_SSE 57 | libSoundTouchSSE_la_CXXFLAGS = -msse $(AM_CXXFLAGS) 58 | else 59 | libSoundTouchSSE_la_CXXFLAGS = $(AM_CXXFLAGS) 60 | endif 61 | 62 | # Let the user disable optimizations if he wishes to. 63 | if !X86_OPTIMIZATIONS 64 | libSoundTouchMMX_la_CXXFLAGS = $(AM_CXXFLAGS) 65 | libSoundTouchSSE_la_CXXFLAGS = $(AM_CXXFLAGS) 66 | endif 67 | 68 | # Modify the default 0.0.0 to LIB_SONAME.0.0 69 | libSoundTouch_la_LDFLAGS=-version-info @LIB_SONAME@ 70 | 71 | # other linking flags to add 72 | # noinst_LTLIBRARIES = libSoundTouchOpt.la 73 | # libSoundTouch_la_LIBADD = libSoundTouchOpt.la 74 | # libSoundTouchOpt_la_SOURCES = mmx_optimized.cpp sse_optimized.cpp 75 | # libSoundTouchOpt_la_CXXFLAGS = -O3 -msse -fcheck-new -I../../include 76 | -------------------------------------------------------------------------------- /soundtouch/SoundTouch/PeakFinder.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue5455/VideoAudioDemo/bb18bbe7f978f657d3191e044739ab38e63290b6/soundtouch/SoundTouch/PeakFinder.cpp -------------------------------------------------------------------------------- /soundtouch/SoundTouch/PeakFinder.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// 3 | /// The routine detects highest value on an array of values and calculates the 4 | /// precise peak location as a mass-center of the 'hump' around the peak value. 5 | /// 6 | /// Author : Copyright (c) Olli Parviainen 7 | /// Author e-mail : oparviai 'at' iki.fi 8 | /// SoundTouch WWW: http://www.surina.net/soundtouch 9 | /// 10 | //////////////////////////////////////////////////////////////////////////////// 11 | // 12 | // Last changed : $Date: 2011-12-30 22:33:46 +0200 (pe, 30 joulu 2011) $ 13 | // File revision : $Revision: 4 $ 14 | // 15 | // $Id: PeakFinder.h 132 2011-12-30 20:33:46Z oparviai $ 16 | // 17 | //////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // License : 20 | // 21 | // SoundTouch audio processing library 22 | // Copyright (c) Olli Parviainen 23 | // 24 | // This library is free software; you can redistribute it and/or 25 | // modify it under the terms of the GNU Lesser General Public 26 | // License as published by the Free Software Foundation; either 27 | // version 2.1 of the License, or (at your option) any later version. 28 | // 29 | // This library is distributed in the hope that it will be useful, 30 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 31 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 32 | // Lesser General Public License for more details. 33 | // 34 | // You should have received a copy of the GNU Lesser General Public 35 | // License along with this library; if not, write to the Free Software 36 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 37 | // 38 | //////////////////////////////////////////////////////////////////////////////// 39 | 40 | #ifndef _PeakFinder_H_ 41 | #define _PeakFinder_H_ 42 | 43 | namespace soundtouch 44 | { 45 | 46 | class PeakFinder 47 | { 48 | protected: 49 | /// Min, max allowed peak positions within the data vector 50 | int minPos, maxPos; 51 | 52 | /// Calculates the mass center between given vector items. 53 | double calcMassCenter(const float *data, ///< Data vector. 54 | int firstPos, ///< Index of first vector item beloging to the peak. 55 | int lastPos ///< Index of last vector item beloging to the peak. 56 | ) const; 57 | 58 | /// Finds the data vector index where the monotoniously decreasing signal crosses the 59 | /// given level. 60 | int findCrossingLevel(const float *data, ///< Data vector. 61 | float level, ///< Goal crossing level. 62 | int peakpos, ///< Peak position index within the data vector. 63 | int direction /// Direction where to proceed from the peak: 1 = right, -1 = left. 64 | ) const; 65 | 66 | // Finds real 'top' of a peak hump from neighnourhood of the given 'peakpos'. 67 | int findTop(const float *data, int peakpos) const; 68 | 69 | 70 | /// Finds the 'ground' level, i.e. smallest level between two neighbouring peaks, to right- 71 | /// or left-hand side of the given peak position. 72 | int findGround(const float *data, /// Data vector. 73 | int peakpos, /// Peak position index within the data vector. 74 | int direction /// Direction where to proceed from the peak: 1 = right, -1 = left. 75 | ) const; 76 | 77 | /// get exact center of peak near given position by calculating local mass of center 78 | double getPeakCenter(const float *data, int peakpos) const; 79 | 80 | public: 81 | /// Constructor. 82 | PeakFinder(); 83 | 84 | /// Detect exact peak position of the data vector by finding the largest peak 'hump' 85 | /// and calculating the mass-center location of the peak hump. 86 | /// 87 | /// \return The location of the largest base harmonic peak hump. 88 | double detectPeak(const float *data, /// Data vector to be analyzed. The data vector has 89 | /// to be at least 'maxPos' items long. 90 | int minPos, ///< Min allowed peak location within the vector data. 91 | int maxPos ///< Max allowed peak location within the vector data. 92 | ); 93 | }; 94 | 95 | } 96 | 97 | #endif // _PeakFinder_H_ 98 | -------------------------------------------------------------------------------- /soundtouch/SoundTouch/SoundTouch.dsw: -------------------------------------------------------------------------------- 1 | Microsoft Developer Studio Workspace File, Format Version 6.00 2 | # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! 3 | # 4 | # $Id: SoundTouch.dsw 11 2008-02-10 16:26:55Z oparviai $ 5 | 6 | ############################################################################### 7 | 8 | Project: "SoundTouch"=.\SoundTouch.dsp - Package Owner=<4> 9 | 10 | Package=<5> 11 | {{{ 12 | }}} 13 | 14 | Package=<4> 15 | {{{ 16 | }}} 17 | 18 | ############################################################################### 19 | 20 | Global: 21 | 22 | Package=<5> 23 | {{{ 24 | }}} 25 | 26 | Package=<3> 27 | {{{ 28 | }}} 29 | 30 | ############################################################################### 31 | 32 | -------------------------------------------------------------------------------- /soundtouch/SoundTouch/SoundTouch.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 10.00 2 | # Visual Studio 2008 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SoundTouch", "SoundTouch.vcproj", "{68A5DD20-7057-448B-8FE0-B6AC8D205509}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | Debug|x64 = Debug|x64 9 | Release|Win32 = Release|Win32 10 | Release|x64 = Release|x64 11 | ReleaseX64|Win32 = ReleaseX64|Win32 12 | ReleaseX64|x64 = ReleaseX64|x64 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Debug|Win32.ActiveCfg = Debug|Win32 16 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Debug|x64.ActiveCfg = Debug|x64 17 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Release|Win32.ActiveCfg = Release|Win32 18 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Release|x64.ActiveCfg = Release|x64 19 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.ReleaseX64|Win32.ActiveCfg = ReleaseX64|Win32 20 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.ReleaseX64|Win32.Build.0 = ReleaseX64|Win32 21 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.ReleaseX64|x64.ActiveCfg = ReleaseX64|x64 22 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.ReleaseX64|x64.Build.0 = ReleaseX64|x64 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /soundtouch/SoundTouch/cpu_detect.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// 3 | /// A header file for detecting the Intel MMX instructions set extension. 4 | /// 5 | /// Please see 'mmx_win.cpp', 'mmx_cpp.cpp' and 'mmx_non_x86.cpp' for the 6 | /// routine implementations for x86 Windows, x86 gnu version and non-x86 7 | /// platforms, respectively. 8 | /// 9 | /// Author : Copyright (c) Olli Parviainen 10 | /// Author e-mail : oparviai 'at' iki.fi 11 | /// SoundTouch WWW: http://www.surina.net/soundtouch 12 | /// 13 | //////////////////////////////////////////////////////////////////////////////// 14 | // 15 | // Last changed : $Date: 2008-02-10 18:26:55 +0200 (su, 10 helmi 2008) $ 16 | // File revision : $Revision: 4 $ 17 | // 18 | // $Id: cpu_detect.h 11 2008-02-10 16:26:55Z oparviai $ 19 | // 20 | //////////////////////////////////////////////////////////////////////////////// 21 | // 22 | // License : 23 | // 24 | // SoundTouch audio processing library 25 | // Copyright (c) Olli Parviainen 26 | // 27 | // This library is free software; you can redistribute it and/or 28 | // modify it under the terms of the GNU Lesser General Public 29 | // License as published by the Free Software Foundation; either 30 | // version 2.1 of the License, or (at your option) any later version. 31 | // 32 | // This library is distributed in the hope that it will be useful, 33 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 34 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 35 | // Lesser General Public License for more details. 36 | // 37 | // You should have received a copy of the GNU Lesser General Public 38 | // License along with this library; if not, write to the Free Software 39 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 40 | // 41 | //////////////////////////////////////////////////////////////////////////////// 42 | 43 | #ifndef _CPU_DETECT_H_ 44 | #define _CPU_DETECT_H_ 45 | 46 | #include "STTypes.h" 47 | 48 | #define SUPPORT_MMX 0x0001 49 | #define SUPPORT_3DNOW 0x0002 50 | #define SUPPORT_ALTIVEC 0x0004 51 | #define SUPPORT_SSE 0x0008 52 | #define SUPPORT_SSE2 0x0010 53 | 54 | /// Checks which instruction set extensions are supported by the CPU. 55 | /// 56 | /// \return A bitmask of supported extensions, see SUPPORT_... defines. 57 | uint detectCPUextensions(void); 58 | 59 | /// Disables given set of instruction extensions. See SUPPORT_... defines. 60 | void disableExtensions(uint wDisableMask); 61 | 62 | #endif // _CPU_DETECT_H_ 63 | -------------------------------------------------------------------------------- /soundtouch/com_netease_soundtouch_SoundTouch.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// 3 | /// Example Interface class for SoundTouch native compilation 4 | /// 5 | /// Author : Copyright (c) Olli Parviainen 6 | /// Author e-mail : oparviai 'at' iki.fi 7 | /// WWW : http://www.surina.net 8 | /// 9 | //////////////////////////////////////////////////////////////////////////////// 10 | // 11 | // $Id: soundtouch-jni.cpp 212 2015-05-15 10:22:36Z oparviai $ 12 | // 13 | //////////////////////////////////////////////////////////////////////////////// 14 | 15 | #include "include/SoundTouch.h" 16 | #include "com_netease_soundtouch_SoundTouch.h" 17 | #include 18 | #include 19 | #define BUFF_SIZE 4096 20 | 21 | using namespace soundtouch; 22 | 23 | #define LOGD(...) __android_log_print((int)ANDROID_LOG_DEBUG, "xue", __VA_ARGS__) 24 | 25 | jlong Java_com_netease_soundtouch_SoundTouch_newInstance(JNIEnv *env, jclass jClass) 26 | { 27 | SoundTouch *soundTouch = new SoundTouch(); 28 | soundTouch->setSampleRate(44100); 29 | soundTouch->setChannels(1); 30 | return (jlong)(soundTouch); 31 | } 32 | 33 | void Java_com_netease_soundtouch_SoundTouch_deleteInstance(JNIEnv *env, jobject thiz, jlong handle) 34 | { 35 | SoundTouch *ptr = (SoundTouch *)handle; 36 | delete ptr; 37 | } 38 | 39 | void Java_com_netease_soundtouch_SoundTouch_setTempo(JNIEnv *env, jobject thiz, jlong handle, jfloat tempo) 40 | { 41 | SoundTouch *ptr = (SoundTouch *)handle; 42 | ptr->setTempo(tempo); 43 | } 44 | 45 | void Java_com_netease_soundtouch_SoundTouch_setPitchSemiTones(JNIEnv *env, jobject thiz, jlong handle, jfloat pitch) 46 | { 47 | SoundTouch *ptr = (SoundTouch *)handle; 48 | ptr->setPitchSemiTones(pitch); 49 | } 50 | 51 | jint Java_com_netease_soundtouch_SoundTouch_getBytes(JNIEnv *env, jobject thiz, jlong handle, jbyteArray output, jint length) 52 | { 53 | int receiveSamples = 0; 54 | int maxReceiveSamples = length/2; 55 | 56 | SoundTouch *soundTouch = (SoundTouch *)handle; 57 | 58 | jbyte *data; 59 | 60 | data = env->GetByteArrayElements(output, JNI_FALSE); 61 | 62 | receiveSamples = soundTouch->receiveSamples((SAMPLETYPE *)data, 63 | maxReceiveSamples); 64 | LOGD("receiveSamples %d",receiveSamples); 65 | 66 | //memcpy(data, sampleBuffer, receiveSize); 67 | 68 | env->ReleaseByteArrayElements(output, data, 0); 69 | 70 | return receiveSamples; 71 | } 72 | 73 | void Java_com_netease_soundtouch_SoundTouch_putBytes(JNIEnv *env, jobject thiz, jlong handle, jbyteArray input, jint offset, jint length) 74 | { 75 | SoundTouch *soundTouch = (SoundTouch *)handle; 76 | 77 | jbyte *data; 78 | 79 | data = env->GetByteArrayElements(input, JNI_FALSE); 80 | 81 | //soundtouch::SAMPLETYPE sampleBuffer[length]; 82 | //memcpy(&sampleBuffer, data, length); 83 | 84 | //(16*1)/8=2bytes,length/2=x;x��sample 85 | 86 | soundTouch->putSamples((SAMPLETYPE *)data, length/2); 87 | 88 | env->ReleaseByteArrayElements(input, data, 0); 89 | } 90 | 91 | 92 | void Java_com_netease_soundtouch_SoundTouch_flush 93 | (JNIEnv *env, jobject thiz, jlong handle){ 94 | SoundTouch* soundTouch = (SoundTouch*)handle; 95 | soundTouch->flush(); 96 | } -------------------------------------------------------------------------------- /soundtouch/com_netease_soundtouch_SoundTouch.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class com_netease_soundtouch_SoundTouch */ 4 | 5 | #ifndef _Included_com_netease_soundtouch_SoundTouch 6 | #define _Included_com_netease_soundtouch_SoundTouch 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | /* 11 | * Class: com_netease_soundtouch_SoundTouch 12 | * Method: setTempo 13 | * Signature: (JF)V 14 | */ 15 | JNIEXPORT void JNICALL Java_com_netease_soundtouch_SoundTouch_setTempo 16 | (JNIEnv *, jobject, jlong, jfloat); 17 | 18 | /* 19 | * Class: com_netease_soundtouch_SoundTouch 20 | * Method: setPitchSemiTones 21 | * Signature: (JF)V 22 | */ 23 | JNIEXPORT void JNICALL Java_com_netease_soundtouch_SoundTouch_setPitchSemiTones 24 | (JNIEnv *, jobject, jlong, jfloat); 25 | 26 | /* 27 | * Class: com_netease_soundtouch_SoundTouch 28 | * Method: putBytes 29 | * Signature: (J[BII)V 30 | */ 31 | JNIEXPORT void JNICALL Java_com_netease_soundtouch_SoundTouch_putBytes 32 | (JNIEnv *, jobject, jlong, jbyteArray, jint, jint); 33 | 34 | /* 35 | * Class: com_netease_soundtouch_SoundTouch 36 | * Method: getBytes 37 | * Signature: (J[BI)I 38 | */ 39 | JNIEXPORT jint JNICALL Java_com_netease_soundtouch_SoundTouch_getBytes 40 | (JNIEnv *, jobject, jlong, jbyteArray, jint); 41 | 42 | /* 43 | * Class: com_netease_soundtouch_SoundTouch 44 | * Method: newInstance 45 | * Signature: ()J 46 | */ 47 | JNIEXPORT jlong JNICALL Java_com_netease_soundtouch_SoundTouch_newInstance 48 | (JNIEnv *, jclass); 49 | 50 | /* 51 | * Class: com_netease_soundtouch_SoundTouch 52 | * Method: deleteInstance 53 | * Signature: (J)V 54 | */ 55 | JNIEXPORT void JNICALL Java_com_netease_soundtouch_SoundTouch_deleteInstance 56 | (JNIEnv *, jobject, jlong); 57 | 58 | /* 59 | * Class: com_netease_soundtouch_SoundTouch 60 | * Method: flush 61 | * Signature: (J)V 62 | */ 63 | JNIEXPORT void JNICALL Java_com_netease_soundtouch_SoundTouch_flush 64 | (JNIEnv *, jobject, jlong); 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif 69 | #endif 70 | -------------------------------------------------------------------------------- /soundtouch/include/Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to create Makefile.in 2 | ## 3 | ## $Id: Makefile.am 11 2008-02-10 16:26:55Z oparviai $ 4 | ## 5 | ## Copyright (C) 2003 - David W. Durham 6 | ## 7 | ## This file is part of SoundTouch, an audio processing library for pitch/time adjustments 8 | ## 9 | ## SoundTouch is free software; you can redistribute it and/or modify it under the 10 | ## terms of the GNU General Public License as published by the Free Software 11 | ## Foundation; either version 2 of the License, or (at your option) any later 12 | ## version. 13 | ## 14 | ## SoundTouch is distributed in the hope that it will be useful, but WITHOUT ANY 15 | ## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | ## A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | ## 18 | ## You should have received a copy of the GNU General Public License along with 19 | ## this program; if not, write to the Free Software Foundation, Inc., 59 Temple 20 | ## Place - Suite 330, Boston, MA 02111-1307, USA 21 | 22 | ## I used config/am_include.mk for common definitions 23 | include $(top_srcdir)/config/am_include.mk 24 | 25 | pkginclude_HEADERS=FIFOSampleBuffer.h FIFOSamplePipe.h SoundTouch.h STTypes.h BPMDetect.h soundtouch_config.h 26 | 27 | -------------------------------------------------------------------------------- /soundtouch/include/soundtouch_config.h.in: -------------------------------------------------------------------------------- 1 | /* Use Float as Sample type */ 2 | #undef SOUNDTOUCH_FLOAT_SAMPLES 3 | 4 | /* Use Integer as Sample type */ 5 | #undef SOUNDTOUCH_INTEGER_SAMPLES 6 | --------------------------------------------------------------------------------