├── .DS_Store ├── .gitignore ├── .idea ├── compiler.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml ├── vcs.xml └── workspace.xml ├── README.md ├── Todo.txt ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── inuker │ │ └── camera │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── inuker │ │ │ └── camera │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── inuker │ └── camera │ └── ExampleUnitTest.java ├── build.gradle ├── doc ├── SurfaceTexture源码解析.md ├── glsurfacepreview.md ├── glsurfacepreview2.md ├── glsurfacepreview3.md ├── multisurfacepreview.md ├── recorder1.md ├── recorder2.md ├── surfacepreview.md └── surfacepreview2.md ├── glsurfacepreview ├── .gitignore ├── README.md ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── inuker │ │ └── glsurfacepreview │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── inuker │ │ │ └── glsurfacepreview │ │ │ ├── CameraSurfaceRender.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── inuker │ └── glsurfacepreview │ └── ExampleUnitTest.java ├── glsurfacepreview2 ├── .gitignore ├── README.md ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── inuker │ │ └── glsurfacepreview2 │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── inuker │ │ │ └── glsurfacepreview2 │ │ │ ├── CameraSurfaceRender.java │ │ │ ├── FilterTextureProgram.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── raw │ │ ├── filter_tex_fragment.glsl │ │ └── filter_tex_vertex.glsl │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── inuker │ └── glsurfacepreview2 │ └── ExampleUnitTest.java ├── glsurfacepreview3 ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── dingjikerbo │ │ └── glsurfacepreview3 │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── dingjikerbo │ │ │ └── glsurfacepreview3 │ │ │ ├── CameraSurfaceRender.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── example │ └── dingjikerbo │ └── glsurfacepreview3 │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── inuker │ │ └── library │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── inuker │ │ │ └── library │ │ │ ├── BaseActivity.java │ │ │ ├── BaseApplication.java │ │ │ ├── BaseSurfaceView.java │ │ │ ├── CameraActivity.java │ │ │ ├── EglCore.java │ │ │ ├── EglSurfaceBase.java │ │ │ ├── EventDispatcher.java │ │ │ ├── EventListener.java │ │ │ ├── Face.java │ │ │ ├── OffscreenSurface.java │ │ │ ├── Rect.java │ │ │ ├── RuntimeCounter.java │ │ │ ├── Shape.java │ │ │ ├── VertexArray.java │ │ │ ├── WindowSurface.java │ │ │ ├── encoder │ │ │ ├── AndroidMuxer.java │ │ │ ├── AudioEncoderCore.java │ │ │ ├── BaseMovieEncoder.java │ │ │ ├── MediaEncoderCore.java │ │ │ ├── MovieEncoder1.java │ │ │ ├── MovieEncoder2.java │ │ │ └── VideoEncoderCore.java │ │ │ ├── program │ │ │ ├── OESProgram.java │ │ │ ├── RectProgram.java │ │ │ ├── ShaderProgram.java │ │ │ ├── ShapeProgram.java │ │ │ ├── TextureProgram.java │ │ │ └── YUVProgram.java │ │ │ └── utils │ │ │ ├── CameraHelper.java │ │ │ ├── GlUtil.java │ │ │ ├── LogUtils.java │ │ │ ├── NativeUtils.java │ │ │ ├── ResourceUtils.java │ │ │ ├── ShaderHelper.java │ │ │ └── TaskUtils.java │ ├── jni │ │ ├── CMakeLists.txt │ │ └── camera.cpp │ └── res │ │ ├── raw │ │ ├── oes_fragment.glsl │ │ ├── oes_vertex.glsl │ │ ├── rect_fragment.glsl │ │ ├── rect_vertex.glsl │ │ ├── tex_fragment.glsl │ │ ├── tex_vertex.glsl │ │ ├── yuv_fragment.glsl │ │ └── yuv_vertex.glsl │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── inuker │ └── library │ └── ExampleUnitTest.java ├── multisurfacepreview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── inuker │ │ └── multiglsurfacepreview │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── inuker │ │ │ └── multisurfacepreview │ │ │ ├── CameraSurfaceView.java │ │ │ ├── Events.java │ │ │ ├── MainActivity.java │ │ │ └── MiniSurfaceView.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── raw │ │ └── filter_tex_fragment.glsl │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── inuker │ └── multiglsurfacepreview │ └── ExampleUnitTest.java ├── recorder1 ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── inuker │ │ └── recorder1 │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── inuker │ │ │ └── recorder1 │ │ │ ├── CameraSurfaceRender.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── inuker │ └── recorder1 │ └── ExampleUnitTest.java ├── recorder2 ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── inuker │ │ └── recorder2 │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── inuker │ │ │ └── recorder2 │ │ │ ├── CameraSurfaceView.java │ │ │ ├── FaceRender.java │ │ │ ├── MainActivity.java │ │ │ └── MyApplication.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── inuker │ └── recorder2 │ └── ExampleUnitTest.java ├── rgbconverter ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── inuker │ │ └── rgbconverter1 │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── inuker │ │ │ └── rgbconverter │ │ │ ├── CameraSurfaceView.java │ │ │ ├── Events.java │ │ │ ├── IRgbConverter.java │ │ │ ├── ISurfaceContainer.java │ │ │ ├── LaunchActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── RgbConverter.java │ │ │ ├── RgbConverter1.java │ │ │ ├── RgbConverter2.java │ │ │ ├── RgbConverter3.java │ │ │ ├── RgbConverter4.java │ │ │ ├── RgbConverter5.java │ │ │ └── SingleRgbConverter.java │ └── res │ │ ├── layout │ │ ├── activity_main.xml │ │ └── launch_activity.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── inuker │ └── rgbconverter1 │ └── ExampleUnitTest.java ├── settings.gradle ├── surfacepreview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── inuker │ │ └── surfaceviewpreview │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── inuker │ │ │ └── surfacepreview │ │ │ ├── CameraSurfaceView.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── inuker │ └── surfaceviewpreview │ └── ExampleUnitTest.java └── surfacepreview2 ├── .gitignore ├── README.md ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── inuker │ └── glsurfacepreview3 │ └── ExampleInstrumentedTest.java ├── main ├── AndroidManifest.xml ├── java │ └── com │ │ └── inuker │ │ └── surfacepreview2 │ │ ├── CameraSurfaceView.java │ │ └── MainActivity.java └── res │ ├── layout │ └── activity_main.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml └── test └── java └── com └── inuker └── glsurfacepreview3 └── ExampleUnitTest.java /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | .idea 4 | local.properties 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 30 | 31 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 22 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android Camera Demos 2 | 3 | ------ 4 | 5 | ## **一、相机预览** 6 | 7 | 8 | |序号|项目名称|内容简介| 9 | |--- |-------|-------| 10 | |1|GLSurfacePreview|[拿到相机帧数据,直接绘制到屏幕](doc/glsurfacepreview.md)| 11 | |2|GLSurfacePreview2|[拿到相机帧数据,先绘制到FBO,离线处理后(变红)绘制到屏幕](doc/glsurfacepreview2.md)| 12 | |3|GLSurfacePreview3|[直接给相机的预览纹理绘制到屏幕](doc/glsurfacepreview3.md)| 13 | |4|SurfacePreview|[拿到相机帧数据,直接绘制到屏幕](doc/surfacepreview.md)| 14 | |5|SurfacePreview2|[拿到相机帧数据,先绘制到PBuffer,再绘制到屏幕](doc/surfacepreview2.md)| 15 | |6|MultiSurfacePreview|[拿到相机帧数据,先转成纹理,再分别绘制到两个SurfaceView](doc/multisurfacepreview.md)| 16 | 17 | ## **二、RGB转换** 18 | 利用GPU将相机帧(NV21)转成RGB并传至CPU,分辨率为1920 * 1080,RGBA 19 | 20 | 另开一个线程做RGB转换,不然如果和相机共用上下文,渲染时需要来回切换,且可能阻塞相机渲染,对性能不利。 21 | 22 | |序号|模块名称|内容简介| 23 | |--- |-------|-------| 24 | |1|RgbConverter1|直接readPixels,~30ms| 25 | |2|RgbConverter2|从Pbuffer调readPixels,性能有较大提升,~30ms| 26 | |3|RgbConverter3|从FBO调readPixels,性能比PBuffer稍好一点,~27ms| 27 | |4|RgbConverter4|从FBO读到PBO,readPixels阻塞, glMapBuffer阻塞,~11ms| 28 | |5|RgbConverter5|从Pbuffer读到PBO,readPixels异步, glMapBuffer阻塞,~6ms| 29 | 30 | ## **三,视频录制** 31 | 32 | |序号|项目名称|内容简介| 33 | |--- |-------|-------| 34 | |1|recorder1|[录制相机预览以及音频](doc/recorder1.md)| 35 | |2|recorder2|[录制纹理以及音频](doc/recorder2.md)| 36 | 37 | 38 | ## **四,视频播放** 39 | 40 | |序号|项目名称|内容简介|状态| 41 | |--- |-------|-------|----| 42 | |1|video1|SurfaceView播放原始视频|Pending| 43 | |2|video2|视频裁剪播放,并增加一层遮罩|Pending| 44 | 45 | 46 | ## **相关文档** 47 | 48 | - [SurfaceTexture源码解析](doc/SurfaceTexture源码解析.md) 49 | 50 | ------ 51 | 有问题或建议可以给我邮件 52 | 53 | Email: dingjikerbo@gmail.com -------------------------------------------------------------------------------- /Todo.txt: -------------------------------------------------------------------------------- 1 | 1, 多窗口,左边预览,右边处理后显示,如标红,或者只裁剪头部 2 | 2, 视频播放,裁剪一部分 -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "26.0.1" 6 | defaultConfig { 7 | applicationId "com.inuker.camera" 8 | minSdkVersion 18 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 28 | testCompile 'junit:junit:4.12' 29 | } 30 | -------------------------------------------------------------------------------- /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 /Users/dingjikerbo/Library/Android/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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/inuker/camera/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.inuker.camera; 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.assertEquals; 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.inuker.camera", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/inuker/camera/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.inuker.camera; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | public class MainActivity extends Activity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_main); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Camera 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/test/java/com/inuker/camera/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.inuker.camera; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | maven { 7 | url 'https://maven.google.com/' 8 | } 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:2.3.2' 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | jcenter() 22 | maven { 23 | url 'https://maven.google.com/' 24 | } 25 | } 26 | } 27 | 28 | task clean(type: Delete) { 29 | delete rootProject.buildDir 30 | } 31 | -------------------------------------------------------------------------------- /doc/glsurfacepreview.md: -------------------------------------------------------------------------------- 1 | # glsurfacepreview工程 2 | 3 | GLSurfaceView.Renderer的几个接口如下: 4 | 5 | ``` 6 | onSurfaceCreated 7 | onSurfaceChanged 8 | onDrawFrame 9 | ``` 10 | 11 | 注意,这几个回调都是在render线程,这是GLSurfaceView专为OpenGL渲染创建的一个子线程。而相机的帧回调onPreviewFrame是在ui线程,如果涉及到buffer操作,记得上锁。 12 | 13 | 这个工程显示Camera预览的原理是,首先通过onPreviewFrame获取相机的NV21数据帧,然后用YUVProgram直接绘制到屏幕上。 14 | 15 | YUVProgram中涉及NV21到RGB的转换,转换过程看yuv_fragment.glsl文件 16 | 17 | 18 | 19 | # 深度解析 20 | 21 | 有以下几个疑问, 22 | 23 | 1. GLSurfaceView.Renderer这几个接口是怎么触发的 24 | 25 | 2. GLSurfaceView.requestRender();干嘛的 26 | 27 | 3. SurfaceTexture.updateTexImage();干嘛的 28 | 29 | 首先看第一个问题,我们需要从GLSurfaceView的源码入手,注释是这么写的 30 | 31 | ``` 32 | An implementation of SurfaceView that uses the dedicated surface for displaying OpenGL rendering. 33 | 34 | A GLSurfaceView provides the following features: 35 | 1) Manages a surface, which is a special piece of memory that can be composited into the Android view system. 36 | 2) Manages an EGL display, which enables OpenGL to render into a surface. 37 | 3) Accepts a user-provided Renderer object that does the actual rendering. 38 | 4) Renders on a dedicated thread to decouple rendering performance from the UI thread. 39 | 5) Supports both on-demand and continuous rendering. 40 | 6) Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls. 41 | ``` 42 | 43 | GLSurfaceView的核心是GLThread,这就是渲染线程,在setRenderer的时候,这个线程启动。创建gl上下文,包括glcontext和glsurface,然后通过eglMakeCurrent将该glsurface设置为当前生效。Renderer接口的几个回调都是在GLThread线程中调到的,根据状态进行回调。 44 | 45 | 再来看第二个问题,requestRender。这个函数只是设置了一个bool标志,表示readToDraw,接下来就会回调到onDrawFrame。 46 | 47 | 再来看第三个问题,可以参考[官方文档](https://developer.android.com/reference/android/graphics/SurfaceTexture)。 48 | 49 | surfaceTexture一般作为相机/MediaCodec/MediaPlayer的输出,当调用updateTexImage时,就从输出流中取最近的那一帧更新到texture上,这个函数必须在GL线程中调用。这里要注意,我个人理解的是不论你取不取,输出流都不会停止,假如相机每秒30帧,而我们每秒只调一次updateTexImage的话,就意味着另外29帧就跳过了。不过通常情况下,我们会为surfaceTexture设置frameAvailableListener,当有帧可用时会收到回调,此时调用requestRender要求绘制,在onDrawFrame中调用updateTexImage取一帧图像更新到surfaceTexture纹理,这样只要onDrawFrame不阻塞,相机的每一帧都能及时更新到surfaceTexture的纹理上。这个frameAvailableListener也是挺奇怪的,它不是说来一帧图像,自动更新到surfaceTexture的纹理上后给我们回调,而是来一帧图像的时候给我们回调,然后由我们自己决定要不要更新到surfaceTexture的纹理上。另外,对于本工程,由于是用的相机的onPreviewFrame获取帧数据来做后续绘制的,没有用到surfaceTexture的纹理,所以这里不调用updateTexImage也没关系。但是对于glsurfacepreview3工程就需要及时调用updateTexImage了,因为后续绘制需要用到surfaceTexture的纹理。 50 | -------------------------------------------------------------------------------- /doc/glsurfacepreview2.md: -------------------------------------------------------------------------------- 1 | # glsurfacepreview2工程 2 | 3 | 本工程和glsurfacepreview相比,区别在于glsurfacepreview拿到相机帧后直接绘制到屏幕,而本工程需要先对相机帧做一些处理,再绘制到屏幕。 4 | 5 | 由于中间多了一层处理的过程,所以这里创建了一个FBO和一个纹理,将纹理挂载在FBO上,先通过YUVProgram将相机帧离线绘制到该纹理上,然后再通过FilterTextureProgram滤镜将该纹理绘制到屏幕上。这个滤镜效果只是简单的给图像染红。 6 | 7 | 这个过程非常常见,相机帧要经过一些处理才能展现给用户,如做一些滤镜效果。通常的做法就是先创建一个FBO,然后挂载一个离线纹理到该FBO。绘制时先绑定到该FBO上,那么接下来所绘制的东西都在该FBO下挂载的纹理上了。当所有的离线绘制完成后,再将该纹理绘制到屏幕上即可,注意此时要解除绑定该FBO,这样绘制才会回到默认的屏幕上。 -------------------------------------------------------------------------------- /doc/glsurfacepreview3.md: -------------------------------------------------------------------------------- 1 | # glsurfacepreview3工程 2 | 3 | 本工程和前两个工程的区别在于,前两个工程都需要通过onPreviewFrame拿到相机的帧数据,然后再做后续处理。而本工程直接给相机的预览纹理绘制到屏幕上。 4 | 5 | 注意这两种纹理的区别,前两个工程都要先给相机的NV21转成RGB,所用的纹理类型是普通的2D纹理,而本工程用的GL_TEXTURE_EXTERNAL_OES类型的纹理,所以fragment shader的写法也略有不同,如下: 6 | 7 | ``` 8 | #extension GL_OES_EGL_image_external : require 9 | 10 | precision mediump float; 11 | 12 | varying vec2 vTextureCoord; 13 | uniform samplerExternalOES sTexture; 14 | 15 | void main() { 16 | gl_FragColor = texture2D(sTexture, vTextureCoord); 17 | } 18 | ``` 19 | 20 | 普通纹理的类型是sampler2D,而此处纹理类型是samplerExternalOES,注意这两者区别。 -------------------------------------------------------------------------------- /doc/multisurfacepreview.md: -------------------------------------------------------------------------------- 1 | # multisurfacepreview工程 2 | 3 | 本工程的意义在于要展示如何共享gl上下文。先在主surfaceview中将相机帧绘制到纹理上,然后将纹理绘制到屏幕上显示。另外开一个mini surfaceview,用于同步显示滤镜效果,需要复用主surfaceview中的纹理,但是这两个surfaceview的gl上下文不同,如何能共享纹理呢? 4 | 5 | 所谓的gl上下文就是EGLContext,而纹理是和gl上下文绑定的,即对于两个surfaceview,由于各自有独立的gl上下文,所以纹理是不能共享的。 6 | 7 | 如果要做到纹理共享,需在创建gl上下文时指定sharedContext。这样在surfaceviewA的gl上下文中创建的纹理对于surfaceviewB也是可用的。 8 | 9 | 关于gl上下文,可参考[官方文档](https://source.android.com/devices/graphics/arch-egl-opengl) 10 | 11 | 原文如下: 12 | 13 | ` 14 | 在使用 GLES 进行任何操作之前,需要创建一个 GL 上下文。在 EGL 中,这意味着要创建一个 EGLContext 和一个 EGLSurface。GLES 操作适用于当前上下文,该上下文通过线程局部存储访问,而不是作为参数进行传递。这意味着您必须注意渲染代码在哪个线程上执行,以及该线程上的当前上下文。 15 | ` -------------------------------------------------------------------------------- /doc/recorder1.md: -------------------------------------------------------------------------------- 1 | # recorder1工程 2 | 3 | 本工程录制摄像头及音频。 4 | 5 | 核心类是MovieEncoder1,由于继承自BaseMovieEncoder,所以持有VideoEncoderCore和AudioEncoderCore,这两个分别用于录制视频和音频。录制是用的系统类MediaCodec,根据传入的MIME_TYPE决定是录制视频还是音频。VideoEncoderCore和AudioEncoderCore内各有一个MediaCodec,但是共用一个MediaMuxer。 6 | 7 | 当相机收到帧可用回调时, 8 | 9 | 对于Audio,先调用drainEncoder给MediaCodec中的可用的OutputBuffers排空到muxer,然后再dequeueInputBuffer,用从AudioRecord中读取的数据填充好,再queueInputBuffer到MediaCodec中。 10 | 11 | 可见,MediaCodec对应着两端,输入端对应着AudioRecord,输出端对应着MediaMexer。从AudioRecord中读取录制的音频数据,然后写到MediaMuxer中去和视频混合。 12 | 13 | 再来看Video,同样有一个MediaCodec,同样分输入端和输出端,输出端和Audio端共用一个MediaMuxer,但是输入端没有类似AudioRecord的东西,而是通过createInputSurface返回了一个Surface,图像直接绘制到这个Surface上即可,这样MediaCodec在drainEncoder时同样可以有输出buffer到MediaMuxer。 14 | 我们拿到这个Surface怎么绘制呢?首先创建OpenGL上下文,拿这个Surface作为参数创建一个EGL WindowSurface,然后makeCurrent,就可以开始渲染了,完后swapBuffer即可推送到前台生效。 15 | 16 | 对于MediaMuxer来说,区分视频和音频是用trackIndex。 17 | 18 | 19 | # 参考文档 20 | 21 | 关于录屏可参考以下工程: 22 | https://bigflake.com/mediacodec/ -------------------------------------------------------------------------------- /doc/recorder2.md: -------------------------------------------------------------------------------- 1 | # recorder2工程 2 | 3 | 本工程和recorder1工程区别在于,recorder1的视频是直接录制相机的帧,根据相机的previewFrame的buffer,绘制到MediaCodec的inputSurface上。 4 | 5 | 本工程是录制纹理,方式更加灵活。先将相机帧绘制到纹理上,然后做一些额外的渲染,再将纹理绘制到MediaCodec的inputSurface上,不过要注意这两个过程是跑在不同的渲染线程,所以纹理要跨线程可用必须共享GL上下文。 -------------------------------------------------------------------------------- /doc/surfacepreview.md: -------------------------------------------------------------------------------- 1 | # surfacepreview工程 2 | 3 | 本工程和前几个工程的区别在于前几个工程都是用GLSurfaceView,而本工程用SurfaceView。 4 | 5 | 这两者的区别在于GLSurfaceView会自动管理OpenGL渲染所需的上下文,我们只需要关注单纯的绘制部分即可,即onDrawFrame中绘制。而SurfaceView中我们需要自己搭建OpenGL渲染的上下文,包括准备好EGL环境,创建渲染线程。 6 | 7 | 虽然看起来麻烦一些,但其实提供了更多的灵活性,在后面的录屏工程中就能体会到这一点。 -------------------------------------------------------------------------------- /doc/surfacepreview2.md: -------------------------------------------------------------------------------- 1 | # surfacepreview2工程 2 | 3 | 本工程和surfacepreview工程的区别在于,surfacepreview工程是直接将相机帧数据绘制到WindowSurface上,而本工程是先将相机帧数据绘制到OffscreenSurface,再通过glBlitFramebuffer绘制到WindowSurface,即增加了一个离线处理的过程。 4 | 5 | 这里要注意此处的OffscreenSurface其内部实现为PBuffer,与之前glsurfacepreview2工程的FBO是有所区别的,虽然同样是离线处理。 6 | 7 | pbuffer是和gl上下文绑定的,意味着切换pbuffer也要切换gl上下文,这个代价很大。相比之下,一个gl上下文下可以创建多个fbo,fbo之间的切换非常快,所以离屏渲染fbo是个更好的方案。 8 | 9 | pbuffer是平台相关的,eglCreateWindowSurface和eglCreatePbufferSurface,切换这两个surface是调用eglMakeCurrent,这个代价很大,另外pbuffer可以做成双缓冲的,和WindowSurface一样,而FBO是不行的。 -------------------------------------------------------------------------------- /glsurfacepreview/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /glsurfacepreview/README.md: -------------------------------------------------------------------------------- 1 | 当相机preview size和屏幕尺寸不一致时 -------------------------------------------------------------------------------- /glsurfacepreview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "26.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.inuker.glsurfacepreview" 9 | minSdkVersion 18 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | 16 | ndk { 17 | abiFilters "armeabi-v7a" 18 | } 19 | } 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | } 27 | 28 | dependencies { 29 | compile fileTree(dir: 'libs', include: ['*.jar']) 30 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 31 | exclude group: 'com.android.support', module: 'support-annotations' 32 | }) 33 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 34 | testCompile 'junit:junit:4.12' 35 | compile project(path: ':library') 36 | } 37 | -------------------------------------------------------------------------------- /glsurfacepreview/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 /Users/dingjikerbo/Library/Android/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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /glsurfacepreview/src/androidTest/java/com/inuker/glsurfacepreview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.inuker.glsurfacepreview; 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.assertEquals; 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.inuker.glsurfacepreview", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /glsurfacepreview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /glsurfacepreview/src/main/java/com/inuker/glsurfacepreview/CameraSurfaceRender.java: -------------------------------------------------------------------------------- 1 | package com.inuker.glsurfacepreview; 2 | 3 | import android.graphics.ImageFormat; 4 | import android.graphics.SurfaceTexture; 5 | import android.hardware.Camera; 6 | import android.opengl.GLSurfaceView; 7 | import android.util.Log; 8 | 9 | import com.inuker.library.program.YUVProgram; 10 | 11 | import java.io.IOException; 12 | import java.nio.ByteBuffer; 13 | import java.nio.ByteOrder; 14 | 15 | import javax.microedition.khronos.egl.EGLConfig; 16 | import javax.microedition.khronos.opengles.GL10; 17 | 18 | import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT; 19 | import static android.opengl.GLES20.GL_DEPTH_BUFFER_BIT; 20 | import static android.opengl.GLES20.glClear; 21 | import static android.opengl.GLES20.glClearColor; 22 | import static android.opengl.GLES20.glGenTextures; 23 | import static android.opengl.GLES20.glViewport; 24 | 25 | /** 26 | * Created by dingjikerbo on 17/8/16. 27 | */ 28 | 29 | public class CameraSurfaceRender implements GLSurfaceView.Renderer, Camera.PreviewCallback { 30 | 31 | private Camera mCamera; 32 | 33 | private SurfaceTexture mSurfaceTexture; 34 | 35 | private YUVProgram mYUVProgram; 36 | 37 | private ByteBuffer mYUVBuffer; 38 | 39 | private GLSurfaceView mGLSurfaceView; 40 | 41 | public CameraSurfaceRender(GLSurfaceView glSurfaceView) { 42 | mGLSurfaceView = glSurfaceView; 43 | } 44 | 45 | @Override 46 | public void onSurfaceCreated(GL10 gl, EGLConfig config) { 47 | mCamera = Camera.open(1); 48 | } 49 | 50 | @Override 51 | public void onSurfaceChanged(GL10 gl, int width, int height) { 52 | glViewport(0, 0, width, height); 53 | 54 | int bufferSize = width * height * ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8; 55 | 56 | mYUVBuffer = ByteBuffer.allocateDirect(bufferSize) 57 | .order(ByteOrder.nativeOrder()); 58 | 59 | int[] textures = new int[1]; 60 | glGenTextures(1, textures, 0); 61 | mSurfaceTexture = new SurfaceTexture(textures[0]); 62 | 63 | mYUVProgram = new YUVProgram(mGLSurfaceView.getContext(), width, height); 64 | 65 | try { 66 | mCamera.setPreviewTexture(mSurfaceTexture); 67 | } catch (IOException e) { 68 | e.printStackTrace(); 69 | } 70 | 71 | mCamera.setPreviewCallbackWithBuffer(this); 72 | 73 | for (int i = 0; i < 2; i++) { 74 | byte[] callbackBuffer = new byte[bufferSize]; 75 | mCamera.addCallbackBuffer(callbackBuffer); 76 | } 77 | 78 | mCamera.startPreview(); 79 | } 80 | 81 | @Override 82 | public void onDrawFrame(GL10 gl) { 83 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 84 | glClearColor(1f, 1f, 1f, 1f); 85 | 86 | synchronized (mYUVBuffer) { 87 | mYUVProgram.draw(mYUVBuffer.array()); 88 | } 89 | 90 | mSurfaceTexture.updateTexImage(); 91 | } 92 | 93 | @Override 94 | public void onPreviewFrame(byte[] data, Camera camera) { 95 | synchronized (mYUVBuffer) { 96 | mYUVBuffer.position(0); 97 | mYUVBuffer.put(data); 98 | } 99 | 100 | mGLSurfaceView.requestRender(); 101 | mCamera.addCallbackBuffer(data); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /glsurfacepreview/src/main/java/com/inuker/glsurfacepreview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.inuker.glsurfacepreview; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.content.Intent; 6 | import android.opengl.GLSurfaceView; 7 | import android.os.Bundle; 8 | 9 | import com.inuker.library.utils.Utils; 10 | 11 | public class MainActivity extends Activity { 12 | 13 | private static final int REQUEST_CAMERA = 1; 14 | 15 | private GLSurfaceView mGLSurfaceView; 16 | 17 | private static final String[] PERMISSIONS = { 18 | Manifest.permission.CAMERA 19 | }; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | 25 | mGLSurfaceView = new GLSurfaceView(this); 26 | setContentView(mGLSurfaceView); 27 | 28 | mGLSurfaceView.setEGLContextClientVersion(3); 29 | mGLSurfaceView.setRenderer(new CameraSurfaceRender(mGLSurfaceView)); 30 | mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 31 | 32 | Utils.requestPermission(this, PERMISSIONS, 1); 33 | } 34 | 35 | @Override 36 | protected void onPause() { 37 | super.onPause(); 38 | mGLSurfaceView.onPause(); 39 | } 40 | 41 | @Override 42 | protected void onResume() { 43 | super.onResume(); 44 | mGLSurfaceView.onResume(); 45 | } 46 | 47 | @Override 48 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 49 | super.onActivityResult(requestCode, resultCode, data); 50 | if (requestCode == REQUEST_CAMERA) { 51 | if (resultCode != RESULT_OK) { 52 | finish(); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | GLSurfacePreview 3 | 4 | -------------------------------------------------------------------------------- /glsurfacepreview/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /glsurfacepreview/src/test/java/com/inuker/glsurfacepreview/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.inuker.glsurfacepreview; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /glsurfacepreview2/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /glsurfacepreview2/README.md: -------------------------------------------------------------------------------- 1 | 相机预览先画到OffscreenTexture上,再将纹理处理后画到Window Surface上。 -------------------------------------------------------------------------------- /glsurfacepreview2/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "26.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.inuker.glsurfacepreview2" 9 | minSdkVersion 18 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | 16 | ndk { 17 | abiFilters "armeabi-v7a" 18 | } 19 | } 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | } 27 | 28 | dependencies { 29 | compile fileTree(dir: 'libs', include: ['*.jar']) 30 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 31 | exclude group: 'com.android.support', module: 'support-annotations' 32 | }) 33 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 34 | testCompile 'junit:junit:4.12' 35 | compile project(path: ':library') 36 | } 37 | -------------------------------------------------------------------------------- /glsurfacepreview2/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 /Users/dingjikerbo/Library/Android/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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /glsurfacepreview2/src/androidTest/java/com/inuker/glsurfacepreview2/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.inuker.glsurfacepreview2; 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.assertEquals; 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.inuker.glsurfacepreview2", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/java/com/inuker/glsurfacepreview2/FilterTextureProgram.java: -------------------------------------------------------------------------------- 1 | package com.inuker.glsurfacepreview2; 2 | 3 | import android.content.Context; 4 | 5 | import com.inuker.library.program.ShaderProgram; 6 | import com.inuker.library.utils.GlUtil; 7 | 8 | import java.nio.FloatBuffer; 9 | 10 | import static android.opengl.GLES20.GL_FLOAT; 11 | import static android.opengl.GLES20.GL_TEXTURE0; 12 | import static android.opengl.GLES20.GL_TEXTURE_2D; 13 | import static android.opengl.GLES20.GL_TRIANGLE_STRIP; 14 | import static android.opengl.GLES20.glActiveTexture; 15 | import static android.opengl.GLES20.glBindTexture; 16 | import static android.opengl.GLES20.glDrawArrays; 17 | import static android.opengl.GLES20.glEnableVertexAttribArray; 18 | import static android.opengl.GLES20.glGetAttribLocation; 19 | import static android.opengl.GLES20.glGetUniformLocation; 20 | import static android.opengl.GLES20.glVertexAttribPointer; 21 | 22 | /** 23 | * Created by dingjikerbo on 17/8/16. 24 | */ 25 | 26 | public class FilterTextureProgram extends ShaderProgram { 27 | 28 | private static final float FULL_RECTANGLE_COORDS[] = { 29 | -1.0f, -1.0f, // 0 bottom left 30 | 1.0f, -1.0f, // 1 bottom right 31 | -1.0f, 1.0f, // 2 top left 32 | 1.0f, 1.0f, // 3 top right 33 | }; 34 | 35 | private static final float FULL_RECTANGLE_TEX_COORDS[] = { 36 | 0.0f, 0.0f, // 0 bottom left 37 | 1.0f, 0.0f, // 1 bottom right 38 | 0.0f, 1.0f, // 2 top left 39 | 1.0f, 1.0f // 3 top right 40 | }; 41 | private static final FloatBuffer FULL_RECTANGLE_BUF = 42 | GlUtil.createFloatBuffer(FULL_RECTANGLE_COORDS); 43 | private static final FloatBuffer FULL_RECTANGLE_TEX_BUF = 44 | GlUtil.createFloatBuffer(FULL_RECTANGLE_TEX_COORDS); 45 | 46 | protected final int mUniformTextureLocation; 47 | 48 | private final int aPositionLocation; 49 | private final int aTextureCoordinatesLocation; 50 | 51 | public FilterTextureProgram(Context context, int width, int height) { 52 | super(context, R.raw.filter_tex_vertex, R.raw.filter_tex_fragment, width, height); 53 | 54 | mUniformTextureLocation = glGetUniformLocation(mProgram, "s_texture"); 55 | 56 | aPositionLocation = glGetAttribLocation(mProgram, "a_Position"); 57 | aTextureCoordinatesLocation = glGetAttribLocation(mProgram, "a_TextureCoordinates"); 58 | } 59 | 60 | public void draw(int texture) { 61 | useProgram(); 62 | 63 | glActiveTexture(GL_TEXTURE0); 64 | glBindTexture(GL_TEXTURE_2D, texture); 65 | 66 | glEnableVertexAttribArray(aPositionLocation); 67 | glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, false, 8, FULL_RECTANGLE_BUF); 68 | 69 | glEnableVertexAttribArray(aTextureCoordinatesLocation); 70 | glVertexAttribPointer(aTextureCoordinatesLocation, 2, GL_FLOAT, false, 8, FULL_RECTANGLE_TEX_BUF); 71 | 72 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/java/com/inuker/glsurfacepreview2/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.inuker.glsurfacepreview2; 2 | 3 | import android.app.Activity; 4 | import android.opengl.GLSurfaceView; 5 | import android.os.Bundle; 6 | 7 | public class MainActivity extends Activity { 8 | 9 | private GLSurfaceView mGLSurfaceView; 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | 15 | mGLSurfaceView = new GLSurfaceView(this); 16 | setContentView(mGLSurfaceView); 17 | 18 | mGLSurfaceView.setEGLContextClientVersion(3); 19 | mGLSurfaceView.setRenderer(new CameraSurfaceRender(mGLSurfaceView)); 20 | mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 21 | } 22 | 23 | @Override 24 | protected void onPause() { 25 | super.onPause(); 26 | mGLSurfaceView.onPause(); 27 | } 28 | 29 | @Override 30 | protected void onResume() { 31 | super.onResume(); 32 | mGLSurfaceView.onResume(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview2/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview2/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview2/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview2/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview2/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview2/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview2/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview2/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview2/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview2/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/raw/filter_tex_fragment.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | varying vec2 v_TextureCoordinates; 4 | 5 | uniform sampler2D s_texture; 6 | 7 | void main() { 8 | float r = texture2D(s_texture, v_TextureCoordinates).r; 9 | float g = texture2D(s_texture, v_TextureCoordinates).g; 10 | float b = texture2D(s_texture, v_TextureCoordinates).b; 11 | gl_FragColor = vec4(1.0, g, b, 1.0); 12 | } -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/raw/filter_tex_vertex.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 a_Position; 2 | attribute vec2 a_TextureCoordinates; 3 | 4 | varying vec2 v_TextureCoordinates; 5 | 6 | void main() { 7 | v_TextureCoordinates = a_TextureCoordinates; 8 | gl_Position = a_Position; 9 | } -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | GlSurfacePreview2 3 | 4 | -------------------------------------------------------------------------------- /glsurfacepreview2/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /glsurfacepreview2/src/test/java/com/inuker/glsurfacepreview2/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.inuker.glsurfacepreview2; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /glsurfacepreview3/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /glsurfacepreview3/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "26.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.example.dingjikerbo.glsurfacepreview3" 9 | minSdkVersion 18 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | compile fileTree(dir: 'libs', include: ['*.jar']) 27 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 28 | exclude group: 'com.android.support', module: 'support-annotations' 29 | }) 30 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 31 | testCompile 'junit:junit:4.12' 32 | compile project(path: ':library') 33 | } 34 | -------------------------------------------------------------------------------- /glsurfacepreview3/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 /Users/dingjikerbo/Library/Android/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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /glsurfacepreview3/src/androidTest/java/com/example/dingjikerbo/glsurfacepreview3/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.dingjikerbo.glsurfacepreview3; 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.assertEquals; 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.dingjikerbo.glsurfacepreview3", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/java/com/example/dingjikerbo/glsurfacepreview3/CameraSurfaceRender.java: -------------------------------------------------------------------------------- 1 | package com.example.dingjikerbo.glsurfacepreview3; 2 | 3 | import android.graphics.SurfaceTexture; 4 | import android.hardware.Camera; 5 | import android.opengl.GLSurfaceView; 6 | 7 | import com.inuker.library.program.OESProgram; 8 | 9 | import java.io.IOException; 10 | 11 | import javax.microedition.khronos.egl.EGLConfig; 12 | import javax.microedition.khronos.opengles.GL10; 13 | 14 | import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT; 15 | import static android.opengl.GLES20.GL_DEPTH_BUFFER_BIT; 16 | import static android.opengl.GLES20.glClear; 17 | import static android.opengl.GLES20.glClearColor; 18 | import static android.opengl.GLES20.glGenTextures; 19 | import static android.opengl.GLES20.glViewport; 20 | 21 | /** 22 | * Created by dingjikerbo on 17/8/16. 23 | */ 24 | 25 | public class CameraSurfaceRender implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { 26 | 27 | private Camera mCamera; 28 | 29 | private int mSurfaceTextureId; 30 | private SurfaceTexture mSurfaceTexture; 31 | private float[] mTransformMatrix = new float[16]; 32 | 33 | private GLSurfaceView mGLSurfaceView; 34 | 35 | private OESProgram mProgram; 36 | 37 | public CameraSurfaceRender(GLSurfaceView glSurfaceView) { 38 | mGLSurfaceView = glSurfaceView; 39 | } 40 | 41 | @Override 42 | public void onSurfaceCreated(GL10 gl, EGLConfig config) { 43 | mCamera = Camera.open(1); 44 | } 45 | 46 | @Override 47 | public void onSurfaceChanged(GL10 gl, int width, int height) { 48 | glViewport(0, 0, width, height); 49 | 50 | int[] textures = new int[1]; 51 | glGenTextures(1, textures, 0); 52 | mSurfaceTextureId = textures[0]; 53 | mSurfaceTexture = new SurfaceTexture(mSurfaceTextureId); 54 | mSurfaceTexture.setOnFrameAvailableListener(this); 55 | 56 | mProgram = new OESProgram(mGLSurfaceView.getContext(), width, height); 57 | 58 | try { 59 | mCamera.setPreviewTexture(mSurfaceTexture); 60 | } catch (IOException e) { 61 | e.printStackTrace(); 62 | } 63 | 64 | mCamera.startPreview(); 65 | } 66 | 67 | @Override 68 | public void onDrawFrame(GL10 gl) { 69 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 70 | glClearColor(1f, 1f, 1f, 1f); 71 | 72 | mSurfaceTexture.updateTexImage(); 73 | mSurfaceTexture.getTransformMatrix(mTransformMatrix); 74 | 75 | mProgram.draw(mSurfaceTextureId, mTransformMatrix); 76 | } 77 | 78 | @Override 79 | public void onFrameAvailable(SurfaceTexture surfaceTexture) { 80 | mGLSurfaceView.requestRender(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/java/com/example/dingjikerbo/glsurfacepreview3/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.dingjikerbo.glsurfacepreview3; 2 | 3 | import android.app.Activity; 4 | import android.opengl.GLSurfaceView; 5 | import android.os.Bundle; 6 | 7 | public class MainActivity extends Activity { 8 | 9 | private GLSurfaceView mGLSurfaceView; 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | 15 | mGLSurfaceView = new GLSurfaceView(this); 16 | setContentView(mGLSurfaceView); 17 | 18 | mGLSurfaceView.setEGLContextClientVersion(3); 19 | mGLSurfaceView.setRenderer(new CameraSurfaceRender(mGLSurfaceView)); 20 | mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 21 | } 22 | 23 | @Override 24 | protected void onPause() { 25 | super.onPause(); 26 | mGLSurfaceView.onPause(); 27 | } 28 | 29 | @Override 30 | protected void onResume() { 31 | super.onResume(); 32 | mGLSurfaceView.onResume(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview3/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview3/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview3/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview3/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview3/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview3/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview3/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview3/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview3/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/glsurfacepreview3/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | GlSurfacePreview3 3 | 4 | -------------------------------------------------------------------------------- /glsurfacepreview3/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /glsurfacepreview3/src/test/java/com/example/dingjikerbo/glsurfacepreview3/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.example.dingjikerbo.glsurfacepreview3; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | org.gradle.parallel=true 18 | #android.useDeprecatedNdk=true 19 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Aug 16 09:53:14 CST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "26.0.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 18 9 | targetSdkVersion 21 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | 15 | externalNativeBuild { 16 | cmake { 17 | arguments '-DANDROID_TOOLCHAIN=gcc', '-DANDROID_STL=gnustl_static', 18 | '-DANDROID_PLATFORM=android-19' 19 | cppFlags "-O3" 20 | } 21 | } 22 | 23 | ndk { 24 | abiFilters "armeabi-v7a" 25 | } 26 | } 27 | 28 | 29 | buildTypes { 30 | release { 31 | minifyEnabled false 32 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 33 | } 34 | } 35 | 36 | externalNativeBuild { 37 | cmake { 38 | path 'src/main/jni/CMakeLists.txt' 39 | } 40 | } 41 | } 42 | 43 | dependencies { 44 | compile fileTree(dir: 'libs', include: ['*.jar']) 45 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 46 | exclude group: 'com.android.support', module: 'support-annotations' 47 | }) 48 | compile 'com.android.support:appcompat-v7:25.3.1' 49 | testCompile 'junit:junit:4.12' 50 | } 51 | -------------------------------------------------------------------------------- /library/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 /Users/dingjikerbo/Library/Android/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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /library/src/androidTest/java/com/inuker/library/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 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.assertEquals; 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.inuker.library.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.os.Handler; 8 | import android.os.Looper; 9 | import android.os.Message; 10 | import android.support.annotation.Nullable; 11 | 12 | /** 13 | * Created by dingjikerbo on 17/8/16. 14 | */ 15 | 16 | public class BaseActivity extends Activity implements Handler.Callback { 17 | 18 | protected Handler mHandler = new Handler(Looper.getMainLooper(), this); 19 | 20 | protected Context mContext; 21 | 22 | @Override 23 | protected void onCreate(@Nullable Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | mContext = this; 26 | } 27 | 28 | @Override 29 | public boolean handleMessage(Message msg) { 30 | return false; 31 | } 32 | 33 | public void postDelayed(Runnable runnable, long delayInMillis) { 34 | mHandler.postDelayed(runnable, delayInMillis); 35 | } 36 | 37 | public void startActivity(final Class target) { 38 | Intent intent = new Intent(this, target); 39 | startActivity(intent); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/BaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.os.Handler; 6 | import android.view.WindowManager; 7 | 8 | import com.inuker.library.utils.LogUtils; 9 | 10 | /** 11 | * Created by dingjikerbo on 17/8/16. 12 | */ 13 | 14 | public class BaseApplication extends Application { 15 | 16 | private static BaseApplication sInstance; 17 | 18 | private static int mScreenWidth, mScreenHeight; 19 | 20 | private static float mDensity; 21 | 22 | private static Handler mHandler; 23 | 24 | public static BaseApplication getInstance() { 25 | return sInstance; 26 | } 27 | 28 | @Override 29 | public void onCreate() { 30 | super.onCreate(); 31 | 32 | sInstance = this; 33 | 34 | WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); 35 | int width = wm.getDefaultDisplay().getWidth(); 36 | int height = wm.getDefaultDisplay().getHeight(); 37 | 38 | mScreenWidth = Math.max(width, height); 39 | mScreenHeight = Math.min(width, height); 40 | 41 | LogUtils.v(String.format("width = %d, height = %d", mScreenWidth, mScreenHeight)); 42 | 43 | mDensity = getResources().getDisplayMetrics().density; 44 | 45 | mHandler = new Handler(); 46 | } 47 | 48 | public static int getScreenWidth() { 49 | return mScreenWidth; 50 | } 51 | 52 | public static int getScreenHeight() { 53 | return mScreenHeight; 54 | } 55 | 56 | public static int dp2px(int dp) { 57 | return (int) (dp * mDensity + 0.5f); 58 | } 59 | 60 | public static void post(Runnable runnable) { 61 | mHandler.post(runnable); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/CameraActivity.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.content.Intent; 6 | import android.content.pm.PackageManager; 7 | import android.os.Bundle; 8 | import android.support.annotation.Nullable; 9 | import android.support.v4.app.ActivityCompat; 10 | import android.support.v4.content.ContextCompat; 11 | 12 | /** 13 | * Created by dingjikerbo on 17/8/16. 14 | */ 15 | 16 | public abstract class CameraActivity extends BaseActivity { 17 | 18 | private static final int REQUEST_CAMERA = 0x7378; 19 | 20 | private static final String[] PERMISSIONS = { 21 | Manifest.permission.CAMERA, 22 | Manifest.permission.ACCESS_FINE_LOCATION 23 | }; 24 | 25 | @Override 26 | protected void onCreate(@Nullable Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | requestPermission(this, PERMISSIONS, REQUEST_CAMERA); 29 | } 30 | 31 | protected abstract void onPermissionGranted(); 32 | 33 | @Override 34 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 35 | super.onActivityResult(requestCode, resultCode, data); 36 | if (requestCode == REQUEST_CAMERA) { 37 | if (resultCode != RESULT_OK) { 38 | finish(); 39 | } else { 40 | dispatchPermissionGranted(); 41 | } 42 | } 43 | } 44 | 45 | private void dispatchPermissionGranted() { 46 | postDelayed(new Runnable() { 47 | @Override 48 | public void run() { 49 | onPermissionGranted(); 50 | } 51 | }, 0); 52 | } 53 | 54 | private void requestPermission(Activity activity, String[] permissions, int request) { 55 | boolean allGranted = true; 56 | for (String permission : permissions) { 57 | if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { 58 | allGranted = false; 59 | break; 60 | } 61 | } 62 | if (!allGranted) { 63 | ActivityCompat.requestPermissions(activity, 64 | permissions, 65 | request); 66 | } else { 67 | dispatchPermissionGranted(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/EventDispatcher.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 2 | 3 | import android.util.SparseArray; 4 | 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by dingjikerbo on 17/8/17. 10 | */ 11 | 12 | public class EventDispatcher { 13 | 14 | private static SparseArray> sListeners = new SparseArray<>(); 15 | 16 | public static void observe(int event, EventListener l) { 17 | if (l == null) { 18 | return; 19 | } 20 | 21 | synchronized (sListeners) { 22 | List listeners = sListeners.get(event); 23 | if (listeners == null) { 24 | listeners = new LinkedList<>(); 25 | sListeners.put(event, listeners); 26 | } 27 | if (!listeners.contains(l)) { 28 | listeners.add(l); 29 | } 30 | } 31 | } 32 | 33 | public static void observe(EventListener l, int... events) { 34 | synchronized (sListeners) { 35 | for (int event : events) { 36 | observe(event, l); 37 | } 38 | } 39 | } 40 | 41 | public static void unObserve(int event, EventListener l) { 42 | if (l == null) { 43 | return; 44 | } 45 | 46 | synchronized (sListeners) { 47 | List listeners = sListeners.get(event); 48 | if (listeners != null) { 49 | listeners.remove(l); 50 | } 51 | } 52 | } 53 | 54 | public static void unObserve(EventListener l, int... events) { 55 | synchronized (sListeners) { 56 | for (int event : events) { 57 | unObserve(event, l); 58 | } 59 | } 60 | } 61 | 62 | private static void dispatch(final int event, final Object object, DispatchCaller caller) { 63 | synchronized (sListeners) { 64 | List listeners = sListeners.get(event); 65 | if (listeners != null) { 66 | for (final EventListener l : listeners) { 67 | caller.onDispatch(event, object, l); 68 | } 69 | } 70 | } 71 | } 72 | 73 | public static void dispatch(final int event, final Object object) { 74 | dispatch(event, object, new DispatchCaller() { 75 | @Override 76 | public void onDispatch(final int event, final Object object, final EventListener l) { 77 | if (l != null) { 78 | BaseApplication.post(new Runnable() { 79 | @Override 80 | public void run() { 81 | l.onEvent(event, object); 82 | } 83 | }); 84 | } 85 | } 86 | }); 87 | } 88 | 89 | public static void dispatchInstant(final int event, final Object object) { 90 | dispatch(event, object, new DispatchCaller() { 91 | @Override 92 | public void onDispatch(final int event, final Object object, final EventListener l) { 93 | if (l != null) { 94 | l.onEvent(event, object); 95 | } 96 | } 97 | }); 98 | } 99 | 100 | private interface DispatchCaller { 101 | void onDispatch(int event, Object object, EventListener l); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/EventListener.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 2 | 3 | /** 4 | * Created by dingjikerbo on 17/8/17. 5 | */ 6 | 7 | public interface EventListener { 8 | 9 | void onEvent(int event, Object object); 10 | } 11 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/Face.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 2 | 3 | import static android.opengl.GLES20.glLineWidth; 4 | 5 | /** 6 | * Created by dingjikerbo on 2017/10/31. 7 | */ 8 | 9 | public class Face extends Rect { 10 | 11 | public Face(int x1, int y1, int x2, int y2, int color) { 12 | super(x1, y1, x2, y2, color); 13 | } 14 | 15 | @Override 16 | public void draw() { 17 | glLineWidth(5f); 18 | super.draw(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/OffscreenSurface.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Google Inc. All rights reserved. 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.inuker.library; 18 | 19 | /** 20 | * Off-screen EGL surface (pbuffer). 21 | *

22 | * It's good practice to explicitly release() the surface, preferably from a "finally" block. 23 | */ 24 | public class OffscreenSurface extends EglSurfaceBase { 25 | /** 26 | * Creates an off-screen surface with the specified width and height. 27 | */ 28 | public OffscreenSurface(EglCore eglCore, int width, int height) { 29 | super(eglCore); 30 | createOffscreenSurface(width, height); 31 | } 32 | 33 | /** 34 | * Releases any resources associated with the surface. 35 | */ 36 | public void release() { 37 | releaseEglSurface(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/Rect.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 2 | 3 | import android.graphics.Color; 4 | 5 | import com.inuker.library.program.RectProgram; 6 | 7 | import static android.opengl.GLES20.GL_LINE_STRIP; 8 | import static android.opengl.GLES20.glDrawArrays; 9 | 10 | /** 11 | * Created by dingjikerbo on 17/6/23. 12 | */ 13 | 14 | public class Rect extends Shape { 15 | 16 | private static final int POSITION_COUNT = 2; 17 | private static final int COLOR_COUNT = 4; 18 | private static final int STRIDE = (POSITION_COUNT + COLOR_COUNT) * 4; 19 | private static final int POINTS_COUNT = 5; 20 | 21 | public Rect(int x1, int y1, int x2, int y2, int color) { 22 | float x1s = transferX(x1); 23 | float y1s = transferY(y1); 24 | float x2s = transferX(x2); 25 | float y2s = transferY(y2); 26 | 27 | float r = Color.red(color) / 255f; 28 | float g = Color.green(color) / 255f; 29 | float b = Color.blue(color) / 255f; 30 | float a = Color.alpha(color) / 255f; 31 | 32 | float[] data = new float[] { 33 | x1s, y1s, r, g, b, a, 34 | x1s, y2s, r, g, b, a, 35 | x2s, y2s, r, g, b, a, 36 | x2s, y1s, r, g, b, a, 37 | x1s, y1s, r, g, b, a, 38 | }; 39 | 40 | mVertexArray = new VertexArray(data); 41 | } 42 | 43 | @Override 44 | public void bindData(RectProgram program) { 45 | mVertexArray.setVertexAttribPointer(0, program.getPositionLocation(), 46 | POSITION_COUNT, STRIDE); 47 | 48 | mVertexArray.setVertexAttribPointer(POSITION_COUNT, program.getColorLocation(), 49 | COLOR_COUNT, STRIDE); 50 | } 51 | 52 | @Override 53 | public void draw() { 54 | glDrawArrays(GL_LINE_STRIP, 0, POINTS_COUNT); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/RuntimeCounter.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 2 | 3 | /** 4 | * Created by dingjikerbo on 17/8/22. 5 | */ 6 | 7 | public class RuntimeCounter { 8 | 9 | private int mCount; 10 | 11 | public long mSum; 12 | 13 | private volatile long mStart; 14 | 15 | public void add(long time) { 16 | mCount++; 17 | mSum += time; 18 | } 19 | 20 | public int getAvg() { 21 | return mCount > 0 ? (int) (mSum / mCount) : 0; 22 | } 23 | 24 | public void clear() { 25 | mCount = 0; 26 | mSum = 0; 27 | } 28 | 29 | public void start() { 30 | mStart = System.currentTimeMillis(); 31 | } 32 | 33 | public void end() { 34 | long now = System.currentTimeMillis(); 35 | add(now - mStart); 36 | mStart = now; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/Shape.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 2 | 3 | import com.inuker.library.program.ShaderProgram; 4 | 5 | /** 6 | * Created by dingjikerbo on 17/6/23. 7 | */ 8 | 9 | public abstract class Shape { 10 | 11 | VertexArray mVertexArray; 12 | 13 | float transferX(int x) { 14 | return 2.0f * x / BaseApplication.getScreenWidth() - 1; 15 | } 16 | 17 | float transferY(int y) { 18 | return -2.0f * y / BaseApplication.getScreenHeight() + 1; 19 | } 20 | 21 | float transferL(int l) { 22 | return 2f * l / BaseApplication.getScreenHeight(); 23 | } 24 | 25 | public abstract void bindData(T program); 26 | 27 | public abstract void draw(); 28 | } 29 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/VertexArray.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.nio.ByteOrder; 5 | import java.nio.FloatBuffer; 6 | 7 | import static android.opengl.GLES20.GL_FLOAT; 8 | import static android.opengl.GLES20.glEnableVertexAttribArray; 9 | import static android.opengl.GLES20.glVertexAttribPointer; 10 | 11 | /** 12 | * Created by dingjikerbo on 17/6/22. 13 | */ 14 | 15 | public class VertexArray { 16 | 17 | private final FloatBuffer floatBuffer; 18 | 19 | public VertexArray(float[] vertexData) { 20 | floatBuffer = ByteBuffer 21 | .allocateDirect(vertexData.length * 4) 22 | .order(ByteOrder.nativeOrder()) 23 | .asFloatBuffer() 24 | .put(vertexData); 25 | } 26 | 27 | public void setVertexAttribPointer(int dataOffset, int attributeLocation, 28 | int componentCount, int stride) { 29 | floatBuffer.position(dataOffset); 30 | glVertexAttribPointer(attributeLocation, componentCount, GL_FLOAT, 31 | false, stride, floatBuffer); 32 | glEnableVertexAttribArray(attributeLocation); 33 | 34 | floatBuffer.position(0); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/encoder/AndroidMuxer.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library.encoder; 2 | 3 | import android.media.MediaCodec; 4 | import android.media.MediaFormat; 5 | import android.media.MediaMuxer; 6 | 7 | import com.inuker.library.utils.LogUtils; 8 | 9 | import java.io.IOException; 10 | import java.nio.ByteBuffer; 11 | 12 | /** 13 | * Created by dingjikerbo on 17/8/1. 14 | */ 15 | 16 | public class AndroidMuxer { 17 | 18 | private final int mExpectedNumTracks = 2; 19 | 20 | private MediaMuxer mMuxer; 21 | 22 | private volatile boolean mStarted; 23 | 24 | private volatile int mNumTracks; 25 | private volatile int mNumReleases; 26 | 27 | public AndroidMuxer(String outputPath) { 28 | try { 29 | mMuxer = new MediaMuxer(outputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 30 | } catch (IOException e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | 35 | public int addTrack(MediaFormat trackFormat) { 36 | if (mStarted) { 37 | throw new IllegalStateException(); 38 | } 39 | 40 | synchronized (mMuxer) { 41 | int track = mMuxer.addTrack(trackFormat); 42 | 43 | if (++mNumTracks == mExpectedNumTracks) { 44 | mMuxer.start(); 45 | mStarted = true; 46 | } 47 | 48 | LogUtils.v(String.format("addTrack mNumTracks = %d", mNumTracks)); 49 | 50 | return track; 51 | } 52 | } 53 | 54 | public boolean isStarted() { 55 | return mStarted; 56 | } 57 | 58 | public void writeSampleData(int trackIndex, ByteBuffer encodedData, MediaCodec.BufferInfo bufferInfo) { 59 | synchronized (mMuxer) { 60 | mMuxer.writeSampleData(trackIndex, encodedData, bufferInfo); 61 | } 62 | } 63 | 64 | public boolean release() { 65 | LogUtils.v("release"); 66 | synchronized (mMuxer) { 67 | if (++mNumReleases == mNumTracks) { 68 | LogUtils.v(String.format("Muxer release")); 69 | mMuxer.stop(); 70 | mMuxer.release(); 71 | return true; 72 | } 73 | } 74 | return false; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/encoder/MovieEncoder1.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library.encoder; 2 | 3 | import android.content.Context; 4 | import android.graphics.ImageFormat; 5 | 6 | import com.inuker.library.program.YUVProgram; 7 | 8 | import java.nio.ByteBuffer; 9 | import java.nio.ByteOrder; 10 | 11 | /** 12 | * Created by dingjikerbo on 2017/10/31. 13 | */ 14 | 15 | public class MovieEncoder1 extends BaseMovieEncoder { 16 | 17 | private YUVProgram mYUVProgram; 18 | private ByteBuffer mYUVBuffer; 19 | 20 | public MovieEncoder1(Context context, int width, int height) { 21 | super(context, width, height); 22 | } 23 | 24 | @Override 25 | public void onPrepareEncoder() { 26 | mYUVProgram = new YUVProgram(mContext, mWidth, mHeight); 27 | mYUVBuffer = ByteBuffer.allocateDirect(mWidth * mHeight * ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8) 28 | .order(ByteOrder.nativeOrder()); 29 | } 30 | 31 | @Override 32 | public void onFrameAvailable(Object object, long timestamp) { 33 | byte[] data = (byte[]) object; 34 | 35 | if (mYUVBuffer == null) { 36 | return; 37 | } 38 | 39 | synchronized (mYUVBuffer) { 40 | mYUVBuffer.position(0); 41 | mYUVBuffer.put(data); 42 | } 43 | 44 | mHandler.sendMessage(mHandler.obtainMessage(MSG_FRAME_AVAILABLE, 45 | (int) (timestamp >> 32), (int) timestamp)); 46 | } 47 | 48 | @Override 49 | public void onFrameAvailable() { 50 | mYUVProgram.useProgram(); 51 | mYUVProgram.draw(mYUVBuffer.array()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/encoder/MovieEncoder2.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library.encoder; 2 | 3 | import android.content.Context; 4 | 5 | import com.inuker.library.program.TextureProgram; 6 | 7 | /** 8 | * Created by dingjikerbo on 2017/10/31. 9 | */ 10 | 11 | public class MovieEncoder2 extends BaseMovieEncoder { 12 | 13 | private int mTexture; 14 | 15 | private TextureProgram mProgram; 16 | 17 | public MovieEncoder2(Context context, int width, int height) { 18 | super(context, width, height); 19 | } 20 | 21 | @Override 22 | public void onPrepareEncoder() { 23 | mProgram = new TextureProgram(mContext, mWidth, mHeight); 24 | } 25 | 26 | @Override 27 | public void onFrameAvailable(Object o, long timestamp) { 28 | mTexture = (int) o; 29 | mHandler.sendMessage(mHandler.obtainMessage(MSG_FRAME_AVAILABLE, 30 | (int) (timestamp >> 32), (int) timestamp)); 31 | } 32 | 33 | @Override 34 | public void onFrameAvailable() { 35 | mProgram.draw(mTexture); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/program/RectProgram.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library.program; 2 | 3 | import android.content.Context; 4 | 5 | import com.inuker.library.R; 6 | 7 | import static android.opengl.GLES20.glUniformMatrix4fv; 8 | 9 | /** 10 | * Created by dingjikerbo on 2017/10/31. 11 | */ 12 | 13 | public class RectProgram extends ShapeProgram { 14 | 15 | public RectProgram(Context context) { 16 | super(context, R.raw.rect_vertex, R.raw.rect_fragment); 17 | } 18 | 19 | public void setUniform() { 20 | glUniformMatrix4fv(uMatrixLocation, 1, false, mMatrix, 0); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/program/ShaderProgram.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library.program; 2 | 3 | import android.content.Context; 4 | 5 | import com.inuker.library.utils.ResourceUtils; 6 | import com.inuker.library.utils.ShaderHelper; 7 | 8 | import static android.opengl.GLES20.glDeleteProgram; 9 | import static android.opengl.GLES20.glUseProgram; 10 | 11 | /** 12 | * Created by dingjikerbo on 17/8/16. 13 | */ 14 | 15 | public class ShaderProgram { 16 | 17 | protected int mProgram; 18 | 19 | protected int mWidth, mHeight; 20 | 21 | protected final Context mContext; 22 | 23 | protected ShaderProgram(Context context, int vertexId, int fragId) { 24 | this(context, vertexId, fragId, 0, 0); 25 | } 26 | 27 | protected ShaderProgram(Context context, int vertexId, int fragId, int width, int height) { 28 | mContext = context; 29 | 30 | mProgram = ShaderHelper.buildProgram(ResourceUtils.readText(context, vertexId), 31 | ResourceUtils.readText(context, fragId)); 32 | 33 | mWidth = width; 34 | mHeight = height; 35 | } 36 | 37 | public void useProgram() { 38 | glUseProgram(mProgram); 39 | } 40 | 41 | public void release() { 42 | glDeleteProgram(mProgram); 43 | mProgram = -1; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/program/ShapeProgram.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library.program; 2 | 3 | import android.content.Context; 4 | 5 | import static android.opengl.GLES20.glGetAttribLocation; 6 | import static android.opengl.GLES20.glGetUniformLocation; 7 | import static android.opengl.Matrix.setIdentityM; 8 | 9 | /** 10 | * Created by dingjikerbo on 2017/10/31. 11 | */ 12 | 13 | public class ShapeProgram extends ShaderProgram { 14 | 15 | private final int aPositionLocation; 16 | 17 | private final int aColorLocation; 18 | 19 | protected final int uMatrixLocation; 20 | 21 | protected float[] mMatrix = new float[16]; 22 | 23 | protected ShapeProgram(Context context, int vertex, int fragment) { 24 | super(context, vertex, fragment); 25 | 26 | useProgram(); 27 | aPositionLocation = glGetAttribLocation(mProgram, "a_Position"); 28 | aColorLocation = glGetAttribLocation(mProgram, "a_Color"); 29 | uMatrixLocation = glGetUniformLocation(mProgram, "u_Matrix"); 30 | 31 | setIdentityM(mMatrix, 0); 32 | // scaleM(mMatrix, 0, -1, 1, 1); 33 | } 34 | 35 | public int getPositionLocation() { 36 | return aPositionLocation; 37 | } 38 | 39 | public int getColorLocation() { 40 | return aColorLocation; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/program/TextureProgram.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library.program; 2 | 3 | import android.content.Context; 4 | 5 | import com.inuker.library.R; 6 | import com.inuker.library.utils.GlUtil; 7 | 8 | import java.nio.FloatBuffer; 9 | 10 | import static android.opengl.GLES20.GL_FLOAT; 11 | import static android.opengl.GLES20.GL_TEXTURE0; 12 | import static android.opengl.GLES20.GL_TEXTURE_2D; 13 | import static android.opengl.GLES20.GL_TRIANGLE_STRIP; 14 | import static android.opengl.GLES20.glActiveTexture; 15 | import static android.opengl.GLES20.glBindTexture; 16 | import static android.opengl.GLES20.glDrawArrays; 17 | import static android.opengl.GLES20.glEnableVertexAttribArray; 18 | import static android.opengl.GLES20.glGetAttribLocation; 19 | import static android.opengl.GLES20.glGetUniformLocation; 20 | import static android.opengl.GLES20.glVertexAttribPointer; 21 | 22 | /** 23 | * Created by dingjikerbo on 17/8/16. 24 | */ 25 | 26 | public class TextureProgram extends ShaderProgram { 27 | 28 | private static final float FULL_RECTANGLE_COORDS[] = { 29 | -1.0f, -1.0f, // 0 bottom left 30 | 1.0f, -1.0f, // 1 bottom right 31 | -1.0f, 1.0f, // 2 top left 32 | 1.0f, 1.0f, // 3 top right 33 | }; 34 | 35 | private static final float FULL_RECTANGLE_TEX_COORDS[] = { 36 | 0.0f, 0.0f, // 0 bottom left 37 | 1.0f, 0.0f, // 1 bottom right 38 | 0.0f, 1.0f, // 2 top left 39 | 1.0f, 1.0f // 3 top right 40 | }; 41 | private static final FloatBuffer FULL_RECTANGLE_BUF = 42 | GlUtil.createFloatBuffer(FULL_RECTANGLE_COORDS); 43 | private static final FloatBuffer FULL_RECTANGLE_TEX_BUF = 44 | GlUtil.createFloatBuffer(FULL_RECTANGLE_TEX_COORDS); 45 | 46 | protected final int mUniformTextureLocation; 47 | 48 | private final int aPositionLocation; 49 | private final int aTextureCoordinatesLocation; 50 | 51 | public TextureProgram(Context context, int vertexShader, int fragmentShader, int width, int height) { 52 | super(context, vertexShader, fragmentShader, width, height); 53 | 54 | mUniformTextureLocation = glGetUniformLocation(mProgram, "s_texture"); 55 | 56 | aPositionLocation = glGetAttribLocation(mProgram, "a_Position"); 57 | aTextureCoordinatesLocation = glGetAttribLocation(mProgram, "a_TextureCoordinates"); 58 | } 59 | 60 | 61 | public TextureProgram(Context context, int width, int height) { 62 | this(context, R.raw.tex_vertex, R.raw.tex_fragment, width, height); 63 | } 64 | 65 | public void draw(int texture) { 66 | useProgram(); 67 | 68 | glActiveTexture(GL_TEXTURE0); 69 | glBindTexture(GL_TEXTURE_2D, texture); 70 | 71 | glEnableVertexAttribArray(aPositionLocation); 72 | glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, false, 8, FULL_RECTANGLE_BUF); 73 | 74 | glEnableVertexAttribArray(aTextureCoordinatesLocation); 75 | glVertexAttribPointer(aTextureCoordinatesLocation, 2, GL_FLOAT, false, 8, FULL_RECTANGLE_TEX_BUF); 76 | 77 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/utils/LogUtils.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library.utils; 2 | 3 | import android.util.Log; 4 | 5 | import java.io.PrintWriter; 6 | import java.io.StringWriter; 7 | import java.io.Writer; 8 | 9 | /** 10 | * Created by dingjikerbo on 17/8/16. 11 | */ 12 | 13 | public class LogUtils { 14 | 15 | private static final String TAG = "bush"; 16 | 17 | public static void v(String msg) { 18 | Log.v(TAG, msg); 19 | } 20 | 21 | public static void v(String tag, String msg) { 22 | Log.v(tag, msg); 23 | } 24 | 25 | public static void e(String msg) { 26 | Log.e(TAG, msg); 27 | } 28 | 29 | public static void e(String tag, String msg) { 30 | Log.e(tag, msg); 31 | } 32 | 33 | public static void w(String msg) { 34 | Log.w(TAG, msg); 35 | } 36 | 37 | public static void w(String tag, String msg) { 38 | Log.w(tag, msg); 39 | } 40 | 41 | public static void e(Throwable e) { 42 | String s = getThrowableString(e); 43 | e(s); 44 | } 45 | 46 | private static String getThrowableString(Throwable e) { 47 | Writer writer = new StringWriter(); 48 | PrintWriter printWriter = new PrintWriter(writer); 49 | 50 | while (e != null) { 51 | e.printStackTrace(printWriter); 52 | e = e.getCause(); 53 | } 54 | 55 | String text = writer.toString(); 56 | 57 | printWriter.close(); 58 | 59 | return text; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/utils/NativeUtils.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library.utils; 2 | 3 | /** 4 | * Created by dingjikerbo on 17/8/22. 5 | */ 6 | 7 | public class NativeUtils { 8 | 9 | static { 10 | System.loadLibrary("camera"); 11 | } 12 | 13 | public static native void glReadPixels(int x, int y, int width, int height, int format, int type); 14 | } 15 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/utils/ResourceUtils.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library.utils; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.InputStreamReader; 10 | 11 | /** 12 | * Created by dingjikerbo on 17/6/22. 13 | */ 14 | 15 | public class ResourceUtils { 16 | 17 | public static String readText(Context context, 18 | int resourceId) { 19 | StringBuilder body = new StringBuilder(); 20 | 21 | try { 22 | InputStream inputStream = context.getResources() 23 | .openRawResource(resourceId); 24 | InputStreamReader inputStreamReader = new InputStreamReader( 25 | inputStream); 26 | BufferedReader bufferedReader = new BufferedReader( 27 | inputStreamReader); 28 | 29 | String nextLine; 30 | 31 | while ((nextLine = bufferedReader.readLine()) != null) { 32 | body.append(nextLine); 33 | body.append('\n'); 34 | } 35 | } catch (IOException e) { 36 | throw new RuntimeException( 37 | "Could not open resource: " + resourceId, e); 38 | } catch (Resources.NotFoundException nfe) { 39 | throw new RuntimeException("Resource not found: " 40 | + resourceId, nfe); 41 | } 42 | 43 | return body.toString(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /library/src/main/java/com/inuker/library/utils/TaskUtils.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library.utils; 2 | 3 | import android.os.AsyncTask; 4 | 5 | import java.util.concurrent.Executor; 6 | 7 | /** 8 | * Created by dingjikerbo on 17/8/22. 9 | */ 10 | 11 | public class TaskUtils { 12 | 13 | public static void execute(final Runnable runnable) { 14 | execute(AsyncTask.THREAD_POOL_EXECUTOR, runnable); 15 | } 16 | 17 | public static void execute(final Executor executor, final Runnable runnable) { 18 | new AsyncTask() { 19 | 20 | @Override 21 | protected Void doInBackground(Void... params) { 22 | runnable.run(); 23 | return null; 24 | } 25 | }.executeOnExecutor(executor); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /library/src/main/jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | set(CMAKE_VERBOSE_MAKEFILE on) 4 | 5 | set(CMAKE_CXX_FLAGS -std=c++11) 6 | 7 | 8 | add_library(camera 9 | SHARED 10 | camera.cpp) 11 | 12 | target_link_libraries(camera log GLESv3) -------------------------------------------------------------------------------- /library/src/main/jni/camera.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by dingjikerbo on 17/6/1. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #define TAG "bush" 12 | 13 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) 14 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) 15 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) 16 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) 17 | #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__) 18 | 19 | void native_glReadPixels(JNIEnv *env, jobject clazz, jint x, jint y, jint width, jint height, jint format, jint type) { 20 | glReadPixels(x, y, width, height, format, type, 0); 21 | } 22 | 23 | static JNINativeMethod gMethods[] = { 24 | {"glReadPixels", "(IIIIII)V", (void *) native_glReadPixels}, 25 | }; 26 | 27 | static int registerNativeMethods(JNIEnv *env, const char *className, 28 | JNINativeMethod *gMethods, int numMethods) { 29 | jclass clazz; 30 | clazz = env->FindClass(className); 31 | if (clazz == NULL) { 32 | return JNI_FALSE; 33 | } 34 | if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { 35 | return JNI_FALSE; 36 | } 37 | 38 | return JNI_TRUE; 39 | } 40 | 41 | static int registerNatives(JNIEnv *env) { 42 | const char *kClassName = "com/inuker/library/utils/NativeUtils"; //指定要注册的类 43 | return registerNativeMethods(env, kClassName, gMethods, 44 | sizeof(gMethods) / sizeof(gMethods[0])); 45 | } 46 | 47 | jint JNI_OnLoad(JavaVM *vm, void *reserved) { 48 | JNIEnv *env = NULL; 49 | if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) { 50 | return JNI_ERR; 51 | } 52 | 53 | if (!registerNatives(env)) { 54 | return JNI_ERR; 55 | } 56 | 57 | return JNI_VERSION_1_6; 58 | } -------------------------------------------------------------------------------- /library/src/main/res/raw/oes_fragment.glsl: -------------------------------------------------------------------------------- 1 | #extension GL_OES_EGL_image_external : require 2 | 3 | precision mediump float; 4 | 5 | varying vec2 vTextureCoord; 6 | uniform samplerExternalOES sTexture; 7 | 8 | void main() { 9 | gl_FragColor = texture2D(sTexture, vTextureCoord); 10 | } -------------------------------------------------------------------------------- /library/src/main/res/raw/oes_vertex.glsl: -------------------------------------------------------------------------------- 1 | uniform mat4 uMVPMatrix; 2 | uniform mat4 uTexMatrix; 3 | 4 | attribute vec4 aPosition; 5 | attribute vec4 aTextureCoord; 6 | 7 | varying vec2 vTextureCoord; 8 | 9 | void main() { 10 | gl_Position = uMVPMatrix * aPosition; 11 | vTextureCoord = (uTexMatrix * aTextureCoord).xy; 12 | } -------------------------------------------------------------------------------- /library/src/main/res/raw/rect_fragment.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | varying vec4 v_Color; 4 | 5 | void main() { 6 | gl_FragColor = v_Color; 7 | } -------------------------------------------------------------------------------- /library/src/main/res/raw/rect_vertex.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 a_Position; 2 | attribute vec4 a_Color; 3 | 4 | varying vec4 v_Color; 5 | 6 | uniform mat4 u_Matrix; 7 | 8 | void main() { 9 | v_Color = a_Color; 10 | gl_Position = u_Matrix * a_Position; 11 | } -------------------------------------------------------------------------------- /library/src/main/res/raw/tex_fragment.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | varying vec2 v_TextureCoordinates; 4 | 5 | uniform sampler2D s_texture; 6 | 7 | void main() { 8 | gl_FragColor = texture2D(s_texture, v_TextureCoordinates); 9 | 10 | // float r = texture2D(s_texture, v_TextureCoordinates).r; 11 | // float g = texture2D(s_texture, v_TextureCoordinates).g; 12 | // float b = texture2D(s_texture, v_TextureCoordinates).b; 13 | // gl_FragColor = vec4(1.0, g, b, 1.0); 14 | } -------------------------------------------------------------------------------- /library/src/main/res/raw/tex_vertex.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 a_Position; 2 | attribute vec2 a_TextureCoordinates; 3 | 4 | varying vec2 v_TextureCoordinates; 5 | 6 | void main() { 7 | v_TextureCoordinates = a_TextureCoordinates; 8 | gl_Position = a_Position; 9 | } -------------------------------------------------------------------------------- /library/src/main/res/raw/yuv_fragment.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | varying vec2 v_TextureCoordinates; 4 | 5 | uniform sampler2D y_texture; 6 | uniform sampler2D uv_texture; 7 | 8 | void main() { 9 | float r, g, b, y, u, v; 10 | 11 | y = texture2D(y_texture, v_TextureCoordinates).r; 12 | u = texture2D(uv_texture, v_TextureCoordinates).a - 0.5; 13 | v = texture2D(uv_texture, v_TextureCoordinates).r - 0.5; 14 | 15 | r = y + 1.13983 * v; 16 | g = y - 0.39465 * u - 0.58060 * v; 17 | b = y + 2.03211 * u; 18 | 19 | gl_FragColor = vec4(r, g, b, 1.0); 20 | } -------------------------------------------------------------------------------- /library/src/main/res/raw/yuv_vertex.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 a_Position; 2 | attribute vec2 a_TextureCoordinates; 3 | 4 | uniform mat4 uMVPMatrix; 5 | 6 | varying vec2 v_TextureCoordinates; 7 | 8 | void main() { 9 | gl_Position = uMVPMatrix * a_Position; 10 | v_TextureCoordinates = a_TextureCoordinates; 11 | } -------------------------------------------------------------------------------- /library/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | library 3 | 4 | -------------------------------------------------------------------------------- /library/src/test/java/com/inuker/library/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.inuker.library; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /multisurfacepreview/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /multisurfacepreview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "26.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.inuker.multiglsurfacepreview" 9 | minSdkVersion 18 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | 16 | ndk { 17 | abiFilters "armeabi-v7a" 18 | } 19 | 20 | } 21 | buildTypes { 22 | release { 23 | minifyEnabled false 24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 25 | } 26 | } 27 | } 28 | 29 | dependencies { 30 | compile fileTree(dir: 'libs', include: ['*.jar']) 31 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 32 | exclude group: 'com.android.support', module: 'support-annotations' 33 | }) 34 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 35 | testCompile 'junit:junit:4.12' 36 | compile project(path: ':library') 37 | } 38 | -------------------------------------------------------------------------------- /multisurfacepreview/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 /Users/dingjikerbo/Library/Android/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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /multisurfacepreview/src/androidTest/java/com/inuker/multiglsurfacepreview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.inuker.multiglsurfacepreview; 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.assertEquals; 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.inuker.multiglsurfacepreview", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /multisurfacepreview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /multisurfacepreview/src/main/java/com/inuker/multisurfacepreview/Events.java: -------------------------------------------------------------------------------- 1 | package com.inuker.multisurfacepreview; 2 | 3 | /** 4 | * Created by dingjikerbo on 17/8/19. 5 | */ 6 | 7 | public class Events { 8 | 9 | public static final int EVENTS_DRAW = 1; 10 | } 11 | -------------------------------------------------------------------------------- /multisurfacepreview/src/main/java/com/inuker/multisurfacepreview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.inuker.multisurfacepreview; 2 | 3 | import android.opengl.EGLContext; 4 | import android.os.Bundle; 5 | import android.widget.FrameLayout; 6 | 7 | import com.inuker.library.BaseActivity; 8 | import com.inuker.library.utils.LogUtils; 9 | 10 | /** 11 | * 两个SurfaceView共享EglContext,CameraSurfaceView将相机预览绘制到 12 | * Texture,MiniSurfaceView再将该Texture处理后绘制到Display Surface 13 | */ 14 | public class MainActivity extends BaseActivity { 15 | 16 | private CameraSurfaceView mLeftSurfaceView; 17 | private MiniSurfaceView mRightSurfaceView; 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_main); 23 | 24 | final FrameLayout left = (FrameLayout) findViewById(R.id.left); 25 | final FrameLayout right = (FrameLayout) findViewById(R.id.right); 26 | 27 | mLeftSurfaceView = new CameraSurfaceView(this); 28 | left.addView(mLeftSurfaceView); 29 | 30 | mLeftSurfaceView.getEglContext(new CameraSurfaceView.SurfaceCallback() { 31 | @Override 32 | public void onCallback(Object object) { 33 | LogUtils.v("SurfaceCallback %s", object.toString()); 34 | 35 | mRightSurfaceView = new MiniSurfaceView(mContext, (EGLContext) object); 36 | right.addView(mRightSurfaceView); 37 | 38 | mRightSurfaceView.setZOrderOnTop(true); 39 | } 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /multisurfacepreview/src/main/java/com/inuker/multisurfacepreview/MiniSurfaceView.java: -------------------------------------------------------------------------------- 1 | package com.inuker.multisurfacepreview; 2 | 3 | import android.content.Context; 4 | import android.opengl.EGLContext; 5 | import android.os.Handler; 6 | import android.os.Message; 7 | import android.view.SurfaceHolder; 8 | 9 | import com.inuker.library.BaseSurfaceView; 10 | import com.inuker.library.EglCore; 11 | import com.inuker.library.EventDispatcher; 12 | import com.inuker.library.EventListener; 13 | import com.inuker.library.WindowSurface; 14 | import com.inuker.library.program.TextureProgram; 15 | import com.inuker.library.utils.GlUtil; 16 | import com.inuker.library.utils.LogUtils; 17 | 18 | import static com.inuker.multisurfacepreview.Events.EVENTS_DRAW; 19 | 20 | /** 21 | * Created by dingjikerbo on 17/8/17. 22 | */ 23 | 24 | public class MiniSurfaceView extends BaseSurfaceView implements Handler.Callback, EventListener { 25 | 26 | private EglCore mEglCore; 27 | 28 | private EGLContext mSharedEGLContext; 29 | 30 | private WindowSurface mWindowSurface; 31 | 32 | private TextureProgram mTextureProgram; 33 | 34 | public MiniSurfaceView(Context context, EGLContext sharedContext) { 35 | super(context); 36 | mSharedEGLContext = sharedContext; 37 | LogUtils.v(String.format("Mini %s", sharedContext)); 38 | } 39 | 40 | @Override 41 | public void onSurfaceCreated(SurfaceHolder holder) { 42 | mEglCore = new EglCore(mSharedEGLContext, EglCore.FLAG_TRY_GLES3); 43 | 44 | mWindowSurface = new WindowSurface(mEglCore, holder.getSurface(), false); 45 | mWindowSurface.makeCurrent(); 46 | 47 | GlUtil.checkGlError("surfaceCreated"); 48 | 49 | EventDispatcher.observe(EVENTS_DRAW, this); 50 | } 51 | 52 | @Override 53 | public void onSurfaceChanged(int width, int height) { 54 | mTextureProgram = new TextureProgram(getContext(), R.raw.tex_vertex, R.raw.filter_tex_fragment, width, height); 55 | GlUtil.checkGlError("surfaceChanged"); 56 | } 57 | 58 | @Override 59 | public void onSurfaceDestroyed() { 60 | EventDispatcher.unObserve(EVENTS_DRAW, this); 61 | 62 | mTextureProgram.release(); 63 | mWindowSurface.release(); 64 | mEglCore.makeNothingCurrent(); 65 | mEglCore.release(); 66 | } 67 | 68 | private void onDrawFrame(int offscreenTexture) { 69 | // LogUtils.v(String.format("%s onDrawFrame %d", getClass().getSimpleName(), offscreenTexture)); 70 | mTextureProgram.draw(offscreenTexture); 71 | mWindowSurface.swapBuffers(); 72 | 73 | GlUtil.checkGlError("onDrawFrame"); 74 | } 75 | 76 | @Override 77 | public void onEvent(int event, Object object) { 78 | if (mRenderHandler != null) { 79 | mRenderHandler.obtainMessage(2, object).sendToTarget(); 80 | } 81 | } 82 | 83 | @Override 84 | public boolean handleMessage(Message msg) { 85 | switch (msg.what) { 86 | case 2: 87 | onDrawFrame((Integer) msg.obj); 88 | break; 89 | } 90 | return super.handleMessage(msg); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/multisurfacepreview/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/multisurfacepreview/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/multisurfacepreview/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/multisurfacepreview/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/multisurfacepreview/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/multisurfacepreview/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/multisurfacepreview/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/multisurfacepreview/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/multisurfacepreview/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingjikerbo/Android-Camera/aa869f65bc0f8735b3e77109283ff863088eb720/multisurfacepreview/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/raw/filter_tex_fragment.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | varying vec2 v_TextureCoordinates; 4 | 5 | uniform sampler2D s_texture; 6 | 7 | void main() { 8 | float r = texture2D(s_texture, v_TextureCoordinates).r; 9 | float g = texture2D(s_texture, v_TextureCoordinates).g; 10 | float b = texture2D(s_texture, v_TextureCoordinates).b; 11 | gl_FragColor = vec4(1.0, g, b, 1.0); 12 | } -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MultiGLSurfacePreview 3 | 4 | -------------------------------------------------------------------------------- /multisurfacepreview/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /multisurfacepreview/src/test/java/com/inuker/multiglsurfacepreview/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.inuker.multiglsurfacepreview; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /recorder1/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /recorder1/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "26.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.inuker.recorder1" 9 | minSdkVersion 18 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | compile fileTree(dir: 'libs', include: ['*.jar']) 27 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 28 | exclude group: 'com.android.support', module: 'support-annotations' 29 | }) 30 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 31 | testCompile 'junit:junit:4.12' 32 | compile project(path: ':library') 33 | } 34 | -------------------------------------------------------------------------------- /recorder1/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 /Users/dingjikerbo/Library/Android/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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /recorder1/src/androidTest/java/com/inuker/recorder1/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.inuker.recorder1; 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.assertEquals; 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.inuker.recorder1", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /recorder1/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /recorder1/src/main/java/com/inuker/recorder1/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.inuker.recorder1; 2 | 3 | import android.opengl.GLSurfaceView; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.Button; 7 | import android.widget.FrameLayout; 8 | 9 | import com.inuker.library.BaseActivity; 10 | 11 | public class MainActivity extends BaseActivity implements View.OnClickListener { 12 | 13 | private FrameLayout mSurfaceContainer; 14 | private GLSurfaceView mGLSurfaceView; 15 | private Button mBtn; 16 | 17 | private CameraSurfaceRender mRender; 18 | 19 | private boolean mRecording; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_main); 25 | 26 | mSurfaceContainer = (FrameLayout) findViewById(R.id.surface); 27 | mBtn = (Button) findViewById(R.id.btn); 28 | 29 | mBtn.setOnClickListener(this); 30 | 31 | mGLSurfaceView = new GLSurfaceView(this); 32 | mGLSurfaceView.setEGLContextClientVersion(3); 33 | mRender = new CameraSurfaceRender(mGLSurfaceView); 34 | mGLSurfaceView.setRenderer(mRender); 35 | mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 36 | } 37 | 38 | @Override 39 | protected void onPause() { 40 | mSurfaceContainer.removeAllViews(); 41 | super.onPause(); 42 | } 43 | 44 | @Override 45 | protected void onResume() { 46 | super.onResume(); 47 | mSurfaceContainer.addView(mGLSurfaceView); 48 | } 49 | 50 | @Override 51 | public void onClick(View v) { 52 | if (mRecording) { 53 | mRecording = false; 54 | mBtn.setText("start"); 55 | mRender.stopRecording(); 56 | } else { 57 | mRecording = true; 58 | mRender.startRecording(); 59 | mBtn.setText("stop"); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /recorder1/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 |