├── .gitignore
├── BasicBeautifyProcessor
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ ├── com
│ └── github
│ │ ├── guikunzhi
│ │ └── beautify
│ │ │ └── BasicBeautifyShaders.java
│ │ └── piasy
│ │ └── cameracompat
│ │ └── processor
│ │ └── basic
│ │ └── BasicBeautifyProcessor.java
│ └── jp
│ └── co
│ └── cyberagent
│ └── android
│ └── gpuimage
│ └── BasicBeautyFilter.java
├── CHANGELOG.md
├── CameraCompat
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── cpp
│ ├── CMakeLists.txt
│ └── RgbYuvEncoder.c
│ ├── java
│ └── com
│ │ └── github
│ │ └── piasy
│ │ └── cameracompat
│ │ ├── CameraCompat.java
│ │ ├── compat
│ │ ├── Camera1Helper.java
│ │ ├── Camera1PreviewCallback.java
│ │ ├── Camera1PreviewFragment.java
│ │ ├── Camera2Helper.java
│ │ ├── Camera2PreviewCallback.java
│ │ ├── Camera2PreviewFragment.java
│ │ ├── CameraFrameCallback.java
│ │ ├── CameraHelper.java
│ │ ├── NoOpChain.java
│ │ ├── PreviewFragment.java
│ │ ├── PreviewSize.java
│ │ └── events
│ │ │ ├── CameraAccessError.java
│ │ │ ├── SwitchBeautifyEvent.java
│ │ │ ├── SwitchCameraEvent.java
│ │ │ ├── SwitchFlashEvent.java
│ │ │ └── SwitchMirrorEvent.java
│ │ ├── gpuimage
│ │ ├── GLFilterGroup.java
│ │ ├── GLRender.java
│ │ └── SurfaceInitCallback.java
│ │ ├── processor
│ │ ├── DirectChain.java
│ │ ├── GPUImageChain.java
│ │ ├── Processor.java
│ │ ├── ProcessorChain.java
│ │ └── RgbYuvConverter.java
│ │ └── utils
│ │ ├── CameraImageUtil.java
│ │ ├── GLUtil.java
│ │ └── Profiler.java
│ └── res
│ └── layout
│ └── preview_fragment.xml
├── LICENSE
├── README.md
├── app
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── github
│ │ └── piasy
│ │ └── cameracompat
│ │ └── example
│ │ ├── DemoApplication.java
│ │ ├── MainActivity.java
│ │ └── PublishActivity.java
│ └── res
│ ├── layout
│ ├── activity_main.xml
│ ├── activity_profiling.xml
│ ├── activity_publish.xml
│ └── activity_watch.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── art
└── screenshot.jpg
├── build.gradle
├── gradle.properties
├── gradle
├── publish.gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── wiki
└── Procedure.md
/.gitignore:
--------------------------------------------------------------------------------
1 | **.iml
2 | .idea
3 | .gradle
4 | /local.properties
5 | .DS_Store
6 | **/build
7 | /captures
8 |
9 | /CameraCompat/.externalNativeBuild
10 | /bintray.properties
11 |
--------------------------------------------------------------------------------
/BasicBeautifyProcessor/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/BasicBeautifyProcessor/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | apply plugin: 'com.android.library'
26 | //apply from: "https://raw.githubusercontent.com/Piasy/BintrayUploadScript/master/bintray.gradle"
27 |
28 | android {
29 | compileSdkVersion rootProject.ext.androidCompileSdkVersion
30 | buildToolsVersion rootProject.ext.androidBuildToolsVersion
31 |
32 | defaultConfig {
33 | minSdkVersion rootProject.ext.minSdkVersion
34 | targetSdkVersion rootProject.ext.targetSdkVersion
35 | versionCode rootProject.ext.releaseVersionCode
36 | versionName rootProject.ext.releaseVersionName
37 | }
38 | buildTypes {
39 | release {
40 | minifyEnabled false
41 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
42 | }
43 | }
44 | }
45 |
46 | dependencies {
47 | compile project(':CameraCompat')
48 | }
49 |
--------------------------------------------------------------------------------
/BasicBeautifyProcessor/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/piasy/tools/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 |
--------------------------------------------------------------------------------
/BasicBeautifyProcessor/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/BasicBeautifyProcessor/src/main/java/com/github/guikunzhi/beautify/BasicBeautifyShaders.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Guikz
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.guikunzhi.beautify;
26 |
27 | /**
28 | * Created by Piasy{github.com/Piasy} on 7/6/16.
29 | */
30 |
31 | public final class BasicBeautifyShaders {
32 | public static final String VERTEX_SHADER =
33 | "attribute vec4 position;\n"
34 | + "attribute vec4 inputTextureCoordinate;\n"
35 | + "const int GAUSSIAN_SAMPLES = 9;\n"
36 | + "uniform float texelWidthOffset;\n"
37 | + "uniform float texelHeightOffset;\n"
38 | + "varying vec2 textureCoordinate;\n"
39 | + "varying vec2 blurCoordinates[GAUSSIAN_SAMPLES];\n"
40 | + "\n"
41 | + "void main() {\n"
42 | + " gl_Position = position;\n"
43 | + " textureCoordinate = inputTextureCoordinate.xy;\n"
44 | + " // Calculate the positions for the blur\n"
45 | + " int multiplier = 0;\n"
46 | + " vec2 blurStep;\n"
47 | + " vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n"
48 | + " for (int i = 0; i < GAUSSIAN_SAMPLES; i++) {\n"
49 | + " multiplier = (i - ((GAUSSIAN_SAMPLES - 1) / 2));\n"
50 | + " // Blur in x (horizontal)\n"
51 | + " blurStep = float(multiplier) * singleStepOffset;\n"
52 | + " blurCoordinates[i] = inputTextureCoordinate.xy + blurStep;\n"
53 | + " }\n"
54 | + "}";
55 |
56 | public static final String FRAGMENT_SHADER =
57 | "uniform sampler2D inputImageTexture;\n"
58 | + "const lowp int GAUSSIAN_SAMPLES = 9;\n"
59 | + "varying mediump vec2 textureCoordinate;\n"
60 | + "varying mediump vec2 blurCoordinates[GAUSSIAN_SAMPLES];\n"
61 | + "\n"
62 | + "uniform mediump float distanceNormalizationFactor;\n"
63 | + "const mediump float smoothDegree = 0.6;\n"
64 | + "\n"
65 | + "void main() {\n"
66 | + " lowp vec4 centralColor;\n"
67 | + " lowp float gaussianWeightTotal;\n"
68 | + " lowp vec4 sum;\n"
69 | + " lowp vec4 sampleColor;\n"
70 | + " lowp float distanceFromCentralColor;\n"
71 | + " lowp float gaussianWeight;\n"
72 | + " mediump vec4 origin = texture2D(inputImageTexture,textureCoordinate);\n"
73 | + "\n"
74 | + " centralColor = texture2D(inputImageTexture, blurCoordinates[4]);\n"
75 | + " gaussianWeightTotal = 0.18;\n"
76 | + " sum = centralColor * 0.18;\n"
77 | + "\n"
78 | + " sampleColor = texture2D(inputImageTexture, blurCoordinates[0]);\n"
79 | + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * "
80 | + "distanceNormalizationFactor, 1.0);\n"
81 | + " gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);\n"
82 | + " gaussianWeightTotal += gaussianWeight;\n"
83 | + " sum += sampleColor * gaussianWeight;\n"
84 | + "\n"
85 | + " sampleColor = texture2D(inputImageTexture, blurCoordinates[1]);\n"
86 | + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * "
87 | + "distanceNormalizationFactor, 1.0);\n"
88 | + " gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);\n"
89 | + " gaussianWeightTotal += gaussianWeight;\n"
90 | + " sum += sampleColor * gaussianWeight;\n"
91 | + "\n"
92 | + " sampleColor = texture2D(inputImageTexture, blurCoordinates[2]);\n"
93 | + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * "
94 | + "distanceNormalizationFactor, 1.0);\n"
95 | + " gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);\n"
96 | + " gaussianWeightTotal += gaussianWeight;\n"
97 | + " sum += sampleColor * gaussianWeight;\n"
98 | + "\n"
99 | + " sampleColor = texture2D(inputImageTexture, blurCoordinates[3]);\n"
100 | + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * "
101 | + "distanceNormalizationFactor, 1.0);\n"
102 | + " gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);\n"
103 | + " gaussianWeightTotal += gaussianWeight;\n"
104 | + " sum += sampleColor * gaussianWeight;\n"
105 | + "\n"
106 | + " sampleColor = texture2D(inputImageTexture, blurCoordinates[5]);\n"
107 | + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * "
108 | + "distanceNormalizationFactor, 1.0);\n"
109 | + " gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);\n"
110 | + " gaussianWeightTotal += gaussianWeight;\n"
111 | + " sum += sampleColor * gaussianWeight;\n"
112 | + "\n"
113 | + " sampleColor = texture2D(inputImageTexture, blurCoordinates[6]);\n"
114 | + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * "
115 | + "distanceNormalizationFactor, 1.0);\n"
116 | + " gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);\n"
117 | + " gaussianWeightTotal += gaussianWeight;\n"
118 | + " sum += sampleColor * gaussianWeight;\n"
119 | + "\n"
120 | + " sampleColor = texture2D(inputImageTexture, blurCoordinates[7]);\n"
121 | + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * "
122 | + "distanceNormalizationFactor, 1.0);\n"
123 | + " gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);\n"
124 | + " gaussianWeightTotal += gaussianWeight;\n"
125 | + " sum += sampleColor * gaussianWeight;\n"
126 | + "\n"
127 | + " sampleColor = texture2D(inputImageTexture, blurCoordinates[8]);\n"
128 | + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * "
129 | + "distanceNormalizationFactor, 1.0);\n"
130 | + " gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);\n"
131 | + " gaussianWeightTotal += gaussianWeight;\n"
132 | + " sum += sampleColor * gaussianWeight;\n"
133 | + "\n"
134 | + " mediump vec4 bilateral = sum / gaussianWeightTotal;\n"
135 | + " mediump vec4 smoothOut;\n"
136 | + " lowp float r = origin.r;\n"
137 | + " lowp float g = origin.g;\n"
138 | + " lowp float b = origin.b;\n"
139 | + " if (r > 0.3725 && g > 0.1568 && b > 0.0784 && r > b && (max(max(r, g), b) - min"
140 | + "(min(r, g), b)) > 0.0588 && abs(r-g) > 0.0588) {\n"
141 | + " smoothOut = (1.0 - smoothDegree) * (origin - bilateral) + bilateral;\n"
142 | + " }\n"
143 | + " else {\n"
144 | + " smoothOut = origin;\n"
145 | + " }\n"
146 | + " smoothOut.r = log(1.0 + 0.2 * smoothOut.r)/log(1.2);\n"
147 | + " smoothOut.g = log(1.0 + 0.2 * smoothOut.g)/log(1.2);\n"
148 | + " smoothOut.b = log(1.0 + 0.2 * smoothOut.b)/log(1.2);\n"
149 | + " gl_FragColor = smoothOut;\n"
150 | + "}\n";
151 | }
152 |
--------------------------------------------------------------------------------
/BasicBeautifyProcessor/src/main/java/com/github/piasy/cameracompat/processor/basic/BasicBeautifyProcessor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.processor.basic;
26 |
27 | import android.media.Image;
28 | import com.github.piasy.cameracompat.processor.Processor;
29 | import java.util.ArrayList;
30 | import java.util.List;
31 | import jp.co.cyberagent.android.gpuimage.BasicBeautyFilter;
32 | import jp.co.cyberagent.android.gpuimage.GPUImageFilter;
33 |
34 | /**
35 | * Created by Piasy{github.com/Piasy} on 17/10/2016.
36 | */
37 |
38 | public class BasicBeautifyProcessor implements Processor {
39 |
40 | @Override
41 | public void setUp() {
42 | }
43 |
44 | @Override
45 | public List getFilters() {
46 | List filters = new ArrayList<>();
47 | filters.add(new GPUImageFilter());
48 | filters.add(new BasicBeautyFilter(4));
49 | return filters;
50 | }
51 |
52 | @Override
53 | public void tearDown() {
54 | }
55 |
56 | @Override
57 | public void onFrameData(byte[] data, int width, int height,
58 | Runnable postProcessedTask) {
59 |
60 | }
61 |
62 | @Override
63 | public void onFrameData(Image image, Runnable postProcessedTask) {
64 |
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/BasicBeautifyProcessor/src/main/java/jp/co/cyberagent/android/gpuimage/BasicBeautyFilter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * @author wysaid
3 | * @mail admin@wysaid.org
4 | */
5 |
6 | package jp.co.cyberagent.android.gpuimage;
7 |
8 | import android.opengl.GLES20;
9 | import com.github.guikunzhi.beautify.BasicBeautifyShaders;
10 |
11 | public class BasicBeautyFilter extends GPUImageTwoPassTextureSamplingFilter {
12 |
13 | private float mDistanceNormalizationFactor = 1f;
14 | private float mTexelSpacingMultiplier = 1f;
15 |
16 | public BasicBeautyFilter(float distanceNormalizationFactor) {
17 | super(BasicBeautifyShaders.VERTEX_SHADER, BasicBeautifyShaders.FRAGMENT_SHADER,
18 | BasicBeautifyShaders.VERTEX_SHADER, BasicBeautifyShaders.FRAGMENT_SHADER);
19 | this.mDistanceNormalizationFactor = distanceNormalizationFactor;
20 | this.mTexelSpacingMultiplier = 4.0f;
21 | }
22 |
23 | @Override
24 | public void onInit() {
25 | super.onInit();
26 | initTexelOffsets();
27 | }
28 |
29 | protected void initTexelOffsets() {
30 | float ratio = getHorizontalTexelOffsetRatio();
31 | GPUImageFilter filter = mFilters.get(0);
32 | int distanceNormalizationFactor = GLES20.glGetUniformLocation(filter.getProgram(),
33 | "distanceNormalizationFactor");
34 | filter.setFloat(distanceNormalizationFactor, this.mDistanceNormalizationFactor);
35 |
36 | int texelWidthOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(),
37 | "texelWidthOffset");
38 | int texelHeightOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(),
39 | "texelHeightOffset");
40 | filter.setFloat(texelWidthOffsetLocation, ratio / mOutputWidth);
41 | filter.setFloat(texelHeightOffsetLocation, 0);
42 |
43 | ratio = getVerticalTexelOffsetRatio();
44 | filter = mFilters.get(1);
45 | distanceNormalizationFactor = GLES20.glGetUniformLocation(filter.getProgram(),
46 | "distanceNormalizationFactor");
47 | filter.setFloat(distanceNormalizationFactor, this.mDistanceNormalizationFactor);
48 |
49 | texelWidthOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(),
50 | "texelWidthOffset");
51 | texelHeightOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(),
52 | "texelHeightOffset");
53 |
54 | filter.setFloat(texelWidthOffsetLocation, 0);
55 | filter.setFloat(texelHeightOffsetLocation, ratio / mOutputHeight);
56 | }
57 |
58 | @Override
59 | public void onOutputSizeChanged(int width, int height) {
60 | super.onOutputSizeChanged(width, height);
61 | initTexelOffsets();
62 | }
63 |
64 | public float getVerticalTexelOffsetRatio() {
65 | return mTexelSpacingMultiplier;
66 | }
67 |
68 | public float getHorizontalTexelOffsetRatio() {
69 | return mTexelSpacingMultiplier;
70 | }
71 |
72 | /**
73 | * A normalization factor for the distance between central color and sample color.
74 | */
75 | public void setDistanceNormalizationFactor(float distanceNormalizationFactor) {
76 | this.mDistanceNormalizationFactor = distanceNormalizationFactor;
77 | runOnDraw(new Runnable() {
78 | @Override
79 | public void run() {
80 | initTexelOffsets();
81 | }
82 | });
83 | }
84 |
85 | /**
86 | * A scaling for the size of the applied blur, default of 4.0
87 | */
88 | public void setTexelSpacingMultiplier(float texelSpacingMultiplier) {
89 | this.mTexelSpacingMultiplier = texelSpacingMultiplier;
90 | runOnDraw(new Runnable() {
91 | @Override
92 | public void run() {
93 | initTexelOffsets();
94 | }
95 | });
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change log
2 |
3 | + v1.3.0
4 | - move out RxQrCode, handle runtime permission
5 | - findOptSize
6 | + v1.2.5
7 | - try better when decode qr code from image file
8 | + v1.2.3
9 | - generate qr code into file
10 | + v1.2.2
11 | - fix: CameraCompat.reset must be called by user, in activity’s onDestroy
12 | + v1.2.1
13 | - fix memory leak in CameraCompat
14 |
--------------------------------------------------------------------------------
/CameraCompat/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'me.tatarka.retrolambda'
3 | apply plugin: 'android-apt'
4 | apply from: "https://raw.githubusercontent.com/Piasy/BintrayUploadScript/master/bintray.gradle"
5 |
6 | apt {
7 | arguments {
8 | fragmentArgsLib true
9 | }
10 | }
11 |
12 | android {
13 | compileSdkVersion rootProject.ext.androidCompileSdkVersion
14 | buildToolsVersion rootProject.ext.androidBuildToolsVersion
15 |
16 | defaultConfig {
17 | minSdkVersion rootProject.ext.minSdkVersion
18 | targetSdkVersion rootProject.ext.targetSdkVersion
19 | versionCode rootProject.ext.releaseVersionCode
20 | versionName rootProject.ext.releaseVersionName
21 |
22 | externalNativeBuild {
23 | cmake {
24 | arguments '-DANDROID_TOOLCHAIN=clang'
25 | }
26 | }
27 |
28 | // annotationProcessor not work for ButterKnife
29 | /*javaCompileOptions {
30 | annotationProcessorOptions {
31 | className 'com.hannesdorfmann.fragmentargs.processor.ArgProcessor'
32 |
33 | // Arguments are optional.
34 | arguments = [ fragmentArgsLib : 'true' ]
35 | }
36 | }*/
37 | }
38 | buildTypes {
39 | release {
40 | minifyEnabled false
41 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
42 | }
43 | }
44 | externalNativeBuild {
45 | cmake {
46 | path "src/main/cpp/CMakeLists.txt"
47 | }
48 | }
49 |
50 | compileOptions {
51 | sourceCompatibility JavaVersion.VERSION_1_8
52 | targetCompatibility JavaVersion.VERSION_1_8
53 | }
54 | }
55 |
56 | dependencies {
57 | compile "com.android.support:support-v4:$rootProject.ext.androidSupportSdkVersion"
58 | compile 'com.getkeepsafe.relinker:relinker:1.2.1'
59 | compile 'com.github.piasy:safelyandroid:1.2.4'
60 | compile group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1'
61 | compile "jp.co.cyberagent.android.gpuimage:gpuimage-library:$rootProject.ext.gpuImageVersion"
62 |
63 | compile "com.hannesdorfmann.fragmentargs:annotation:$rootProject.ext.fragmentArgsVersion"
64 | apt "com.hannesdorfmann.fragmentargs:processor:$rootProject.ext.fragmentArgsVersion"
65 |
66 | compile 'org.greenrobot:eventbus:3.0.0'
67 |
68 | compile('com.tbruyelle.rxpermissions2:rxpermissions:0.8.2') {
69 | exclude module: 'rxjava'
70 | }
71 | compile 'io.reactivex.rxjava2:rxjava:2.0.0'
72 | }
73 |
--------------------------------------------------------------------------------
/CameraCompat/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/piasy/tools/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 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.4.1)
2 |
3 | add_library(rgb-yuv-converter-library SHARED
4 | RgbYuvEncoder.c)
5 |
6 | # Include libraries needed for rgb-yuv-converter-library
7 | target_link_libraries(rgb-yuv-converter-library
8 | android
9 | log)
10 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/CameraCompat.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat;
26 |
27 | import android.content.Context;
28 | import android.os.Build;
29 | import android.os.Bundle;
30 | import android.support.annotation.IdRes;
31 | import android.support.annotation.IntDef;
32 | import android.support.annotation.WorkerThread;
33 | import android.support.v4.app.FragmentManager;
34 | import com.github.piasy.cameracompat.compat.Camera1PreviewFragment;
35 | import com.github.piasy.cameracompat.compat.Camera1PreviewFragmentBuilder;
36 | import com.github.piasy.cameracompat.compat.Camera2PreviewFragment;
37 | import com.github.piasy.cameracompat.compat.Camera2PreviewFragmentBuilder;
38 | import com.github.piasy.cameracompat.compat.events.SwitchBeautifyEvent;
39 | import com.github.piasy.cameracompat.compat.events.SwitchCameraEvent;
40 | import com.github.piasy.cameracompat.compat.events.SwitchFlashEvent;
41 | import com.github.piasy.cameracompat.compat.events.SwitchMirrorEvent;
42 | import com.github.piasy.cameracompat.processor.DirectChain;
43 | import com.github.piasy.cameracompat.processor.GPUImageChain;
44 | import com.github.piasy.cameracompat.processor.Processor;
45 | import com.github.piasy.cameracompat.processor.ProcessorChain;
46 | import com.github.piasy.cameracompat.processor.RgbYuvConverter;
47 | import com.github.piasy.cameracompat.utils.Profiler;
48 | import java.util.ArrayList;
49 | import java.util.List;
50 | import org.greenrobot.eventbus.EventBus;
51 |
52 | /**
53 | * Created by Piasy{github.com/Piasy} on 5/29/16.
54 | */
55 | public final class CameraCompat {
56 |
57 | public static final String CAMERA_PREVIEW_FRAGMENT = "CameraPreviewFragment";
58 | public static final int ERR_PERMISSION = 1;
59 | public static final int ERR_UNKNOWN = 2;
60 | private static final int DEFAULT_WIDTH = 640;
61 | private static final int DEFAULT_HEIGHT = 480;
62 | private static final int REQUEST_CODE = 1234;
63 | private static volatile CameraCompat sCameraCompat;
64 | private final int mPreviewWidth;
65 | private final int mPreviewHeight;
66 | private final boolean mIsFrontCamera;
67 | private final boolean mIsFlashOpen;
68 | private final boolean mIsBeautifyOn;
69 | private final boolean mIsMirrorEnabled;
70 | private final EventBus mEventBus;
71 | private final ProcessorChain mProcessorChain;
72 | private final Profiler mProfiler;
73 | private final VideoCaptureCallback mVideoCaptureCallback;
74 | private final ErrorHandler mErrorHandler;
75 |
76 | private CameraCompat(Builder builder) {
77 | mPreviewWidth = builder.mPreviewWidth;
78 | mPreviewHeight = builder.mPreviewHeight;
79 | mIsFrontCamera = builder.mIsFrontCamera;
80 | mIsFlashOpen = builder.mIsFlashOpen;
81 | mIsBeautifyOn = builder.mIsBeautifyOn;
82 | mIsMirrorEnabled = builder.mIsMirrorEnabled;
83 | mEventBus = builder.mEventBus;
84 | mVideoCaptureCallback = builder.mVideoCaptureCallback;
85 | mErrorHandler = builder.mErrorHandler;
86 | if (builder.mMetricListener != null) {
87 | mProfiler = new Profiler(builder.mMetricListener);
88 | } else {
89 | mProfiler = null;
90 | }
91 | if (builder.mProcessors.isEmpty()) {
92 | mProcessorChain = new DirectChain(mIsFrontCamera, mVideoCaptureCallback);
93 | } else {
94 | mProcessorChain = new GPUImageChain(builder.mProcessors, mIsBeautifyOn,
95 | mIsFrontCamera, mVideoCaptureCallback, mProfiler);
96 | }
97 | }
98 |
99 | public static void init(Context context) {
100 | RgbYuvConverter.loadLibrary(context);
101 | }
102 |
103 | /**
104 | * can't be called from {@link com.github.piasy.cameracompat.compat.PreviewFragment},
105 | * otherwise recreate will have race condition
106 | */
107 | public static void reset() {
108 | sCameraCompat = null;
109 | }
110 |
111 | public static CameraCompat getInstance() {
112 | if (sCameraCompat == null) {
113 | throw new IllegalStateException("CameraCompat is not initialized!");
114 | }
115 | return sCameraCompat;
116 | }
117 |
118 | /**
119 | * a short-cut
120 | */
121 | @WorkerThread
122 | public static void onError(@ErrorCode int code) {
123 | if (sCameraCompat == null) {
124 | throw new IllegalStateException("CameraCompat is not initialized!");
125 | }
126 | sCameraCompat.mErrorHandler.onError(code);
127 | }
128 |
129 | /**
130 | * add {@link Camera1PreviewFragment} or {@link Camera2PreviewFragment} to start preview
131 | *
132 | * @param savedInstance to determine whether should add a new fragment
133 | * @param fragmentManager the fragment manager
134 | * @param container the container id to hold this fragment
135 | * @return {@code true} if the fragment is newly added
136 | */
137 | public boolean startPreview(Bundle savedInstance, FragmentManager fragmentManager,
138 | @IdRes int container) {
139 | // API 21 has bug on Camera2, the YUV_420_888 data has all zero in UV planes,
140 | // ref: comments of `convertYUV_420_888ToRGB` function in this blog post:
141 | // https://attiapp.wordpress.com/2015/06/28/convert-yuv_420_888-to-rgb-with-camera2-api-2/
142 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
143 | if (savedInstance == null
144 | || fragmentManager.findFragmentByTag(CAMERA_PREVIEW_FRAGMENT) == null) {
145 | Camera2PreviewFragment fragment =
146 | Camera2PreviewFragmentBuilder.newCamera2PreviewFragment(mIsBeautifyOn,
147 | mIsFlashOpen, mIsFrontCamera, mIsMirrorEnabled, mPreviewHeight,
148 | mPreviewWidth);
149 | fragmentManager.beginTransaction()
150 | .add(container, fragment, CAMERA_PREVIEW_FRAGMENT)
151 | .commit();
152 | return true;
153 | }
154 | } else {
155 | if (savedInstance == null
156 | || fragmentManager.findFragmentByTag(CAMERA_PREVIEW_FRAGMENT) == null) {
157 | Camera1PreviewFragment fragment =
158 | Camera1PreviewFragmentBuilder.newCamera1PreviewFragment(mIsBeautifyOn,
159 | mIsFlashOpen, mIsFrontCamera, mIsMirrorEnabled, mPreviewHeight,
160 | mPreviewWidth);
161 | fragmentManager.beginTransaction()
162 | .add(container, fragment, CAMERA_PREVIEW_FRAGMENT)
163 | .commit();
164 | return true;
165 | }
166 | }
167 | return false;
168 | }
169 |
170 | public EventBus getEventBus() {
171 | return mEventBus;
172 | }
173 |
174 | public void switchBeautify() {
175 | mEventBus.post(new SwitchBeautifyEvent());
176 | }
177 |
178 | public void switchCamera() {
179 | mEventBus.post(new SwitchCameraEvent());
180 | }
181 |
182 | public void switchFlash() {
183 | mEventBus.post(new SwitchFlashEvent());
184 | }
185 |
186 | public void switchMirror() {
187 | mEventBus.post(new SwitchMirrorEvent());
188 | }
189 |
190 | public Profiler getProfiler() {
191 | return mProfiler;
192 | }
193 |
194 | public VideoCaptureCallback getVideoCaptureCallback() {
195 | return mVideoCaptureCallback;
196 | }
197 |
198 | public ProcessorChain getProcessorChain() {
199 | return mProcessorChain;
200 | }
201 |
202 | /**
203 | * Video will have the specified width, but the height will be trimmed.
204 | *
205 | * width > height
206 | */
207 | public interface VideoCaptureCallback {
208 | /**
209 | * will be called only once, just before the first call of {@link #onFrameData(byte[], int,
210 | * int)} with new size.
211 | */
212 | @WorkerThread
213 | void onVideoSizeChanged(int width, int height);
214 |
215 | @WorkerThread
216 | void onFrameData(final byte[] data, final int width, final int height);
217 | }
218 |
219 | public interface ErrorHandler {
220 | @WorkerThread
221 | void onError(@ErrorCode int code);
222 | }
223 |
224 | @IntDef(value = { ERR_PERMISSION, ERR_UNKNOWN })
225 | public @interface ErrorCode {
226 | }
227 |
228 | public static final class Builder {
229 | private final VideoCaptureCallback mVideoCaptureCallback;
230 | private final ErrorHandler mErrorHandler;
231 | private final List mProcessors;
232 | private int mPreviewWidth = DEFAULT_WIDTH;
233 | private int mPreviewHeight = DEFAULT_HEIGHT;
234 | private boolean mIsFrontCamera;
235 | private boolean mIsFlashOpen;
236 | private boolean mIsBeautifyOn;
237 | private boolean mIsMirrorEnabled;
238 | private EventBus mEventBus;
239 | private Profiler.MetricListener mMetricListener;
240 |
241 | public Builder(VideoCaptureCallback videoCaptureCallback, ErrorHandler errorHandler) {
242 | mVideoCaptureCallback = videoCaptureCallback;
243 | mErrorHandler = errorHandler;
244 | mProcessors = new ArrayList<>();
245 | }
246 |
247 | /**
248 | * @param previewWidth sensor width, e.g. 640*480, width is 640, no matter what orientation
249 | */
250 | public Builder previewWidth(int previewWidth) {
251 | mPreviewWidth = previewWidth;
252 | return this;
253 | }
254 |
255 | /**
256 | * @param previewHeight sensor width, e.g. 640*480, height is 480, no matter what
257 | * orientation
258 | */
259 | public Builder previewHeight(int previewHeight) {
260 | mPreviewHeight = previewHeight;
261 | return this;
262 | }
263 |
264 | public Builder frontCamera(boolean frontCamera) {
265 | mIsFrontCamera = frontCamera;
266 | return this;
267 | }
268 |
269 | public Builder flashOpen(boolean flashOpen) {
270 | mIsFlashOpen = flashOpen;
271 | return this;
272 | }
273 |
274 | public Builder beautifyOn(boolean beautifyOn) {
275 | mIsBeautifyOn = beautifyOn;
276 | return this;
277 | }
278 |
279 | public Builder enableMirror(boolean enableMirror) {
280 | mIsMirrorEnabled = enableMirror;
281 | return this;
282 | }
283 |
284 | public Builder eventBus(EventBus eventBus) {
285 | mEventBus = eventBus;
286 | return this;
287 | }
288 |
289 | public Builder addProcessor(Processor processor) {
290 | mProcessors.add(processor);
291 | return this;
292 | }
293 |
294 | public Builder metricListener(Profiler.MetricListener metricListener) {
295 | mMetricListener = metricListener;
296 | return this;
297 | }
298 |
299 | public CameraCompat build() {
300 | if (mEventBus == null) {
301 | mEventBus = EventBus.builder().build();
302 | }
303 | CameraCompat instance = new CameraCompat(this);
304 | sCameraCompat = instance;
305 | return instance;
306 | }
307 | }
308 | }
309 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/Camera1Helper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat;
26 |
27 | import android.annotation.TargetApi;
28 | import android.hardware.Camera;
29 | import android.os.Build;
30 | import com.github.piasy.cameracompat.CameraCompat;
31 | import java.util.ArrayList;
32 | import java.util.List;
33 | import jp.co.cyberagent.android.gpuimage.Rotation;
34 |
35 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
36 | class Camera1Helper extends CameraHelper {
37 |
38 | private final CameraController mCameraController;
39 | private final Camera1PreviewCallback mPreviewCallback;
40 | private Camera mCamera;
41 |
42 | Camera1Helper(int previewWidth, int previewHeight, int activityRotation, boolean isFront,
43 | CameraController cameraController, Camera1PreviewCallback previewCallback) {
44 | super(previewWidth, previewHeight, activityRotation, isFront);
45 | mCameraController = cameraController;
46 | mPreviewCallback = previewCallback;
47 | }
48 |
49 | @Override
50 | protected boolean startPreview() {
51 | try {
52 | mCamera = openCamera();
53 | Camera.Parameters parameters = mCamera.getParameters();
54 | if (parameters.getSupportedFocusModes()
55 | .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
56 | parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
57 | }
58 | PreviewSize previewSize = findOptSize(mPreviewWidth, mPreviewHeight);
59 | parameters.setPreviewSize(previewSize.getWidth(), previewSize.getHeight());
60 | mCamera.setParameters(parameters);
61 | mCamera.setPreviewCallback(mPreviewCallback);
62 | Rotation rotation = getRotation();
63 | mCamera.setDisplayOrientation(mIsFront ? (360 - rotation.asInt()) : rotation.asInt());
64 | mCameraController.onOpened(mCamera, rotation, mIsFront, false);
65 | } catch (RuntimeException e) {
66 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
67 | return false;
68 | }
69 | return true;
70 | }
71 |
72 | @Override
73 | protected boolean stopPreview() {
74 | if (mCamera == null) {
75 | return true;
76 | }
77 | try {
78 | mCamera.stopPreview();
79 | mCamera.setPreviewCallback(null);
80 | mCamera.release();
81 | mCamera = null;
82 | } catch (RuntimeException e) {
83 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
84 | return false;
85 | }
86 | return true;
87 | }
88 |
89 | @Override
90 | protected int getSensorDegree() {
91 | return getCameraInfo(getCurrentCameraId()).orientation;
92 | }
93 |
94 | @Override
95 | protected boolean canOperateFlash() {
96 | return mCamera != null;
97 | }
98 |
99 | @Override
100 | protected void doOpenFlash() throws RuntimeException {
101 | Camera.Parameters parameters = mCamera.getParameters();
102 | parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
103 | mCamera.setParameters(parameters);
104 | }
105 |
106 | @Override
107 | protected void doCloseFlash() throws RuntimeException {
108 | Camera.Parameters parameters = mCamera.getParameters();
109 | parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
110 | mCamera.setParameters(parameters);
111 | }
112 |
113 | @Override
114 | protected List getSupportedSize() throws RuntimeException {
115 | List supportedSize = mCamera.getParameters().getSupportedPreviewSizes();
116 | List results = new ArrayList<>();
117 | for (int i = 0, size = supportedSize.size(); i < size; i++) {
118 | Camera.Size option = supportedSize.get(i);
119 | results.add(new PreviewSize(option.width, option.height));
120 | }
121 | return results;
122 | }
123 |
124 | private Camera openCamera() {
125 | return Camera.open(mIsFront ? Camera.CameraInfo.CAMERA_FACING_FRONT
126 | : Camera.CameraInfo.CAMERA_FACING_BACK);
127 | }
128 |
129 | private int getCurrentCameraId() {
130 | return mIsFront ? Camera.CameraInfo.CAMERA_FACING_FRONT
131 | : Camera.CameraInfo.CAMERA_FACING_BACK;
132 | }
133 |
134 | private Camera.CameraInfo getCameraInfo(final int cameraId) {
135 | Camera.CameraInfo info = new Camera.CameraInfo();
136 | Camera.getCameraInfo(cameraId, info);
137 | return info;
138 | }
139 |
140 | interface CameraController {
141 | void onOpened(final Camera camera, final Rotation rotation, final boolean flipHorizontal,
142 | final boolean flipVertical);
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/Camera1PreviewCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat;
26 |
27 | import android.annotation.TargetApi;
28 | import android.hardware.Camera;
29 | import android.os.Build;
30 | import com.github.piasy.cameracompat.CameraCompat;
31 |
32 | /**
33 | * Created by Piasy{github.com/Piasy} on 5/24/16.
34 | */
35 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
36 | class Camera1PreviewCallback implements Camera.PreviewCallback {
37 | private final CameraFrameCallback mCameraFrameCallback;
38 |
39 | Camera1PreviewCallback(CameraFrameCallback cameraFrameCallback) {
40 | mCameraFrameCallback = cameraFrameCallback;
41 | }
42 |
43 | @Override
44 | public void onPreviewFrame(final byte[] data, final Camera camera) {
45 | try {
46 | Camera.Size size = camera.getParameters().getPreviewSize();
47 | mCameraFrameCallback.onFrameData(data, size.width, size.height, () -> {
48 | camera.addCallbackBuffer(data);
49 | // errors will be caught at where this task is executed
50 | });
51 | } catch (RuntimeException | OutOfMemoryError e) {
52 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/Camera1PreviewFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat;
26 |
27 | import android.annotation.TargetApi;
28 | import android.graphics.SurfaceTexture;
29 | import android.hardware.Camera;
30 | import android.os.Build;
31 | import android.os.Bundle;
32 | import android.support.annotation.Nullable;
33 | import android.support.v4.app.Fragment;
34 | import com.github.piasy.cameracompat.CameraCompat;
35 | import com.github.piasy.safelyandroid.misc.CheckUtil;
36 | import com.hannesdorfmann.fragmentargs.annotation.FragmentWithArgs;
37 | import java.io.IOException;
38 | import jp.co.cyberagent.android.gpuimage.Rotation;
39 |
40 | /**
41 | * A simple {@link Fragment} subclass.
42 | */
43 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
44 | @FragmentWithArgs
45 | public class Camera1PreviewFragment extends PreviewFragment
46 | implements Camera1Helper.CameraController {
47 |
48 | public Camera1PreviewFragment() {
49 | // Required empty public constructor
50 | }
51 |
52 | @Override
53 | public void onCreate(@Nullable Bundle savedInstanceState) {
54 | super.onCreate(savedInstanceState);
55 | Camera1PreviewFragmentBuilder.injectArguments(this);
56 | }
57 |
58 | @Override
59 | protected CameraHelper createCameraHelper() {
60 | int activityRotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
61 | return new Camera1Helper(mPreviewWidth, mPreviewHeight, activityRotation,
62 | mIsDefaultFrontCamera, this, new Camera1PreviewCallback(mProcessorChain));
63 | }
64 |
65 | @Override
66 | public synchronized void onOpened(final Camera camera, Rotation rotation, boolean flipHorizontal,
67 | boolean flipVertical) {
68 | if (!isResumed() || !CheckUtil.nonNull(mProcessorChain)) {
69 | return;
70 | }
71 | mProcessorChain.onCameraOpened(rotation, flipHorizontal, flipVertical,
72 | surfaceTexture -> startPreviewDirectly(surfaceTexture, camera));
73 | }
74 |
75 | private void startPreviewDirectly(SurfaceTexture surfaceTexture, Camera camera) {
76 | try {
77 | camera.setPreviewTexture(surfaceTexture);
78 | camera.startPreview();
79 | mProcessorChain.resume();
80 | } catch (IOException | RuntimeException e) {
81 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/Camera2Helper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat;
26 |
27 | import android.annotation.TargetApi;
28 | import android.graphics.ImageFormat;
29 | import android.graphics.SurfaceTexture;
30 | import android.hardware.camera2.CameraAccessException;
31 | import android.hardware.camera2.CameraCaptureSession;
32 | import android.hardware.camera2.CameraCharacteristics;
33 | import android.hardware.camera2.CameraDevice;
34 | import android.hardware.camera2.CameraManager;
35 | import android.hardware.camera2.params.StreamConfigurationMap;
36 | import android.media.ImageReader;
37 | import android.os.Build;
38 | import android.os.Handler;
39 | import android.os.HandlerThread;
40 | import android.support.annotation.NonNull;
41 | import android.text.TextUtils;
42 | import android.util.Size;
43 | import android.view.Surface;
44 | import com.github.piasy.cameracompat.CameraCompat;
45 | import com.github.piasy.cameracompat.compat.events.CameraAccessError;
46 | import java.util.ArrayList;
47 | import java.util.Collections;
48 | import java.util.List;
49 | import jp.co.cyberagent.android.gpuimage.Rotation;
50 |
51 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
52 | class Camera2Helper extends CameraHelper {
53 |
54 | private final CameraController mCameraController;
55 | private final Camera2PreviewCallback mPreviewCallback;
56 | private final CameraManager mCameraManager;
57 | private String mFrontCameraId;
58 | private String mBackCameraId;
59 | private CameraDevice mCameraDevice;
60 | private HandlerThread mBackgroundThread;
61 | private Handler mCamera2Handler;
62 | private CameraCaptureSession mCaptureSession;
63 | private ImageReader mImageReader;
64 | private final CameraDevice.StateCallback mCameraCallback = new CameraDevice.StateCallback() {
65 | @Override
66 | public void onOpened(@NonNull CameraDevice camera) {
67 | try {
68 | mCameraDevice = camera;
69 | mCameraController.onOpened(mCameraDevice, mImageReader, mCamera2Handler,
70 | getRotation(), mIsFront, false);
71 | } catch (IllegalStateException e) {
72 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
73 | }
74 | }
75 |
76 | @Override
77 | public void onDisconnected(@NonNull CameraDevice camera) {
78 | camera.close();
79 | mCameraDevice = null;
80 | }
81 |
82 | @Override
83 | public void onError(@NonNull CameraDevice camera, int error) {
84 | camera.close();
85 | mCameraDevice = null;
86 | }
87 | };
88 | private List mOutputTargets;
89 |
90 | Camera2Helper(int previewWidth, int previewHeight, int activityRotation, boolean isFront,
91 | CameraController cameraController, CameraManager cameraManager,
92 | Camera2PreviewCallback previewCallback) throws CameraAccessException {
93 | super(previewWidth, previewHeight, activityRotation, isFront);
94 | mCameraController = cameraController;
95 | mCameraManager = cameraManager;
96 | mPreviewCallback = previewCallback;
97 | initCameraIds();
98 | }
99 |
100 | void previewSessionStarted(CameraCaptureSession captureSession) {
101 | mCaptureSession = captureSession;
102 | }
103 |
104 | void outputTargetChanged(List targets) {
105 | mOutputTargets = targets;
106 | }
107 |
108 | @Override
109 | protected boolean startPreview() {
110 | try {
111 | mBackgroundThread = new HandlerThread("PreviewFragmentV21Thread");
112 | mBackgroundThread.start();
113 | mCamera2Handler = new Handler(mBackgroundThread.getLooper());
114 | PreviewSize size = findOptSize(mPreviewWidth, mPreviewHeight);
115 | mImageReader = ImageReader.newInstance(size.getWidth(), size.getHeight(),
116 | ImageFormat.YUV_420_888, 2);
117 | mImageReader.setOnImageAvailableListener(mPreviewCallback, mCamera2Handler);
118 | mCameraManager.openCamera(getCurrentCameraId(), mCameraCallback, mCamera2Handler);
119 | } catch (SecurityException | CameraAccessException | IllegalStateException |
120 | CameraAccessError e) {
121 | CameraCompat.onError(CameraCompat.ERR_PERMISSION);
122 | return false;
123 | } catch (RuntimeException e) {
124 | // http://crashes.to/s/3a4227c2262
125 | // http://crashes.to/s/17d9761180d
126 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
127 | return false;
128 | }
129 | return true;
130 | }
131 |
132 | @Override
133 | protected boolean stopPreview() {
134 | try {
135 | if (null != mCaptureSession) {
136 | mCaptureSession.close();
137 | mCaptureSession = null;
138 | }
139 | if (null != mCameraDevice) {
140 | mCameraDevice.close();
141 | mCameraDevice = null;
142 | }
143 | if (null != mBackgroundThread) {
144 | mBackgroundThread.quitSafely();
145 | mBackgroundThread.join();
146 | mBackgroundThread = null;
147 | mCamera2Handler = null;
148 | }
149 | if (mImageReader != null) {
150 | // http://crashes.to/s/099a8255d2b
151 | mImageReader.setOnImageAvailableListener(null, null);
152 | }
153 | } catch (InterruptedException e) {
154 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
155 | return false;
156 | }
157 | return true;
158 | }
159 |
160 | @Override
161 | protected int getSensorDegree() {
162 | CameraCharacteristics characteristics;
163 | Integer orientation = null;
164 | try {
165 | characteristics = mCameraManager.getCameraCharacteristics(getCurrentCameraId());
166 | orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
167 | } catch (CameraAccessException | SecurityException e) {
168 | CameraCompat.onError(CameraCompat.ERR_PERMISSION);
169 | }
170 | return orientation == null ? 0 : orientation;
171 | }
172 |
173 | @Override
174 | protected boolean canOperateFlash() {
175 | return mCameraDevice != null;
176 | }
177 |
178 | @Override
179 | protected void doOpenFlash() throws RuntimeException {
180 | try {
181 | operateFlash(true);
182 | } catch (CameraAccessException e) {
183 | throw new CameraAccessError();
184 | }
185 | }
186 |
187 | @Override
188 | protected void doCloseFlash() throws RuntimeException {
189 | try {
190 | operateFlash(false);
191 | } catch (CameraAccessException e) {
192 | throw new CameraAccessError();
193 | }
194 | }
195 |
196 | @Override
197 | protected List getSupportedSize() {
198 | try {
199 | CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(
200 | getCurrentCameraId());
201 | StreamConfigurationMap map =
202 | characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
203 | if (map == null) {
204 | return Collections.singletonList(new PreviewSize(mPreviewWidth, mPreviewHeight));
205 | }
206 | Size[] supportedSize = map.getOutputSizes(SurfaceTexture.class);
207 | if (supportedSize == null || supportedSize.length == 0) {
208 | return Collections.singletonList(new PreviewSize(mPreviewWidth, mPreviewHeight));
209 | }
210 | List results = new ArrayList<>();
211 | for (Size size : supportedSize) {
212 | results.add(new PreviewSize(size.getWidth(), size.getHeight()));
213 | }
214 | return results;
215 | } catch (CameraAccessException e) {
216 | throw new CameraAccessError();
217 | }
218 | }
219 |
220 | private void operateFlash(boolean isOpen) throws CameraAccessException, SecurityException {
221 | CameraCharacteristics characteristics =
222 | mCameraManager.getCameraCharacteristics(mBackCameraId);
223 | Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
224 | boolean flashSupported = available == null ? false : available;
225 | if (!flashSupported) {
226 | return;
227 | }
228 | mCameraController.onSettingsChanged(mCameraDevice, mCaptureSession, mOutputTargets, isOpen,
229 | mCamera2Handler);
230 | }
231 |
232 | private void initCameraIds() throws CameraAccessException {
233 | for (String cameraId : mCameraManager.getCameraIdList()) {
234 | CameraCharacteristics characteristics =
235 | mCameraManager.getCameraCharacteristics(cameraId);
236 |
237 | Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
238 | if (facing != null) {
239 | if (facing == CameraCharacteristics.LENS_FACING_FRONT) {
240 | mFrontCameraId = cameraId;
241 | } else if (facing == CameraCharacteristics.LENS_FACING_BACK) {
242 | mBackCameraId = cameraId;
243 | }
244 | }
245 | }
246 | }
247 |
248 | private String getCurrentCameraId() throws IllegalStateException {
249 | String id = mIsFront ? mFrontCameraId : mBackCameraId;
250 | if (TextUtils.isEmpty(id)) {
251 | throw new IllegalStateException("Get a null camera id: " + mIsFront);
252 | }
253 | return id;
254 | }
255 |
256 | interface CameraController {
257 | void onOpened(final CameraDevice cameraDevice, final ImageReader imageReader,
258 | final Handler cameraHandler, final Rotation rotation, final boolean flipHorizontal,
259 | final boolean flipVertical);
260 |
261 | void onSettingsChanged(final CameraDevice cameraDevice,
262 | final CameraCaptureSession captureSession, final List targets,
263 | final boolean isFlashOn, final Handler cameraHandler);
264 | }
265 | }
266 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/Camera2PreviewCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat;
26 |
27 | import android.annotation.TargetApi;
28 | import android.media.Image;
29 | import android.media.ImageReader;
30 | import android.os.Build;
31 | import com.github.piasy.cameracompat.CameraCompat;
32 |
33 | /**
34 | * Created by Piasy{github.com/Piasy} on 5/24/16.
35 | */
36 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
37 | class Camera2PreviewCallback implements ImageReader.OnImageAvailableListener {
38 | private final CameraFrameCallback mCameraFrameCallback;
39 |
40 | Camera2PreviewCallback(CameraFrameCallback cameraFrameCallback) {
41 | mCameraFrameCallback = cameraFrameCallback;
42 | }
43 |
44 | @Override
45 | public void onImageAvailable(ImageReader reader) {
46 | try {
47 | final Image image = reader.acquireLatestImage();
48 | if (image != null) {
49 | mCameraFrameCallback.onFrameData(image, image::close);
50 | }
51 | } catch (OutOfMemoryError | IllegalStateException e) {
52 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/Camera2PreviewFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat;
26 |
27 | import android.annotation.TargetApi;
28 | import android.content.Context;
29 | import android.hardware.camera2.CameraAccessException;
30 | import android.hardware.camera2.CameraCaptureSession;
31 | import android.hardware.camera2.CameraDevice;
32 | import android.hardware.camera2.CameraManager;
33 | import android.hardware.camera2.CameraMetadata;
34 | import android.hardware.camera2.CaptureRequest;
35 | import android.media.ImageReader;
36 | import android.os.Build;
37 | import android.os.Bundle;
38 | import android.os.Handler;
39 | import android.support.annotation.NonNull;
40 | import android.support.annotation.Nullable;
41 | import android.view.Surface;
42 | import com.github.piasy.cameracompat.CameraCompat;
43 | import com.github.piasy.safelyandroid.misc.CheckUtil;
44 | import com.hannesdorfmann.fragmentargs.annotation.FragmentWithArgs;
45 | import java.util.Arrays;
46 | import java.util.List;
47 | import jp.co.cyberagent.android.gpuimage.Rotation;
48 |
49 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
50 | @FragmentWithArgs
51 | public class Camera2PreviewFragment extends PreviewFragment
52 | implements Camera2Helper.CameraController {
53 |
54 | private Camera2Helper mCamera2Helper;
55 |
56 | public Camera2PreviewFragment() {
57 | // Required empty public constructor
58 | }
59 |
60 | @Override
61 | public void onCreate(@Nullable Bundle savedInstanceState) {
62 | super.onCreate(savedInstanceState);
63 | Camera2PreviewFragmentBuilder.injectArguments(this);
64 | }
65 |
66 | @Override
67 | protected CameraHelper createCameraHelper() {
68 | try {
69 | CameraManager cameraManager =
70 | (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
71 | int activityRotation =
72 | getActivity().getWindowManager().getDefaultDisplay().getRotation();
73 | mCamera2Helper = new Camera2Helper(mPreviewWidth, mPreviewHeight, activityRotation,
74 | mIsDefaultFrontCamera, this, cameraManager,
75 | new Camera2PreviewCallback(mProcessorChain));
76 | } catch (CameraAccessException | SecurityException e) {
77 | CameraCompat.onError(CameraCompat.ERR_PERMISSION);
78 | } catch (AssertionError e) {
79 | // http://crashes.to/s/7e3aebc3390
80 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
81 | }
82 | return mCamera2Helper;
83 | }
84 |
85 | /**
86 | * Creates a new {@link CameraCaptureSession} for camera preview.
87 | */
88 | private void startPreviewDirectly(final CameraDevice cameraDevice, List targets,
89 | final boolean isFlashOn, final Handler cameraHandler) {
90 | try {
91 | if (cameraDevice == null) {
92 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
93 | return;
94 | }
95 | final CaptureRequest.Builder captureRequestBuilder =
96 | cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
97 | for (int i = 0, size = targets.size(); i < size; i++) {
98 | captureRequestBuilder.addTarget(targets.get(i));
99 | }
100 |
101 | cameraDevice.createCaptureSession(targets, new CameraCaptureSession.StateCallback() {
102 | @Override
103 | public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
104 | try {
105 | captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
106 | CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO);
107 | captureRequestBuilder.set(CaptureRequest.FLASH_MODE,
108 | isFlashOn ? CameraMetadata.FLASH_MODE_TORCH
109 | : CameraMetadata.FLASH_MODE_OFF);
110 |
111 | cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(),
112 | null, cameraHandler);
113 | mCamera2Helper.previewSessionStarted(cameraCaptureSession);
114 | mProcessorChain.resume();
115 | } catch (CameraAccessException | SecurityException e) {
116 | CameraCompat.onError(CameraCompat.ERR_PERMISSION);
117 | } catch (IllegalStateException e) {
118 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
119 | }
120 | }
121 |
122 | @Override
123 | public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
124 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
125 | }
126 | }, cameraHandler);
127 | } catch (CameraAccessException | SecurityException e) {
128 | CameraCompat.onError(CameraCompat.ERR_PERMISSION);
129 | } catch (IllegalStateException e) {
130 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
131 | }
132 | }
133 |
134 | @Override
135 | public void onOpened(final CameraDevice cameraDevice, final ImageReader imageReader,
136 | final Handler cameraHandler, final Rotation rotation, final boolean flipHorizontal,
137 | final boolean flipVertical) {
138 | if (!isResumed() || !CheckUtil.nonNull(mProcessorChain)) {
139 | return;
140 | }
141 | mProcessorChain.onCameraOpened(rotation, flipHorizontal, flipVertical,
142 | surfaceTexture -> {
143 | // fix MX5 preview not show bug: http://stackoverflow.com/a/34337226/3077508
144 | surfaceTexture.setDefaultBufferSize(mPreviewWidth, mPreviewHeight);
145 | Surface surface = new Surface(surfaceTexture);
146 | List targets = Arrays.asList(surface, imageReader.getSurface());
147 | mCamera2Helper.outputTargetChanged(targets);
148 | startPreviewDirectly(cameraDevice, targets, mIsDefaultFlashOpen, cameraHandler);
149 | });
150 | }
151 |
152 | @Override
153 | public void onSettingsChanged(final CameraDevice cameraDevice,
154 | final CameraCaptureSession captureSession, final List targets,
155 | final boolean isFlashOn, final Handler cameraHandler) {
156 | try {
157 | final CaptureRequest.Builder captureRequestBuilder =
158 | cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
159 | for (int i = 0, size = targets.size(); i < size; i++) {
160 | captureRequestBuilder.addTarget(targets.get(i));
161 | }
162 | captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
163 | CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO);
164 | captureRequestBuilder.set(CaptureRequest.FLASH_MODE,
165 | isFlashOn ? CameraMetadata.FLASH_MODE_TORCH : CameraMetadata.FLASH_MODE_OFF);
166 | captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, cameraHandler);
167 | } catch (CameraAccessException | SecurityException e) {
168 | CameraCompat.onError(CameraCompat.ERR_PERMISSION);
169 | } catch (IllegalStateException e) {
170 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
171 | }
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/CameraFrameCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat;
26 |
27 | import android.annotation.TargetApi;
28 | import android.media.Image;
29 | import android.os.Build;
30 |
31 | /**
32 | * Created by Piasy{github.com/Piasy} on 5/24/16.
33 | */
34 | public interface CameraFrameCallback {
35 | void onFrameData(final byte[] data, final int width, final int height,
36 | final Runnable postProcessedTask);
37 |
38 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
39 | void onFrameData(final Image image, final Runnable postProcessedTask);
40 | }
41 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/CameraHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat;
26 |
27 | import android.view.Surface;
28 | import com.github.piasy.cameracompat.CameraCompat;
29 | import com.github.piasy.cameracompat.compat.events.CameraAccessError;
30 | import java.util.ArrayList;
31 | import java.util.Collections;
32 | import java.util.List;
33 | import jp.co.cyberagent.android.gpuimage.Rotation;
34 |
35 | /**
36 | * Created by Piasy{github.com/Piasy} on 7/21/16.
37 | */
38 |
39 | abstract class CameraHelper {
40 | protected final int mPreviewWidth;
41 | protected final int mPreviewHeight;
42 | protected boolean mIsFront;
43 |
44 | private final int mActivityRotation;
45 | private boolean mFlashLightOn;
46 |
47 | CameraHelper(int previewWidth, int previewHeight, int activityRotation, boolean isFront) {
48 | mPreviewWidth = previewWidth;
49 | mPreviewHeight = previewHeight;
50 | mActivityRotation = activityRotation;
51 | mIsFront = isFront;
52 | }
53 |
54 | final Rotation getRotation() {
55 | int activityDegree = 0;
56 | switch (mActivityRotation) {
57 | case Surface.ROTATION_0:
58 | activityDegree = 0;
59 | break;
60 | case Surface.ROTATION_90:
61 | activityDegree = 90;
62 | break;
63 | case Surface.ROTATION_180:
64 | activityDegree = 180;
65 | break;
66 | case Surface.ROTATION_270:
67 | activityDegree = 270;
68 | break;
69 | }
70 |
71 | int sensorDegree = getSensorDegree();
72 | int degree;
73 | if (mIsFront) {
74 | degree = (sensorDegree + activityDegree) % 360;
75 | } else {
76 | degree = (sensorDegree - activityDegree + 360) % 360;
77 | }
78 | Rotation ret = Rotation.NORMAL;
79 | switch (degree) {
80 | case 90:
81 | ret = Rotation.ROTATION_90;
82 | break;
83 | case 180:
84 | ret = Rotation.ROTATION_180;
85 | break;
86 | case 270:
87 | ret = Rotation.ROTATION_270;
88 | break;
89 | }
90 | return ret;
91 | }
92 |
93 | boolean switchCamera() {
94 | if (!stopPreview()) {
95 | return false;
96 | }
97 | mIsFront = !mIsFront;
98 | if (mIsFront) {
99 | mFlashLightOn = false;
100 | }
101 | return startPreview();
102 | }
103 |
104 | boolean switchFlash() {
105 | if (mIsFront || !canOperateFlash()) {
106 | return false;
107 | }
108 | try {
109 | mFlashLightOn = !mFlashLightOn;
110 | if (mFlashLightOn) {
111 | doOpenFlash();
112 | } else {
113 | doCloseFlash();
114 | }
115 | } catch (CameraAccessError | SecurityException e) {
116 | CameraCompat.onError(CameraCompat.ERR_PERMISSION);
117 | return false;
118 | } catch (RuntimeException e) {
119 | CameraCompat.onError(CameraCompat.ERR_UNKNOWN);
120 | return false;
121 | }
122 |
123 | return true;
124 | }
125 |
126 | protected PreviewSize findOptSize(int desiredWidth, int desiredHeight) {
127 | List supportedSize = getSupportedSize();
128 | List qualifiedSize = new ArrayList<>();
129 | for (int i = 0, size = supportedSize.size(); i < size; i++) {
130 | PreviewSize option = supportedSize.get(i);
131 | if (desiredWidth > desiredHeight) {
132 | if (option.getWidth() >= desiredWidth && option.getHeight() >= desiredHeight) {
133 | qualifiedSize.add(option);
134 | }
135 | } else {
136 | if (option.getWidth() >= desiredHeight && option.getHeight() >= desiredWidth) {
137 | qualifiedSize.add(option);
138 | }
139 | }
140 | }
141 | if (qualifiedSize.size() > 0) {
142 | return Collections.min(qualifiedSize, (lhs, rhs) -> {
143 | int delta = lhs.getWidth() * lhs.getHeight() - rhs.getWidth() * rhs.getHeight();
144 | return Integer.signum(delta);
145 | });
146 | } else {
147 | return new PreviewSize(desiredWidth, desiredHeight);
148 | }
149 | }
150 |
151 | protected abstract boolean startPreview();
152 |
153 | protected abstract boolean stopPreview();
154 |
155 | protected abstract int getSensorDegree();
156 |
157 | protected abstract boolean canOperateFlash();
158 |
159 | protected abstract void doOpenFlash() throws RuntimeException;
160 |
161 | protected abstract void doCloseFlash() throws RuntimeException;
162 |
163 | protected abstract List getSupportedSize() throws RuntimeException;
164 | }
165 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/NoOpChain.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat;
26 |
27 | import android.content.Context;
28 | import android.media.Image;
29 | import android.view.View;
30 | import com.github.piasy.cameracompat.gpuimage.SurfaceInitCallback;
31 | import com.github.piasy.cameracompat.processor.ProcessorChain;
32 | import jp.co.cyberagent.android.gpuimage.Rotation;
33 |
34 | /**
35 | * Created by Piasy{github.com/Piasy} on 27/10/2016.
36 | */
37 |
38 | final class NoOpChain implements ProcessorChain {
39 | static final NoOpChain INSTANCE = new NoOpChain();
40 |
41 | private NoOpChain() {
42 | }
43 |
44 | @Override
45 | public void setUp() {
46 |
47 | }
48 |
49 | @Override
50 | public View createSurface(Context context) {
51 | return new View(context);
52 | }
53 |
54 | @Override
55 | public void initSurface(Context context) {
56 |
57 | }
58 |
59 | @Override
60 | public void onCameraOpened(Rotation rotation, boolean flipHorizontal, boolean flipVertical,
61 | SurfaceInitCallback callback) {
62 |
63 | }
64 |
65 | @Override
66 | public void pause() {
67 |
68 | }
69 |
70 | @Override
71 | public void resume() {
72 |
73 | }
74 |
75 | @Override
76 | public void cameraSwitched() {
77 |
78 | }
79 |
80 | @Override
81 | public void switchMirror() {
82 |
83 | }
84 |
85 | @Override
86 | public void tearDown() {
87 |
88 | }
89 |
90 | @Override
91 | public void onFrameData(byte[] data, int width, int height,
92 | Runnable postProcessedTask) {
93 |
94 | }
95 |
96 | @Override
97 | public void onFrameData(Image image, Runnable postProcessedTask) {
98 |
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/PreviewFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat;
26 |
27 | import android.Manifest;
28 | import android.content.Context;
29 | import android.os.Bundle;
30 | import android.support.annotation.Nullable;
31 | import android.support.v4.app.Fragment;
32 | import android.view.LayoutInflater;
33 | import android.view.View;
34 | import android.view.ViewGroup;
35 | import com.github.piasy.cameracompat.CameraCompat;
36 | import com.github.piasy.cameracompat.R;
37 | import com.github.piasy.cameracompat.compat.events.SwitchBeautifyEvent;
38 | import com.github.piasy.cameracompat.compat.events.SwitchCameraEvent;
39 | import com.github.piasy.cameracompat.compat.events.SwitchFlashEvent;
40 | import com.github.piasy.cameracompat.compat.events.SwitchMirrorEvent;
41 | import com.github.piasy.cameracompat.processor.GPUImageChain;
42 | import com.github.piasy.cameracompat.processor.ProcessorChain;
43 | import com.github.piasy.safelyandroid.misc.CheckUtil;
44 | import com.hannesdorfmann.fragmentargs.annotation.Arg;
45 | import com.tbruyelle.rxpermissions2.RxPermissions;
46 | import io.reactivex.disposables.Disposable;
47 | import javax.annotation.concurrent.GuardedBy;
48 | import org.greenrobot.eventbus.EventBus;
49 | import org.greenrobot.eventbus.Subscribe;
50 | import org.greenrobot.eventbus.ThreadMode;
51 |
52 | /**
53 | * Created by Piasy{github.com/Piasy} on 6/29/16.
54 | */
55 |
56 | abstract class PreviewFragment extends Fragment {
57 |
58 | @GuardedBy("this")
59 | protected ProcessorChain mProcessorChain;
60 |
61 | @Arg
62 | int mPreviewWidth;
63 | @Arg
64 | int mPreviewHeight;
65 | @Arg
66 | boolean mIsDefaultFrontCamera;
67 | @Arg
68 | boolean mIsDefaultFlashOpen;
69 | @Arg
70 | boolean mIsDefaultBeautifyOn;
71 | @Arg
72 | boolean mIsDefaultMirrorEnabled;
73 |
74 | private ViewGroup mPreviewContainer;
75 | private CameraHelper mCameraHelper;
76 | @GuardedBy("this")
77 | private EventBus mEventBus;
78 | private Disposable mPermissionRequest;
79 |
80 | public PreviewFragment() {
81 | // Required empty public constructor
82 | }
83 |
84 | @Override
85 | public void onAttach(Context context) {
86 | super.onAttach(context);
87 | try {
88 | mProcessorChain = CameraCompat.getInstance().getProcessorChain();
89 | mEventBus = CameraCompat.getInstance().getEventBus();
90 | } catch (IllegalStateException e) {
91 | // this could happen when the host Activity is recreated, and before user init
92 | // CameraCompat instance, this preview fragment get attached.
93 |
94 | // currently we could only cover this problem to avoid crash, but
95 | // TODO: 27/10/2016 could we notify user that error happen?
96 | // although leave this Activity and enter again would solve this problem
97 |
98 | mProcessorChain = NoOpChain.INSTANCE;
99 | mEventBus = EventBus.getDefault();
100 | }
101 | }
102 |
103 | @Override
104 | public void onCreate(@Nullable Bundle savedInstanceState) {
105 | super.onCreate(savedInstanceState);
106 | setRetainInstance(true);
107 | }
108 |
109 | @Override
110 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
111 | Bundle savedInstanceState) {
112 | mEventBus.register(this);
113 | mProcessorChain.setUp();
114 | return inflater.inflate(R.layout.preview_fragment, container, false);
115 | }
116 |
117 | @Override
118 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
119 | super.onViewCreated(view, savedInstanceState);
120 |
121 | mPreviewContainer = (ViewGroup) view.findViewById(R.id.mPreviewContainer);
122 | mPreviewContainer.addView(mProcessorChain.createSurface(getContext()));
123 | mCameraHelper = createCameraHelper();
124 | mProcessorChain.initSurface(getContext());
125 | }
126 |
127 | @Override
128 | public void onResume() {
129 | super.onResume();
130 |
131 | disposePermissionRequest();
132 | mPermissionRequest = RxPermissions.getInstance(getContext())
133 | .request(Manifest.permission.CAMERA)
134 | .subscribe(grant -> {
135 | if (grant && CheckUtil.nonNull(mCameraHelper)) {
136 | mCameraHelper.startPreview();
137 | } else {
138 | CameraCompat.onError(CameraCompat.ERR_PERMISSION);
139 | }
140 | }, throwable -> CameraCompat.onError(CameraCompat.ERR_PERMISSION));
141 | }
142 |
143 | @Override
144 | public void onPause() {
145 | super.onPause();
146 |
147 | if (CheckUtil.nonNull(mCameraHelper)) {
148 | mCameraHelper.stopPreview();
149 | }
150 | }
151 |
152 | @Override
153 | public void onDestroyView() {
154 | super.onDestroyView();
155 | mEventBus.unregister(this);
156 | mProcessorChain.tearDown();
157 | disposePermissionRequest();
158 | }
159 |
160 | @Override
161 | public void onDetach() {
162 | super.onDetach();
163 |
164 | synchronized (this) {
165 | mProcessorChain = null;
166 | mEventBus = null;
167 | }
168 | }
169 |
170 | private void disposePermissionRequest() {
171 | if (mPermissionRequest != null && !mPermissionRequest.isDisposed()) {
172 | mPermissionRequest.dispose();
173 | mPermissionRequest = null;
174 | }
175 | }
176 |
177 | protected abstract CameraHelper createCameraHelper();
178 |
179 | @Subscribe(threadMode = ThreadMode.ASYNC)
180 | public synchronized void onSwitchBeautify(SwitchBeautifyEvent event) {
181 | if (isResumed() && mProcessorChain instanceof GPUImageChain) {
182 | ((GPUImageChain) mProcessorChain).switchBeautify();
183 | }
184 | }
185 |
186 | @Subscribe(threadMode = ThreadMode.ASYNC)
187 | public synchronized void onSwitchCamera(SwitchCameraEvent event) {
188 | if (isResumed() && CheckUtil.nonNull(mProcessorChain, mCameraHelper)) {
189 | mProcessorChain.pause();
190 | mCameraHelper.switchCamera();
191 | mProcessorChain.cameraSwitched();
192 | }
193 | }
194 |
195 | @Subscribe(threadMode = ThreadMode.ASYNC)
196 | public synchronized void onSwitchFlash(SwitchFlashEvent event) {
197 | if (isResumed() && CheckUtil.nonNull(mCameraHelper)) {
198 | mCameraHelper.switchFlash();
199 | }
200 | }
201 |
202 | @Subscribe(threadMode = ThreadMode.ASYNC)
203 | public synchronized void onSwitchMirror(SwitchMirrorEvent event) {
204 | if (isResumed() && CheckUtil.nonNull(mProcessorChain)) {
205 | mProcessorChain.switchMirror();
206 | }
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/PreviewSize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat;
26 |
27 | /**
28 | * Created by Piasy{github.com/Piasy} on 30/11/2016.
29 | */
30 |
31 | public class PreviewSize {
32 | private final int mWidth;
33 | private final int mHeight;
34 |
35 | public PreviewSize(int width, int height) {
36 | mWidth = width;
37 | mHeight = height;
38 | }
39 |
40 | public int getWidth() {
41 | return mWidth;
42 | }
43 |
44 | public int getHeight() {
45 | return mHeight;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/events/CameraAccessError.java:
--------------------------------------------------------------------------------
1 | package com.github.piasy.cameracompat.compat.events;
2 |
3 | /**
4 | * Created by Piasy{github.com/Piasy} on 8/3/16.
5 | */
6 |
7 | public class CameraAccessError extends RuntimeException {
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/events/SwitchBeautifyEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat.events;
26 |
27 | /**
28 | * Created by Piasy{github.com/Piasy} on 6/29/16.
29 | */
30 |
31 | public class SwitchBeautifyEvent {
32 | }
33 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/events/SwitchCameraEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat.events;
26 |
27 | /**
28 | * Created by Piasy{github.com/Piasy} on 6/29/16.
29 | */
30 |
31 | public class SwitchCameraEvent {
32 | }
33 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/events/SwitchFlashEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat.events;
26 |
27 | /**
28 | * Created by Piasy{github.com/Piasy} on 6/29/16.
29 | */
30 |
31 | public class SwitchFlashEvent {
32 | }
33 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/compat/events/SwitchMirrorEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.compat.events;
26 |
27 | /**
28 | * Created by Piasy{github.com/Piasy} on 6/29/16.
29 | */
30 |
31 | public class SwitchMirrorEvent {
32 | }
33 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/gpuimage/GLFilterGroup.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.gpuimage;
26 |
27 | import android.annotation.SuppressLint;
28 | import android.opengl.GLES20;
29 | import com.github.piasy.cameracompat.utils.GLUtil;
30 | import java.nio.ByteBuffer;
31 | import java.nio.ByteOrder;
32 | import java.nio.FloatBuffer;
33 | import java.util.ArrayList;
34 | import java.util.List;
35 | import jp.co.cyberagent.android.gpuimage.GPUImageFilter;
36 | import jp.co.cyberagent.android.gpuimage.Rotation;
37 | import jp.co.cyberagent.android.gpuimage.util.TextureRotationUtil;
38 |
39 | import static jp.co.cyberagent.android.gpuimage.util.TextureRotationUtil.TEXTURE_NO_ROTATION;
40 |
41 | /**
42 | * Created by Piasy{github.com/Piasy} on 5/31/16.
43 | */
44 | public class GLFilterGroup extends GPUImageFilter {
45 |
46 | protected List mFilters;
47 | protected List mMergedFilters;
48 | private final FloatBuffer mGLCubeBuffer;
49 | private final FloatBuffer mGLTextureBuffer;
50 | private final FloatBuffer mGLTextureFlipBuffer;
51 | private int[] mFrameBuffers;
52 | private int[] mFrameBufferTextures;
53 | private ImageDumpedListener mImageDumpedListener;
54 | private volatile int mImageWidth;
55 | private volatile int mImageHeight;
56 | private ByteBuffer mRgbaBuf;
57 |
58 | /**
59 | * Instantiates a new GPUImageFilterGroup with the given filters.
60 | *
61 | * @param filters the filters which represent this filter
62 | */
63 | public GLFilterGroup(List filters) {
64 | mFilters = filters;
65 | if (mFilters == null) {
66 | mFilters = new ArrayList<>();
67 | } else {
68 | updateMergedFilters();
69 | }
70 |
71 | mGLCubeBuffer = ByteBuffer.allocateDirect(GLRender.CUBE.length * 4)
72 | .order(ByteOrder.nativeOrder())
73 | .asFloatBuffer();
74 | mGLCubeBuffer.put(GLRender.CUBE).position(0);
75 |
76 | mGLTextureBuffer = ByteBuffer.allocateDirect(TEXTURE_NO_ROTATION.length * 4)
77 | .order(ByteOrder.nativeOrder())
78 | .asFloatBuffer();
79 | mGLTextureBuffer.put(TEXTURE_NO_ROTATION).position(0);
80 |
81 | float[] flipTexture = TextureRotationUtil.getRotation(Rotation.NORMAL, false, true);
82 | mGLTextureFlipBuffer = ByteBuffer.allocateDirect(flipTexture.length * 4)
83 | .order(ByteOrder.nativeOrder())
84 | .asFloatBuffer();
85 | mGLTextureFlipBuffer.put(flipTexture).position(0);
86 | }
87 |
88 | public void setImageDumpedListener(ImageDumpedListener imageDumpedListener) {
89 | mImageDumpedListener = imageDumpedListener;
90 | }
91 |
92 | /*
93 | * (non-Javadoc)
94 | * @see jp.co.cyberagent.android.gpuimage.GPUImageFilter#onInit()
95 | */
96 | @Override
97 | public void onInit() {
98 | super.onInit();
99 | for (GPUImageFilter filter : mFilters) {
100 | filter.init();
101 | }
102 | }
103 |
104 | /*
105 | * (non-Javadoc)
106 | * @see jp.co.cyberagent.android.gpuimage.GPUImageFilter#onDestroy()
107 | */
108 | @Override
109 | public void onDestroy() {
110 | destroyFrameBuffers();
111 | for (GPUImageFilter filter : mFilters) {
112 | filter.destroy();
113 | }
114 | super.onDestroy();
115 | }
116 |
117 | /*
118 | * (non-Javadoc)
119 | * @see
120 | * jp.co.cyberagent.android.gpuimage.GPUImageFilter#onOutputSizeChanged(int,
121 | * int)
122 | */
123 | @Override
124 | public void onOutputSizeChanged(final int width, final int height) {
125 | super.onOutputSizeChanged(width, height);
126 | if (mFrameBuffers != null) {
127 | destroyFrameBuffers();
128 | }
129 |
130 | int size = mFilters.size();
131 | for (int i = 0; i < size - 1; i++) {
132 | mFilters.get(i).onOutputSizeChanged(mImageHeight, mImageWidth);
133 | }
134 | mFilters.get(size - 1).onOutputSizeChanged(width, height);
135 |
136 | if (mMergedFilters.size() > 0) {
137 | size = mMergedFilters.size();
138 | mFrameBuffers = new int[size - 1];
139 | mFrameBufferTextures = new int[size - 1];
140 |
141 | for (int i = 0; i < size - 1; i++) {
142 | GLES20.glGenFramebuffers(1, mFrameBuffers, i);
143 | GLES20.glGenTextures(1, mFrameBufferTextures, i);
144 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFrameBufferTextures[i]);
145 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mImageHeight,
146 | mImageWidth, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
147 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
148 | GLES20.GL_LINEAR);
149 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
150 | GLES20.GL_LINEAR);
151 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
152 | GLES20.GL_CLAMP_TO_EDGE);
153 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
154 | GLES20.GL_CLAMP_TO_EDGE);
155 |
156 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffers[i]);
157 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
158 | GLES20.GL_TEXTURE_2D, mFrameBufferTextures[i], 0);
159 |
160 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
161 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
162 | }
163 | }
164 | }
165 |
166 | /*
167 | * (non-Javadoc)
168 | * @see jp.co.cyberagent.android.gpuimage.GPUImageFilter#onDraw(int,
169 | * java.nio.FloatBuffer, java.nio.FloatBuffer)
170 | */
171 | @SuppressLint("WrongCall")
172 | @Override
173 | public void onDraw(final int textureId, final FloatBuffer cubeBuffer,
174 | final FloatBuffer textureBuffer) {
175 | runPendingOnDrawTasks();
176 | if (!isInitialized() || mFrameBuffers == null || mFrameBufferTextures == null) {
177 | return;
178 | }
179 | int size = mMergedFilters.size();
180 | int previousTexture = textureId;
181 | int currentOutputWidth = mOutputWidth;
182 | int currentOutputHeight = mOutputHeight;
183 | for (int i = 0; i < size; i++) {
184 | GPUImageFilter filter = mMergedFilters.get(i);
185 | boolean isLast = i == size - 1;
186 | if (!isLast) {
187 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffers[i]);
188 | GLES20.glClearColor(0, 0, 0, 0);
189 |
190 | mOutputWidth = mImageHeight;
191 | mOutputHeight = mImageWidth;
192 | GLES20.glViewport(0, 0, mOutputWidth, mOutputHeight);
193 | } else {
194 | mOutputWidth = currentOutputWidth;
195 | mOutputHeight = currentOutputHeight;
196 | // avoid extra stride at the edge of screen
197 | GLES20.glViewport(-7, -7, mOutputWidth + 14, mOutputHeight + 14);
198 | }
199 |
200 | if (i == 0) {
201 | filter.onDraw(previousTexture, cubeBuffer, textureBuffer);
202 | } else if (isLast) {
203 | filter.onDraw(previousTexture, mGLCubeBuffer,
204 | (size % 2 == 0) ? mGLTextureFlipBuffer : mGLTextureBuffer);
205 | } else {
206 | filter.onDraw(previousTexture, mGLCubeBuffer, mGLTextureBuffer);
207 | }
208 | if (i == size - 2 && mOutputWidth * mOutputHeight != 0) {
209 | // just before last filter, read data from GPU
210 | dumpImage(mOutputWidth, mOutputHeight);
211 | }
212 |
213 | if (!isLast) {
214 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
215 | previousTexture = mFrameBufferTextures[i];
216 | }
217 | }
218 | }
219 |
220 | private void destroyFrameBuffers() {
221 | if (mFrameBufferTextures != null) {
222 | GLES20.glDeleteTextures(mFrameBufferTextures.length, mFrameBufferTextures, 0);
223 | mFrameBufferTextures = null;
224 | }
225 | if (mFrameBuffers != null) {
226 | GLES20.glDeleteFramebuffers(mFrameBuffers.length, mFrameBuffers, 0);
227 | mFrameBuffers = null;
228 | }
229 | }
230 |
231 | public void onImageSizeChanged(int imageWidth, int imageHeight) {
232 | mImageWidth = imageWidth;
233 | mImageHeight = imageHeight;
234 | mRgbaBuf = ByteBuffer.allocateDirect(mImageWidth * mImageHeight * 4);
235 | onOutputSizeChanged(mOutputWidth, mOutputHeight);
236 | }
237 |
238 | private void dumpImage(int width, int height) {
239 | if (mImageDumpedListener == null) {
240 | return;
241 | }
242 | mRgbaBuf.position(0);
243 | GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mRgbaBuf);
244 | GLUtil.dumpGlError("glReadPixels");
245 | mImageDumpedListener.imageDumped(mRgbaBuf, width, height);
246 | }
247 |
248 | public List getFilters() {
249 | return mFilters;
250 | }
251 |
252 | public List getMergedFilters() {
253 | return mMergedFilters;
254 | }
255 |
256 | public void updateMergedFilters() {
257 | if (mFilters == null) {
258 | return;
259 | }
260 |
261 | if (mMergedFilters == null) {
262 | mMergedFilters = new ArrayList<>();
263 | } else {
264 | mMergedFilters.clear();
265 | }
266 |
267 | List filters;
268 | for (GPUImageFilter filter : mFilters) {
269 | if (filter instanceof GLFilterGroup) {
270 | ((GLFilterGroup) filter).updateMergedFilters();
271 | filters = ((GLFilterGroup) filter).getMergedFilters();
272 | if (filters == null || filters.isEmpty()) continue;
273 | mMergedFilters.addAll(filters);
274 | continue;
275 | }
276 | mMergedFilters.add(filter);
277 | }
278 | }
279 |
280 | public interface ImageDumpedListener {
281 | void imageDumped(ByteBuffer rgba, int width, int height);
282 | }
283 | }
284 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/gpuimage/SurfaceInitCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.gpuimage;
26 |
27 | import android.graphics.SurfaceTexture;
28 |
29 | /**
30 | * Created by Piasy{github.com/Piasy} on 5/24/16.
31 | */
32 | public interface SurfaceInitCallback {
33 | void onSurfaceTextureInitiated(SurfaceTexture surfaceTexture);
34 | }
35 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/processor/DirectChain.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.processor;
26 |
27 | import android.annotation.TargetApi;
28 | import android.content.Context;
29 | import android.graphics.SurfaceTexture;
30 | import android.media.Image;
31 | import android.os.Build;
32 | import android.view.TextureView;
33 | import android.view.View;
34 | import android.view.ViewGroup;
35 | import android.widget.FrameLayout;
36 | import com.github.piasy.cameracompat.CameraCompat;
37 | import com.github.piasy.cameracompat.gpuimage.SurfaceInitCallback;
38 | import java.nio.ByteBuffer;
39 | import jp.co.cyberagent.android.gpuimage.Rotation;
40 |
41 | /**
42 | * Created by Piasy{github.com/Piasy} on 18/10/2016.
43 | */
44 |
45 | public class DirectChain implements ProcessorChain, TextureView.SurfaceTextureListener {
46 | private final CameraCompat.VideoCaptureCallback mVideoCaptureCallback;
47 |
48 | private TextureView mTextureView;
49 | private volatile SurfaceInitCallback mPendingNotify = null;
50 |
51 | private Rotation mRotation;
52 |
53 | private int mOutputWidth;
54 | private int mOutputHeight;
55 | private volatile int mVideoWidth;
56 | private volatile int mVideoHeight;
57 |
58 | private volatile boolean mIsFrontCamera;
59 | private volatile boolean mEnableMirror;
60 |
61 | private ByteBuffer mGLYuvBuffer;
62 |
63 | public DirectChain(boolean defaultFrontCamera,
64 | CameraCompat.VideoCaptureCallback videoCaptureCallback) {
65 | mVideoCaptureCallback = videoCaptureCallback;
66 | mIsFrontCamera = defaultFrontCamera;
67 | }
68 |
69 | @Override
70 | public void setUp() {
71 | }
72 |
73 | @Override
74 | public View createSurface(Context context) {
75 | mTextureView = new TextureView(context);
76 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
77 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
78 | mTextureView.setLayoutParams(params);
79 | mTextureView.setKeepScreenOn(true);
80 | return mTextureView;
81 | }
82 |
83 | @Override
84 | public void initSurface(Context context) {
85 | mTextureView.setSurfaceTextureListener(this);
86 | }
87 |
88 | @Override
89 | public void onCameraOpened(Rotation rotation, boolean flipHorizontal, boolean flipVertical,
90 | SurfaceInitCallback callback) {
91 | mRotation = rotation;
92 | if (mTextureView.getSurfaceTexture() != null) {
93 | callback.onSurfaceTextureInitiated(mTextureView.getSurfaceTexture());
94 | mTextureView.post(this::adjustImageScaling);
95 | } else {
96 | mPendingNotify = callback;
97 | }
98 | }
99 |
100 | @Override
101 | public void pause() {
102 | }
103 |
104 | @Override
105 | public void resume() {
106 | }
107 |
108 | @Override
109 | public void cameraSwitched() {
110 | mIsFrontCamera = !mIsFrontCamera;
111 | }
112 |
113 | @Override
114 | public void switchMirror() {
115 | mEnableMirror = !mEnableMirror;
116 | }
117 |
118 | @Override
119 | public void tearDown() {
120 | }
121 |
122 | @Override
123 | public void onFrameData(byte[] data, int width, int height,
124 | Runnable postProcessedTask) {
125 | notifyVideoSizeChanged(width, height);
126 | sendNormalImage(width, height, data);
127 | postProcessedTask.run();
128 | }
129 |
130 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
131 | @Override
132 | public void onFrameData(Image image, Runnable postProcessedTask) {
133 | notifyVideoSizeChanged(image.getWidth(), image.getHeight());
134 | sendNormalImage(image);
135 | postProcessedTask.run();
136 | }
137 |
138 | /**
139 | * direct chain won't change frame size, so the size is ignored, but actually they are equal.
140 | */
141 | private void notifyVideoSizeChanged(int width, int height) {
142 | if (mVideoWidth != 0) {
143 | return;
144 | }
145 | mVideoWidth = width;
146 | mVideoHeight = height;
147 | if (mGLYuvBuffer == null) {
148 | mGLYuvBuffer = ByteBuffer.allocateDirect(mVideoWidth * mVideoHeight * 3 / 2);
149 | }
150 | mVideoCaptureCallback.onVideoSizeChanged(mVideoWidth, mVideoHeight);
151 | mTextureView.post(this::adjustImageScaling);
152 | }
153 |
154 | private void adjustImageScaling() {
155 | if (mRotation == null || mVideoWidth == 0 || mVideoHeight == 0) {
156 | return;
157 | }
158 | float videoWidth = mVideoWidth;
159 | float videoHeight = mVideoHeight;
160 | if (mRotation == Rotation.ROTATION_270 || mRotation == Rotation.ROTATION_90) {
161 | videoWidth = mVideoHeight;
162 | videoHeight = mVideoWidth;
163 | }
164 | float ratioW = mOutputWidth / videoWidth;
165 | float ratioH = mOutputHeight / videoHeight;
166 | float ratioMax = Math.max(ratioW, ratioH);
167 | int outputWidthNew = Math.round(videoWidth * ratioMax);
168 | int outputHeightNew = Math.round(videoHeight * ratioMax);
169 | FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mTextureView.getLayoutParams();
170 | params.width = outputWidthNew;
171 | params.height = outputHeightNew;
172 | if (ratioW > ratioH) {
173 | params.topMargin = -((int) Math.ceil((outputHeightNew - mOutputHeight) / 2));
174 | } else {
175 | params.leftMargin = -((int) Math.ceil((outputWidthNew - mOutputWidth) / 2));
176 | }
177 | mTextureView.setLayoutParams(params);
178 | }
179 |
180 | private void sendNormalImage(int width, int height, byte[] data) {
181 | if (mIsFrontCamera && mEnableMirror) {
182 | if (mRotation == Rotation.ROTATION_90) {
183 | RgbYuvConverter.yuvCropFlip(width, height, data, mVideoHeight,
184 | mGLYuvBuffer.array());
185 | } else {
186 | RgbYuvConverter.yuvCropRotateC180Flip(width, height, data, mVideoHeight,
187 | mGLYuvBuffer.array());
188 | }
189 | } else {
190 | if (mRotation == Rotation.ROTATION_90) {
191 | RgbYuvConverter.yuvCropRotateC180(width, height, data, mVideoHeight,
192 | mGLYuvBuffer.array());
193 | } else {
194 | RgbYuvConverter.yuvCrop(width, height, data, mVideoHeight, mGLYuvBuffer.array());
195 | }
196 | }
197 | mVideoCaptureCallback.onFrameData(mGLYuvBuffer.array(), width, mVideoHeight);
198 | }
199 |
200 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
201 | private void sendNormalImage(Image image) {
202 | if (mIsFrontCamera && mEnableMirror) {
203 | if (mRotation == Rotation.ROTATION_90) {
204 | RgbYuvConverter.image2yuvCropFlip(image, mVideoHeight, mGLYuvBuffer.array());
205 | } else {
206 | RgbYuvConverter.image2yuvCropRotateC180Flip(image, mVideoHeight,
207 | mGLYuvBuffer.array());
208 | }
209 | } else {
210 | if (mRotation == Rotation.ROTATION_90) {
211 | RgbYuvConverter.image2yuvCropRotateC180(image, mVideoHeight, mGLYuvBuffer.array());
212 | } else {
213 | RgbYuvConverter.image2yuvCrop(image, mVideoHeight, mGLYuvBuffer.array());
214 | }
215 | }
216 | mVideoCaptureCallback.onFrameData(mGLYuvBuffer.array(), image.getWidth(), mVideoHeight);
217 | }
218 |
219 | @Override
220 | public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
221 | mOutputWidth = width;
222 | mOutputHeight = height;
223 | adjustImageScaling();
224 | if (mPendingNotify != null) {
225 | mPendingNotify.onSurfaceTextureInitiated(surface);
226 | mPendingNotify = null;
227 | }
228 | }
229 |
230 | @Override
231 | public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
232 | }
233 |
234 | @Override
235 | public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
236 | return false;
237 | }
238 |
239 | @Override
240 | public void onSurfaceTextureUpdated(SurfaceTexture surface) {
241 | }
242 | }
243 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/processor/GPUImageChain.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.processor;
26 |
27 | import android.annotation.TargetApi;
28 | import android.content.Context;
29 | import android.graphics.PixelFormat;
30 | import android.media.Image;
31 | import android.opengl.GLSurfaceView;
32 | import android.os.Build;
33 | import android.view.View;
34 | import android.view.ViewGroup;
35 | import android.widget.FrameLayout;
36 | import com.github.piasy.cameracompat.CameraCompat;
37 | import com.github.piasy.cameracompat.gpuimage.GLFilterGroup;
38 | import com.github.piasy.cameracompat.gpuimage.GLRender;
39 | import com.github.piasy.cameracompat.gpuimage.SurfaceInitCallback;
40 | import com.github.piasy.cameracompat.utils.GLUtil;
41 | import com.github.piasy.cameracompat.utils.Profiler;
42 | import java.nio.ByteBuffer;
43 | import java.util.ArrayList;
44 | import java.util.Collections;
45 | import java.util.List;
46 | import jp.co.cyberagent.android.gpuimage.GPUImageFilter;
47 | import jp.co.cyberagent.android.gpuimage.Rotation;
48 |
49 | /**
50 | * Created by Piasy{github.com/Piasy} on 18/10/2016.
51 | */
52 |
53 | public class GPUImageChain implements ProcessorChain, GLFilterGroup.ImageDumpedListener,
54 | GLRender.VideoSizeChangedListener {
55 | private final List mProcessors;
56 | private final CameraCompat.VideoCaptureCallback mVideoCaptureCallback;
57 | private final boolean mDefaultFilterEnabled;
58 | private final Profiler mProfiler;
59 |
60 | private GLSurfaceView mGLSurfaceView;
61 | private GLRender mGLRender;
62 | private volatile boolean mIsFrontCamera;
63 | private volatile boolean mEnableMirror;
64 |
65 | private ByteBuffer mGLRgbaBuffer;
66 | private ByteBuffer mGLYuvBuffer;
67 |
68 | public GPUImageChain(List processors, boolean defaultEnableFilter,
69 | boolean defaultFrontCamera, CameraCompat.VideoCaptureCallback videoCaptureCallback,
70 | Profiler profiler) {
71 | mProcessors = Collections.unmodifiableList(new ArrayList<>(processors));
72 | mVideoCaptureCallback = videoCaptureCallback;
73 | mDefaultFilterEnabled = defaultEnableFilter;
74 | mIsFrontCamera = defaultFrontCamera;
75 | mProfiler = profiler;
76 | }
77 |
78 | @Override
79 | public void setUp() {
80 | for (Processor processor : mProcessors) {
81 | processor.setUp();
82 | }
83 | }
84 |
85 | @Override
86 | public View createSurface(Context context) {
87 | mGLSurfaceView = new GLSurfaceView(context);
88 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
89 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
90 | mGLSurfaceView.setLayoutParams(params);
91 | mGLSurfaceView.setKeepScreenOn(true);
92 | return mGLSurfaceView;
93 | }
94 |
95 | @Override
96 | public void initSurface(Context context) {
97 | List filters = new ArrayList<>();
98 | for (Processor processor : mProcessors) {
99 | filters.addAll(processor.getFilters());
100 | }
101 | filters.add(new GPUImageFilter());
102 | GLFilterGroup filterGroup = new GLFilterGroup(filters);
103 | filterGroup.setImageDumpedListener(this);
104 | mGLRender = new GLRender(filterGroup, mDefaultFilterEnabled, this, mProfiler);
105 |
106 | if (GLUtil.isSupportOpenGLES2(context)) {
107 | mGLSurfaceView.setEGLContextClientVersion(2);
108 | }
109 | mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
110 | mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888);
111 | mGLSurfaceView.setRenderer(mGLRender);
112 | mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
113 | mGLSurfaceView.requestRender();
114 | }
115 |
116 | @Override
117 | public void onCameraOpened(Rotation rotation, boolean flipHorizontal, boolean flipVertical,
118 | SurfaceInitCallback callback) {
119 | mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
120 | mGLRender.setRotationCamera(rotation, flipHorizontal, flipVertical);
121 | mGLRender.setUpSurfaceTexture(callback);
122 | }
123 |
124 | @Override
125 | public void pause() {
126 | mGLRender.pauseDrawing();
127 | }
128 |
129 | @Override
130 | public void resume() {
131 | mGLRender.resumeDrawing();
132 | }
133 |
134 | @Override
135 | public synchronized void cameraSwitched() {
136 | mIsFrontCamera = !mIsFrontCamera;
137 | }
138 |
139 | @Override
140 | public synchronized void switchMirror() {
141 | mEnableMirror = !mEnableMirror;
142 | }
143 |
144 | @Override
145 | public void tearDown() {
146 | for (Processor processor : mProcessors) {
147 | processor.tearDown();
148 | }
149 | }
150 |
151 | public synchronized void switchBeautify() {
152 | mGLRender.switchFilter();
153 | }
154 |
155 | @Override
156 | public void onFrameData(byte[] data, int width, int height,
157 | Runnable postProcessedTask) {
158 | if (mGLRgbaBuffer == null) {
159 | mGLRgbaBuffer = ByteBuffer.allocateDirect(width * height * 4);
160 | }
161 | if (mGLYuvBuffer == null) {
162 | // 16 bytes alignment
163 | int bufHeight = (width * mGLRender.getFrameWidth() / mGLRender.getFrameHeight())
164 | & 0xfffffff0;
165 | mGLYuvBuffer = ByteBuffer.allocateDirect(width * bufHeight * 3 / 2);
166 | }
167 | if (!mGLRender.isBusyDrawing()) {
168 | RgbYuvConverter.yuv2rgba(width, height, data, mGLRgbaBuffer.array());
169 | mGLRender.scheduleDrawFrame(mGLRgbaBuffer, width, height, () -> {
170 | if (!mGLRender.isEnableFilter() && !mGLRender.isPaused()) {
171 | sendNormalImage(width, height, data);
172 | }
173 | postProcessedTask.run();
174 | });
175 | }
176 | }
177 |
178 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
179 | @Override
180 | public void onFrameData(final Image image, final Runnable postProcessedTask) {
181 | final int width = image.getWidth();
182 | final int height = image.getHeight();
183 | if (mGLRgbaBuffer == null) {
184 | mGLRgbaBuffer = ByteBuffer.allocateDirect(width * height * 4);
185 | }
186 | if (mGLYuvBuffer == null) {
187 | // 16 bytes alignment
188 | int bufHeight = (width * mGLRender.getFrameWidth() / mGLRender.getFrameHeight())
189 | & 0xfffffff0;
190 | mGLYuvBuffer = ByteBuffer.allocateDirect(width * bufHeight * 3 / 2);
191 | }
192 | if (!mGLRender.isBusyDrawing()) {
193 | RgbYuvConverter.image2rgba(image, mGLRgbaBuffer.array());
194 | mGLRender.scheduleDrawFrame(mGLRgbaBuffer, width, height, () -> {
195 | if (!mGLRender.isEnableFilter() && !mGLRender.isPaused()) {
196 | sendNormalImage(image);
197 | }
198 | postProcessedTask.run();
199 | });
200 | } else {
201 | postProcessedTask.run();
202 | }
203 | }
204 |
205 | @Override
206 | public void imageDumped(ByteBuffer rgba, int width, int height) {
207 | sendBeautifyImage(rgba, width, height);
208 | }
209 |
210 | private void sendBeautifyImage(ByteBuffer rgba, int width, int height) {
211 | if (mIsFrontCamera) {
212 | if (mEnableMirror) {
213 | RgbYuvConverter.rgba2yuvRotateC90(width, height, rgba.array(),
214 | mGLYuvBuffer.array());
215 | } else {
216 | RgbYuvConverter.rgba2yuvRotateC90Flip(width, height, rgba.array(),
217 | mGLYuvBuffer.array());
218 | }
219 | } else {
220 | RgbYuvConverter.rgba2yuvRotateC90(width, height, rgba.array(), mGLYuvBuffer.array());
221 | }
222 | mVideoCaptureCallback.onFrameData(mGLYuvBuffer.array(), height, width);
223 | }
224 |
225 | private void sendNormalImage(int width, int height, byte[] data) {
226 | if (mIsFrontCamera && mEnableMirror) {
227 | if (mGLRender.getRotation() == Rotation.ROTATION_90) {
228 | RgbYuvConverter.yuvCropFlip(width, height, data, mGLRender.getVideoHeight(),
229 | mGLYuvBuffer.array());
230 | } else {
231 | RgbYuvConverter.yuvCropRotateC180Flip(width, height, data,
232 | mGLRender.getVideoHeight(), mGLYuvBuffer.array());
233 | }
234 | } else {
235 | if (mGLRender.getRotation() == Rotation.ROTATION_90) {
236 | RgbYuvConverter.yuvCropRotateC180(width, height, data, mGLRender.getVideoHeight(),
237 | mGLYuvBuffer.array());
238 | } else {
239 | RgbYuvConverter.yuvCrop(width, height, data, mGLRender.getVideoHeight(),
240 | mGLYuvBuffer.array());
241 | }
242 | }
243 | mVideoCaptureCallback.onFrameData(mGLYuvBuffer.array(), width, mGLRender.getVideoHeight());
244 | }
245 |
246 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
247 | private void sendNormalImage(Image image) {
248 | if (mIsFrontCamera && mEnableMirror) {
249 | if (mGLRender.getRotation() == Rotation.ROTATION_90) {
250 | RgbYuvConverter.image2yuvCropFlip(image, mGLRender.getVideoHeight(),
251 | mGLYuvBuffer.array());
252 | } else {
253 | RgbYuvConverter.image2yuvCropRotateC180Flip(image, mGLRender.getVideoHeight(),
254 | mGLYuvBuffer.array());
255 | }
256 | } else {
257 | if (mGLRender.getRotation() == Rotation.ROTATION_90) {
258 | RgbYuvConverter.image2yuvCropRotateC180(image, mGLRender.getVideoHeight(),
259 | mGLYuvBuffer.array());
260 | } else {
261 | RgbYuvConverter.image2yuvCrop(image, mGLRender.getVideoHeight(),
262 | mGLYuvBuffer.array());
263 | }
264 | }
265 | mVideoCaptureCallback.onFrameData(mGLYuvBuffer.array(), image.getWidth(),
266 | mGLRender.getVideoHeight());
267 | }
268 |
269 | @Override
270 | public void onVideoSizeChanged(int width, int height) {
271 | mVideoCaptureCallback.onVideoSizeChanged(width, height);
272 | }
273 | }
274 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/processor/Processor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.processor;
26 |
27 | import com.github.piasy.cameracompat.compat.CameraFrameCallback;
28 | import java.util.List;
29 | import jp.co.cyberagent.android.gpuimage.GPUImageFilter;
30 |
31 | /**
32 | * Created by Piasy{github.com/Piasy} on 17/10/2016.
33 | */
34 |
35 | public interface Processor extends CameraFrameCallback {
36 | void setUp();
37 |
38 | List getFilters();
39 |
40 | void tearDown();
41 | }
42 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/processor/ProcessorChain.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.processor;
26 |
27 | import android.content.Context;
28 | import android.view.View;
29 | import com.github.piasy.cameracompat.compat.CameraFrameCallback;
30 | import com.github.piasy.cameracompat.gpuimage.SurfaceInitCallback;
31 | import jp.co.cyberagent.android.gpuimage.Rotation;
32 |
33 | /**
34 | * Created by Piasy{github.com/Piasy} on 18/10/2016.
35 | */
36 |
37 | public interface ProcessorChain extends CameraFrameCallback {
38 | void setUp();
39 |
40 | View createSurface(Context context);
41 |
42 | void initSurface(Context context);
43 |
44 | void onCameraOpened(Rotation rotation, boolean flipHorizontal, boolean flipVertical,
45 | SurfaceInitCallback callback);
46 |
47 | void pause();
48 |
49 | void resume();
50 |
51 | void cameraSwitched();
52 |
53 | void switchMirror();
54 |
55 | void tearDown();
56 | }
57 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/processor/RgbYuvConverter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.processor;
26 |
27 | import android.annotation.TargetApi;
28 | import android.content.Context;
29 | import android.media.Image;
30 | import android.os.Build;
31 | import com.getkeepsafe.relinker.ReLinker;
32 | import java.nio.ByteBuffer;
33 |
34 | /**
35 | * Created by Piasy{github.com/Piasy} on 6/2/16.
36 | *
37 | * from http://www.equasys.de/colorconversion.html
38 | * https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
39 | *
40 | * packed mode, and Cr comes first, ref: http://stackoverflow.com/a/12610396/3077508
41 | *
42 | * {@code
43 | * float operation:
44 | * R = 1.164 * (Y-16) + 1.596 * (Cr-128)
45 | * G = 1.164 * (Y-16) - 0.392 * (Cb-128) - 0.813 * (Cr-128)
46 | * B = 1.164 * (Y-16) + 2.017 * (Cb-128)
47 | *
48 | * transform to bit operation:
49 | * 1.164 = 1 + (1 >> 3) + (1 >> 5) + (1 >> 7) ~= 1 + (1 >> 3) + (1 >> 5) = 1.15625 , 0.0078125 , 2
50 | * 1.596 = 1 + (1 >> 1) + (1 >> 4) + (1 >> 5)
51 | * 0.392 = (1 >> 2) + (1 >> 3) + (1 >> 6) ~= (1 >> 1) - (1 >> 3) = 0.375 , 0.017 , 4.352
52 | * 0.813 = (1 >> 1) + (1 >> 2) + (1 >> 4) ~= 1 - (1 >> 3) - (1 >> 4) = 0.8125 , 0.0005 , 0.128
53 | * 2.017 = 2 + (1 >> 6) ~= 2 , 0.017 , 4
54 | *
55 | * Y = Y - 16, Cb = Cb - 128, Cr = Cr - 128
56 | * Y = Y + (Y >> 3) + (Y >> 5) + (Y >> 7)
57 | *
58 | * R = Y + Cr + (Cr >> 1) + (Cr >> 4) + (Cr >> 5)
59 | * G = Y - (Cb >> 2) - (Cb >> 3) - (Cb >> 6) - (Cr >> 1) - (Cr >> 2) - (Cr >> 4)
60 | * B = Y + (Cb << 1) + (Cb >> 6)
61 | * }
62 | *
63 | * Perf:
64 | * float 640*480: 458060886 ns
65 | * bit 640*480: 406342604 ns, 12.7 % faster than float
66 | * jni (bit) 640*480: 15664062 ns, 2494.1 % faster than bit
67 | * jni (GpuImage) 640*480: 13116771 ns, 19.4 % faster than jni, but why??
68 | *
69 | *
70 | * {@code
71 | * float operation:
72 | * Y = 0.257 * R + 0.504 * G + 0.098 * B + 16
73 | * Cb = -0.148 * R - 0.291 * G + 0.439 * B + 128
74 | * Cr = 0.439 * R - 0.368 * G - 0.071 * B + 128
75 | *
76 | * transform to bit operation:
77 | * 0.257 = (1 >> 2) + (1 >> 7)
78 | * 0.504 = (1 >> 1) + (1 >> 8)
79 | * 0.098 = (1 >> 4) + (1 >> 5) + (1 >> 8)
80 | * 0.148 = (1 >> 3) + (1 >> 6) + (1 >> 7)
81 | * 0.291 = (1 >> 2) + (1 >> 5) + (1 >> 7)
82 | * 0.439 = (1 >> 2) + (1 >> 3) + (1 >> 4) = (1 >> 1) - (1 >> 4)
83 | * 0.368 = (1 >> 2) + (1 >> 3) - (1 >> 7)
84 | * 0.071 = (1 >> 4) + (1 >> 7)
85 | *
86 | * Y = (R >> 2) + (R >> 7) + (G >> 1) + (G >> 8) + (B >> 4) + (B >> 5) + (B >> 8) + 16
87 | * Cb = -(R >> 3) - (R >> 6) - (R >> 7) - (G >> 2) - (G >> 5) - (G >> 7) + (B >> 1) - (B >> 4) + 128
88 | * Cr = (R >> 1) - (R >> 4) - (G >> 2) - (G >> 3) + (G >> 7) - (B >> 4) - (B >> 7) + 128
89 | * }
90 | *
91 | * Perf:
92 | * float 640*480: 227084323 ns
93 | * bit 640*480: 181100573 ns, 25.4 % faster than float
94 | * jni (bit) 640*480: 11113646 ns, 1529.5 % faster than bit
95 | */
96 | public class RgbYuvConverter {
97 |
98 | public static void loadLibrary(Context context) {
99 | ReLinker.loadLibrary(context, "rgb-yuv-converter-library");
100 | }
101 |
102 | public static native int yuv2rgba(int width, int height, byte[] yuvIn, byte[] rgbaOut);
103 |
104 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
105 | public static int image2rgba(Image image, byte[] rgbaOut) {
106 | Image.Plane[] planes = image.getPlanes();
107 | ByteBuffer Y = planes[0].getBuffer();
108 | ByteBuffer Cr = planes[2].getBuffer();
109 | int CrPixelStride = planes[2].getPixelStride();
110 | ByteBuffer Cb = planes[1].getBuffer();
111 | int CbPixelStride = planes[1].getPixelStride();
112 | return image2rgba(image.getWidth(), image.getHeight(), Y, Cr, Cb, CrPixelStride,
113 | CbPixelStride, rgbaOut);
114 | }
115 |
116 | private static native int image2rgba(int width, int height, ByteBuffer Y, ByteBuffer Cr,
117 | ByteBuffer Cb, int CrPixelStride, int CbPixelStride, byte[] rgbaOut);
118 |
119 | /**
120 | * rotate 90 degree in counter clockwise and change to yuv
121 | */
122 | public static native int rgba2yuv(int width, int height, int[] rgbaIn, byte[] yuvOut);
123 |
124 | /**
125 | * rotate 90 degree in counter clockwise and change to yuv
126 | */
127 | public static native int rgba2yuvRotateC90(int width, int height, byte[] rgbaIn, byte[] yuvOut);
128 |
129 | /**
130 | * rotate 90 degree in counter clockwise and change to yuv
131 | */
132 | public static native int rgba2yuvRotateC90Flip(int width, int height, byte[] rgbaIn,
133 | byte[] yuvOut);
134 |
135 | /**
136 | * rotate 180 degree in counter clockwise
137 | */
138 | public static native int yuvCropRotateC180(int width, int height, byte[] yuvIn,
139 | int outputHeight, byte[] yuvOut);
140 |
141 | public static native int yuvCrop(int width, int height, byte[] yuvIn,
142 | int outputHeight, byte[] yuvOut);
143 |
144 | public static native int yuvCropRotateC180Flip(int width, int height, byte[] yuvIn,
145 | int outputHeight, byte[] yuvOut);
146 |
147 | public static native int yuvCropFlip(int width, int height, byte[] yuvIn,
148 | int outputHeight, byte[] yuvOut);
149 |
150 | /**
151 | * rotate 180 degree in counter clockwise and change to yuv
152 | */
153 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
154 | public static int image2yuvCropRotateC180(Image imageIn, int outputHeight, byte[] yuvOut) {
155 | Image.Plane[] planes = imageIn.getPlanes();
156 | ByteBuffer Y = planes[0].getBuffer();
157 | ByteBuffer Cr = planes[2].getBuffer();
158 | int CrPixelStride = planes[2].getPixelStride();
159 | ByteBuffer Cb = planes[1].getBuffer();
160 | int CbPixelStride = planes[1].getPixelStride();
161 | return image2yuvCropRotateC180(imageIn.getWidth(), imageIn.getHeight(), Y, Cr, Cb,
162 | CrPixelStride, CbPixelStride, outputHeight, yuvOut);
163 | }
164 |
165 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
166 | public static int image2yuvCrop(Image imageIn, int outputHeight, byte[] yuvOut) {
167 | Image.Plane[] planes = imageIn.getPlanes();
168 | ByteBuffer Y = planes[0].getBuffer();
169 | ByteBuffer Cr = planes[2].getBuffer();
170 | int CrPixelStride = planes[2].getPixelStride();
171 | ByteBuffer Cb = planes[1].getBuffer();
172 | int CbPixelStride = planes[1].getPixelStride();
173 | return image2yuvCrop(imageIn.getWidth(), imageIn.getHeight(), Y, Cr, Cb, CrPixelStride,
174 | CbPixelStride, outputHeight, yuvOut);
175 | }
176 |
177 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
178 | public static int image2yuvCropRotateC180Flip(Image imageIn, int outputHeight, byte[] yuvOut) {
179 | Image.Plane[] planes = imageIn.getPlanes();
180 | ByteBuffer Y = planes[0].getBuffer();
181 | ByteBuffer Cr = planes[2].getBuffer();
182 | int CrPixelStride = planes[2].getPixelStride();
183 | ByteBuffer Cb = planes[1].getBuffer();
184 | int CbPixelStride = planes[1].getPixelStride();
185 | return image2yuvCropRotateC180Flip(imageIn.getWidth(), imageIn.getHeight(), Y, Cr, Cb,
186 | CrPixelStride, CbPixelStride, outputHeight, yuvOut);
187 | }
188 |
189 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
190 | public static int image2yuvCropFlip(Image imageIn, int outputHeight, byte[] yuvOut) {
191 | Image.Plane[] planes = imageIn.getPlanes();
192 | ByteBuffer Y = planes[0].getBuffer();
193 | ByteBuffer Cr = planes[2].getBuffer();
194 | int CrPixelStride = planes[2].getPixelStride();
195 | ByteBuffer Cb = planes[1].getBuffer();
196 | int CbPixelStride = planes[1].getPixelStride();
197 | return image2yuvCropFlip(imageIn.getWidth(), imageIn.getHeight(), Y, Cr, Cb, CrPixelStride,
198 | CbPixelStride, outputHeight, yuvOut);
199 | }
200 |
201 | private static native int image2yuvCropRotateC180(int width, int height, ByteBuffer Y,
202 | ByteBuffer Cr, ByteBuffer Cb, int CrPixelStride, int CbPixelStride, int outputWidth,
203 | byte[] yuvOut);
204 |
205 | private static native int image2yuvCrop(int width, int height, ByteBuffer Y, ByteBuffer Cr,
206 | ByteBuffer Cb, int CrPixelStride, int CbPixelStride, int outputWidth, byte[] yuvOut);
207 |
208 | private static native int image2yuvCropRotateC180Flip(int width, int height, ByteBuffer Y,
209 | ByteBuffer Cr, ByteBuffer Cb, int CrPixelStride, int CbPixelStride, int outputWidth,
210 | byte[] yuvOut);
211 |
212 | private static native int image2yuvCropFlip(int width, int height, ByteBuffer Y, ByteBuffer Cr,
213 | ByteBuffer Cb, int CrPixelStride, int CbPixelStride, int outputWidth, byte[] yuvOut);
214 | }
215 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/utils/CameraImageUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.utils;
26 |
27 | import android.annotation.TargetApi;
28 | import android.graphics.Bitmap;
29 | import android.graphics.ImageFormat;
30 | import android.graphics.Rect;
31 | import android.media.Image;
32 | import android.os.Build;
33 | import android.os.Environment;
34 | import android.util.Log;
35 | import java.io.BufferedOutputStream;
36 | import java.io.File;
37 | import java.io.FileOutputStream;
38 | import java.io.IOException;
39 | import java.nio.Buffer;
40 | import java.nio.ByteBuffer;
41 |
42 | /**
43 | * Created by Piasy{github.com/Piasy} on 5/27/16.
44 | */
45 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
46 | public class CameraImageUtil {
47 |
48 | public static byte[] getDataFromImage(Image image) {
49 | Rect crop = image.getCropRect();
50 | int format = image.getFormat();
51 | int width = crop.width();
52 | int height = crop.height();
53 | Image.Plane[] planes = image.getPlanes();
54 | byte[] data = new byte[width * height * ImageFormat.getBitsPerPixel(format) / 8];
55 | byte[] rowData = new byte[planes[0].getRowStride()];
56 | int channelOffset = 0;
57 | int outputStride = 1;
58 | for (int i = 0; i < planes.length; i++) {
59 | switch (i) {
60 | case 0:
61 | channelOffset = 0;
62 | outputStride = 1;
63 | break;
64 | case 1:
65 | channelOffset = width * height;
66 | outputStride = 1;
67 | break;
68 | case 2:
69 | channelOffset = (int) (width * height * 1.25);
70 | outputStride = 1;
71 | break;
72 | }
73 | ByteBuffer buffer = planes[i].getBuffer();
74 | int rowStride = planes[i].getRowStride();
75 | int pixelStride = planes[i].getPixelStride();
76 | int shift = (i == 0) ? 0 : 1;
77 | int w = width >> shift;
78 | int h = height >> shift;
79 | buffer.position(rowStride * (crop.top >> shift) + pixelStride * (crop.left >> shift));
80 | for (int row = 0; row < h; row++) {
81 | int length;
82 | if (pixelStride == 1) {
83 | length = w;
84 | buffer.get(data, channelOffset, length);
85 | channelOffset += length;
86 | } else {
87 | length = (w - 1) * pixelStride + 1;
88 | buffer.get(rowData, 0, length);
89 | for (int col = 0; col < w; col++) {
90 | data[channelOffset] = rowData[col * pixelStride];
91 | channelOffset += outputStride;
92 | }
93 | }
94 | if (row < h - 1) {
95 | buffer.position(buffer.position() + rowStride - length);
96 | }
97 | }
98 | }
99 | return data;
100 | }
101 |
102 | public static void image2yuv(Image imageIn, byte[] yuvOut) {
103 | Image.Plane[] planes = imageIn.getPlanes();
104 | ByteBuffer Y = planes[0].getBuffer();
105 | ByteBuffer Cr = planes[2].getBuffer();
106 | int CrPixelStride = planes[2].getPixelStride();
107 | ByteBuffer Cb = planes[1].getBuffer();
108 | int CbPixelStride = planes[1].getPixelStride();
109 | for (int i = 0, size = imageIn.getWidth() * imageIn.getHeight(); i < size; i++) {
110 | yuvOut[i] = Y.get(i);
111 | }
112 | for (int i = 0, size = imageIn.getWidth() * imageIn.getHeight(); i < size / 4; i++) {
113 | yuvOut[size + i * 2] = Cr.get(i * CrPixelStride);
114 | yuvOut[size + i * 2 + 1] = Cb.get(i * CbPixelStride);
115 | }
116 | try {
117 | File file = new File(
118 | Environment.getExternalStorageDirectory().getAbsolutePath() + "/dump.y");
119 | FileOutputStream outputStream = new FileOutputStream(file);
120 | byte[] bytes = new byte[Y.remaining()];
121 | Y.get(bytes);
122 | outputStream.write(bytes);
123 | outputStream.close();
124 |
125 | file = new File(
126 | Environment.getExternalStorageDirectory().getAbsolutePath() + "/dump.cb");
127 | outputStream = new FileOutputStream(file);
128 | bytes = new byte[Cb.remaining()];
129 | Cb.get(bytes);
130 | outputStream.write(bytes);
131 | outputStream.close();
132 |
133 | file = new File(
134 | Environment.getExternalStorageDirectory().getAbsolutePath() + "/dump.cr");
135 | outputStream = new FileOutputStream(file);
136 | bytes = new byte[Cr.remaining()];
137 | Cr.get(bytes);
138 | outputStream.write(bytes);
139 | outputStream.close();
140 | } catch (IOException e) {
141 | e.printStackTrace();
142 | }
143 | }
144 |
145 | public static void saveRgb2Bitmap(Buffer buf, String filename, int width, int height) {
146 | // Save the generated bitmap to a PNG so we can see what it looks like.
147 | Log.d("CameraCompat", "Creating "
148 | + Environment.getExternalStorageDirectory().getAbsolutePath()
149 | + "/"
150 | + filename);
151 | BufferedOutputStream bos = null;
152 | try {
153 | bos = new BufferedOutputStream(new FileOutputStream(
154 | Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + filename));
155 | Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
156 | bmp.copyPixelsFromBuffer(buf);
157 | bmp.compress(Bitmap.CompressFormat.PNG, 90, bos);
158 | bmp.recycle();
159 | } catch (IOException e) {
160 | e.printStackTrace();
161 | } finally {
162 | if (bos != null) {
163 | try {
164 | bos.close();
165 | } catch (IOException e) {
166 | e.printStackTrace();
167 | }
168 | }
169 | }
170 | }
171 |
172 | public static void saveRawRgbData(ByteBuffer buf, int width, int height, String prefix) {
173 | // Save the generated bitmap to a PNG so we can see what it looks like.
174 | String filename = Environment.getExternalStorageDirectory().getAbsolutePath()
175 | + "/"
176 | + prefix
177 | + "_"
178 | + width
179 | + "_"
180 | + height
181 | + ".rgb";
182 | Log.d("CameraCompat", "Creating " + filename);
183 | FileOutputStream outputStream;
184 | try {
185 | outputStream = new FileOutputStream(filename);
186 | outputStream.write(buf.array());
187 | outputStream.close();
188 | } catch (IOException e) {
189 | e.printStackTrace();
190 | }
191 | }
192 |
193 | public static void saveRawRgbData(byte[] buf, int width, int height) {
194 | // Save the generated bitmap to a PNG so we can see what it looks like.
195 | String filename = Environment.getExternalStorageDirectory().getAbsolutePath()
196 | + "/dump_r_"
197 | + width
198 | + "_"
199 | + height
200 | + ".rgb";
201 | Log.d("CameraCompat", "Creating " + filename);
202 | FileOutputStream outputStream;
203 | try {
204 | outputStream = new FileOutputStream(filename);
205 | outputStream.write(buf);
206 | outputStream.close();
207 | } catch (IOException e) {
208 | e.printStackTrace();
209 | }
210 | }
211 |
212 | public static void saveRawYuvData(byte[] buf, int width, int height, String prefix) {
213 | // Save the generated bitmap to a PNG so we can see what it looks like.
214 | String filename = Environment.getExternalStorageDirectory().getAbsolutePath()
215 | + "/"
216 | + prefix
217 | + "_"
218 | + width
219 | + "_"
220 | + height
221 | + ".yuv";
222 | Log.d("CameraCompat", "Creating " + filename);
223 | FileOutputStream outputStream;
224 | try {
225 | outputStream = new FileOutputStream(filename);
226 | outputStream.write(buf);
227 | outputStream.close();
228 | } catch (IOException e) {
229 | e.printStackTrace();
230 | }
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/utils/GLUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.utils;
26 |
27 | import android.app.ActivityManager;
28 | import android.content.Context;
29 | import android.content.pm.ConfigurationInfo;
30 | import android.graphics.Bitmap;
31 | import android.opengl.GLES20;
32 | import android.util.Log;
33 | import java.nio.ByteBuffer;
34 | import java.nio.IntBuffer;
35 | import jp.co.cyberagent.android.gpuimage.OpenGlUtils;
36 |
37 | /**
38 | * Created by Piasy{github.com/Piasy} on 5/24/16.
39 | */
40 |
41 | public final class GLUtil {
42 | public static final int NO_TEXTURE = -1;
43 |
44 | private GLUtil() {
45 | // no instance
46 | }
47 |
48 | public static boolean isSupportOpenGLES2(final Context context) {
49 | final ActivityManager activityManager =
50 | (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
51 | final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
52 | return configurationInfo.reqGlEsVersion >= 0x20000;
53 | }
54 |
55 | public static int loadTexture(final Bitmap img, final int usedTexId) {
56 | return OpenGlUtils.loadTexture(img, usedTexId, true);
57 | }
58 |
59 | public static int loadTexture(final ByteBuffer data, final int width, final int height,
60 | final int usedTexId) {
61 | int textures[] = new int[1];
62 | if (usedTexId == NO_TEXTURE) {
63 | GLES20.glGenTextures(1, textures, 0);
64 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
65 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
66 | GLES20.GL_LINEAR);
67 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
68 | GLES20.GL_LINEAR);
69 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
70 | GLES20.GL_CLAMP_TO_EDGE);
71 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
72 | GLES20.GL_CLAMP_TO_EDGE);
73 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0,
74 | GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, data);
75 | } else {
76 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, usedTexId);
77 | GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, width, height, GLES20.GL_RGBA,
78 | GLES20.GL_UNSIGNED_BYTE, data);
79 | textures[0] = usedTexId;
80 | }
81 | return textures[0];
82 | }
83 |
84 | public static int loadTextureAsBitmap(final IntBuffer data, final int width, final int height,
85 | final int usedTexId) {
86 | Bitmap bitmap = Bitmap.createBitmap(data.array(), width, height, Bitmap.Config.ARGB_8888);
87 | return loadTexture(bitmap, usedTexId);
88 | }
89 |
90 | public static int loadShader(final String strSource, final int iType) {
91 | return OpenGlUtils.loadShader(strSource, iType);
92 | }
93 |
94 | public static int loadProgram(final String strVSource, final String strFSource) {
95 | return OpenGlUtils.loadProgram(strVSource, strFSource);
96 | }
97 |
98 | public static float rnd(final float min, final float max) {
99 | return OpenGlUtils.rnd(min, max);
100 | }
101 |
102 | public static void dumpGlError(String op) {
103 | int error;
104 | while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
105 | Log.d("CameraCompat", "** " + op + ": glError " + error);
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/java/com/github/piasy/cameracompat/utils/Profiler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.utils;
26 |
27 | /**
28 | * Created by Piasy{github.com/Piasy} on 7/6/16.
29 | */
30 |
31 | public class Profiler {
32 | private final MetricListener mMetricListener;
33 |
34 | public Profiler(MetricListener metricListener) {
35 | mMetricListener = metricListener;
36 | }
37 |
38 | public void metric(long preDraw, long yuv2rgba, long draw, long readPixels, long rgba2yuv) {
39 | if (preDraw <= 0 || yuv2rgba <= 0 || draw <= 0 || readPixels <= 0 || rgba2yuv <= 0) {
40 | return;
41 | }
42 | mMetricListener.onMetric(new Metric(preDraw, yuv2rgba, draw, readPixels, rgba2yuv));
43 | }
44 |
45 | public interface MetricListener {
46 | void onMetric(Metric metric);
47 | }
48 |
49 | public static class Metric {
50 | public final long preDraw;
51 | public final long yuv2rgba;
52 | public final long draw;
53 | public final long readPixels;
54 | public final long rgba2yuv;
55 |
56 | public Metric(long preDraw, long yuv2rgba, long draw, long readPixels, long rgba2yuv) {
57 | this.preDraw = preDraw;
58 | this.yuv2rgba = yuv2rgba;
59 | this.draw = draw;
60 | this.readPixels = readPixels;
61 | this.rgba2yuv = rgba2yuv;
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/CameraCompat/src/main/res/layout/preview_fragment.xml:
--------------------------------------------------------------------------------
1 |
24 |
25 |
31 |
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Piasy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CameraCompat
2 |
3 | Create a camera preview app with beautify and camera api compatibility!
4 |
5 | [  ](https://bintray.com/piasy/maven/CameraCompat/_latestVersion)
6 |
7 | 
8 |
9 | ## Usage
10 |
11 | ### dependency
12 |
13 | ``` gradle
14 | allprojects {
15 | repositories {
16 | maven {
17 | url "http://dl.bintray.com/piasy/maven"
18 | }
19 | }
20 | }
21 |
22 | compile 'com.github.piasy:CameraCompat:1.3.0'
23 |
24 | // sorry that it doesn't work now, pr is welcome!
25 | compile 'com.github.piasy:BasicBeautifyProcessor:1.3.0'
26 | ```
27 |
28 | ### initialize
29 |
30 | ``` java
31 | // initialize in application's onCreate
32 | CameraCompat.init(getApplicationContext());
33 | ```
34 |
35 | ### add a ViewGroup into your layout
36 |
37 | ``` xml
38 |
43 | ```
44 |
45 | ### start preview
46 |
47 | ``` java
48 | // start preview in your activity or fragment
49 | CameraCompat.Builder builder = new CameraCompat.Builder(this, this)
50 | .beautifyOn(false) // default beautify option
51 | .flashOpen(false) // default flash option
52 | .previewWidth(639) // preview width
53 | .previewHeight(479) // preview height
54 | .enableMirror(false) // default mirror option
55 | .frontCamera(false); // default camera option
56 | if (mBeautifyCapable) {
57 | // add beautify processor, sorry that BasicBeautifyProcessor doesn't work now,
58 | // but in our production app, our real beautify processor works well,
59 | // I'm not an expert about open-gl, pr is welcome!
60 | builder.addProcessor(new BasicBeautifyProcessor());
61 | }
62 | mCameraCompat = builder.build();
63 | mCameraCompat.startPreview(null,
64 | getSupportFragmentManager(),
65 | R.id.mPreviewContainer); // add this ViewGroup in your layout
66 | ```
67 |
68 | ### receive callbacks
69 |
70 | ``` java
71 | @WorkerThread
72 | @Override
73 | public void onVideoSizeChanged(int width, int height) {
74 | Log.d("PublishActivity", "onVideoSizeChanged width = " + width
75 | + ", height = " + height);
76 | }
77 |
78 | @WorkerThread
79 | @Override
80 | public void onFrameData(final byte[] data, final int width, final int height) {
81 | Log.d("PublishActivity", "onFrameData width = " + width
82 | + ", height = " + height
83 | + ", data length = " + data.length);
84 | }
85 |
86 | @WorkerThread
87 | @Override
88 | public void onError(@CameraCompat.ErrorCode int code) {
89 | runOnUiThread(() ->
90 | Toast.makeText(this, "@CameraCompat.ErrorCode " + code, Toast.LENGTH_SHORT).show());
91 | }
92 | ```
93 |
94 | ### control behaviour
95 |
96 | ``` java
97 | mCameraCompat.switchBeautify();
98 | mCameraCompat.switchCamera();
99 | mCameraCompat.switchFlash();
100 | mCameraCompat.switchMirror();
101 | ```
102 |
103 | for resize and visibility control, just operate your `ViewGroup`.
104 |
105 | [Full example can be found here](https://github.com/Piasy/CameraCompat/blob/master/app/src/main/java/com/github/piasy/cameracompat/example/PublishActivity.java).
106 |
107 | ## Try demo app
108 |
109 | Demo app can be downloaded from https://fir.im/CCT . Thanks for fir.im!
110 |
111 | ## Todo
112 |
113 | - [ ] basic beautify processor
114 | - [ ] configure data format received in `onFrameData`, currently the frame is 90 degree rotated clockwise
115 | - [ ] focus
116 | - [ ] use libyuv rather than self writen converter
117 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'me.tatarka.retrolambda'
3 | apply plugin: 'android-apt'
4 | apply plugin: 'com.jakewharton.butterknife'
5 |
6 | android {
7 | compileSdkVersion rootProject.ext.androidCompileSdkVersion
8 | buildToolsVersion rootProject.ext.androidBuildToolsVersion
9 |
10 | defaultConfig {
11 | minSdkVersion rootProject.ext.minSdkVersion
12 | targetSdkVersion rootProject.ext.targetSdkVersion
13 | versionCode rootProject.ext.releaseVersionCode
14 | versionName rootProject.ext.releaseVersionName
15 |
16 | applicationId "com.github.piasy.cameracompat.example"
17 | ndk {
18 | abiFilter "armeabi"
19 | }
20 | }
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 |
28 | compileOptions {
29 | sourceCompatibility JavaVersion.VERSION_1_8
30 | targetCompatibility JavaVersion.VERSION_1_8
31 | }
32 | }
33 |
34 | dependencies {
35 | compile "com.android.support:appcompat-v7:$rootProject.ext.androidSupportSdkVersion"
36 | compile "com.jakewharton:butterknife:$rootProject.ext.butterKnifeVersion"
37 | apt "com.jakewharton:butterknife-compiler:$rootProject.ext.butterKnifeVersion"
38 | compile "com.github.yatatsu:autobundle:$rootProject.ext.autoBundleVersion"
39 | apt "com.github.yatatsu:autobundle-processor:$rootProject.ext.autoBundleVersion"
40 | compile 'com.afollestad.material-dialogs:core:0.9.0.2'
41 |
42 | compile 'com.squareup.leakcanary:leakcanary-android:1.5'
43 |
44 | compile project(':CameraCompat')
45 | compile project(':BasicBeautifyProcessor')
46 |
47 | compile("io.reactivex:rxandroid:$rootProject.ext.rxAndroidVersion") {
48 | exclude module: 'rxjava'
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/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/piasy/tools/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 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
27 |
28 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/piasy/cameracompat/example/DemoApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.example;
26 |
27 | import android.app.Application;
28 | import com.squareup.leakcanary.LeakCanary;
29 |
30 | /**
31 | * Created by Piasy{github.com/Piasy} on 04/11/2016.
32 | */
33 |
34 | public class DemoApplication extends Application {
35 | @Override
36 | public void onCreate() {
37 | super.onCreate();
38 |
39 | if (LeakCanary.isInAnalyzerProcess(this)) {
40 | return;
41 | }
42 | LeakCanary.install(this);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/piasy/cameracompat/example/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.example;
26 |
27 | import android.os.Bundle;
28 | import android.support.v7.app.AppCompatActivity;
29 | import butterknife.ButterKnife;
30 | import butterknife.OnClick;
31 | import com.github.piasy.cameracompat.CameraCompat;
32 |
33 | public class MainActivity extends AppCompatActivity {
34 |
35 | @Override
36 | protected void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 |
39 | CameraCompat.init(getApplicationContext());
40 |
41 | setContentView(R.layout.activity_main);
42 | ButterKnife.bind(this);
43 | }
44 |
45 | @OnClick(R2.id.mBtnBeautifyPublish)
46 | public void beautifyPublish() {
47 | startActivity(PublishActivityAutoBundle.createIntentBuilder(true).build(this));
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/piasy/cameracompat/example/PublishActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.piasy.cameracompat.example;
26 |
27 | import android.os.Bundle;
28 | import android.support.annotation.WorkerThread;
29 | import android.support.v7.app.AppCompatActivity;
30 | import android.util.Log;
31 | import android.view.View;
32 | import android.view.ViewGroup;
33 | import android.view.WindowManager;
34 | import android.widget.FrameLayout;
35 | import android.widget.Toast;
36 | import butterknife.BindView;
37 | import butterknife.ButterKnife;
38 | import butterknife.OnClick;
39 | import com.github.piasy.cameracompat.CameraCompat;
40 | import com.github.piasy.cameracompat.processor.basic.BasicBeautifyProcessor;
41 | import com.yatatsu.autobundle.AutoBundle;
42 | import com.yatatsu.autobundle.AutoBundleField;
43 |
44 | public class PublishActivity extends AppCompatActivity implements CameraCompat.VideoCaptureCallback,
45 | CameraCompat.ErrorHandler {
46 |
47 | @AutoBundleField
48 | boolean mBeautifyCapable;
49 |
50 | @BindView(R2.id.mPreviewContainer)
51 | View mContainer;
52 | @BindView(R2.id.mBtnSwitchBeautify)
53 | View mBtnSwitchBeautify;
54 |
55 | private CameraCompat mCameraCompat;
56 |
57 | private boolean mHide = false;
58 | private boolean mIsBig = true;
59 |
60 | @Override
61 | protected void onCreate(Bundle savedInstanceState) {
62 | AutoBundle.bind(this);
63 | super.onCreate(savedInstanceState);
64 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
65 |
66 | setContentView(R.layout.activity_publish);
67 | ButterKnife.bind(this);
68 |
69 | if (!mBeautifyCapable) {
70 | mBtnSwitchBeautify.setVisibility(View.GONE);
71 | }
72 |
73 | start();
74 | }
75 |
76 | @Override
77 | protected void onDestroy() {
78 | super.onDestroy();
79 | CameraCompat.reset();
80 | }
81 |
82 | @OnClick(R2.id.mBtnSwitchBeautify)
83 | public void switchBeautify() {
84 | mCameraCompat.switchBeautify();
85 | }
86 |
87 | @OnClick(R2.id.mBtnSwitchCamera)
88 | public void switchCamera() {
89 | mCameraCompat.switchCamera();
90 | }
91 |
92 | @OnClick(R2.id.mBtnSwitchFlash)
93 | public void switchFlash() {
94 | mCameraCompat.switchFlash();
95 | }
96 |
97 | @OnClick(R2.id.mBtnSwitchMirror)
98 | public void switchMirror() {
99 | mCameraCompat.switchMirror();
100 | }
101 |
102 | @OnClick(R2.id.mBtnSwitchVisibility)
103 | public void switchVisibility() {
104 | if (mHide) {
105 | mHide = false;
106 | mContainer.setVisibility(View.VISIBLE);
107 | } else {
108 | mHide = true;
109 | mContainer.setVisibility(View.INVISIBLE);
110 | }
111 | }
112 |
113 | @OnClick(R2.id.mBtnResize)
114 | public void resize() {
115 | if (mIsBig) {
116 | mIsBig = false;
117 | FrameLayout.LayoutParams params
118 | = (FrameLayout.LayoutParams) mContainer.getLayoutParams();
119 | params.height = 300;
120 | params.width = 160;
121 | mContainer.setLayoutParams(params);
122 |
123 | getSupportFragmentManager().beginTransaction()
124 | .remove(getSupportFragmentManager().findFragmentByTag(
125 | CameraCompat.CAMERA_PREVIEW_FRAGMENT))
126 | .commit();
127 |
128 | start();
129 | } else {
130 | mIsBig = true;
131 | FrameLayout.LayoutParams params
132 | = (FrameLayout.LayoutParams) mContainer.getLayoutParams();
133 | params.height = ViewGroup.LayoutParams.MATCH_PARENT;
134 | params.width = ViewGroup.LayoutParams.MATCH_PARENT;
135 | mContainer.setLayoutParams(params);
136 |
137 | getSupportFragmentManager().beginTransaction()
138 | .remove(getSupportFragmentManager().findFragmentByTag(
139 | CameraCompat.CAMERA_PREVIEW_FRAGMENT))
140 | .commit();
141 |
142 | start();
143 | }
144 | }
145 |
146 | private void start() {
147 | CameraCompat.Builder builder = new CameraCompat.Builder(this, this)
148 | .beautifyOn(false) // default beautify option
149 | .flashOpen(false) // default flash option
150 | .previewWidth(639) // preview width
151 | .previewHeight(479) // preview height
152 | .enableMirror(false) // default mirror option
153 | .frontCamera(false); // default camera option
154 | if (mBeautifyCapable) {
155 | // add beautify processor, sorry that BasicBeautifyProcessor doesn't work now,
156 | // but in our production app, our real beautify processor works well,
157 | // I'm not an expert about open-gl, pr is welcome!
158 | builder.addProcessor(new BasicBeautifyProcessor());
159 | }
160 | mCameraCompat = builder.build();
161 | mCameraCompat.startPreview(null,
162 | getSupportFragmentManager(),
163 | R.id.mPreviewContainer); // add this ViewGroup in your layout
164 | }
165 |
166 | @WorkerThread
167 | @Override
168 | public void onVideoSizeChanged(int width, int height) {
169 | Log.d("PublishActivity", "onVideoSizeChanged width = " + width
170 | + ", height = " + height);
171 | }
172 |
173 | @WorkerThread
174 | @Override
175 | public void onFrameData(final byte[] data, final int width, final int height) {
176 | Log.d("PublishActivity", "onFrameData width = " + width
177 | + ", height = " + height
178 | + ", data length = " + data.length);
179 | }
180 |
181 | @WorkerThread
182 | @Override
183 | public void onError(@CameraCompat.ErrorCode int code) {
184 | runOnUiThread(() ->
185 | Toast.makeText(this, "@CameraCompat.ErrorCode " + code, Toast.LENGTH_SHORT).show());
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
31 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_profiling.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
31 |
36 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_publish.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
32 |
37 |
43 |
50 |
57 |
64 |
71 |
78 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_watch.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
38 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/CameraCompat/099f48d47172ab75e65b06bf947f60964d3ff6bd/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/CameraCompat/099f48d47172ab75e65b06bf947f60964d3ff6bd/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/CameraCompat/099f48d47172ab75e65b06bf947f60964d3ff6bd/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/CameraCompat/099f48d47172ab75e65b06bf947f60964d3ff6bd/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/CameraCompat/099f48d47172ab75e65b06bf947f60964d3ff6bd/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | CameraCompat
3 |
4 |
5 | Hello blank fragment
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/art/screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/CameraCompat/099f48d47172ab75e65b06bf947f60964d3ff6bd/art/screenshot.jpg
--------------------------------------------------------------------------------
/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 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.2'
9 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
10 |
11 | classpath 'me.tatarka:gradle-retrolambda:3.3.0'
12 | classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0'
13 | classpath 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2'
14 |
15 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.1'
16 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
17 | }
18 | configurations.classpath.exclude group: 'com.android.tools.external.lombok'
19 | }
20 |
21 | allprojects {
22 | repositories {
23 | jcenter()
24 | }
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
31 | ext {
32 | userName = 'Piasy'
33 | developer = [
34 | id : 'piasy',
35 | name : 'piasy',
36 | email: 'xz4215@gmail.com'
37 | ]
38 | license = [
39 | id : 'MIT',
40 | name: 'The MIT License (MIT)',
41 | url : 'http://opensource.org/licenses/MIT'
42 | ]
43 | groupName = 'com.github.piasy'
44 | artifactName = 'CameraCompat'
45 | artifactDescription = 'Create a camera preview app with beautify and camera api compatibility!'
46 | artifactLabels = ['Camera', 'Preview', 'GPUImage', 'Beautify', 'Compat']
47 | releaseVersionCode = 14
48 | releaseVersionName = '1.3.0'
49 |
50 | minSdkVersion = 15
51 | androidCompileSdkVersion = 24
52 | androidBuildToolsVersion = '25.0.0'
53 | targetSdkVersion = 24
54 | androidSupportSdkVersion = '25.0.0'
55 |
56 | fragmentArgsVersion = '3.0.2'
57 | gpuImageVersion = '1.4.1'
58 | rxJavaVersion = '1.2.1'
59 | rxAndroidVersion = '1.2.1'
60 | timberVersion = '4.3.1'
61 | retroLambdaVersion = '2.3.0'
62 | butterKnifeVersion = '8.4.0'
63 | autoBundleVersion = '3.1.1'
64 | }
65 |
--------------------------------------------------------------------------------
/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 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
--------------------------------------------------------------------------------
/gradle/publish.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2016 Piasy
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | publishing {
26 | publications {
27 | aar(MavenPublication) {
28 | groupId rootProject.ext.groupName
29 | version rootProject.ext.releaseVersionName
30 | artifactId project.name
31 |
32 | artifact("$buildDir/outputs/aar/${artifactId}-release.aar")
33 |
34 | pom.withXml {
35 | def root = asNode()
36 |
37 | def dependenciesNode = root.appendNode('dependencies')
38 | configurations.compile.allDependencies.each {
39 | if (it.group && it.name && it.version) {
40 | def dependencyNode = dependenciesNode.appendNode('dependency')
41 | dependencyNode.appendNode('groupId', it.group)
42 | dependencyNode.appendNode('artifactId', it.name)
43 | dependencyNode.appendNode('version', it.version)
44 | }
45 | }
46 | }
47 | }
48 | }
49 | }
50 |
51 | artifactory {
52 | contextUrl = 'http://47.88.103.205:8081/artifactory'
53 | publish {
54 | repository {
55 | repoKey = 'libs-release-local'
56 |
57 | username = artifactory_username
58 | password = artifactory_password
59 | }
60 | defaults {
61 | publications('aar')
62 | publishArtifacts = true
63 |
64 | properties = ['qa.level': 'basic', 'q.os': 'android', 'dev.team': 'core']
65 | publishPom = true
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/CameraCompat/099f48d47172ab75e65b06bf947f60964d3ff6bd/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Sep 12 11:50:58 CST 2016
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-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':CameraCompat', ':BasicBeautifyProcessor'
--------------------------------------------------------------------------------
/wiki/Procedure.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Camera1
4 |
5 | 1. `PreviewFragment#onViewCreated`:
6 |
7 | ~~~ java
8 | @Override
9 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
10 | super.onViewCreated(view, savedInstanceState);
11 |
12 | mPreviewContainer.addView(mProcessorChain.createSurface(getContext()));
13 | mCameraHelper = createCameraHelper();
14 | mProcessorChain.initSurface(getContext());
15 | }
16 | ~~~
17 |
18 | 2. `PreviewFragment#onResume` ->
19 | 3. `mCameraHelper.startPreview()` ->
20 | 4. `Camera1PreviewFragment#onOpened()` ->
21 | 5. `Camera1PreviewFragment#startPreviewDirectly()` ->
22 | 6. `camera.startPreview()`,`mRenderer.resumeDrawing()`
23 |
24 | 数据流:Camera -> Camera1PreviewCallback -> ProcessorChain
25 |
26 | `ProcessorChain.resume()` 之后,`GLRender` 才会对相机数据进行处理。
27 |
28 | 如果开启美颜,则走:
29 |
30 | 1. `ProcessorChain#onFrameData` ->
31 | 2. filter draw ->
32 | 3. `GLFilterGroup#dumpImage` ->
33 | 4. `ProcessorChain#imageDumped` ->
34 | 5. `CameraCompat.VideoCaptureCallback#onFrameData` ->
35 | 6. 外部使用方实现的回调
36 |
37 | 否则直接走(当然也会渲染到 GLSurfaceView 上):
38 |
39 | 1. `ProcessorChain#onFrameData` ->
40 | 2. `CameraCompat.VideoCaptureCallback#onFrameData` ->
41 | 3. 外部使用方实现的回调
42 |
43 | `PreviewFragment#onPause` -> `mCameraHelper.stopPreview()`
44 |
45 | ## Camera2
46 |
47 | 和 Camera1 基本一致。
48 |
--------------------------------------------------------------------------------