├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── CMakeLists.txt ├── ProgramInfo ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── cj │ │ └── videoeditor │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── filter │ │ │ ├── brannan_blowout.png │ │ │ ├── brannan_contrast.png │ │ │ ├── brannan_luma.png │ │ │ ├── brannan_process.png │ │ │ ├── brannan_screen.png │ │ │ ├── edgeburn.png │ │ │ ├── freud_rand.png │ │ │ ├── hefemap.png │ │ │ ├── hefemetal.png │ │ │ ├── hefesoftlight.png │ │ │ ├── hudsonbackground.png │ │ │ ├── hudsonmap.png │ │ │ ├── inkwellmap.png │ │ │ ├── n1977blowout.png │ │ │ ├── n1977map.png │ │ │ ├── nashvillemap.png │ │ │ └── overlaymap.png │ │ └── shader │ │ │ ├── base_fragment.sh │ │ │ ├── base_record_fragment.sh │ │ │ ├── base_record_vertex.sh │ │ │ ├── base_vertex.sh │ │ │ ├── oes_base_fragment.sh │ │ │ └── oes_base_vertex.sh │ ├── cpp │ │ └── native-lib.cpp │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── cj │ │ │ └── videoeditor │ │ │ ├── Constants.java │ │ │ ├── MyApplication.java │ │ │ ├── MyClassLoader.java │ │ │ ├── activity │ │ │ ├── AudioEditorActivity.java │ │ │ ├── AudioMixActivity.java │ │ │ ├── AudioPreviewActivity.java │ │ │ ├── AudioSelectActivity.java │ │ │ ├── BaseActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── MediaSelectVideoActivity.java │ │ │ ├── PreviewActivity.java │ │ │ ├── RecordedActivity.java │ │ │ ├── VideoConnectActivity.java │ │ │ └── VideoSelectActivity.java │ │ │ ├── adapter │ │ │ ├── AudioAdapter.java │ │ │ ├── VideoAdapter.java │ │ │ └── VideoSelectAdapter.java │ │ │ ├── bean │ │ │ ├── AudioSettingInfo.java │ │ │ ├── CutBean.java │ │ │ ├── MediaDecode.java │ │ │ └── Song.java │ │ │ ├── camera │ │ │ ├── CameraController.java │ │ │ ├── ICamera.java │ │ │ └── SensorController.java │ │ │ ├── drawer │ │ │ ├── CameraDrawer.java │ │ │ ├── TextureRender.java │ │ │ └── VideoDrawer.java │ │ │ ├── filter │ │ │ ├── AFilter.java │ │ │ ├── CameraFilter.java │ │ │ ├── GroupFilter.java │ │ │ ├── NoFilter.java │ │ │ ├── OesFilter.java │ │ │ ├── ProcessFilter.java │ │ │ ├── RotationOESFilter.java │ │ │ └── WaterMarkFilter.java │ │ │ ├── gpufilter │ │ │ ├── SlideGpuFilterGroup.java │ │ │ ├── basefilter │ │ │ │ ├── GPUImageFilter.java │ │ │ │ └── MagicCameraInputFilter.java │ │ │ ├── filter │ │ │ │ ├── MagicAntiqueFilter.java │ │ │ │ ├── MagicBeautyFilter.java │ │ │ │ ├── MagicBrannanFilter.java │ │ │ │ ├── MagicCoolFilter.java │ │ │ │ ├── MagicFreudFilter.java │ │ │ │ ├── MagicHefeFilter.java │ │ │ │ ├── MagicHudsonFilter.java │ │ │ │ ├── MagicInkwellFilter.java │ │ │ │ ├── MagicN1977Filter.java │ │ │ │ └── MagicNashvilleFilter.java │ │ │ ├── helper │ │ │ │ ├── MagicFilterFactory.java │ │ │ │ └── MagicFilterType.java │ │ │ └── utils │ │ │ │ ├── OpenGlUtils.java │ │ │ │ ├── Rotation.java │ │ │ │ └── TextureRotationUtil.java │ │ │ ├── jni │ │ │ └── AudioJniUtils.java │ │ │ ├── media │ │ │ ├── MediaCodecInfo.java │ │ │ ├── MediaPlayerWrapper.java │ │ │ └── VideoInfo.java │ │ │ ├── mediacodec │ │ │ ├── AudioCodec.java │ │ │ ├── AudioDecodeRunnable.java │ │ │ ├── AudioEncodeRunnable.java │ │ │ ├── AudioRunnable.java │ │ │ ├── InputSurface.java │ │ │ ├── MediaMuxerRunnable.java │ │ │ ├── OutputSurface.java │ │ │ ├── OutputSurfaceTwo.java │ │ │ ├── TextureRender.java │ │ │ ├── VideoClipper.java │ │ │ └── VideoRunnable.java │ │ │ ├── record │ │ │ ├── gles │ │ │ │ ├── EglCore.java │ │ │ │ └── EglSurfaceBase.java │ │ │ └── video │ │ │ │ ├── TextureMovieEncoder.java │ │ │ │ ├── VideoEncoderCore.java │ │ │ │ └── WindowSurface.java │ │ │ ├── utils │ │ │ ├── DateUtils.java │ │ │ ├── DensityUtils.java │ │ │ ├── EasyGlUtils.java │ │ │ ├── MatrixUtils.java │ │ │ ├── OpenGlUtils.java │ │ │ └── TimeFormatUtils.java │ │ │ └── widget │ │ │ ├── CameraView.java │ │ │ ├── CircularProgressView.java │ │ │ ├── FocusImageView.java │ │ │ ├── LoadingDialog.java │ │ │ ├── TitleView.java │ │ │ └── VideoPreviewView.java │ └── res │ │ ├── anim │ │ └── focusview_show.xml │ │ ├── drawable │ │ ├── app_back_selector.xml │ │ ├── bg_circle_yellow.xml │ │ ├── bt_capture.xml │ │ ├── btn_camera_beauty.xml │ │ ├── btn_camera_filter.xml │ │ ├── selector_beauty.xml │ │ ├── selector_btn_image_choose.xml │ │ ├── selector_rewardcamera.xml │ │ ├── selector_title_bar_btn.xml │ │ ├── setting_text_color_selector.xml │ │ ├── t_progressbar.xml │ │ └── toast_shape.xml │ │ ├── layout │ │ ├── activity_audio.xml │ │ ├── activity_audio_mix.xml │ │ ├── activity_audio_preview.xml │ │ ├── activity_connect.xml │ │ ├── activity_main.xml │ │ ├── activity_media_select_video.xml │ │ ├── activity_music_select.xml │ │ ├── activity_recorde.xml │ │ ├── activity_video_connect.xml │ │ ├── activity_video_preview.xml │ │ ├── activity_video_select.xml │ │ ├── item_media_audio.xml │ │ ├── item_media_video.xml │ │ ├── item_video_select.xml │ │ ├── t_loading.xml │ │ └── view_titlebar.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ ├── btn_back_n.png │ │ ├── btn_back_p.png │ │ ├── btn_back_white_n.png │ │ ├── editor_beauty_normal.png │ │ ├── editor_beauty_pressed.png │ │ ├── editor_img_confirm.png │ │ ├── editor_img_def_video.png │ │ ├── editor_record_back.png │ │ ├── editor_record_close.png │ │ ├── focus_focus_failed.9.png │ │ ├── focus_focused.9.png │ │ ├── focus_focusing.9.png │ │ ├── ic_camera_beauty.png │ │ ├── ic_camera_beauty_pressed.png │ │ ├── ic_camera_filter.png │ │ ├── ic_launcher.png │ │ ├── icon_choice_nor.png │ │ ├── icon_choice_selected.png │ │ ├── img_aac.png │ │ ├── img_mp3.png │ │ ├── img_wma.png │ │ ├── record_camera_switch_normal.png │ │ ├── record_camera_switch_press.png │ │ ├── t_loading_2.png │ │ └── watermark.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── raw │ │ ├── amaro.glsl │ │ ├── antique.glsl │ │ ├── beauty.glsl │ │ ├── blackcat.glsl │ │ ├── brannan.glsl │ │ ├── brooklyn.glsl │ │ ├── calm.glsl │ │ ├── cool.glsl │ │ ├── crayon.glsl │ │ ├── default_fragment.glsl │ │ ├── default_vertex.glsl │ │ ├── earlybird.glsl │ │ ├── emerald.glsl │ │ ├── evergreen.glsl │ │ ├── freud.glsl │ │ ├── healthy.glsl │ │ ├── hefe.glsl │ │ ├── hudson.glsl │ │ ├── inkwell.glsl │ │ ├── kevin_new.glsl │ │ ├── latte.glsl │ │ ├── lomo.glsl │ │ ├── n1977.glsl │ │ ├── nashville.glsl │ │ ├── nostalgia.glsl │ │ ├── pixar.glsl │ │ ├── rise.glsl │ │ ├── romance.glsl │ │ ├── sakura.glsl │ │ ├── sierra.glsl │ │ ├── sketch.glsl │ │ ├── skinwhiten.glsl │ │ ├── suger_tablets.glsl │ │ ├── sunrise.glsl │ │ ├── sunset.glsl │ │ ├── sutro.glsl │ │ ├── sweets.glsl │ │ ├── tender.glsl │ │ ├── toaster2_filter_shader.glsl │ │ ├── valencia.glsl │ │ ├── walden.glsl │ │ ├── warm.glsl │ │ ├── whitecat.glsl │ │ └── xproii_filter_shader.glsl │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── example │ └── cj │ └── videoeditor │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.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 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VideoEditor-For-Android 2 | 一个Android的视频编辑器,包括了视频录制、剪切、增加bgm、美白、加滤镜、加水印等多种功能 3 | 4 | 基于android硬编码的视频编辑器,不支持4.3以下系统,通过android的api完成视频采集,通过OpenGL,完成视频数据帧的处理,通过android的硬编码器MeidaCodec 5 | 对采集到的视频流进行硬编码。 6 | 利用OpenGL完成视频的美白、加滤镜、加水印等功能。利用MediaCodec完成音视频的分离和音频的一些混音处理 7 | 8 | 注:该项目属于是一个半成品项目。并没有直接使用的商业价值。我也看到了很多人提的issues,但是因为作者最近事情比较多,以后会补上剩下的通过OpenGl拼接视频,以及给视频增加bgm等功能,也会解决那些issues。 9 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Sets the minimum version of CMake required to build the native 2 | # library. You should either keep the default value or only pass a 3 | # value of 3.4.0 or lower. 4 | 5 | cmake_minimum_required(VERSION 3.4.1) 6 | 7 | # Creates and names a library, sets it as either STATIC 8 | # or SHARED, and provides the relative paths to its source code. 9 | # You can define multiple libraries, and CMake builds it for you. 10 | # Gradle automatically packages shared libraries with your APK. 11 | 12 | add_library( # Sets the name of the library. 13 | native-lib 14 | 15 | # Sets the library as a shared library. 16 | SHARED 17 | 18 | # Provides a relative path to your source file(s). 19 | # Associated headers in the same location as their source 20 | # file are automatically included. 21 | src/main/cpp/native-lib.cpp ) 22 | 23 | # Searches for a specified prebuilt library and stores the path as a 24 | # variable. Because system libraries are included in the search path by 25 | # default, you only need to specify the name of the public NDK library 26 | # you want to add. CMake verifies that the library exists before 27 | # completing its build. 28 | 29 | find_library( # Sets the name of the path variable. 30 | log-lib 31 | 32 | # Specifies the name of the NDK library that 33 | # you want CMake to locate. 34 | log ) 35 | 36 | # Specifies libraries CMake should link to your target library. You 37 | # can link multiple libraries, such as libraries you define in the 38 | # build script, prebuilt third-party libraries, or system libraries. 39 | 40 | target_link_libraries( # Specifies the target library. 41 | native-lib 42 | 43 | # Links the target library to the log library 44 | # included in the NDK. 45 | ${log-lib} ) 46 | -------------------------------------------------------------------------------- /app/ProgramInfo: -------------------------------------------------------------------------------- 1 | 2 | github 地址 3 | https://github.com/qqchenjian318/VideoEditor-For-Android -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.3" 6 | defaultConfig { 7 | applicationId "com.example.cj.videoeditor" 8 | minSdkVersion 18 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | externalNativeBuild { 14 | cmake { 15 | cppFlags "" 16 | } 17 | } 18 | 19 | } 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | externalNativeBuild { 27 | cmake { 28 | path "CMakeLists.txt" 29 | } 30 | } 31 | } 32 | 33 | dependencies { 34 | compile fileTree(include: ['*.jar'], dir: 'libs') 35 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 36 | exclude group: 'com.android.support', module: 'support-annotations' 37 | }) 38 | compile 'com.android.support:appcompat-v7:26.0.0-alpha1' 39 | testCompile 'junit:junit:4.12' 40 | compile 'com.github.bumptech.glide:glide:3.7.0' 41 | compile 'com.android.support:cardview-v7:27.0.2' 42 | } 43 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\sdk\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/example/cj/videoeditor/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor; 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 | * Instrumentation 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.example.cj.videoeditor", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/assets/filter/brannan_blowout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/brannan_blowout.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/brannan_contrast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/brannan_contrast.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/brannan_luma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/brannan_luma.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/brannan_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/brannan_process.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/brannan_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/brannan_screen.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/edgeburn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/edgeburn.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/freud_rand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/freud_rand.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/hefemap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/hefemap.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/hefemetal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/hefemetal.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/hefesoftlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/hefesoftlight.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/hudsonbackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/hudsonbackground.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/hudsonmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/hudsonmap.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/inkwellmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/inkwellmap.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/n1977blowout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/n1977blowout.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/n1977map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/n1977map.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/nashvillemap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/nashvillemap.png -------------------------------------------------------------------------------- /app/src/main/assets/filter/overlaymap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqchenjian318/VideoEditor-For-Android/e116fda60c6bc271d8babfd62c04998e46d292c1/app/src/main/assets/filter/overlaymap.png -------------------------------------------------------------------------------- /app/src/main/assets/shader/base_fragment.sh: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | varying vec2 textureCoordinate; 3 | uniform sampler2D vTexture; 4 | void main() { 5 | gl_FragColor = texture2D( vTexture, textureCoordinate ); 6 | } -------------------------------------------------------------------------------- /app/src/main/assets/shader/base_record_fragment.sh: -------------------------------------------------------------------------------- 1 | #extension GL_OES_EGL_image_external : require 2 | precision mediump float; 3 | varying vec2 vTextureCoord; 4 | uniform samplerExternalOES sTexture; 5 | void main() { 6 | gl_FragColor = texture2D(sTexture, vTextureCoord); 7 | } -------------------------------------------------------------------------------- /app/src/main/assets/shader/base_record_vertex.sh: -------------------------------------------------------------------------------- 1 | uniform mat4 uMVPMatrix; 2 | uniform mat4 uSTMatrix; 3 | attribute vec4 aPosition; 4 | attribute vec4 aTextureCoord; 5 | varying vec2 vTextureCoord; 6 | void main() { 7 | gl_Position = uMVPMatrix * aPosition; 8 | vTextureCoord = (uSTMatrix * aTextureCoord).xy; 9 | }; -------------------------------------------------------------------------------- /app/src/main/assets/shader/base_vertex.sh: -------------------------------------------------------------------------------- 1 | attribute vec4 vPosition; 2 | attribute vec2 vCoord; 3 | uniform mat4 vMatrix; 4 | 5 | varying vec2 textureCoordinate; 6 | 7 | void main(){ 8 | gl_Position = vMatrix*vPosition; 9 | textureCoordinate = vCoord; 10 | } -------------------------------------------------------------------------------- /app/src/main/assets/shader/oes_base_fragment.sh: -------------------------------------------------------------------------------- 1 | #extension GL_OES_EGL_image_external : require 2 | precision mediump float; 3 | varying vec2 textureCoordinate; 4 | uniform samplerExternalOES vTexture; 5 | void main() { 6 | gl_FragColor = texture2D( vTexture, textureCoordinate ); 7 | } -------------------------------------------------------------------------------- /app/src/main/assets/shader/oes_base_vertex.sh: -------------------------------------------------------------------------------- 1 | attribute vec4 vPosition; 2 | attribute vec2 vCoord; 3 | uniform mat4 vMatrix; 4 | varying vec2 textureCoordinate; 5 | 6 | void main(){ 7 | gl_Position = vMatrix*vPosition; 8 | textureCoordinate = vCoord; 9 | } -------------------------------------------------------------------------------- /app/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern "C"{ 5 | jbyteArray 6 | Java_com_example_cj_videoeditor_jni_AudioJniUtils_audioMix(JNIEnv *env, jclass type, jbyteArray sourceA_, 7 | jbyteArray sourceB_, jbyteArray dst_, jfloat firstVol, 8 | jfloat secondVol) { 9 | jbyte *sourceA = env->GetByteArrayElements(sourceA_, NULL); 10 | jbyte *sourceB = env->GetByteArrayElements(sourceB_, NULL); 11 | jbyte *dst = env->GetByteArrayElements(dst_, NULL); 12 | //归一化混音 13 | int aL = env->GetArrayLength(sourceA_); 14 | int bL = env->GetArrayLength(sourceB_); 15 | int row = aL / 2; 16 | short sA[row]; 17 | for (int i = 0; i < row; ++i) { 18 | sA[i] = (short) ((sourceA[i * 2] & 0xff) | (sourceA[i * 2 + 1] & 0xff) << 8); 19 | } 20 | 21 | short sB[row]; 22 | for (int i = 0; i < row; ++i) { 23 | sB[i] = (short) ((sourceB[i * 2] & 0xff) | (sourceB[i * 2 + 1] & 0xff) << 8); 24 | } 25 | short result[row]; 26 | for (int i = 0; i < row; ++i) { 27 | int a = (int) (sA[i] * firstVol); 28 | int b = (int) (sB[i] * secondVol); 29 | if (a < 0 && b < 0){ 30 | int i1 = a + b - a * b / (-32768); 31 | if (i1 > 32768){ 32 | result[i] = 32767; 33 | } else if (i1 < - 32768){ 34 | result[i] = - 32768; 35 | } else{ 36 | result[i] = (short) i1; 37 | } 38 | } else if (a > 0 && b > 0){ 39 | int i1 = a + b - a * b / 32767; 40 | if (i1 > 32767){ 41 | result[i] = 32767; 42 | }else if (i1 < - 32768){ 43 | result[i] = -32768; 44 | }else { 45 | result[i] = (short) i1; 46 | } 47 | } else{ 48 | int i1 = a + b ; 49 | if (i1 > 32767){ 50 | result[i] = 32767; 51 | }else if (i1 < - 32768){ 52 | result[i] = -32768; 53 | }else { 54 | result[i] = (short) i1; 55 | } 56 | } 57 | } 58 | for (int i = 0; i > 8); 60 | dst[i * 2] = (jbyte) (result[i] & 0x00FF); 61 | } 62 | 63 | jbyteArray result1 = env ->NewByteArray(aL); 64 | env->SetByteArrayRegion(result1, 0, aL, dst); 65 | 66 | env->ReleaseByteArrayElements(sourceA_, sourceA, 0); 67 | env->ReleaseByteArrayElements(sourceB_, sourceB, 0); 68 | env->ReleaseByteArrayElements(dst_, dst, 0); 69 | 70 | return result1; 71 | } 72 | 73 | } 74 | 75 | extern "C" 76 | JNIEXPORT jstring JNICALL 77 | Java_com_example_cj_videoeditor_jni_AudioJniUtils_putString(JNIEnv *env, jclass type, 78 | jstring info_) { 79 | const char *info = env->GetStringUTFChars(info_, 0); 80 | char buf[128]; 81 | if (info == NULL) 82 | return NULL; 83 | sprintf(buf,"From C %s ",info); 84 | 85 | env->ReleaseStringUTFChars(info_, info); 86 | 87 | return env->NewStringUTF(buf); 88 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/Constants.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor; 2 | 3 | import android.content.Context; 4 | import android.os.Environment; 5 | import android.util.DisplayMetrics; 6 | 7 | 8 | import java.io.File; 9 | 10 | /** 11 | * Created by cj on 2017/6/26 . 12 | */ 13 | 14 | public class Constants { 15 | /** 16 | * 屏幕宽高 17 | */ 18 | public static int screenWidth; 19 | public static int screenHeight; 20 | 21 | /** 22 | * 画幅,视频的样式 9:16 1:1 16:9 23 | */ 24 | public static final int MODE_POR_9_16 = 0; 25 | public static final int MODE_POR_1_1 = 1; 26 | public static final int MODE_POR_16_9 = 2; 27 | 28 | /** 29 | * 三种画幅的具体显示尺寸 30 | */ 31 | public static int mode_por_width_9_16; 32 | public static int mode_por_height_9_16; 33 | public static int mode_por_width_1_1; 34 | public static int mode_por_height_1_1; 35 | public static int mode_por_width_16_9; 36 | public static int mode_por_height_16_9; 37 | 38 | /** 39 | * 三种画幅的具体编码尺寸(参考VUE) 40 | */ 41 | public static final int mode_por_encode_width_9_16 = 540; 42 | public static final int mode_por_encode_height_9_16 = 960; 43 | public static final int mode_por_encode_width_1_1 = 540; 44 | public static final int mode_por_encode_height_1_1 = 540; 45 | public static final int mode_por_encode_width_16_9 = 960; 46 | public static final int mode_por_encode_height_16_9 = 540; 47 | 48 | public static void init(Context context) { 49 | DisplayMetrics mDisplayMetrics = context.getResources() 50 | .getDisplayMetrics(); 51 | screenWidth = mDisplayMetrics.widthPixels; 52 | screenHeight = mDisplayMetrics.heightPixels; 53 | mode_por_width_9_16 = screenWidth; 54 | mode_por_height_9_16 = screenHeight; 55 | mode_por_width_1_1 = screenWidth; 56 | mode_por_height_1_1 = screenWidth; 57 | mode_por_width_16_9 = screenWidth; 58 | mode_por_height_16_9 = screenWidth / 16 * 9; 59 | } 60 | 61 | public static String getBaseFolder() { 62 | String baseFolder = Environment.getExternalStorageDirectory() + "/Codec/"; 63 | File f = new File(baseFolder); 64 | if (!f.exists()) { 65 | boolean b = f.mkdirs(); 66 | if (!b) { 67 | baseFolder = MyApplication.getContext().getExternalFilesDir(null).getAbsolutePath() + "/"; 68 | } 69 | } 70 | return baseFolder; 71 | } 72 | 73 | //获取VideoPath 74 | public static String getPath(String path, String fileName) { 75 | String p = getBaseFolder() + path; 76 | File f = new File(p); 77 | if (!f.exists() && !f.mkdirs()) { 78 | return getBaseFolder() + fileName; 79 | } 80 | return p + fileName; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.os.Handler; 6 | import android.util.DisplayMetrics; 7 | import android.util.Log; 8 | 9 | import com.example.cj.videoeditor.media.VideoInfo; 10 | import com.example.cj.videoeditor.mediacodec.VideoRunnable; 11 | 12 | import java.io.FileInputStream; 13 | import java.io.FileOutputStream; 14 | import java.nio.ByteBuffer; 15 | 16 | /** 17 | * Created by cj on 2017/8/6. 18 | * 19 | */ 20 | 21 | public class MyApplication extends Application{ 22 | private static Context mContext; 23 | 24 | 25 | 26 | @Override 27 | public void onCreate() { 28 | super.onCreate(); 29 | mContext = this; 30 | Log.e("thread"," 线程值 "+Thread.currentThread()); 31 | Constants.init(this); 32 | } 33 | 34 | @Override 35 | protected void attachBaseContext(Context base) { 36 | super.attachBaseContext(base); 37 | 38 | } 39 | 40 | public static Context getContext() { 41 | return mContext; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/MyClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor; 2 | 3 | /** 4 | * Created by cj on 2018/1/9. 5 | * desc 6 | */ 7 | 8 | public class MyClassLoader extends ClassLoader{ 9 | public MyClassLoader(){ 10 | super(); 11 | } 12 | 13 | @Override 14 | protected Class findClass(String name) throws ClassNotFoundException { 15 | return super.findClass(name); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/activity/AudioEditorActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.activity; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.support.annotation.Nullable; 7 | import android.view.View; 8 | import android.widget.Toast; 9 | 10 | import com.example.cj.videoeditor.Constants; 11 | import com.example.cj.videoeditor.R; 12 | import com.example.cj.videoeditor.mediacodec.AudioCodec; 13 | 14 | import java.io.File; 15 | 16 | /** 17 | * Created by cj on 2017/11/5. 18 | * 19 | */ 20 | 21 | public class AudioEditorActivity extends BaseActivity implements View.OnClickListener { 22 | @Override 23 | protected void onCreate(@Nullable Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_audio); 26 | findViewById(R.id.video_select).setOnClickListener(this); 27 | findViewById(R.id.audio_select).setOnClickListener(this); 28 | findViewById(R.id.pcm_to_audio).setOnClickListener(this); 29 | findViewById(R.id.audio_mix).setOnClickListener(this); 30 | 31 | } 32 | 33 | @Override 34 | public void onClick(View v) { 35 | switch (v.getId()){ 36 | case R.id.video_select: 37 | //去选择视频 38 | VideoSelectActivity.openActivity(this); 39 | break; 40 | case R.id.audio_select: 41 | startActivity(new Intent(AudioEditorActivity.this , AudioSelectActivity.class)); 42 | break; 43 | case R.id.pcm_to_audio: 44 | //pcm文件转音频 45 | String path = Constants.getPath("audio/outputPCM/", "PCM_1511078423497.pcm"); 46 | if (!new File(path).exists()){ 47 | Toast.makeText(this,"PCM文件不存在,请设置为本地已有PCM文件",Toast.LENGTH_SHORT).show(); 48 | return; 49 | } 50 | final String audioPath = Constants.getPath("audio/outputAudio/", "audio_"+System.currentTimeMillis()+".aac"); 51 | showLoading("音频编码中..."); 52 | AudioCodec.PCM2Audio(path, audioPath, new AudioCodec.AudioDecodeListener() { 53 | @Override 54 | public void decodeOver() { 55 | Toast.makeText(AudioEditorActivity.this,"数据编码成功 文件保存位置为—>>"+audioPath,Toast.LENGTH_SHORT).show(); 56 | endLoading(); 57 | } 58 | 59 | @Override 60 | public void decodeFail() { 61 | Toast.makeText(AudioEditorActivity.this,"数据编码失败 maybe same Exception ,please look at logcat "+audioPath,Toast.LENGTH_SHORT).show(); 62 | endLoading(); 63 | } 64 | }); 65 | break; 66 | case R.id.audio_mix: 67 | startActivity(new Intent(this,AudioMixActivity.class)); 68 | break; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/activity/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.activity; 2 | 3 | import android.app.Activity; 4 | import android.os.Build; 5 | import android.os.Looper; 6 | import android.support.v7.app.AppCompatActivity; 7 | 8 | import com.example.cj.videoeditor.widget.LoadingDialog; 9 | 10 | /** 11 | * Created by cj on 2017/10/16. 12 | * desc 13 | */ 14 | 15 | public class BaseActivity extends AppCompatActivity{ 16 | public LoadingDialog loading; 17 | 18 | @Override 19 | protected void onDestroy() { 20 | super.onDestroy(); 21 | if (loading != null){ 22 | loading.dismiss(); 23 | } 24 | } 25 | 26 | /** 27 | * 修改加载提示信息 28 | * 29 | * @param tips 30 | */ 31 | public void setLoading(String tips) { 32 | if (null == loading) { 33 | loading = new LoadingDialog(this); 34 | loading.setTips(tips); 35 | loading.show(); 36 | } else { 37 | loading.setTips(tips); 38 | } 39 | } 40 | 41 | /** 42 | * 显示加载提示 43 | * 44 | * @param tips 45 | */ 46 | public void showLoading(final String tips) { 47 | if (null == loading || loading.isWithTitle()) 48 | loading = new LoadingDialog(this); 49 | 50 | if (Thread.currentThread() == Looper.getMainLooper().getThread()) { 51 | loading.setTips(tips); 52 | loading.show(); 53 | } else { 54 | runOnUiThread(new Runnable() { 55 | @Override 56 | public void run() { 57 | loading.setTips(tips); 58 | loading.show(); 59 | } 60 | }); 61 | 62 | } 63 | } 64 | 65 | /** 66 | * @param tips 67 | * @param cancelable 是否可取消 false 不可以 true 可以 68 | */ 69 | public void showLoading(final String tips, final boolean cancelable) { 70 | if (isDestroyed()){ 71 | return; 72 | } 73 | endLoading(); 74 | if (Thread.currentThread() == Looper.getMainLooper().getThread()) { 75 | loading = new LoadingDialog(this, tips, cancelable); 76 | loading.show(); 77 | } else { 78 | runOnUiThread(new Runnable() { 79 | @Override 80 | public void run() { 81 | loading = new LoadingDialog(BaseActivity.this, tips, cancelable); 82 | loading.show(); 83 | } 84 | }); 85 | } 86 | } 87 | 88 | /** 89 | * 显示加载提示 90 | * 91 | * @param title 标题 92 | * @param tips 提示 93 | */ 94 | public void showLoading(String title, String tips) { 95 | endLoading(); 96 | loading = new LoadingDialog(this, title, tips); 97 | loading.show(); 98 | } 99 | 100 | /** 101 | * 是否响应back键 102 | * 103 | * @param cancelable true:响应,false:不响应 104 | */ 105 | public void setLoadingCancelable(boolean cancelable) { 106 | if (null != loading) { 107 | loading.setCancelable(cancelable); 108 | } 109 | } 110 | 111 | /** 112 | * 隐藏loading 113 | */ 114 | public void endLoading() { 115 | if (null != loading) { 116 | loading.dismiss(); 117 | } 118 | } 119 | public boolean isLoading(){ 120 | return loading != null && loading.isShowing(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.activity; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.Button; 7 | import android.widget.Toast; 8 | 9 | import com.example.cj.videoeditor.R; 10 | 11 | public class MainActivity extends BaseActivity implements View.OnClickListener { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_main); 17 | 18 | Button recordBtn = (Button) findViewById(R.id.record_activity); 19 | Button selectBtn = (Button) findViewById(R.id.select_activity); 20 | Button audioBtn = (Button) findViewById(R.id.audio_activity); 21 | Button videoBtn = (Button) findViewById(R.id.video_connect); 22 | 23 | recordBtn.setOnClickListener(this); 24 | selectBtn.setOnClickListener(this); 25 | audioBtn.setOnClickListener(this); 26 | videoBtn.setOnClickListener(this); 27 | } 28 | 29 | @Override 30 | public void onClick(View v) { 31 | switch (v.getId()){ 32 | case R.id.record_activity: 33 | startActivity(new Intent(MainActivity.this , RecordedActivity.class)); 34 | break; 35 | case R.id.select_activity: 36 | VideoSelectActivity.openActivity(this); 37 | break; 38 | case R.id.audio_activity: 39 | startActivity(new Intent(MainActivity.this , AudioEditorActivity.class)); 40 | break; 41 | case R.id.video_connect: 42 | // Toast.makeText(this,"该功能还未完成!!!",Toast.LENGTH_SHORT).show(); 43 | startActivity(new Intent(MainActivity.this , VideoConnectActivity.class)); 44 | break; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/adapter/AudioAdapter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.adapter; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.BaseAdapter; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | 12 | import com.example.cj.videoeditor.R; 13 | import com.example.cj.videoeditor.bean.Song; 14 | import com.example.cj.videoeditor.utils.DateUtils; 15 | 16 | import java.util.List; 17 | 18 | 19 | /** 20 | * Created by cj on 2017/6/27. 21 | * desc 22 | */ 23 | 24 | public class AudioAdapter extends BaseAdapter{ 25 | private List mData; 26 | private Context mContext; 27 | public AudioAdapter(Context context, List data){ 28 | mContext = context; 29 | mData = data; 30 | 31 | } 32 | public void setData(List data){ 33 | mData = data; 34 | } 35 | @Override 36 | public int getCount() { 37 | if (mData != null && mData.size() > 0) 38 | return mData.size(); 39 | return 0; 40 | } 41 | 42 | @Override 43 | public Object getItem(int position) { 44 | return mData.get(position); 45 | } 46 | 47 | @Override 48 | public long getItemId(int position) { 49 | return position; 50 | } 51 | 52 | @Override 53 | public View getView(int position, View convertView, ViewGroup parent) { 54 | ViewHolder holder; 55 | if (convertView == null){ 56 | holder = new ViewHolder(); 57 | convertView = LayoutInflater.from(mContext).inflate(R.layout.item_media_audio , parent,false); 58 | holder.audioType = (ImageView) convertView.findViewById(R.id.audio_type); 59 | holder.audioName = (TextView) convertView.findViewById(R.id.audio_name); 60 | holder.audioSize= (TextView) convertView.findViewById(R.id.audio_size); 61 | holder.audioDuration = (TextView) convertView.findViewById(R.id.audio_duration); 62 | convertView.setTag(holder); 63 | }else { 64 | holder = (ViewHolder) convertView.getTag(); 65 | } 66 | Song song = mData.get(position); 67 | holder.audioName.setText(song.getName()); 68 | 69 | holder.audioSize.setText(song.getSize()); 70 | holder.audioDuration.setText(DateUtils.covertToDate(song.getDuration())); 71 | if ("mp3".equals(song.getType())){ 72 | holder.audioType.setImageResource(R.mipmap.img_mp3); 73 | }else if ("aac".equals(song.getType())){ 74 | holder.audioType.setImageResource(R.mipmap.img_aac); 75 | }else if ("wma".equals(song.getType())){ 76 | holder.audioType.setImageResource(R.mipmap.img_wma); 77 | }else { 78 | holder.audioType.setImageResource(R.mipmap.ic_launcher); 79 | } 80 | 81 | return convertView; 82 | } 83 | class ViewHolder{ 84 | ImageView audioType; 85 | TextView audioName; 86 | TextView audioSize; 87 | TextView audioDuration; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/bean/AudioSettingInfo.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.bean; 2 | 3 | /** 4 | * Created by cj on 2017/6/28. 5 | * desc 6 | */ 7 | 8 | public class AudioSettingInfo { 9 | public boolean isSet;//是否设置过 10 | public String filePath;//bgm的文件路径 11 | public int volFirst;//原生音量大小 12 | public int volSecond;//bgm大小 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/bean/CutBean.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.bean; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | /** 7 | * Created by cj on 2017/7/10. 8 | * desc 以video的path和position为关键key 9 | * 记录 当前视频剪切的选择参数 10 | * 便于后面剪切视频 11 | */ 12 | 13 | public class CutBean implements Parcelable { 14 | public int position;//这个选择参数 在当前视频集里的位置 15 | public String videoPath; 16 | public long startPoint;//开始剪切的时间点 17 | public long cutDuration;//剪切的时长 18 | public long videoDuration;//video的总长度 19 | public CutBean(){ 20 | 21 | } 22 | 23 | protected CutBean(Parcel in) { 24 | position = in.readInt(); 25 | videoPath = in.readString(); 26 | startPoint = in.readLong(); 27 | cutDuration = in.readLong(); 28 | videoDuration = in.readLong(); 29 | } 30 | 31 | public static final Creator CREATOR = new Creator() { 32 | @Override 33 | public CutBean createFromParcel(Parcel in) { 34 | return new CutBean(in); 35 | } 36 | 37 | @Override 38 | public CutBean[] newArray(int size) { 39 | return new CutBean[size]; 40 | } 41 | }; 42 | 43 | @Override 44 | public int describeContents() { 45 | return 0; 46 | } 47 | 48 | @Override 49 | public void writeToParcel(Parcel dest, int flags) { 50 | dest.writeInt(position); 51 | dest.writeString(videoPath); 52 | dest.writeLong(startPoint); 53 | dest.writeLong(cutDuration); 54 | dest.writeLong(videoDuration); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/bean/MediaDecode.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.bean; 2 | 3 | import android.media.MediaExtractor; 4 | 5 | /** 6 | * Created by cj on 2017/7/11. 7 | * desc 音频解码的info类 包含了音频path 音频的MediaExtractor 8 | * 和本段音频的截取点cutPoint 9 | * 以及剪切时长 cutDuration 10 | */ 11 | 12 | public class MediaDecode { 13 | public String path; 14 | public MediaExtractor extractor; 15 | public int cutPoint; 16 | public int cutDuration; 17 | public int duration; 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/bean/Song.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.bean; 2 | 3 | /** 4 | * Created by cj on 2017/6/27. 5 | * desc 歌曲的bean 6 | */ 7 | 8 | public class Song { 9 | public String artist; 10 | public String path; 11 | public String title; 12 | public String name; 13 | public String size; 14 | public int duration; 15 | 16 | public String getType() { 17 | return type; 18 | } 19 | 20 | public void setType(String type) { 21 | this.type = type; 22 | } 23 | 24 | public String type; 25 | 26 | public String getName() { 27 | return name; 28 | } 29 | 30 | public void setName(String name) { 31 | this.name = name; 32 | } 33 | 34 | public String getArtist() { 35 | return artist; 36 | } 37 | 38 | public void setArtist(String artist) { 39 | this.artist = artist; 40 | } 41 | 42 | public String getPath() { 43 | return path; 44 | } 45 | 46 | public void setPath(String path) { 47 | this.path = path; 48 | } 49 | 50 | public String getTitle() { 51 | return title; 52 | } 53 | 54 | public void setTitle(String title) { 55 | this.title = title; 56 | } 57 | 58 | public String getSize() { 59 | return size; 60 | } 61 | 62 | public void setSize(String size) { 63 | this.size = size; 64 | } 65 | 66 | public int getDuration() { 67 | return duration; 68 | } 69 | 70 | public void setDuration(int duration) { 71 | this.duration = duration; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/camera/ICamera.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.camera; 2 | 3 | import android.graphics.Point; 4 | import android.graphics.SurfaceTexture; 5 | import android.hardware.Camera; 6 | 7 | /** 8 | * Created by cj on 2017/8/2. 9 | * desc 相机的接口控制类 10 | */ 11 | 12 | public interface ICamera { 13 | /** 14 | * open the camera 15 | */ 16 | void open(int cameraId); 17 | 18 | /** 19 | * set the preview texture 20 | */ 21 | void setPreviewTexture(SurfaceTexture texture); 22 | 23 | /** 24 | * set the camera config 25 | */ 26 | void setConfig(Config config); 27 | 28 | void setOnPreviewFrameCallback(PreviewFrameCallback callback); 29 | 30 | void preview(); 31 | 32 | Camera.Size getPreviewSize(); 33 | 34 | /** 35 | * close the camera 36 | */ 37 | boolean close(); 38 | 39 | class Config { 40 | public float rate = 1.778f; //宽高比 41 | public int minPreviewWidth; 42 | public int minPictureWidth; 43 | } 44 | 45 | interface PreviewFrameCallback { 46 | void onPreviewFrame(byte[] bytes, int width, int height); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/filter/CameraFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.filter; 2 | 3 | import android.content.res.Resources; 4 | 5 | 6 | /** 7 | * Description: 8 | */ 9 | public class CameraFilter extends OesFilter { 10 | 11 | public CameraFilter(Resources mRes) { 12 | super(mRes); 13 | } 14 | 15 | @Override 16 | public void setFlag(int flag) { 17 | super.setFlag(flag); 18 | float[] coord; 19 | if(getFlag()==1){ //前置摄像头 顺时针旋转90,并上下颠倒 20 | coord=new float[]{ 21 | 1.0f, 1.0f, 22 | 0.0f, 1.0f, 23 | 1.0f, 0.0f, 24 | 0.0f, 0.0f, 25 | }; 26 | }else{ //后置摄像头 顺时针旋转90度 27 | coord=new float[]{ 28 | 0.0f, 1.0f, 29 | 1.0f, 1.0f, 30 | 0.0f, 0.0f, 31 | 1.0f, 0.0f, 32 | }; 33 | } 34 | mTexBuffer.clear(); 35 | mTexBuffer.put(coord); 36 | mTexBuffer.position(0); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/filter/NoFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.filter; 2 | 3 | import android.content.res.Resources; 4 | import android.opengl.GLES20; 5 | import android.util.Log; 6 | 7 | /** 8 | * Description: 9 | */ 10 | public class NoFilter extends AFilter { 11 | 12 | public NoFilter(Resources res) { 13 | super(res); 14 | } 15 | 16 | @Override 17 | protected void onCreate() { 18 | Log.e("thread", "---初始化NoFilter "+Thread.currentThread()); 19 | createProgramByAssetsFile("shader/base_vertex.sh", 20 | "shader/base_fragment.sh"); 21 | } 22 | 23 | /** 24 | * 背景默认为黑色 25 | */ 26 | @Override 27 | protected void onClear() { 28 | Log.e("thread", "---onClear? 1 "+Thread.currentThread()); 29 | 30 | GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 31 | Log.e("thread", "---onClear? 2 "+Thread.currentThread()); 32 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 33 | Log.e("thread", "---onClear? 3 "); 34 | } 35 | 36 | @Override 37 | protected void onSizeChanged(int width, int height) { 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/filter/OesFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.filter; 2 | 3 | import android.content.res.Resources; 4 | import android.opengl.GLES11Ext; 5 | import android.opengl.GLES20; 6 | 7 | /** 8 | * Description: 加载默认的滤镜的filter 9 | */ 10 | public class OesFilter extends AFilter{ 11 | 12 | public OesFilter(Resources mRes) { 13 | super(mRes); 14 | } 15 | 16 | @Override 17 | protected void onCreate() { 18 | createProgramByAssetsFile("shader/oes_base_vertex.sh","shader/oes_base_fragment.sh"); 19 | } 20 | 21 | @Override 22 | protected void onBindTexture() { 23 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0+getTextureType()); 24 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,getTextureId()); 25 | GLES20.glUniform1i(mHTexture,getTextureType()); 26 | } 27 | 28 | @Override 29 | protected void onSizeChanged(int width, int height) { 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/filter/ProcessFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.filter; 2 | 3 | import android.content.res.Resources; 4 | import android.opengl.GLES20; 5 | 6 | import com.example.cj.videoeditor.utils.EasyGlUtils; 7 | import com.example.cj.videoeditor.utils.MatrixUtils; 8 | 9 | 10 | /** 11 | * draw并不执行父类的draw方法,所以矩阵对它无效 12 | * Description: 13 | */ 14 | public class ProcessFilter extends AFilter { 15 | 16 | private AFilter mFilter; 17 | //创建离屏buffer 18 | private int[] fFrame = new int[1]; 19 | private int[] fRender = new int[1]; 20 | private int[] fTexture = new int[1]; 21 | 22 | private int width; 23 | private int height; 24 | 25 | 26 | public ProcessFilter(Resources mRes) { 27 | super(mRes); 28 | mFilter=new NoFilter(mRes); 29 | float[] OM= MatrixUtils.getOriginalMatrix(); 30 | MatrixUtils.flip(OM,false,true);//矩阵上下翻转 31 | mFilter.setMatrix(OM); 32 | } 33 | 34 | @Override 35 | protected void initBuffer() { 36 | 37 | } 38 | 39 | @Override 40 | protected void onCreate() { 41 | mFilter.create(); 42 | } 43 | 44 | @Override 45 | public int getOutputTexture() { 46 | return fTexture[0]; 47 | } 48 | 49 | @Override 50 | public void draw() { 51 | boolean b= GLES20.glIsEnabled(GLES20.GL_CULL_FACE); 52 | if(b){ 53 | GLES20.glDisable(GLES20.GL_CULL_FACE); 54 | } 55 | GLES20.glViewport(0,0,width,height); 56 | EasyGlUtils.bindFrameTexture(fFrame[0],fTexture[0]); 57 | GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, 58 | GLES20.GL_RENDERBUFFER, fRender[0]); 59 | mFilter.setTextureId(getTextureId()); 60 | mFilter.draw(); 61 | EasyGlUtils.unBindFrameBuffer(); 62 | if(b){ 63 | GLES20.glEnable(GLES20.GL_CULL_FACE); 64 | } 65 | } 66 | 67 | @Override 68 | protected void onSizeChanged(int width, int height) { 69 | if(this.width!=width&&this.height!=height){ 70 | this.width=width; 71 | this.height=height; 72 | mFilter.setSize(width,height); 73 | deleteFrameBuffer(); 74 | GLES20.glGenFramebuffers(1,fFrame,0); 75 | GLES20.glGenRenderbuffers(1,fRender,0); 76 | GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER,fRender[0]); 77 | GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, 78 | width, height); 79 | GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, 80 | GLES20.GL_RENDERBUFFER, fRender[0]); 81 | GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER,0); 82 | EasyGlUtils.genTexturesWithParameter(1,fTexture,0, GLES20.GL_RGBA,width,height); 83 | } 84 | } 85 | 86 | private void deleteFrameBuffer() { 87 | GLES20.glDeleteRenderbuffers(1, fRender, 0); 88 | GLES20.glDeleteFramebuffers(1, fFrame, 0); 89 | GLES20.glDeleteTextures(1, fTexture, 0); 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/filter/RotationOESFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.filter; 2 | 3 | import android.content.res.Resources; 4 | 5 | /** 6 | * Created by Administrator on 2017/6/19 0019. 7 | */ 8 | 9 | public class RotationOESFilter extends OesFilter { 10 | public static final int ROT_0 = 0; 11 | public static final int ROT_90 = 90; 12 | public static final int ROT_180 = 180; 13 | public static final int ROT_270 = 270; 14 | 15 | public RotationOESFilter(Resources mRes) { 16 | super(mRes); 17 | } 18 | 19 | /** 20 | * 旋转视频操作 21 | * 22 | * @param rotation 23 | */ 24 | public void setRotation(int rotation) { 25 | float[] coord; 26 | switch (rotation) { 27 | case ROT_0: 28 | coord = new float[]{ 29 | 0.0f, 0.0f, 30 | 0.0f, 1.0f, 31 | 1.0f, 0.0f, 32 | 1.0f, 1.0f, 33 | }; 34 | break; 35 | case ROT_90: 36 | coord = new float[]{ 37 | 0.0f, 1.0f, 38 | 1.0f, 1.0f, 39 | 0.0f, 0.0f, 40 | 1.0f, 0.0f 41 | }; 42 | break; 43 | case ROT_180: 44 | coord = new float[]{ 45 | 1.0f, 1.0f, 46 | 1.0f, 0.0f, 47 | 0.0f, 1.0f, 48 | 0.0f, 0.0f, 49 | }; 50 | break; 51 | case ROT_270: 52 | coord = new float[]{ 53 | 1.0f, 0.0f, 54 | 0.0f, 0.0f, 55 | 1.0f, 1.0f, 56 | 0.0f, 1.0f 57 | }; 58 | break; 59 | default: 60 | return; 61 | } 62 | mTexBuffer.clear(); 63 | mTexBuffer.put(coord); 64 | mTexBuffer.position(0); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/filter/WaterMarkFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.filter; 2 | 3 | import android.content.res.Resources; 4 | import android.graphics.Bitmap; 5 | import android.opengl.GLES20; 6 | import android.opengl.GLUtils; 7 | 8 | import com.example.cj.videoeditor.utils.MatrixUtils; 9 | 10 | /** 11 | * Created by qqche_000 on 2017/8/20. 12 | * 水印的Filter 13 | */ 14 | 15 | public class WaterMarkFilter extends NoFilter{ 16 | /**水印的放置位置和宽高*/ 17 | private int x,y,w,h; 18 | /**控件的大小*/ 19 | private int width,height; 20 | /**水印图片的bitmap*/ 21 | private Bitmap mBitmap; 22 | /***/ 23 | private NoFilter mFilter; 24 | 25 | public WaterMarkFilter(Resources mRes) { 26 | super(mRes); 27 | mFilter=new NoFilter(mRes){ 28 | @Override 29 | protected void onClear() { 30 | } 31 | }; 32 | } 33 | public void setWaterMark(Bitmap bitmap){ 34 | if(this.mBitmap!=null){ 35 | this.mBitmap.recycle(); 36 | } 37 | this.mBitmap=bitmap; 38 | } 39 | @Override 40 | public void draw() { 41 | super.draw(); 42 | GLES20.glViewport(x,y,w == 0 ? mBitmap.getWidth():w,h==0?mBitmap.getHeight():h); 43 | GLES20.glDisable(GLES20.GL_DEPTH_TEST); 44 | GLES20.glEnable(GLES20.GL_BLEND); 45 | GLES20.glBlendFunc(GLES20.GL_SRC_COLOR, GLES20.GL_DST_ALPHA); 46 | mFilter.draw(); 47 | GLES20.glDisable(GLES20.GL_BLEND); 48 | GLES20.glViewport(0,0,width,height); 49 | } 50 | 51 | @Override 52 | protected void onCreate() { 53 | super.onCreate(); 54 | mFilter.create(); 55 | createTexture(); 56 | } 57 | private int[] textures=new int[1]; 58 | private void createTexture() { 59 | if(mBitmap!=null){ 60 | //生成纹理 61 | GLES20.glGenTextures(1,textures,0); 62 | //生成纹理 63 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textures[0]); 64 | //设置缩小过滤为使用纹理中坐标最接近的一个像素的颜色作为需要绘制的像素颜色 65 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 66 | //设置放大过滤为使用纹理中坐标最接近的若干个颜色,通过加权平均算法得到需要绘制的像素颜色 67 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 68 | //设置环绕方向S,截取纹理坐标到[1/2n,1-1/2n]。将导致永远不会与border融合 69 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 70 | //设置环绕方向T,截取纹理坐标到[1/2n,1-1/2n]。将导致永远不会与border融合 71 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 72 | GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBitmap, 0); 73 | //对画面进行矩阵旋转 74 | MatrixUtils.flip(mFilter.getMatrix(),false,true); 75 | 76 | mFilter.setTextureId(textures[0]); 77 | } 78 | } 79 | 80 | @Override 81 | protected void onSizeChanged(int width, int height) { 82 | this.width=width; 83 | this.height=height; 84 | mFilter.setSize(width,height); 85 | } 86 | public void setPosition(int x,int y,int width,int height){ 87 | this.x=x; 88 | this.y=y; 89 | this.w=width; 90 | this.h=height; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/filter/MagicBeautyFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.gpufilter.filter; 2 | 3 | import android.opengl.GLES20; 4 | 5 | 6 | import com.example.cj.videoeditor.R; 7 | import com.example.cj.videoeditor.gpufilter.basefilter.GPUImageFilter; 8 | import com.example.cj.videoeditor.gpufilter.utils.OpenGlUtils; 9 | 10 | 11 | 12 | /** 13 | * Created by cj on 2017/5/22. 14 | * 美白的filter 15 | */ 16 | public class MagicBeautyFilter extends GPUImageFilter { 17 | private int mSingleStepOffsetLocation; 18 | private int mParamsLocation; 19 | private int mLevel; 20 | 21 | public MagicBeautyFilter(){ 22 | super(NO_FILTER_VERTEX_SHADER , 23 | OpenGlUtils.readShaderFromRawResource(R.raw.beauty)); 24 | } 25 | 26 | protected void onInit() { 27 | super.onInit(); 28 | mSingleStepOffsetLocation = GLES20.glGetUniformLocation(getProgram(), "singleStepOffset"); 29 | mParamsLocation = GLES20.glGetUniformLocation(getProgram(), "params"); 30 | setBeautyLevel(3);//beauty Level 31 | } 32 | 33 | private void setTexelSize(final float w, final float h) { 34 | setFloatVec2(mSingleStepOffsetLocation, new float[] {2.0f / w, 2.0f / h}); 35 | } 36 | 37 | @Override 38 | public void onInputSizeChanged(final int width, final int height) { 39 | super.onInputSizeChanged(width, height); 40 | setTexelSize(width, height); 41 | } 42 | 43 | public void setBeautyLevel(int level){ 44 | mLevel=level; 45 | switch (level) { 46 | case 1: 47 | setFloat(mParamsLocation, 1.0f); 48 | break; 49 | case 2: 50 | setFloat(mParamsLocation, 0.8f); 51 | break; 52 | case 3: 53 | setFloat(mParamsLocation,0.6f); 54 | break; 55 | case 4: 56 | setFloat(mParamsLocation, 0.4f); 57 | break; 58 | case 5: 59 | setFloat(mParamsLocation,0.33f); 60 | break; 61 | default: 62 | break; 63 | } 64 | } 65 | public int getBeautyLevel(){ 66 | return mLevel; 67 | } 68 | public void onBeautyLevelChanged(){ 69 | setBeautyLevel(3);//beauty level 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/filter/MagicBrannanFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.gpufilter.filter; 2 | 3 | import android.opengl.GLES20; 4 | 5 | import com.example.cj.videoeditor.MyApplication; 6 | import com.example.cj.videoeditor.R; 7 | import com.example.cj.videoeditor.gpufilter.basefilter.GPUImageFilter; 8 | import com.example.cj.videoeditor.gpufilter.utils.OpenGlUtils; 9 | 10 | 11 | public class MagicBrannanFilter extends GPUImageFilter { 12 | private int[] inputTextureHandles = {-1,-1,-1,-1,-1}; 13 | private int[] inputTextureUniformLocations = {-1,-1,-1,-1,-1}; 14 | private int mGLStrengthLocation; 15 | 16 | public MagicBrannanFilter(){ 17 | super(NO_FILTER_VERTEX_SHADER, OpenGlUtils.readShaderFromRawResource(R.raw.brannan)); 18 | } 19 | 20 | protected void onDestroy() { 21 | super.onDestroy(); 22 | GLES20.glDeleteTextures(inputTextureHandles.length, inputTextureHandles, 0); 23 | for(int i = 0; i < inputTextureHandles.length; i++) 24 | inputTextureHandles[i] = -1; 25 | } 26 | 27 | protected void onDrawArraysAfter(){ 28 | for(int i = 0; i < inputTextureHandles.length 29 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 30 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3)); 31 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 32 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 33 | } 34 | } 35 | 36 | protected void onDrawArraysPre(){ 37 | for(int i = 0; i < inputTextureHandles.length 38 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 39 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3) ); 40 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTextureHandles[i]); 41 | GLES20.glUniform1i(inputTextureUniformLocations[i], (i+3)); 42 | } 43 | } 44 | 45 | protected void onInit(){ 46 | super.onInit(); 47 | for(int i=0; i < inputTextureUniformLocations.length; i++) 48 | inputTextureUniformLocations[i] = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture"+(2+i)); 49 | mGLStrengthLocation = GLES20.glGetUniformLocation(mGLProgId, 50 | "strength"); 51 | } 52 | 53 | protected void onInitialized(){ 54 | super.onInitialized(); 55 | setFloat(mGLStrengthLocation, 1.0f); 56 | runOnDraw(new Runnable(){ 57 | public void run(){ 58 | inputTextureHandles[0] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/brannan_process.png"); 59 | inputTextureHandles[1] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/brannan_blowout.png"); 60 | inputTextureHandles[2] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/brannan_contrast.png"); 61 | inputTextureHandles[3] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/brannan_luma.png"); 62 | inputTextureHandles[4] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/brannan_screen.png"); 63 | } 64 | }); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/filter/MagicFreudFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.gpufilter.filter; 2 | 3 | import android.opengl.GLES20; 4 | 5 | import com.example.cj.videoeditor.MyApplication; 6 | import com.example.cj.videoeditor.R; 7 | import com.example.cj.videoeditor.gpufilter.basefilter.GPUImageFilter; 8 | import com.example.cj.videoeditor.gpufilter.utils.OpenGlUtils; 9 | 10 | 11 | public class MagicFreudFilter extends GPUImageFilter { 12 | private int mTexelHeightUniformLocation; 13 | private int mTexelWidthUniformLocation; 14 | private int[] inputTextureHandles = {-1}; 15 | private int[] inputTextureUniformLocations = {-1}; 16 | private int mGLStrengthLocation; 17 | 18 | public MagicFreudFilter(){ 19 | super(NO_FILTER_VERTEX_SHADER, OpenGlUtils.readShaderFromRawResource(R.raw.freud)); 20 | } 21 | 22 | protected void onDestroy() { 23 | super.onDestroy(); 24 | GLES20.glDeleteTextures(1, inputTextureHandles, 0); 25 | for(int i = 0; i < inputTextureHandles.length; i++) 26 | inputTextureHandles[i] = -1; 27 | } 28 | 29 | protected void onDrawArraysAfter(){ 30 | for(int i = 0; i < inputTextureHandles.length 31 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 32 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3)); 33 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 34 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 35 | } 36 | } 37 | 38 | protected void onDrawArraysPre(){ 39 | for(int i = 0; i < inputTextureHandles.length 40 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 41 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3) ); 42 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTextureHandles[i]); 43 | GLES20.glUniform1i(inputTextureUniformLocations[i], (i+3)); 44 | } 45 | } 46 | 47 | protected void onInit(){ 48 | super.onInit(); 49 | inputTextureUniformLocations[0] = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture2"); 50 | 51 | mTexelWidthUniformLocation = GLES20.glGetUniformLocation(getProgram(), "inputImageTextureWidth"); 52 | mTexelHeightUniformLocation = GLES20.glGetUniformLocation(getProgram(), "inputImageTextureHeight"); 53 | 54 | mGLStrengthLocation = GLES20.glGetUniformLocation(mGLProgId, 55 | "strength"); 56 | } 57 | 58 | protected void onInitialized(){ 59 | super.onInitialized(); 60 | setFloat(mGLStrengthLocation, 1.0f); 61 | runOnDraw(new Runnable(){ 62 | public void run(){ 63 | inputTextureHandles[0] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/freud_rand.png"); 64 | } 65 | }); 66 | } 67 | 68 | public void onInputSizeChanged(final int width, final int height) { 69 | super.onInputSizeChanged(width, height); 70 | runOnDraw(new Runnable() { 71 | @Override 72 | public void run() { 73 | GLES20.glUniform1f(mTexelWidthUniformLocation, (float)width); 74 | GLES20.glUniform1f(mTexelHeightUniformLocation, (float)height); 75 | } 76 | }); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/filter/MagicHefeFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.gpufilter.filter; 2 | 3 | import android.opengl.GLES20; 4 | 5 | import com.example.cj.videoeditor.MyApplication; 6 | import com.example.cj.videoeditor.R; 7 | import com.example.cj.videoeditor.gpufilter.basefilter.GPUImageFilter; 8 | import com.example.cj.videoeditor.gpufilter.utils.OpenGlUtils; 9 | 10 | 11 | public class MagicHefeFilter extends GPUImageFilter { 12 | private int[] inputTextureHandles = {-1,-1,-1,-1}; 13 | private int[] inputTextureUniformLocations = {-1,-1,-1,-1}; 14 | private int mGLStrengthLocation; 15 | 16 | public MagicHefeFilter(){ 17 | super(NO_FILTER_VERTEX_SHADER, OpenGlUtils.readShaderFromRawResource(R.raw.hefe)); 18 | } 19 | 20 | protected void onDestroy() { 21 | super.onDestroy(); 22 | GLES20.glDeleteTextures(inputTextureHandles.length, inputTextureHandles, 0); 23 | for(int i = 0; i < inputTextureHandles.length; i++) 24 | inputTextureHandles[i] = -1; 25 | } 26 | 27 | protected void onDrawArraysAfter(){ 28 | for(int i = 0; i < inputTextureHandles.length 29 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 30 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3)); 31 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 32 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 33 | } 34 | } 35 | 36 | protected void onDrawArraysPre(){ 37 | for(int i = 0; i < inputTextureHandles.length 38 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 39 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3) ); 40 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTextureHandles[i]); 41 | GLES20.glUniform1i(inputTextureUniformLocations[i], (i+3)); 42 | } 43 | } 44 | 45 | protected void onInit(){ 46 | super.onInit(); 47 | for(int i=0; i < inputTextureUniformLocations.length; i++) 48 | inputTextureUniformLocations[i] = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture"+(2+i)); 49 | mGLStrengthLocation = GLES20.glGetUniformLocation(mGLProgId, 50 | "strength"); 51 | } 52 | 53 | protected void onInitialized(){ 54 | super.onInitialized(); 55 | setFloat(mGLStrengthLocation, 1.0f); 56 | runOnDraw(new Runnable(){ 57 | public void run(){ 58 | inputTextureHandles[0] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/edgeburn.png"); 59 | inputTextureHandles[1] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/hefemap.png"); 60 | inputTextureHandles[2] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/hefemetal.png"); 61 | inputTextureHandles[3] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/hefesoftlight.png"); 62 | } 63 | }); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/filter/MagicHudsonFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.gpufilter.filter; 2 | 3 | import android.opengl.GLES20; 4 | 5 | 6 | import com.example.cj.videoeditor.MyApplication; 7 | import com.example.cj.videoeditor.R; 8 | import com.example.cj.videoeditor.gpufilter.basefilter.GPUImageFilter; 9 | import com.example.cj.videoeditor.gpufilter.utils.OpenGlUtils; 10 | 11 | 12 | 13 | public class MagicHudsonFilter extends GPUImageFilter { 14 | private int[] inputTextureHandles = {-1,-1,-1}; 15 | private int[] inputTextureUniformLocations = {-1,-1,-1}; 16 | private int mGLStrengthLocation; 17 | 18 | public MagicHudsonFilter(){ 19 | super(NO_FILTER_VERTEX_SHADER, OpenGlUtils.readShaderFromRawResource(R.raw.hudson)); 20 | } 21 | 22 | protected void onDestroy() { 23 | super.onDestroy(); 24 | GLES20.glDeleteTextures(inputTextureHandles.length, inputTextureHandles, 0); 25 | for(int i = 0; i < inputTextureHandles.length; i++) 26 | inputTextureHandles[i] = -1; 27 | } 28 | 29 | protected void onDrawArraysAfter(){ 30 | for(int i = 0; i < inputTextureHandles.length 31 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 32 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3)); 33 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 34 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 35 | } 36 | } 37 | 38 | protected void onDrawArraysPre(){ 39 | for(int i = 0; i < inputTextureHandles.length 40 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 41 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3) ); 42 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTextureHandles[i]); 43 | GLES20.glUniform1i(inputTextureUniformLocations[i], (i+3)); 44 | } 45 | } 46 | 47 | protected void onInit(){ 48 | super.onInit(); 49 | for(int i=0; i < inputTextureUniformLocations.length; i++) 50 | inputTextureUniformLocations[i] = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture"+(2+i)); 51 | mGLStrengthLocation = GLES20.glGetUniformLocation(mGLProgId, 52 | "strength"); 53 | } 54 | 55 | protected void onInitialized(){ 56 | super.onInitialized(); 57 | setFloat(mGLStrengthLocation, 1.0f); 58 | runOnDraw(new Runnable(){ 59 | public void run(){ 60 | inputTextureHandles[0] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/hudsonbackground.png"); 61 | inputTextureHandles[1] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/overlaymap.png"); 62 | inputTextureHandles[2] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/hudsonmap.png"); 63 | } 64 | }); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/filter/MagicInkwellFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.gpufilter.filter; 2 | 3 | import android.opengl.GLES20; 4 | 5 | import com.example.cj.videoeditor.MyApplication; 6 | import com.example.cj.videoeditor.R; 7 | import com.example.cj.videoeditor.gpufilter.basefilter.GPUImageFilter; 8 | import com.example.cj.videoeditor.gpufilter.utils.OpenGlUtils; 9 | 10 | 11 | public class MagicInkwellFilter extends GPUImageFilter { 12 | private int[] inputTextureHandles = {-1}; 13 | private int[] inputTextureUniformLocations = {-1}; 14 | private int mGLStrengthLocation; 15 | 16 | public MagicInkwellFilter(){ 17 | super(NO_FILTER_VERTEX_SHADER, OpenGlUtils.readShaderFromRawResource(R.raw.inkwell)); 18 | } 19 | 20 | public void onDestroy() { 21 | super.onDestroy(); 22 | GLES20.glDeleteTextures(1, inputTextureHandles, 0); 23 | for(int i = 0; i < inputTextureHandles.length; i++) 24 | inputTextureHandles[i] = -1; 25 | } 26 | 27 | protected void onDrawArraysAfter(){ 28 | for(int i = 0; i < inputTextureHandles.length 29 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 30 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3)); 31 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 32 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 33 | } 34 | } 35 | 36 | protected void onDrawArraysPre(){ 37 | for(int i = 0; i < inputTextureHandles.length 38 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 39 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3) ); 40 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTextureHandles[i]); 41 | GLES20.glUniform1i(inputTextureUniformLocations[i], (i+3)); 42 | } 43 | } 44 | 45 | protected void onInit(){ 46 | super.onInit(); 47 | for(int i=0; i < inputTextureUniformLocations.length; i++) 48 | inputTextureUniformLocations[i] = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture"+(2+i)); 49 | mGLStrengthLocation = GLES20.glGetUniformLocation(mGLProgId, 50 | "strength"); 51 | } 52 | 53 | protected void onInitialized(){ 54 | super.onInitialized(); 55 | setFloat(mGLStrengthLocation, 1.0f); 56 | runOnDraw(new Runnable(){ 57 | public void run(){ 58 | inputTextureHandles[0] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/inkwellmap.png"); 59 | } 60 | }); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/filter/MagicN1977Filter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.gpufilter.filter; 2 | 3 | import android.opengl.GLES20; 4 | 5 | import com.example.cj.videoeditor.MyApplication; 6 | import com.example.cj.videoeditor.R; 7 | import com.example.cj.videoeditor.gpufilter.basefilter.GPUImageFilter; 8 | import com.example.cj.videoeditor.gpufilter.utils.OpenGlUtils; 9 | 10 | 11 | public class MagicN1977Filter extends GPUImageFilter { 12 | private int[] inputTextureHandles = {-1,-1}; 13 | private int[] inputTextureUniformLocations = {-1,-1}; 14 | private int mGLStrengthLocation; 15 | 16 | public MagicN1977Filter(){ 17 | super(NO_FILTER_VERTEX_SHADER, OpenGlUtils.readShaderFromRawResource(R.raw.n1977)); 18 | } 19 | 20 | protected void onDrawArraysAfter(){ 21 | for(int i = 0; i < inputTextureHandles.length 22 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 23 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3)); 24 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 25 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 26 | } 27 | } 28 | 29 | protected void onDrawArraysPre(){ 30 | for(int i = 0; i < inputTextureHandles.length 31 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 32 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3) ); 33 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTextureHandles[i]); 34 | GLES20.glUniform1i(inputTextureUniformLocations[i], (i+3)); 35 | } 36 | } 37 | 38 | protected void onInit(){ 39 | super.onInit(); 40 | for(int i=0; i < inputTextureUniformLocations.length; i++) 41 | inputTextureUniformLocations[i] = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture"+(2+i)); 42 | mGLStrengthLocation = GLES20.glGetUniformLocation(mGLProgId, 43 | "strength"); 44 | } 45 | 46 | protected void onInitialized(){ 47 | super.onInitialized(); 48 | setFloat(mGLStrengthLocation, 1.0f); 49 | runOnDraw(new Runnable(){ 50 | public void run(){ 51 | inputTextureHandles[0] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/n1977map.png"); 52 | inputTextureHandles[1] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/n1977blowout.png"); 53 | } 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/filter/MagicNashvilleFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.gpufilter.filter; 2 | 3 | import android.opengl.GLES20; 4 | 5 | import com.example.cj.videoeditor.MyApplication; 6 | import com.example.cj.videoeditor.R; 7 | import com.example.cj.videoeditor.gpufilter.basefilter.GPUImageFilter; 8 | import com.example.cj.videoeditor.gpufilter.utils.OpenGlUtils; 9 | 10 | 11 | public class MagicNashvilleFilter extends GPUImageFilter { 12 | private int[] inputTextureHandles = {-1}; 13 | private int[] inputTextureUniformLocations = {-1}; 14 | private int mGLStrengthLocation; 15 | 16 | public MagicNashvilleFilter(){ 17 | super(NO_FILTER_VERTEX_SHADER, OpenGlUtils.readShaderFromRawResource(R.raw.nashville)); 18 | } 19 | 20 | public void onDestroy() { 21 | super.onDestroy(); 22 | GLES20.glDeleteTextures(1, inputTextureHandles, 0); 23 | for(int i = 0; i < inputTextureHandles.length; i++) 24 | inputTextureHandles[i] = -1; 25 | } 26 | 27 | protected void onDrawArraysAfter(){ 28 | for(int i = 0; i < inputTextureHandles.length 29 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 30 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3)); 31 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 32 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 33 | } 34 | } 35 | 36 | protected void onDrawArraysPre(){ 37 | for(int i = 0; i < inputTextureHandles.length 38 | && inputTextureHandles[i] != OpenGlUtils.NO_TEXTURE; i++){ 39 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + (i+3) ); 40 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTextureHandles[i]); 41 | GLES20.glUniform1i(inputTextureUniformLocations[i], (i+3)); 42 | } 43 | } 44 | 45 | public void onInit(){ 46 | super.onInit(); 47 | for(int i=0; i < inputTextureUniformLocations.length; i++) 48 | inputTextureUniformLocations[i] = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture"+(2+i)); 49 | mGLStrengthLocation = GLES20.glGetUniformLocation(mGLProgId, 50 | "strength"); 51 | } 52 | 53 | public void onInitialized(){ 54 | super.onInitialized(); 55 | setFloat(mGLStrengthLocation, 1.0f); 56 | runOnDraw(new Runnable(){ 57 | public void run(){ 58 | inputTextureHandles[0] = OpenGlUtils.loadTexture(MyApplication.getContext(), "filter/nashvillemap.png"); 59 | } 60 | }); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/helper/MagicFilterFactory.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.gpufilter.helper; 2 | 3 | 4 | import com.example.cj.videoeditor.gpufilter.basefilter.GPUImageFilter; 5 | import com.example.cj.videoeditor.gpufilter.filter.MagicAntiqueFilter; 6 | import com.example.cj.videoeditor.gpufilter.filter.MagicBrannanFilter; 7 | import com.example.cj.videoeditor.gpufilter.filter.MagicCoolFilter; 8 | import com.example.cj.videoeditor.gpufilter.filter.MagicFreudFilter; 9 | import com.example.cj.videoeditor.gpufilter.filter.MagicHefeFilter; 10 | import com.example.cj.videoeditor.gpufilter.filter.MagicHudsonFilter; 11 | import com.example.cj.videoeditor.gpufilter.filter.MagicInkwellFilter; 12 | import com.example.cj.videoeditor.gpufilter.filter.MagicN1977Filter; 13 | import com.example.cj.videoeditor.gpufilter.filter.MagicNashvilleFilter; 14 | 15 | public class MagicFilterFactory { 16 | 17 | private static MagicFilterType filterType = MagicFilterType.NONE; 18 | 19 | public static GPUImageFilter initFilters(MagicFilterType type) { 20 | if (type == null) { 21 | return null; 22 | } 23 | filterType = type; 24 | switch (type) { 25 | case ANTIQUE: 26 | return new MagicAntiqueFilter(); 27 | case BRANNAN: 28 | return new MagicBrannanFilter(); 29 | case FREUD: 30 | return new MagicFreudFilter(); 31 | case HEFE: 32 | return new MagicHefeFilter(); 33 | case HUDSON: 34 | return new MagicHudsonFilter(); 35 | case INKWELL: 36 | return new MagicInkwellFilter(); 37 | case N1977: 38 | return new MagicN1977Filter(); 39 | case NASHVILLE: 40 | return new MagicNashvilleFilter(); 41 | case COOL: 42 | return new MagicCoolFilter(); 43 | case WARM: 44 | return new MagicWarmFilter(); 45 | default: 46 | return null; 47 | } 48 | } 49 | 50 | public MagicFilterType getCurrentFilterType() { 51 | return filterType; 52 | } 53 | 54 | private static class MagicWarmFilter extends GPUImageFilter { 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/helper/MagicFilterType.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.gpufilter.helper; 2 | 3 | /** 4 | * Created by why8222 on 2016/2/25. 5 | */ 6 | public enum MagicFilterType { 7 | NONE, 8 | WARM, 9 | ANTIQUE, 10 | COOL, 11 | BRANNAN, 12 | FREUD, 13 | HEFE, 14 | HUDSON, 15 | INKWELL, 16 | N1977, 17 | NASHVILLE, 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/utils/Rotation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 CyberAgent 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.cj.videoeditor.gpufilter.utils; 18 | 19 | public enum Rotation { 20 | NORMAL, ROTATION_90, ROTATION_180, ROTATION_270; 21 | 22 | /** 23 | * Retrieves the int representation of the Rotation. 24 | * 25 | * @return 0, 90, 180 or 270 26 | */ 27 | public int asInt() { 28 | switch (this) { 29 | case NORMAL: return 0; 30 | case ROTATION_90: return 90; 31 | case ROTATION_180: return 180; 32 | case ROTATION_270: return 270; 33 | default: throw new IllegalStateException("Unknown Rotation!"); 34 | } 35 | } 36 | 37 | /** 38 | * Create a Rotation from an integer. Needs to be either 0, 90, 180 or 270. 39 | * 40 | * @param rotation 0, 90, 180 or 270 41 | * @return Rotation object 42 | */ 43 | public static Rotation fromInt(int rotation) { 44 | switch (rotation) { 45 | case 0: return NORMAL; 46 | case 90: return ROTATION_90; 47 | case 180: return ROTATION_180; 48 | case 270: return ROTATION_270; 49 | case 360: return NORMAL; 50 | default: throw new IllegalStateException( 51 | rotation + " is an unknown rotation. Needs to be either 0, 90, 180 or 270!"); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/gpufilter/utils/TextureRotationUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 CyberAgent 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.cj.videoeditor.gpufilter.utils; 18 | 19 | public class TextureRotationUtil { 20 | 21 | public static final float TEXTURE_NO_ROTATION[] = { 22 | 0.0f, 1.0f, 23 | 1.0f, 1.0f, 24 | 0.0f, 0.0f, 25 | 1.0f, 0.0f, 26 | }; 27 | 28 | public static final float TEXTURE_ROTATED_90[] = { 29 | 1.0f, 1.0f, 30 | 1.0f, 0.0f, 31 | 0.0f, 1.0f, 32 | 0.0f, 0.0f, 33 | }; 34 | public static final float TEXTURE_ROTATED_180[] = { 35 | 1.0f, 0.0f, 36 | 0.0f, 0.0f, 37 | 1.0f, 1.0f, 38 | 0.0f, 1.0f, 39 | }; 40 | public static final float TEXTURE_ROTATED_270[] = { 41 | 0.0f, 0.0f, 42 | 0.0f, 1.0f, 43 | 1.0f, 0.0f, 44 | 1.0f, 1.0f, 45 | }; 46 | 47 | public static final float CUBE[] = { 48 | -1.0f, -1.0f, 49 | 1.0f, -1.0f, 50 | -1.0f, 1.0f, 51 | 1.0f, 1.0f, 52 | }; 53 | 54 | private TextureRotationUtil() {} 55 | 56 | public static float[] getRotation(final Rotation rotation, final boolean flipHorizontal, 57 | final boolean flipVertical) { 58 | float[] rotatedTex; 59 | switch (rotation) { 60 | case ROTATION_90: 61 | rotatedTex = TEXTURE_ROTATED_90; 62 | break; 63 | case ROTATION_180: 64 | rotatedTex = TEXTURE_ROTATED_180; 65 | break; 66 | case ROTATION_270: 67 | rotatedTex = TEXTURE_ROTATED_270; 68 | break; 69 | case NORMAL: 70 | default: 71 | rotatedTex = TEXTURE_NO_ROTATION; 72 | break; 73 | } 74 | if (flipHorizontal) { 75 | rotatedTex = new float[]{ 76 | flip(rotatedTex[0]), rotatedTex[1], 77 | flip(rotatedTex[2]), rotatedTex[3], 78 | flip(rotatedTex[4]), rotatedTex[5], 79 | flip(rotatedTex[6]), rotatedTex[7], 80 | }; 81 | } 82 | if (flipVertical) { 83 | rotatedTex = new float[]{ 84 | rotatedTex[0], flip(rotatedTex[1]), 85 | rotatedTex[2], flip(rotatedTex[3]), 86 | rotatedTex[4], flip(rotatedTex[5]), 87 | rotatedTex[6], flip(rotatedTex[7]), 88 | }; 89 | } 90 | return rotatedTex; 91 | } 92 | 93 | 94 | private static float flip(final float i) { 95 | if (i == 0.0f) { 96 | return 1.0f; 97 | } 98 | return 0.0f; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/jni/AudioJniUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.jni; 2 | 3 | /** 4 | * Created by cj on 2017/10/11. 5 | * desc 6 | */ 7 | 8 | public class AudioJniUtils { 9 | 10 | 11 | static { 12 | System.loadLibrary("native-lib"); 13 | } 14 | public static native byte[] audioMix(byte[] sourceA,byte[] sourceB,byte[] dst,float firstVol , float secondVol); 15 | 16 | public static native String putString(String info); 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/media/MediaCodecInfo.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.media; 2 | 3 | import android.media.MediaExtractor; 4 | 5 | /** 6 | * Created by cj on 2017/7/11. 7 | * desc 音频解码的info类 包含了音频path 音频的MediaExtractor 8 | * 和本段音频的截取点cutPoint 9 | * 以及剪切时长 cutDuration 10 | */ 11 | 12 | public class MediaCodecInfo { 13 | public String path; 14 | public MediaExtractor extractor; 15 | public int cutPoint; 16 | public int cutDuration; 17 | public int duration; 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/media/VideoInfo.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.media; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by Administrator on 2017/6/29 0029. 7 | * 视频的信息bean 8 | */ 9 | 10 | public class VideoInfo implements Serializable{ 11 | public String path;//路径 12 | public int rotation;//旋转角度 13 | public int width;//宽 14 | public int height;//高 15 | public int bitRate;//比特率 16 | public int frameRate;//帧率 17 | public int frameInterval;//关键帧间隔 18 | public int duration;//时长 19 | 20 | public int expWidth;//期望宽度 21 | public int expHeight;//期望高度 22 | public int cutPoint;//剪切的开始点 23 | public int cutDuration;//剪切的时长 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/utils/DateUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.utils; 2 | 3 | import java.text.DateFormat; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | 7 | /** 8 | * Created by cj on 2017/6/28. 9 | * desc 10 | */ 11 | 12 | public class DateUtils { 13 | 14 | public static String covertToDate(long duration){ 15 | Date date = new Date(duration); 16 | SimpleDateFormat format = new SimpleDateFormat("mm:ss"); 17 | return format.format(date); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/utils/DensityUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.utils; 2 | 3 | import android.content.Context; 4 | import android.util.DisplayMetrics; 5 | import android.util.TypedValue; 6 | import android.view.WindowManager; 7 | 8 | public class DensityUtils { 9 | 10 | private DensityUtils() { 11 | throw new UnsupportedOperationException("cannot be instantiated"); 12 | } 13 | 14 | /** 15 | * dp转px 16 | */ 17 | public static int dp2px(Context context, float dpVal) { 18 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 19 | dpVal, context.getResources().getDisplayMetrics()); 20 | } 21 | 22 | /** 23 | * sp转px 24 | */ 25 | public static int sp2px(Context context, float spVal) { 26 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 27 | spVal, context.getResources().getDisplayMetrics()); 28 | } 29 | 30 | /** 31 | * px转dp 32 | */ 33 | public static float px2dp(Context context, float pxVal) { 34 | final float scale = context.getResources().getDisplayMetrics().density; 35 | return (pxVal / scale); 36 | } 37 | 38 | /** 39 | * px转sp 40 | */ 41 | public static float px2sp(Context context, float pxVal) { 42 | return (pxVal / context.getResources().getDisplayMetrics().scaledDensity); 43 | } 44 | /** 45 | * 获取屏幕宽度 46 | * */ 47 | public static int getScreenWidth(Context context) { 48 | int width = 0; 49 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 50 | DisplayMetrics dm = new DisplayMetrics(); 51 | wm.getDefaultDisplay().getMetrics(dm); 52 | width = dm.widthPixels; 53 | return width; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/utils/EasyGlUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.utils; 2 | 3 | import android.opengl.GLES20; 4 | 5 | /** 6 | * Description: 7 | */ 8 | public enum EasyGlUtils { 9 | ; 10 | EasyGlUtils(){ 11 | 12 | } 13 | 14 | public static void useTexParameter(){ 15 | //设置缩小过滤为使用纹理中坐标最接近的一个像素的颜色作为需要绘制的像素颜色 16 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 17 | //设置放大过滤为使用纹理中坐标最接近的若干个颜色,通过加权平均算法得到需要绘制的像素颜色 18 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 19 | //设置环绕方向S,截取纹理坐标到[1/2n,1-1/2n]。将导致永远不会与border融合 20 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 21 | //设置环绕方向T,截取纹理坐标到[1/2n,1-1/2n]。将导致永远不会与border融合 22 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 23 | } 24 | 25 | public static void useTexParameter(int gl_wrap_s,int gl_wrap_t,int gl_min_filter, 26 | int gl_mag_filter){ 27 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,gl_wrap_s); 28 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,gl_wrap_t); 29 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,gl_min_filter); 30 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,gl_mag_filter); 31 | } 32 | 33 | public static void genTexturesWithParameter(int size,int[] textures,int start, 34 | int gl_format,int width,int height){ 35 | GLES20.glGenTextures(size, textures, start); 36 | for (int i = 0; i < size; i++) { 37 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[i]); 38 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0,gl_format, width, height, 39 | 0, gl_format, GLES20.GL_UNSIGNED_BYTE, null); 40 | useTexParameter(); 41 | } 42 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,0); 43 | } 44 | 45 | public static void bindFrameTexture(int frameBufferId,int textureId){ 46 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId); 47 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, 48 | GLES20.GL_TEXTURE_2D, textureId, 0); 49 | } 50 | 51 | public static void unBindFrameBuffer(){ 52 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,0); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/utils/OpenGlUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.utils; 2 | 3 | import android.content.res.Resources; 4 | 5 | import com.example.cj.videoeditor.MyApplication; 6 | 7 | import java.io.InputStream; 8 | 9 | /** 10 | * Created by qqche_000 on 2018/6/3. 11 | * 用于OpenGl的工具类 12 | */ 13 | 14 | public class OpenGlUtils { 15 | //通过资源路径加载shader脚本文件 16 | public static String uRes(String path) { 17 | Resources resources = MyApplication.getContext().getResources(); 18 | StringBuilder result = new StringBuilder(); 19 | try { 20 | InputStream is = resources.getAssets().open(path); 21 | int ch; 22 | byte[] buffer = new byte[1024]; 23 | while (-1 != (ch = is.read(buffer))) { 24 | result.append(new String(buffer, 0, ch)); 25 | } 26 | } catch (Exception e) { 27 | return null; 28 | } 29 | return result.toString().replaceAll("\\r\\n", "\n"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/utils/TimeFormatUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.utils; 2 | 3 | /** 4 | * Created by Administrator on 2017/6/30 0030. 5 | */ 6 | 7 | public class TimeFormatUtils { 8 | /** 9 | * 00:00:00 时分秒 10 | * @param millisec 11 | * @return 12 | */ 13 | public static String formatMillisec(int millisec){ 14 | int sec=millisec/1000; 15 | int min=sec/60; 16 | int hour=min/60; 17 | min=min%60; 18 | sec=sec%60; 19 | String t=""; 20 | t=hour>=10?t+hour:t+"0"+hour+":"; 21 | t=min>=10?t+min:t+"0"+min+":"; 22 | t=sec>=10?t+sec:t+"0"+sec; 23 | return t; 24 | } 25 | 26 | /** 27 | * 00:00 分秒 28 | * @param millisec 29 | * @return 30 | */ 31 | public static String formatMillisecWithoutHours(int millisec){ 32 | int sec=millisec/1000; 33 | int min=sec/60; 34 | sec=sec%60; 35 | String t=""; 36 | t=min>=10?t+min:t+"0"+min+":"; 37 | t=sec>=10?t+sec:t+"0"+sec; 38 | return t; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/cj/videoeditor/widget/FocusImageView.java: -------------------------------------------------------------------------------- 1 | package com.example.cj.videoeditor.widget; 2 | 3 | 4 | import android.content.Context; 5 | import android.content.res.TypedArray; 6 | import android.graphics.Point; 7 | import android.os.Handler; 8 | import android.util.AttributeSet; 9 | import android.view.View; 10 | import android.view.animation.Animation; 11 | import android.view.animation.AnimationUtils; 12 | import android.widget.ImageView; 13 | import android.widget.RelativeLayout; 14 | 15 | import com.example.cj.videoeditor.R; 16 | 17 | 18 | /** 19 | *create by GH 相机对焦控件 20 | */ 21 | public class FocusImageView extends ImageView { 22 | public final static String TAG = "FocusImageView"; 23 | private static final int NO_ID = -1; 24 | private int mFocusImg = NO_ID; 25 | private int mFocusSucceedImg = NO_ID; 26 | private int mFocusFailedImg = NO_ID; 27 | private Animation mAnimation; 28 | private Handler mHandler; 29 | 30 | public FocusImageView(Context context) { 31 | super(context); 32 | mAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.focusview_show); 33 | setVisibility(View.GONE); 34 | mHandler = new Handler(); 35 | } 36 | 37 | public FocusImageView(Context context, AttributeSet attrs) { 38 | super(context, attrs); 39 | mAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.focusview_show); 40 | mHandler = new Handler(); 41 | 42 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FocusImageView); 43 | mFocusImg = a.getResourceId(R.styleable.FocusImageView_focus_focusing_id, NO_ID); 44 | mFocusSucceedImg = a.getResourceId(R.styleable.FocusImageView_focus_success_id, NO_ID); 45 | mFocusFailedImg = a.getResourceId(R.styleable.FocusImageView_focus_fail_id, NO_ID); 46 | a.recycle(); 47 | 48 | } 49 | 50 | public void startFocus(Point point) { 51 | RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams(); 52 | params.topMargin = point.y - getHeight() / 2; 53 | params.leftMargin = point.x - getWidth() / 2; 54 | setLayoutParams(params); 55 | setVisibility(View.VISIBLE); 56 | setImageResource(mFocusImg); 57 | startAnimation(mAnimation); 58 | mHandler.postDelayed(new Runnable() { 59 | @Override 60 | public void run() { 61 | setVisibility(View.GONE); 62 | } 63 | }, 3500); 64 | } 65 | 66 | public void onFocusSuccess() { 67 | setImageResource(mFocusSucceedImg); 68 | mHandler.removeCallbacks(null, null); 69 | mHandler.postDelayed(new Runnable() { 70 | @Override 71 | public void run() { 72 | setVisibility(View.GONE); 73 | } 74 | }, 1000); 75 | 76 | } 77 | 78 | public void onFocusFailed() { 79 | setImageResource(mFocusFailedImg); 80 | mHandler.removeCallbacks(null, null); 81 | mHandler.postDelayed(new Runnable() { 82 | @Override 83 | public void run() { 84 | setVisibility(View.GONE); 85 | } 86 | }, 1000); 87 | } 88 | 89 | public void setFocusImg(int focus) { 90 | this.mFocusImg = focus; 91 | } 92 | 93 | public void setFocusSucceedImg(int focusSucceed) { 94 | this.mFocusSucceedImg = focusSucceed; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/res/anim/focusview_show.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/app_back_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_circle_yellow.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bt_capture.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_camera_beauty.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_camera_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_beauty.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_image_choose.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_rewardcamera.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_title_bar_btn.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/setting_text_color_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/t_progressbar.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/toast_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_audio.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 |